refactor: Introduce ApplicationController to centralize logic

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-02-13 17:29:04 -07:00
parent 87c354f79d
commit fa5852b8db
6 changed files with 230 additions and 92 deletions

View File

@@ -0,0 +1,122 @@
#include "ApplicationController.h"
#include "Document.h"
#include "SketchFeature.h"
#include "MainWindow.h"
#include <QInputDialog>
#include <QFileDialog>
#include <QMessageBox>
#include <QDir>
#include <QFileInfo>
ApplicationController* ApplicationController::instance()
{
static ApplicationController instance;
return &instance;
}
ApplicationController::ApplicationController(QObject *parent)
: QObject(parent)
{
m_document = new Document(this);
}
ApplicationController::~ApplicationController()
{
}
void ApplicationController::setMainWindow(MainWindow* mainWindow)
{
m_mainWindow = mainWindow;
}
Document* ApplicationController::document() const
{
return m_document;
}
void ApplicationController::newDocument()
{
m_document->clear();
setCurrentFile(QString());
}
bool ApplicationController::openDocument()
{
const QString fileName = QFileDialog::getOpenFileName(m_mainWindow);
if (!fileName.isEmpty()) {
if (!m_document->load(fileName)) {
QMessageBox::warning(m_mainWindow, tr("OpenCAD"),
tr("Cannot read file %1").arg(QDir::toNativeSeparators(fileName)));
return false;
}
setCurrentFile(fileName);
return true;
}
return false;
}
bool ApplicationController::saveDocument()
{
if (m_currentFile.isEmpty()) {
return saveDocumentAs();
} else {
if (!m_document->save(m_currentFile)) {
QMessageBox::warning(m_mainWindow, tr("OpenCAD"),
tr("Cannot write file %1").arg(QDir::toNativeSeparators(m_currentFile)));
return false;
}
return true;
}
}
bool ApplicationController::saveDocumentAs()
{
QFileDialog dialog(m_mainWindow);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() != QDialog::Accepted)
return false;
const QString fileName = dialog.selectedFiles().first();
setCurrentFile(fileName);
return saveDocument();
}
void ApplicationController::beginSketchCreation()
{
QStringList items;
items << "XY-Plane" << "XZ-Plane" << "YZ-Plane";
bool ok;
QString item = QInputDialog::getItem(m_mainWindow, "Select Sketch Plane",
"Plane:", items, 0, false, &ok);
if (ok && !item.isEmpty()) {
auto feature = new SketchFeature("Sketch");
ViewportWidget::SketchPlane plane;
if (item == "XY-Plane") {
plane = ViewportWidget::SketchPlane::XY;
feature->setPlane(SketchFeature::SketchPlane::XY);
} else if (item == "XZ-Plane") {
plane = ViewportWidget::SketchPlane::XZ;
feature->setPlane(SketchFeature::SketchPlane::XZ);
} else { // "YZ-Plane"
plane = ViewportWidget::SketchPlane::YZ;
feature->setPlane(SketchFeature::SketchPlane::YZ);
}
m_document->addFeature(feature);
emit sketchModeStarted(plane);
}
}
void ApplicationController::endSketch()
{
emit sketchModeEnded();
}
void ApplicationController::setCurrentFile(const QString& fileName)
{
m_currentFile = fileName;
m_document->setFileName(fileName);
emit currentFileChanged(m_currentFile);
}

View File

@@ -0,0 +1,46 @@
#ifndef APPLICATIONCONTROLLER_H
#define APPLICATIONCONTROLLER_H
#include <QObject>
#include "ViewportWidget.h" // For SketchPlane enum
class Document;
class MainWindow;
class ApplicationController : public QObject
{
Q_OBJECT
public:
static ApplicationController* instance();
void setMainWindow(MainWindow* mainWindow);
Document* document() const;
public slots:
void newDocument();
bool openDocument();
bool saveDocument();
bool saveDocumentAs();
void beginSketchCreation();
void endSketch();
signals:
void sketchModeStarted(ViewportWidget::SketchPlane plane);
void sketchModeEnded();
void currentFileChanged(const QString& path);
private:
explicit ApplicationController(QObject *parent = nullptr);
~ApplicationController();
ApplicationController(const ApplicationController&) = delete;
ApplicationController& operator=(const ApplicationController&) = delete;
void setCurrentFile(const QString& fileName);
Document* m_document;
QString m_currentFile;
MainWindow* m_mainWindow = nullptr;
};
#endif // APPLICATIONCONTROLLER_H

