| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "qg_layerwidget.h" |
| |
|
| | #include <QAbstractTableModel> |
| | #include <QContextMenuEvent> |
| | #include <QHeaderView> |
| | #include <QIcon> |
| | #include <QLineEdit> |
| | #include <QMenu> |
| | #include <QObject> |
| | #include <QScrollBar> |
| | #include <QTableView> |
| | #include <QToolButton> |
| |
|
| | #include "lc_actiongroupmanager.h" |
| | #include "lc_flexlayout.h" |
| | #include "qc_applicationwindow.h" |
| | #include "qg_actionhandler.h" |
| | #include "rs_debug.h" |
| | #include "rs_entitycontainer.h" |
| | #include "rs_graphic.h" |
| | #include "rs_graphicview.h" |
| | #include "rs_layer.h" |
| | #include "rs_layerlist.h" |
| | #include "rs_settings.h" |
| |
|
| | QG_LayerModel::QG_LayerModel(QObject * parent) : ::QAbstractTableModel(parent) { |
| | m_iconLayerVisible = QIcon(":/icons/visible.lci"); |
| | |
| | m_iconLayerHidden = QIcon(":/icons/not_visible.lci"); |
| | m_iconLayerDefreeze = QIcon(":/icons/unlocked.lci"); |
| | m_iconLayerFreeze = QIcon(":/icons/locked.lci"); |
| | m_iconLayerPrint = QIcon(":/icons/print.lci"); |
| | m_iconLayerNoPrint = QIcon(":/icons/noprint.lci"); |
| | m_iconLayerConstruction = QIcon(":/icons/construction_layer.lci"); |
| | m_iconLayerNoConstruction = QIcon(":/icons/noconstruction.lci"); |
| | } |
| |
|
| | int QG_LayerModel::rowCount ( const QModelIndex & ) const { |
| | return m_listLayer.size(); |
| | } |
| |
|
| | QModelIndex QG_LayerModel::parent ( const QModelIndex & ) const { |
| | return QModelIndex(); |
| | } |
| |
|
| | QModelIndex QG_LayerModel::index ( int row, int column, const QModelIndex & ) const { |
| | if ( row >= m_listLayer.size() || row < 0) |
| | return QModelIndex(); |
| | return createIndex ( row, column); |
| | } |
| |
|
| | void QG_LayerModel::setLayerList(RS_LayerList* ll) { |
| | |
| | |
| | |
| | beginResetModel(); |
| | m_listLayer.clear(); |
| | if (ll == nullptr) { |
| | endResetModel(); |
| | return; |
| | } |
| | for (unsigned i=0; i < ll->count(); ++i) { |
| | m_listLayer.append(ll->at(i)); |
| | } |
| | setActiveLayer(ll->getActive()); |
| | std::sort( m_listLayer.begin(), m_listLayer.end(), [](const RS_Layer *s1, const RS_Layer *s2)-> bool{ |
| | return s1->getName() < s2->getName(); |
| | } ); |
| |
|
| | |
| | endResetModel(); |
| | } |
| |
|
| | RS_Layer *QG_LayerModel::getLayer(int row) const { |
| | if ( row >= m_listLayer.size() || row < 0) { |
| | return nullptr; |
| | } |
| | return m_listLayer.at(row); |
| | } |
| |
|
| | QModelIndex QG_LayerModel::getIndex (RS_Layer * lay) const { |
| | int row = m_listLayer.indexOf(lay); |
| | if (row<0) { |
| | return {}; |
| | } |
| | return createIndex (row, NAME); |
| | } |
| | QVariant QG_LayerModel::data ( const QModelIndex & index, int role ) const{ |
| | if (!index.isValid() || index.row() >= m_listLayer.size()) |
| | return QVariant(); |
| |
|
| | RS_Layer *layer{m_listLayer.at(index.row())}; |
| | int col{index.column()}; |
| |
|
| | switch (role) { |
| | case Qt::DecorationRole: |
| | switch (col) { |
| | case VISIBLE: |
| | if (!layer->isFrozen()) { |
| | return m_iconLayerVisible; |
| | } |
| | return m_iconLayerHidden; |
| |
|
| | case LOCKED: |
| | if (!layer->isLocked()) { |
| | return m_iconLayerDefreeze; |
| | } |
| | return m_iconLayerFreeze; |
| |
|
| | case PRINT: |
| | if (!layer->isPrint()) { |
| | return m_iconLayerNoPrint; |
| | } |
| | return m_iconLayerPrint; |
| |
|
| | case CONSTRUCTION: |
| | if (!layer->isConstruction()) { |
| | return m_iconLayerNoConstruction; |
| | } |
| | return m_iconLayerConstruction; |
| |
|
| | default: |
| | break; |
| | } |
| | break; |
| |
|
| | case Qt::DisplayRole: |
| | if (NAME == col) { |
| | return layer->getName(); |
| | } |
| | break; |
| |
|
| | #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) |
| | case Qt::BackgroundRole: |
| | #else |
| | case Qt::BackgroundColorRole: |
| | #endif |
| | if (COLOR_SAMPLE == col) { |
| | return layer->getPen().getColor().toQColor(); |
| | } |
| | break; |
| |
|
| | case Qt::FontRole: |
| | if (NAME == col) { |
| | if (m_activeLayer && m_activeLayer == layer) { |
| | QFont font; |
| | font.setBold(true); |
| | return font; |
| | } |
| | } |
| | break; |
| | default: |
| | break; |
| | } |
| |
|
| | return QVariant(); |
| | } |
| |
|
| | void QG_LayerWidget::addToolbarButton(LC_FlexLayout* layButtons, RS2::ActionType actionType) { |
| | QAction* action = m_actionGroupManager->getActionByType(actionType); |
| | if (action != nullptr) { |
| | auto button = new QToolButton(this); |
| | button->setDefaultAction(action); |
| | layButtons->addWidget(button); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | QG_LayerWidget::QG_LayerWidget(LC_ActionGroupManager* agm, QG_ActionHandler *ah, QWidget *parent, const char *name, Qt::WindowFlags f) |
| | : LC_GraphicViewAwareWidget(parent, name, f){ |
| | m_actionHandler = ah; |
| | m_actionGroupManager = agm; |
| | m_layerList = nullptr; |
| | m_showByBlock = false; |
| | m_lastLayer = nullptr; |
| |
|
| | m_layerModel = new QG_LayerModel(this); |
| | m_layerView = new QTableView(this); |
| | m_layerView->setModel(m_layerModel); |
| | m_layerView->setShowGrid(true); |
| | m_layerView->setSelectionMode(QAbstractItemView::ExtendedSelection); |
| | m_layerView->setEditTriggers(QAbstractItemView::NoEditTriggers); |
| | m_layerView->setFocusPolicy(Qt::NoFocus); |
| | |
| | m_layerView->setMinimumHeight(60); |
| | QHeaderView *pHeader {m_layerView->horizontalHeader()}; |
| | pHeader->setMinimumSectionSize( QG_LayerModel::ICONWIDTH + 4); |
| | pHeader->setStretchLastSection(true); |
| | pHeader->hide(); |
| | m_layerView->setColumnWidth(QG_LayerModel::VISIBLE, QG_LayerModel::ICONWIDTH); |
| | m_layerView->setColumnWidth(QG_LayerModel::VISIBLE, QG_LayerModel::ICONWIDTH); |
| | m_layerView->setColumnWidth(QG_LayerModel::LOCKED, QG_LayerModel::ICONWIDTH); |
| | m_layerView->setColumnWidth(QG_LayerModel::PRINT, QG_LayerModel::ICONWIDTH); |
| | m_layerView->setColumnWidth(QG_LayerModel::CONSTRUCTION, QG_LayerModel::ICONWIDTH); |
| | m_layerView->setColumnWidth(QG_LayerModel::COLOR_SAMPLE, QG_LayerModel::ICONWIDTH); |
| | m_layerView->verticalHeader()->hide(); |
| |
|
| | #ifndef DONT_FORCE_WIDGETS_CSS |
| | m_layerView->setStyleSheet("QWidget {background-color: white;} QScrollBar{ background-color: none }"); |
| | #endif |
| |
|
| | auto* lay = new QVBoxLayout(this); |
| | lay->setContentsMargins(2, 2, 2, 2); |
| |
|
| | auto *layButtons = new LC_FlexLayout(0,5,5); |
| |
|
| | addToolbarButton(layButtons, RS2::ActionLayersDefreezeAll); |
| | addToolbarButton(layButtons, RS2::ActionLayersFreezeAll); |
| | addToolbarButton(layButtons, RS2::ActionLayersUnlockAll); |
| | addToolbarButton(layButtons, RS2::ActionLayersLockAll); |
| | addToolbarButton(layButtons, RS2::ActionLayersAdd); |
| | addToolbarButton(layButtons, RS2::ActionLayersRemove); |
| | addToolbarButton(layButtons, RS2::ActionLayersEdit); |
| |
|
| | |
| | m_matchLayerName = new QLineEdit(this); |
| | m_matchLayerName->setReadOnly(false); |
| | m_matchLayerName->setPlaceholderText(tr("Filter")); |
| | m_matchLayerName->setClearButtonEnabled(true); |
| | m_matchLayerName->setToolTip(tr("Looking for matching layer names")); |
| | connect(m_matchLayerName, &QLineEdit::textChanged, this, &QG_LayerWidget::slotUpdateLayerList); |
| |
|
| | lay->addWidget(m_matchLayerName); |
| | lay->addLayout(layButtons); |
| | lay->addWidget(m_layerView); |
| | this->setLayout(lay); |
| |
|
| | connect(m_layerView, &QTableView::clicked, this, &QG_LayerWidget::slotActivated); |
| | connect(m_layerView->selectionModel(), &QItemSelectionModel::selectionChanged, |
| | this, &QG_LayerWidget::slotSelectionChanged); |
| |
|
| | updateWidgetSettings(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void QG_LayerWidget::setLayerList(RS_LayerList* layerList, bool showByBlock) { |
| | if (m_layerList != nullptr) { |
| | m_layerList->removeListener(this); |
| | } |
| |
|
| | m_layerList = layerList; |
| | m_showByBlock = showByBlock; |
| |
|
| | if (layerList != nullptr) { |
| | m_layerList->addListener(this); |
| | } |
| | update(); |
| | } |
| |
|
| | void QG_LayerWidget::updateFiltering(){ |
| | if (! m_matchLayerName->text().isEmpty()) { |
| | slotUpdateLayerList(); |
| | } |
| | } |
| |
|
| | void QG_LayerWidget::layerAdded(RS_Layer* layer){ |
| | update(); |
| | updateFiltering(); |
| | activateLayer(layer); |
| | update(); |
| | } |
| |
|
| | void QG_LayerWidget::layerEdited([[maybe_unused]]RS_Layer *rs_layer){ |
| | update(); |
| | updateFiltering(); |
| | } |
| |
|
| | void QG_LayerWidget::layerRemoved([[maybe_unused]]RS_Layer *rs_layer){ |
| | update(); |
| | updateFiltering(); |
| | update(); |
| | activateLayer(m_layerList->at(0)); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | QString QG_LayerWidget::getActiveName() const{ |
| | if (m_layerList != nullptr) { |
| | RS_Layer *activeLayer = m_layerList->getActive(); |
| | if (activeLayer != nullptr) { |
| | return activeLayer->getName(); |
| | } |
| | } |
| | return QString(); |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::update() { |
| | RS_DEBUG->print("QG_LayerWidget::update() begin"); |
| |
|
| | if (!m_layerView) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LayerWidget::update: nullptr layerView"); |
| | return; |
| | } |
| | int yPos = m_layerView->verticalScrollBar()->value(); |
| | m_layerView->resizeRowsToContents(); |
| | m_layerView->verticalScrollBar()->setValue(yPos); |
| |
|
| | m_layerModel->setLayerList(m_layerList); |
| |
|
| | if (m_layerList == nullptr) { |
| | RS_DEBUG->print(RS_Debug::D_NOTICE, "QG_LayerWidget::update: nullptr layerList"); |
| | return; |
| | } |
| |
|
| | RS_DEBUG->print("QG_LayerWidget::update: reactivating current layer"); |
| |
|
| | RS_Layer* activeLayer = m_layerList->getActive(); |
| | if (activeLayer == nullptr) { |
| | RS_DEBUG->print(RS_Debug::D_NOTICE, "QG_LayerWidget::update: nullptr activeLayer"); |
| | m_layerModel->setActiveLayer(nullptr); |
| | return; |
| | } |
| |
|
| | if (m_lastLayer == nullptr) { |
| | RS_DEBUG->print(RS_Debug::D_NOTICE, "QG_LayerWidget::update: nullptr lastLayer"); |
| | m_lastLayer = activeLayer; |
| | } |
| |
|
| | restoreSelections(); |
| |
|
| | RS_DEBUG->print("QG_LayerWidget::update(): OK"); |
| | } |
| |
|
| | void QG_LayerWidget::restoreSelections() { |
| | QItemSelectionModel* selectionModel = m_layerView->selectionModel(); |
| | for (auto* layer: *m_layerList) { |
| | if (!layer) continue; |
| | if (!layer->isVisibleInLayerList()) continue; |
| | if (!layer->isSelectedInLayerList()) continue; |
| |
|
| | QModelIndex idx = m_layerModel->getIndex(layer); |
| | QItemSelection selection(idx, idx); |
| | selectionModel->select(selection, QItemSelectionModel::Select); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void QG_LayerWidget::activateLayer(RS_Layer* layer, bool updateScroll) { |
| | RS_DEBUG->print("QG_LayerWidget::activateLayer() begin"); |
| |
|
| | if (!layer || !m_layerList) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LayerWidget::activateLayer: nullptr layer or layerList"); |
| | return; |
| | } |
| |
|
| | m_layerList->activate(layer); |
| |
|
| | if (!m_layerModel) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LayerWidget::activateLayer: nullptr layerModel"); |
| | return; |
| | } |
| | QModelIndex idx = m_layerModel->getIndex(layer); |
| |
|
| | if (!idx.model() || !m_layerView) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LayerWidget::activateLayer: invalid layer or nullptr layerView"); |
| | return; |
| | } |
| |
|
| | |
| | bool selected = layer->isSelectedInLayerList(); |
| |
|
| | m_layerView->setCurrentIndex(idx); |
| | m_layerModel->setActiveLayer(layer); |
| | m_layerView->viewport()->update(); |
| |
|
| | |
| | QItemSelectionModel::SelectionFlag selFlag; |
| | if (selected) { |
| | selFlag = QItemSelectionModel::Select; |
| | } else { |
| | selFlag = QItemSelectionModel::Deselect; |
| | } |
| | layer->selectedInLayerList(selected); |
| | m_layerView->selectionModel()->select(QItemSelection(idx, idx), selFlag); |
| |
|
| | if (!updateScroll) { |
| | int yPos = m_layerView->verticalScrollBar()->value(); |
| | m_layerView->verticalScrollBar()->setValue(yPos); |
| | } |
| |
|
| | |
| | QC_ApplicationWindow::getAppWindow()->slotUpdateActiveLayer(); |
| |
|
| | RS_DEBUG->print("QG_LayerWidget::activateLayer() end"); |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::slotActivated(QModelIndex layerIdx ) { |
| | if (!layerIdx.isValid() || m_layerList==nullptr) { |
| | return; |
| | } |
| |
|
| | RS_Layer* lay = m_layerModel->getLayer(layerIdx.row()); |
| | if (lay == nullptr) |
| | return; |
| |
|
| | if (layerIdx.column() == QG_LayerModel::NAME) { |
| | m_layerList->activate(lay, true); |
| | return; |
| | } |
| |
|
| | switch (layerIdx.column()) { |
| | case QG_LayerModel::VISIBLE: |
| | m_actionHandler->setCurrentAction(RS2::ActionLayersToggleView, lay); |
| | break; |
| | case QG_LayerModel::LOCKED: |
| | m_actionHandler->setCurrentAction(RS2::ActionLayersToggleLock, lay); |
| | |
| | break; |
| | case QG_LayerModel::PRINT: |
| | m_actionHandler->setCurrentAction(RS2::ActionLayersTogglePrint, lay); |
| | |
| | break; |
| | case QG_LayerModel::CONSTRUCTION: |
| | m_actionHandler->setCurrentAction(RS2::ActionLayersToggleConstruction, lay); |
| | |
| | break; |
| | default: |
| | break; |
| | } |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::slotSelectionChanged( |
| | const QItemSelection &selected, |
| | const QItemSelection &deselected){ |
| | QModelIndex index; |
| | QItemSelectionModel *selectionModel {m_layerView->selectionModel()}; |
| |
|
| | foreach (index, selected.indexes()) { |
| | auto layer = m_layerModel->getLayer(index.row()); |
| | if (layer) { |
| | layer->selectedInLayerList(true); |
| | selectionModel->select(QItemSelection(index, index), QItemSelectionModel::Select); |
| | } |
| | } |
| |
|
| | foreach (index, deselected.indexes()) { |
| | auto layer = m_layerModel->getLayer(index.row()); |
| | if (layer && layer->isVisibleInLayerList()) { |
| | layer->selectedInLayerList(false); |
| | selectionModel->select(QItemSelection(index, index), QItemSelectionModel::Deselect); |
| | } |
| | } |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::slotUpdateLayerList() { |
| | QRegularExpression rx = QRegularExpression::fromWildcard(m_matchLayerName->text()); |
| |
|
| | for (unsigned i=0; i<m_layerList->count() ; i++) { |
| | QString s=m_layerModel->getLayer(i)->getName(); |
| | if (m_matchLayerName->text().isEmpty() || s.indexOf(rx) == 0) { |
| | m_layerView->showRow(i); |
| | m_layerModel->getLayer(i)->visibleInLayerList(true); |
| | } else { |
| | m_layerView->hideRow(i); |
| | m_layerModel->getLayer(i)->visibleInLayerList(false); |
| | } |
| | } |
| |
|
| | restoreSelections(); |
| | } |
| |
|
| | void QG_LayerWidget::addMenuItem(QMenu* contextMenu, RS2::ActionType actionType) { |
| | auto action = m_actionGroupManager->getActionByType(actionType); |
| | if (action != nullptr) { |
| | contextMenu->QWidget::addAction(action); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::contextMenuEvent(QContextMenuEvent *e) { |
| | auto menu = new QMenu(this); |
| | addMenuItem(menu, RS2::ActionLayersDefreezeAll); |
| | addMenuItem(menu, RS2::ActionLayersFreezeAll); |
| | addMenuItem(menu, RS2::ActionLayersUnlockAll); |
| | addMenuItem(menu, RS2::ActionLayersLockAll); |
| | menu->addSeparator(); |
| | |
| | addMenuItem(menu, RS2::ActionLayersToggleView); |
| | addMenuItem(menu, RS2::ActionLayersToggleLock); |
| | addMenuItem(menu, RS2::ActionLayersTogglePrint); |
| | addMenuItem(menu, RS2::ActionLayersToggleConstruction); |
| | addMenuItem(menu, RS2::ActionLayersRemove); |
| | menu->addSeparator(); |
| | |
| | addMenuItem(menu, RS2::ActionLayersAdd); |
| | addMenuItem(menu, RS2::ActionLayersEdit); |
| | menu->addSeparator(); |
| | addMenuItem(menu, RS2::ActionLayersExportSelected); |
| | addMenuItem(menu, RS2::ActionLayersExportVisible); |
| | menu->exec(QCursor::pos()); |
| | e->accept(); |
| | } |
| |
|
| | |
| | |
| | |
| | void QG_LayerWidget::keyPressEvent(QKeyEvent* e) { |
| | switch (e->key()) { |
| |
|
| | case Qt::Key_Escape: { |
| | emit escape(); |
| | break; |
| | } |
| | default: |
| | QWidget::keyPressEvent(e); |
| | break; |
| | } |
| | } |
| |
|
| | void QG_LayerWidget::activateLayer(int row){ |
| | auto layer = m_layerModel->getLayer(row); |
| | if (layer) { |
| | m_layerList->activate(layer, true); |
| | } |
| | else |
| | qWarning("activateLayer: row %d doesn't exist", row); |
| | } |
| |
|
| | void QG_LayerWidget::updateWidgetSettings(){ |
| | LC_GROUP("Widgets"); { |
| | bool flatIcons = LC_GET_BOOL("DockWidgetsFlatIcons", true); |
| | int iconSize = LC_GET_INT("DockWidgetsIconSize", 16); |
| |
|
| | QSize size(iconSize, iconSize); |
| |
|
| | QList<QToolButton *> widgets = this->findChildren<QToolButton *>(); |
| | foreach(QToolButton *w, widgets) { |
| | w->setAutoRaise(flatIcons); |
| | w->setIconSize(size); |
| | } |
| | } |
| | LC_GROUP_END(); |
| | } |
| |
|
| | void QG_LayerWidget::setGraphicView(RS_GraphicView *gview){ |
| | if (gview == nullptr) { |
| | setLayerList(nullptr, false); |
| | } |
| | else { |
| | auto doc = gview->getContainer(); |
| | bool showByBlock = doc->rtti() == RS2::EntityBlock; |
| | if (showByBlock) { |
| | setLayerList(gview->getGraphic(true)->getLayerList(), false); |
| | } |
| | else { |
| | auto layerList = doc->getGraphic()->getLayerList(); |
| | setLayerList(layerList, showByBlock); |
| | } |
| | } |
| | } |
| |
|