Move editing modes tool bar, tool options widget stack and model list view into the main window

Tue, 07 Jun 2022 21:35:29 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 07 Jun 2022 21:35:29 +0300
changeset 203
1909a0123c72
parent 202
b05af0bab735
child 204
52e10e8d88cc

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">
--- a/src/ui/canvas.h	Tue Jun 07 20:44:19 2022 +0300
+++ b/src/ui/canvas.h	Tue Jun 07 21:35:29 2022 +0300
@@ -13,6 +13,8 @@
 	DrawMode
 };
 
+Q_DECLARE_METATYPE(EditingMode);
+
 struct DrawState
 {
 	std::vector<glm::vec3> polygon;

mercurial