Tue, 07 Jun 2022 21:35:29 +0300
Move editing modes tool bar, tool options widget stack and model list view into the main window
src/document.cpp | file | annotate | diff | comparison | revisions | |
src/document.h | file | annotate | diff | comparison | revisions | |
src/document.ui | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/mainwindow.ui | file | annotate | diff | comparison | revisions | |
src/ui/canvas.h | file | annotate | diff | comparison | revisions |
--- a/src/document.cpp Tue Jun 07 20:44:19 2022 +0300 +++ b/src/document.cpp Tue Jun 07 21:35:29 2022 +0300 @@ -18,8 +18,8 @@ #include <QMouseEvent> #include <QMessageBox> +#include <QVBoxLayout> #include "document.h" -#include "ui_document.h" #include "model.h" #include "ui/objecteditor.h" @@ -33,56 +33,24 @@ canvas{new Canvas{model, this, documents, colorTable, this}}, model{model}, documents{documents}, - vertexMap{model}, - ui{*new Ui_Document}, - toolsBar{new QToolBar{this}} + vertexMap{model} { - this->ui.setupUi(this); - const int listWidth = static_cast<int>(this->width() / 3); - this->ui.viewportListSplitter->setSizes({listWidth * 2, listWidth}); - this->ui.toolsBarContainer->setLayout(new QVBoxLayout{this->ui.toolsBarContainer}); - this->ui.toolsBarContainer->layout()->addWidget(this->toolsBar); - this->ui.listView->setModel(model); - this->ui.viewportFrame->setLayout(new QVBoxLayout{this->ui.listView}); - this->ui.viewportFrame->layout()->addWidget(this->canvas); - this->toolsBar->setOrientation(Qt::Vertical); this->setMouseTracking(true); - connect(this->ui.viewportListSplitter, &QSplitter::splitterMoved, this, &EditorTabWidget::splitterChanged); connect(this->canvas, &Canvas::mouseClick, this, &EditorTabWidget::canvasMouseClick); connect(this->canvas, &Canvas::mouseMove, this, &EditorTabWidget::canvasMouseMove); connect(this->canvas, &Canvas::newStatusText, this, &EditorTabWidget::newStatusText); - connect(this->ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged, - [&](const QItemSelection& selected, const QItemSelection& deselected) - { - auto resolveIndex = [this](const QModelIndex& index){ return this->model->idAt(index.row()); }; - auto resolve = [resolveIndex](const QItemSelection& selection) - { - return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex); - }; - this->canvas->handleSelectionChange(resolve(selected), resolve(deselected)); - }); connect(this->model, &Model::dataChanged, this->canvas, qOverload<>(&Canvas::update)); connect(&this->vertexMap, &VertexMap::verticesChanged, [&]() { this->canvas->rebuildVertices(this); }); this->canvas->drawState = &this->drawState; - this->initializeTools(); + QVBoxLayout* layout = new QVBoxLayout{this}; + layout->addWidget(this->canvas); } EditorTabWidget::~EditorTabWidget() { - delete &this->ui; -} - -QByteArray EditorTabWidget::saveSplitterState() const -{ - return this->ui.viewportListSplitter->saveState(); -} - -void EditorTabWidget::restoreSplitterState(const QByteArray& state) -{ - this->ui.viewportListSplitter->restoreState(state); } void EditorTabWidget::applyToVertices(VertexMap::ApplyFunction fn) const @@ -90,61 +58,9 @@ this->vertexMap.apply(fn); } -const char INDEX_PROPERTY[] = "_editing_mode_index"; - -void EditorTabWidget::initializeTools() +void EditorTabWidget::setEditMode(EditingMode mode) { - const struct - { - QString name, tooltip; - QPixmap icon; - QWidget* widget; - } editingModesInfo[] = { - { - .name = tr("Select"), - .tooltip = tr("Select elements from the model."), - .icon = {":/icons/navigate-outline.png"}, - //.widget = this->objectEditor, - }, - { - .name = tr("Draw"), - .tooltip = tr("Draw new elements into the model."), - .icon = {":/icons/pencil-outline.png"}, - .widget = nullptr, - }, - }; - for (int i = 0; i < countof(editingModesInfo); ++i) { - const auto& editingModeInfo = editingModesInfo[i]; - QAction* action = new QAction{editingModeInfo.name, this}; - action->setCheckable(true); - action->setChecked(i == 0); - action->setToolTip(editingModeInfo.tooltip); - action->setIcon(QPixmap{editingModeInfo.icon}); - action->setProperty(INDEX_PROPERTY, i); - this->toolsBar->addAction(action); - QWidget* widget = editingModeInfo.widget; - if (widget == nullptr) { - widget = new QWidget{this}; - } - this->ui.toolWidgetStack->addWidget(widget); - this->toolActions.push_back(action); - connect(action, &QAction::triggered, this, &EditorTabWidget::editingModeTriggered); - } - this->ui.listView->selectAll(); -} - -void EditorTabWidget::editingModeTriggered() -{ - QAction* triggeredAction = qobject_cast<QAction*>(this->sender()); - if (triggeredAction != nullptr) - { - const int index = triggeredAction->property(INDEX_PROPERTY).toInt(); - this->drawState.mode = static_cast<EditingMode>(index); - this->ui.toolWidgetStack->setCurrentIndex(index); - for (QAction* action : this->toolActions) { - action->setChecked(action == triggeredAction); - } - } + this->drawState.mode = mode; } void updatePreviewPolygon(DrawState* drawState) @@ -184,7 +100,7 @@ if (highlighted != ModelId{0}) { selected.insert(highlighted); } - this->select(selected); + //this->select(selected); event->accept(); } break; @@ -232,6 +148,7 @@ break; } } +/* void EditorTabWidget::select(const QSet<ModelId> &selected) { @@ -248,12 +165,17 @@ } selectionModel->select(itemSelection, QItemSelectionModel::ClearAndSelect); } - +*/ const QSet<ModelId> EditorTabWidget::selectedObjects() const { return this->canvas->selectedObjects(); } +EditingMode EditorTabWidget::currentEditingMode() const +{ + return this->drawState.mode; +} + void EditorTabWidget::closeShape() { if (this->drawState.polygon.size() >= 2 and this->drawState.polygon.size() <= 4)
--- a/src/document.h Tue Jun 07 20:44:19 2022 +0300 +++ b/src/document.h Tue Jun 07 21:35:29 2022 +0300 @@ -34,27 +34,21 @@ const ldraw::ColorTable& colorTable, QWidget *parent = nullptr); ~EditorTabWidget() override; - QByteArray saveSplitterState() const; - void restoreSplitterState(const QByteArray& state); void applyToVertices(VertexMap::ApplyFunction fn) const; const QSet<ModelId> selectedObjects() const; const ldraw::ColorTable& colorTable; Canvas* const canvas; Model* const model; - Q_SLOT void editingModeTriggered(); + EditingMode currentEditingMode() const; + Q_SLOT void setEditMode(EditingMode mode); Q_SLOT void canvasMouseClick(QMouseEvent* event); Q_SLOT void canvasMouseMove(QMouseEvent* event); - void select(const QSet<ModelId> &selected); Q_SIGNALS: void newStatusText(const QString& newStatusText); void splitterChanged(); private: - void initializeTools(); void closeShape(); DrawState drawState; DocumentManager* const documents; VertexMap vertexMap; - class Ui_Document& ui; - QToolBar* toolsBar; - std::vector<QAction*> toolActions; };
--- a/src/document.ui Tue Jun 07 20:44:19 2022 +0300 +++ b/src/document.ui Tue Jun 07 21:35:29 2022 +0300 @@ -13,65 +13,30 @@ <property name="windowTitle"> <string>Form</string> </property> - <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1"> - <item> - <widget class="QWidget" name="toolsBarContainer" native="true"/> - </item> + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QSplitter" name="splitter_2"> + <widget class="QSplitter" name="viewportListSplitter"> <property name="orientation"> - <enum>Qt::Vertical</enum> + <enum>Qt::Horizontal</enum> </property> - <widget class="QSplitter" name="viewportListSplitter"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> + <widget class="QFrame" name="viewportFrame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> </property> - <widget class="QFrame" name="viewportFrame"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - </widget> - <widget class="QListView" name="listView"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - </widget> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> </widget> - <widget class="QScrollArea" name="scrollArea"> - <property name="widgetResizable"> + <widget class="QListView" name="listView"> + <property name="alternatingRowColors"> <bool>true</bool> </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>921</width> - <height>73</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QStackedWidget" name="toolWidgetStack"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - </widget> - </item> - </layout> - </widget> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> </widget> </widget> </item>
--- a/src/main.cpp Tue Jun 07 20:44:19 2022 +0300 +++ b/src/main.cpp Tue Jun 07 21:35:29 2022 +0300 @@ -2,6 +2,7 @@ #include <QFileDialog> #include <QMessageBox> #include <QMdiSubWindow> +#include <QStackedWidget> #include "mainwindow.h" #include "ui_mainwindow.h" #include "version.h" @@ -146,18 +147,6 @@ } } -static void handleTabCloseButton(Ui_MainWindow* ui, DocumentManager* documents, int tabIndex) -{ - /* - if (tabIndex >= 0 and tabIndex < ui->tabs->count()) { - EditorTabWidget* tab = qobject_cast<EditorTabWidget*>(ui->tabs->widget(tabIndex)); - if (tab != nullptr) { - closeDocument(documents, tab); - } - } - */ -} - static std::optional<ModelId> findCurrentModelId(Ui_MainWindow* ui, DocumentManager* documents) { const EditorTabWidget* tab = currentTabWidget(ui); @@ -236,6 +225,44 @@ }; } +void initializeTools(Ui_MainWindow* ui, QWidget* parent) +{ + const struct + { + QString name, tooltip; + QPixmap icon; + QWidget* widget; + } editingModesInfo[] = { + { + .name = QObject::tr("Select"), + .tooltip = QObject::tr("Select elements from the model."), + .icon = {":/icons/navigate-outline.png"}, + //.widget = this->objectEditor, + }, + { + .name = QObject::tr("Draw"), + .tooltip = QObject::tr("Draw new elements into the model."), + .icon = {":/icons/pencil-outline.png"}, + .widget = nullptr, + }, + }; + for (int i = 0; i < countof(editingModesInfo); ++i) { + const auto& editingModeInfo = editingModesInfo[i]; + QAction* action = new QAction{editingModeInfo.name, parent}; + action->setCheckable(true); + action->setChecked(i == 0); + action->setData(static_cast<EditingMode>(i)); + action->setToolTip(editingModeInfo.tooltip); + action->setIcon(QPixmap{editingModeInfo.icon}); + ui->editingModesToolBar->addAction(action); + QWidget* widget = editingModeInfo.widget; + if (widget == nullptr) { + widget = new QWidget{parent}; + } + ui->toolWidgetStack->addWidget(widget); + } +} + int main(int argc, char *argv[]) { doQtRegistrations(); @@ -251,6 +278,7 @@ QStringList recentlyOpenedFiles; ldraw::ColorTable colorTable; gl::RenderPreferences renderPreferences; + QMap<Model*, QItemSelectionModel*> itemSelectionModels; ui.setupUi(&mainWindow); const uiutilities::KeySequenceMap defaultKeyboardShortcuts = uiutilities::makeKeySequenceMap(uiutilities::collectActions(&mainWindow)); @@ -299,11 +327,22 @@ updateRecentlyOpenedDocumentsMenu(); }; const auto openModelForEditing = [&](const ModelId modelId){ - EditorTabWidget* document = new EditorTabWidget{ - documents.getModelById(modelId), - &documents, - colorTable, - }; + Model* model = documents.getModelById(modelId); + EditorTabWidget* document = new EditorTabWidget{model, &documents, colorTable}; + QItemSelectionModel* selectionModel = new QItemSelectionModel{model}; + itemSelectionModels[model] = selectionModel; + QObject::connect(selectionModel, &QItemSelectionModel::selectionChanged, + [model, document](const QItemSelection& selected, const QItemSelection& deselected) + { + auto resolveIndex = [&model](const QModelIndex& index){ + return model->idAt(index.row()); + }; + auto resolve = [&resolveIndex](const QItemSelection& selection) + { + return fn::map<QSet<ModelId>>(selection.indexes(), resolveIndex); + }; + document->canvas->handleSelectionChange(resolve(selected), resolve(deselected)); + }); document->canvas->setRenderPreferences(renderPreferences); QObject::connect( document, @@ -315,7 +354,6 @@ QMdiSubWindow* subWindow = ui.mdiArea->addSubWindow(document); subWindow->setWindowTitle(tabName(fileInfo)); subWindow->show(); - document->restoreSplitterState(documentSplitterState); }; QObject::connect(ui.actionNew, &QAction::triggered, [&]{ openModelForEditing(documents.newModel()); @@ -409,11 +447,6 @@ } } }); - /* - QObject::connect(ui.mdiArea, &QTabWidget::tabCloseRequested, [&](int index){ - handleTabCloseButton(&ui, &documents, index); - }); - */ QObject::connect(ui.actionDrawAxes, &QAction::triggered, [&](bool drawAxes){ renderPreferences.drawAxes = drawAxes; saveSettings(); @@ -427,6 +460,34 @@ updateRenderPreferences(&ui, &renderPreferences); }); } + const auto checkEditingModeAction = [&ui](EditingMode mode) { + for (QAction* action : ui.editingModesToolBar->actions()) { + action->setChecked(action->data().value<EditingMode>() == mode); + } + }; + initializeTools(&ui, &mainWindow); + for (QAction* action : ui.editingModesToolBar->actions()) { + QObject::connect(action, &QAction::triggered, [&, action]{ + EditorTabWidget* tab = currentTabWidget(&ui); + if (tab != nullptr) { + const EditingMode mode = action->data().value<EditingMode>(); + tab->setEditMode(mode); + checkEditingModeAction(mode); + } + }); + } + QObject::connect(ui.mdiArea, &QMdiArea::subWindowActivated, + [&](QMdiSubWindow* subWindow){ + EditorTabWidget* tab = qobject_cast<EditorTabWidget*>(subWindow->widget()); + if (tab != nullptr) { + checkEditingModeAction(tab->currentEditingMode()); + QItemSelectionModel* selectionModel = itemSelectionModels.value(tab->model); + if (selectionModel != nullptr) { + ui.modelListView->setModel(tab->model); + ui.modelListView->setSelectionModel(selectionModel); + } + } + }); mainWindow.setWindowTitle(title()); mainWindow.restoreGeometry(settings.mainWindowGeometry()); restoreSettings();
--- a/src/mainwindow.ui Tue Jun 07 20:44:19 2022 +0300 +++ b/src/mainwindow.ui Tue Jun 07 21:35:29 2022 +0300 @@ -14,7 +14,7 @@ <string>LDForge</string> </property> <widget class="QWidget" name="centralwidget"> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <widget class="QMdiArea" name="mdiArea"> <property name="viewMode"> @@ -136,6 +136,47 @@ <addaction name="actionGridMedium"/> <addaction name="actionGridCoarse"/> </widget> + <widget class="QToolBar" name="editingModesToolBar"> + <property name="windowTitle"> + <string>toolBar_2</string> + </property> + <attribute name="toolBarArea"> + <enum>LeftToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + </widget> + <widget class="QDockWidget" name="dockWidget_2"> + <property name="windowTitle"> + <string>Tool options</string> + </property> + <attribute name="dockWidgetArea"> + <number>8</number> + </attribute> + <widget class="QWidget" name="dockWidgetContents_2"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QStackedWidget" name="toolWidgetStack"/> + </item> + </layout> + </widget> + </widget> + <widget class="QDockWidget" name="dockWidget_3"> + <property name="windowTitle"> + <string>Model body</string> + </property> + <attribute name="dockWidgetArea"> + <number>2</number> + </attribute> + <widget class="QWidget" name="dockWidgetContents_3"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QListView" name="modelListView"/> + </item> + </layout> + </widget> + </widget> <action name="actionQuit"> <property name="icon"> <iconset resource="../ldforge.qrc">