View File

@@ -3,6 +3,7 @@
#include "Document.h" #include "Document.h"
#include "SketchFeature.h" #include "SketchFeature.h"
#include "Feature.h" #include "Feature.h"
#include "ApplicationController.h"
#include <QMenuBar> #include <QMenuBar>
#include <QMenu> #include <QMenu>
@@ -116,107 +117,74 @@ MainWindow::MainWindow(QWidget *parent)
m_viewport = new ViewportWidget; m_viewport = new ViewportWidget;
setCentralWidget(m_viewport); setCentralWidget(m_viewport);
m_document = new Document(this); ApplicationController::instance()->setMainWindow(this);
m_viewport->setDocument(m_document); Document* document = ApplicationController::instance()->document();
connect(m_document, &Document::featureAdded, m_viewport, QOverload<>::of(&QWidget::update));
connect(m_document, &Document::cleared, m_viewport, QOverload<>::of(&QWidget::update));
setCurrentFile(QString()); m_viewport->setDocument(document);
connect(document, &Document::featureAdded, m_viewport, QOverload<>::of(&QWidget::update));
connect(document, &Document::cleared, m_viewport, QOverload<>::of(&QWidget::update));
connect(ApplicationController::instance(), &ApplicationController::sketchModeStarted, this, &MainWindow::enterSketchMode);
connect(ApplicationController::instance(), &ApplicationController::sketchModeEnded, this, &MainWindow::exitSketchMode);
connect(ApplicationController::instance(), &ApplicationController::sketchModeStarted, m_viewport, &ViewportWidget::onSketchModeStarted);
connect(ApplicationController::instance(), &ApplicationController::sketchModeEnded, m_viewport, &ViewportWidget::onSketchModeEnded);
connect(ApplicationController::instance(), &ApplicationController::currentFileChanged, this, &MainWindow::updateWindowTitle);
updateWindowTitle(QString());
} }
void MainWindow::createSketch() void MainWindow::createSketch()
{ {
QStringList items; ApplicationController::instance()->beginSketchCreation();
items << "XY-Plane" << "XZ-Plane" << "YZ-Plane";
bool ok;
QString item = QInputDialog::getItem(this, "Select Sketch Plane",
"Plane:", items, 0, false, &ok);
if (ok && !item.isEmpty()) {
auto feature = new SketchFeature("Sketch");
if (item == "XY-Plane") {
m_viewport->startSketch(ViewportWidget::SketchPlane::XY);
feature->setPlane(SketchFeature::SketchPlane::XY);
} else if (item == "XZ-Plane") {
m_viewport->startSketch(ViewportWidget::SketchPlane::XZ);
feature->setPlane(SketchFeature::SketchPlane::XZ);
} else if (item == "YZ-Plane") {
m_viewport->startSketch(ViewportWidget::SketchPlane::YZ);
feature->setPlane(SketchFeature::SketchPlane::YZ);
} }
m_document->addFeature(feature);
void MainWindow::saveSketch()
{
ApplicationController::instance()->endSketch();
}
void MainWindow::newFile()
{
ApplicationController::instance()->newDocument();
}
void MainWindow::open()
{
ApplicationController::instance()->openDocument();
}
bool MainWindow::save()
{
return ApplicationController::instance()->saveDocument();
}
bool MainWindow::saveAs()
{
return ApplicationController::instance()->saveDocumentAs();
}
void MainWindow::enterSketchMode()
{
m_tabWidget->removeTab(m_tabWidget->indexOf(m_toolsTab)); m_tabWidget->removeTab(m_tabWidget->indexOf(m_toolsTab));
m_tabWidget->removeTab(m_tabWidget->indexOf(m_surfaceTab)); m_tabWidget->removeTab(m_tabWidget->indexOf(m_surfaceTab));
m_tabWidget->removeTab(m_tabWidget->indexOf(m_solidTab)); m_tabWidget->removeTab(m_tabWidget->indexOf(m_solidTab));
m_tabWidget->addTab(m_sketchTab, "SKETCH"); m_tabWidget->addTab(m_sketchTab, "SKETCH");
} }
}
void MainWindow::saveSketch() void MainWindow::exitSketchMode()
{ {
m_viewport->saveSketch();
m_tabWidget->removeTab(m_tabWidget->indexOf(m_sketchTab)); m_tabWidget->removeTab(m_tabWidget->indexOf(m_sketchTab));
m_tabWidget->addTab(m_solidTab, "SOLID"); m_tabWidget->addTab(m_solidTab, "SOLID");
m_tabWidget->addTab(m_surfaceTab, "SURFACE"); m_tabWidget->addTab(m_surfaceTab, "SURFACE");
m_tabWidget->addTab(m_toolsTab, "TOOLS"); m_tabWidget->addTab(m_toolsTab, "TOOLS");
} }
void MainWindow::newFile() void MainWindow::updateWindowTitle(const QString& filePath)
{ {
m_document->clear(); setWindowFilePath(filePath);
setCurrentFile(QString());
}
void MainWindow::open() QString shownName = filePath;
{ if (filePath.isEmpty())
const QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty()) {
if (!m_document->load(fileName)) {
QMessageBox::warning(this, tr("OpenCAD"),
tr("Cannot read file %1").arg(QDir::toNativeSeparators(fileName)));
return;
}
setCurrentFile(fileName);
}
}
bool MainWindow::save()
{
if (m_currentFile.isEmpty()) {
return saveAs();
} else {
if (!m_document->save(m_currentFile)) {
QMessageBox::warning(this, tr("OpenCAD"),
tr("Cannot write file %1").arg(QDir::toNativeSeparators(m_currentFile)));
return false;
}
return true;
}
}
bool MainWindow::saveAs()
{
QFileDialog dialog(this);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() != QDialog::Accepted)
return false;
const QString fileName = dialog.selectedFiles().first();
setCurrentFile(fileName);
return save();
}
void MainWindow::setCurrentFile(const QString &fileName)
{
m_currentFile = fileName;
m_document->setFileName(fileName);
setWindowFilePath(m_currentFile);
QString shownName = m_currentFile;
if (m_currentFile.isEmpty())
shownName = "Untitled"; shownName = "Untitled";
setWindowTitle(tr("%1[*] - %2").arg(QFileInfo(shownName).fileName(), tr("OpenCAD"))); setWindowTitle(tr("%1[*] - %2").arg(QFileInfo(shownName).fileName(), tr("OpenCAD")));
} }

View File

@@ -24,12 +24,12 @@ private slots:
void createSketch(); void createSketch();
void saveSketch(); void saveSketch();
private: void enterSketchMode();
void setCurrentFile(const QString &fileName); void exitSketchMode();
void updateWindowTitle(const QString& filePath);
private:
ViewportWidget *m_viewport; ViewportWidget *m_viewport;
Document *m_document;
QString m_currentFile;
QTabWidget *m_tabWidget; QTabWidget *m_tabWidget;
QWidget *m_solidTab; QWidget *m_solidTab;

View File

@@ -168,7 +168,7 @@ void ViewportWidget::wheelEvent(QWheelEvent *event)
update(); update();
} }
void ViewportWidget::startSketch(SketchPlane plane) void ViewportWidget::onSketchModeStarted(SketchPlane plane)
{ {
m_currentPlane = plane; m_currentPlane = plane;
@@ -237,7 +237,7 @@ void ViewportWidget::startSketch(SketchPlane plane)
animGroup->start(QAbstractAnimation::DeleteWhenStopped); animGroup->start(QAbstractAnimation::DeleteWhenStopped);
} }
void ViewportWidget::saveSketch() void ViewportWidget::onSketchModeEnded()
{ {
auto* animGroup = new QParallelAnimationGroup(this); auto* animGroup = new QParallelAnimationGroup(this);

View File

@@ -34,10 +34,12 @@ public:
explicit ViewportWidget(QWidget *parent = nullptr); explicit ViewportWidget(QWidget *parent = nullptr);
~ViewportWidget(); ~ViewportWidget();
void startSketch(SketchPlane plane);
void saveSketch();
void setDocument(Document* document); void setDocument(Document* document);
public slots:
void onSketchModeStarted(SketchPlane plane);
void onSketchModeEnded();
float xRotation() const; float xRotation() const;
void setXRotation(float angle); void setXRotation(float angle);