From 30e4b72f7e32e50301e501dc4953304f2a674724 Mon Sep 17 00:00:00 2001 From: Federico Ponchio Date: Wed, 24 Jan 2024 17:21:14 +0100 Subject: [PATCH] refactoring actions into relightapp. --- relightlab/actions.cpp | 28 ---------- relightlab/actions.h | 17 ------ relightlab/homeframe.cpp | 10 ++-- relightlab/imagestab.cpp | 14 +++++ relightlab/imagestab.h | 11 ++++ relightlab/mainwindow.cpp | 99 ++++++++++++++++++++++++++--------- relightlab/mainwindow.h | 4 +- relightlab/recentprojects.cpp | 8 ++- relightlab/recentprojects.h | 4 +- relightlab/relightapp.cpp | 28 ++++++++++ relightlab/relightapp.h | 47 +++-------------- relightlab/relightlab.pro | 67 +++++++++++++++++------- src/project.cpp | 41 ++++++++++----- src/project.h | 6 ++- 14 files changed, 236 insertions(+), 148 deletions(-) delete mode 100644 relightlab/actions.cpp delete mode 100644 relightlab/actions.h create mode 100644 relightlab/imagestab.cpp create mode 100644 relightlab/imagestab.h diff --git a/relightlab/actions.cpp b/relightlab/actions.cpp deleted file mode 100644 index 4c3865d6..00000000 --- a/relightlab/actions.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "actions.h" - -QAction *Action::new_project = nullptr; -QAction *Action::open_project = nullptr; -QAction *Action::close_project = nullptr; -QAction *Action::exit = nullptr; - -void Action::initialize() { - new_project = new QAction("New project..."); - new_project->setShortcut(QKeySequence("Ctrl+N")); - - open_project = new QAction("Open project..."); - open_project->setShortcut(QKeySequence("Ctrl+O")); - - close_project = new QAction("Close project..."); - close_project->setShortcut(QKeySequence("Ctrl+W")); - close_project->setEnabled(false); - - exit = new QAction("Exit"); - exit->setShortcut(QKeySequence("Alt+F4")); -} - -void Action::cleanup() { - delete new_project; - delete open_project; - delete close_project; - delete exit; -} diff --git a/relightlab/actions.h b/relightlab/actions.h deleted file mode 100644 index 427b96cc..00000000 --- a/relightlab/actions.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ACTIONS_H -#define ACTIONS_H - -#include - -class Action { -public: - static void initialize(); - static void cleanup(); - - static QAction *new_project; - static QAction *open_project; - static QAction *close_project; - static QAction *exit; -}; - -#endif // ACTIONS_H diff --git a/relightlab/homeframe.cpp b/relightlab/homeframe.cpp index 6148ba45..b8a38543 100644 --- a/relightlab/homeframe.cpp +++ b/relightlab/homeframe.cpp @@ -1,10 +1,12 @@ -#include "homeframe.h" #include #include #include #include #include -#include "actions.h" +#include + +#include "homeframe.h" +#include "relightapp.h" void setDefaultAction(QPushButton *button, QAction *action) { QObject::connect(button, SIGNAL(clicked(bool)), action, SLOT(trigger())); @@ -30,11 +32,11 @@ HomeFrame::HomeFrame() { leftColumnLayout->addWidget(titleLabel); QPushButton *new_project = new QPushButton(this); - setDefaultAction(new_project, Action::new_project); + setDefaultAction(new_project, qRelightApp->action("new_project")); leftColumnLayout->addWidget(new_project); QPushButton *open_project = new QPushButton(this); - setDefaultAction(open_project, Action::open_project); + setDefaultAction(open_project, qRelightApp->action("open_project")); leftColumnLayout->addWidget(open_project); QLabel *recentLabel = new QLabel("Recent projects:"); diff --git a/relightlab/imagestab.cpp b/relightlab/imagestab.cpp new file mode 100644 index 00000000..2759d771 --- /dev/null +++ b/relightlab/imagestab.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +#include "imagestab.h" +#include "relightapp.h" + +ImagesTab::ImagesTab() { + + QVBoxLayout *container = new QVBoxLayout(this); + + QToolBar *toolbar = new QToolBar(this); + toolbar->addAction(qRelightApp->action("fullscreen")); +} diff --git a/relightlab/imagestab.h b/relightlab/imagestab.h new file mode 100644 index 00000000..1c6c20db --- /dev/null +++ b/relightlab/imagestab.h @@ -0,0 +1,11 @@ +#ifndef IMAGESTAB_H +#define IMAGESTAB_H + +#include + +class ImagesTab: public QFrame { +public: + ImagesTab(); +}; + +#endif // IMAGESTAB_H diff --git a/relightlab/mainwindow.cpp b/relightlab/mainwindow.cpp index 42ec58ef..7dfb0c96 100644 --- a/relightlab/mainwindow.cpp +++ b/relightlab/mainwindow.cpp @@ -8,13 +8,11 @@ #include "tabwidget.h" #include "homeframe.h" #include "imageframe.h" -#include "actions.h" #include using namespace std; MainWindow::MainWindow() { - Action::initialize(); setupActions(); createMenu(); @@ -38,45 +36,86 @@ void MainWindow::createMenu() { menuFile->setTitle("File"); menubar->addAction(menuFile->menuAction()); - menuFile->addAction(Action::new_project); - menuFile->addAction(Action::open_project); - menuFile->addAction(Action::close_project); + menuFile->addAction(qRelightApp->action("new_project")); + menuFile->addAction(qRelightApp->action("open_project")); + menuFile->addAction(qRelightApp->action("close_project")); menuFile->addSeparator(); menuFile->addSeparator(); - menuFile->addAction(Action::exit); + menuFile->addAction(qRelightApp->action("exit")); setMenuBar(menubar); } void MainWindow::setupActions() { - connect(Action::new_project, SIGNAL(triggered(bool)), this, SLOT(newProject())); - connect(Action::open_project, SIGNAL(triggered(bool)), this, SLOT(openProject())); - connect(Action::close_project, SIGNAL(triggered(bool)), this, SLOT(closeProject())); + connect(qRelightApp->action("new_project"), SIGNAL(triggered(bool)), this, SLOT(newProject())); + connect(qRelightApp->action("open_project"), SIGNAL(triggered(bool)), this, SLOT(openProject())); + connect(qRelightApp->action("close_project"), SIGNAL(triggered(bool)), this, SLOT(closeProject())); - connect(Action::exit, SIGNAL(triggered(bool)), this, SLOT(close())); + connect(qRelightApp->action("exit"), SIGNAL(triggered(bool)), this, SLOT(close())); } -void MainWindow::clear() { +void MainWindow::newProject() { + if(!needsSavingProceed()) + return; -} + QString dir = QFileDialog::getExistingDirectory(this, "Choose picture folder", qRelightApp->lastProjectDir()); + if(dir.isNull()) return; -void MainWindow::newProject() { - cout << "New Project" << endl; - Action::close_project->setEnabled(true); + + Project project; + project.setDir(QDir(dir)); + bool ok = project.scanDir(); + if(!project.size()) { + QMessageBox::critical(this, "Houston we have a problem!", "Could not find images in directory: " + project.dir.path()); + return; + } + + if(!ok) { + //check if we can rotate a few images. + bool canrotate = false; + for(Image &image: project.images) { + if(image.size == project.imgsize) + continue; + + if(image.isRotated(project.imgsize)) + canrotate = true; + } + if(canrotate) { + int answer = QMessageBox::question(this, "Some images are rotated.", "Do you wish to uniform image rotation?", QMessageBox::Yes, QMessageBox::No); + if(answer != QMessageBox::No) + project.rotateImages(); + } else + QMessageBox::critical(this, "Resolution problem", "Not all of the images in the folder have the same resolution,\nyou might need to fix this problem manually."); + } + + qRelightApp->project() = project; + + initInterface(); + +/* TODO: move this into the lights tab + QStringList img_ext; + img_ext << "*.lp"; + QStringList lps = QDir(dir).entryList(img_ext); + if(lps.size() > 0) { + int answer = QMessageBox::question(this, "Found an .lp file: " + lps[0], "Do you wish to load " + lps[0] + "?", QMessageBox::Yes, QMessageBox::No); + if(answer != QMessageBox::No) + loadLP(lps[0]); + } +*/ + + qRelightApp->action("close_project")->setEnabled(true); tabs->setCurrentIndex(1); } void MainWindow::openProject() { - QString lastDir = QSettings().value("LastDir", QDir::homePath()).toString(); - - QString filename = QFileDialog::getOpenFileName(this, "Select a project", lastDir, "*.relight"); + if(!needsSavingProceed()) + return; + QString filename = QFileDialog::getOpenFileName(this, "Select a project", qRelightApp->lastProjectDir(), "*.relight"); if(filename.isNull()) return; - clear(); - Project project; try { project.load(filename); @@ -121,17 +160,29 @@ void MainWindow::openProject() { } } - clear(); qRelightApp->project() = project; project_filename = filename; //project.dir.relativeFilePath(filename); + qRelightApp->setLastProjectDir(project.dir.path()); - QSettings().setValue("LastDir", project.dir.path()); + initInterface(); + qRelightApp->action("close_project")->setEnabled(true); - Action::close_project->setEnabled(true); tabs->setCurrentIndex(1); } void MainWindow::closeProject() { + cout << "close Project" << endl; - Action::close_project->setEnabled(false); + qRelightApp->action("close_project")->setEnabled(false); +} + +void MainWindow::initInterface() { + +} + +bool MainWindow::needsSavingProceed() { + if(!qRelightApp->project().needs_saving); + return true; + auto answer = QMessageBox::question(this, "Current project is unsaved", "Do you want to proceed without saving?"); + return answer == QMessageBox::Yes; } diff --git a/relightlab/mainwindow.h b/relightlab/mainwindow.h index 47603f8c..e425e54a 100644 --- a/relightlab/mainwindow.h +++ b/relightlab/mainwindow.h @@ -12,7 +12,7 @@ class MainWindow: public QMainWindow { MainWindow(); void setupActions(); void createMenu(); - void clear(); + void initInterface(); //initialize interface using the current project public slots: void newProject(); @@ -22,6 +22,8 @@ public slots: private: TabWidget *tabs; QString project_filename; //last filename project opened or saved filename. + + bool needsSavingProceed(); //return false if userd oesn't want to proceed }; #endif // MAINWINDOW_H diff --git a/relightlab/recentprojects.cpp b/relightlab/recentprojects.cpp index 058c45fd..5315a7d2 100644 --- a/relightlab/recentprojects.cpp +++ b/relightlab/recentprojects.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "recentprojects.h" @@ -20,7 +21,7 @@ QVariant RecentProject::toVariant() { return recent; } -void RecentProject::fromVariant(QVariant &v) { +void RecentProject::fromVariant(const QVariant &v) { QMap recent = v.toMap(); filename = recent["filename"].toString(); title = recent["title"].toString(); @@ -28,7 +29,12 @@ void RecentProject::fromVariant(QVariant &v) { } static std::vector getRecentProjects() { + QList recents = QSettings().value("RecentProjects", QList()).toList(); + std::vector recentProjects; + for(const QVariant &v: recents) { + recentProjects.push_back(v); + } } static void addRecentProject(QString filename, QString title, QString notes) { diff --git a/relightlab/recentprojects.h b/relightlab/recentprojects.h index defe30e7..a6484bee 100644 --- a/relightlab/recentprojects.h +++ b/relightlab/recentprojects.h @@ -10,8 +10,10 @@ class RecentProject { QString title; QString notes; + RecentProject() {} + RecentProject(const QVariant &v) { fromVariant(v); } QVariant toVariant(); - void fromVariant(QVariant &v); + void fromVariant(const QVariant &v); }; static std::vector getRecentProjects(); diff --git a/relightlab/relightapp.cpp b/relightlab/relightapp.cpp index fdcb8c09..bfff6e6f 100644 --- a/relightlab/relightapp.cpp +++ b/relightlab/relightapp.cpp @@ -1,2 +1,30 @@ #include "relightapp.h" +#include + + +RelightApp::RelightApp(int &argc, char **argv): QApplication(argc, argv) { + QTemporaryDir tmp; + if(!tmp.isValid()) { + QMessageBox::critical(nullptr, "Temporary folder is needed", "Could not create a temporary file for the scripts.\nSelect a folder in File->Preferences"); + } + + QFile style(":/css/style.txt"); + style.open(QFile::ReadOnly); + setStyleSheet(style.readAll()); + + ProcessQueue &queue = ProcessQueue::instance(); + queue.start(); + + + addAction("new_project", "New project...", "Ctrl+N"); + addAction("open_project", "Open project...", "Ctrl+O"); + addAction("close_project", "Close project", "Ctrl-W"); + addAction("exit", "Exit", "Alt+F4"); +} + +void RelightApp::addAction(const QString &id, const QString &label, const QString &shortcut) { + QAction *a = new QAction(label); + a->setShortcut(shortcut); + actions[id] = a; +} diff --git a/relightlab/relightapp.h b/relightlab/relightapp.h index 5d3db13b..45349c0f 100644 --- a/relightlab/relightapp.h +++ b/relightlab/relightapp.h @@ -7,63 +7,32 @@ #include #include #include + #include "../src/project.h" #include "../relight/processqueue.h" #define qRelightApp (static_cast(QCoreApplication::instance())) -class RecentProject { -public: - QString filename; - QString title; - QString notes; - QVariant toVariant(); - void fromVariane(QVariant &v); -}; class RelightApp: public QApplication { public: Project m_project; + QMap actions; - RelightApp(int &argc, char **argv): QApplication(argc, argv) { - QTemporaryDir tmp; - if(!tmp.isValid()) { - QMessageBox::critical(nullptr, "Temporary folder is needed", "Could not create a temporary file for the scripts.\nSelect a folder in File->Preferences"); - } - - QFile style(":/css/style.txt"); - style.open(QFile::ReadOnly); - setStyleSheet(style.readAll()); - - ProcessQueue &queue = ProcessQueue::instance(); - queue.start(); - - } + RelightApp(int &argc, char **argv); Project &project() { return m_project; } + QAction *action(const QString &id) { return actions[id]; } + QString lastProjectDir() { return QSettings().value("LastProjectDir", QDir::homePath()).toString(); } void setLastProjectDir(QString dir) { QSettings().setValue("LastProjectDir", dir); } - std::vector recents() { - QList list = QSettings().value("Recents", QList()).toList(); - std::vector m_recents; - for(QVariant &v: list) { - auto r = v.toMap(); - RecentProject p; - p.filename = r["filename"].toString(); - } - - return m_recents; - } - void addRecent(QString filename, QString title, QString notes) { - - } - void clearRecents() { - - } +protected + : + void addAction(const QString &id, const QString &label, const QString &shortcut); }; #endif diff --git a/relightlab/relightlab.pro b/relightlab/relightlab.pro index f84c94f1..b5bac944 100644 --- a/relightlab/relightlab.pro +++ b/relightlab/relightlab.pro @@ -1,34 +1,53 @@ -#QT += widgets #quick -QT += quick widgets +QT += widgets CONFIG += c++11 -# The following define makes your compiler emit warnings if you use -# any feature of Qt which as been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += _USE_MATH_DEFINES +DEFINES += NOMINMAX + +win32:INCLUDEPATH += ../external/libjpeg-turbo-2.0.6/include \ + ../external/eigen-3.3.9/ \ + ../src/ +win32:LIBS += ../external/libjpeg-turbo-2.0.6/lib/jpeg-static.lib + +unix:INCLUDEPATH += /usr/include/eigen3 +unix:LIBS += -ljpeg -liomp5 +unix:QMAKE_CXXFLAGS += -fopenmp + + +mac:INCLUDEPATH += /usr/local/Cellar/jpeg-turbo/2.0.6/include \ + /usr/local/include \ + /usr/local/include/eigen3 +mac:LIBS += -L/usr/local/Cellar/jpeg-turbo/2.0.6/lib/ -ljpeg +mac:LIBS += -framework Accelerate +mac:QMAKE_CXXFLAGS += -fopenmp +mac:QMAKE_CXXFLAGS += -Xpreprocessor -fopenmp -lomp -I/usr/local/include +mac:QMAKE_LFLAGS += -lomp +mac:LIBS += -L /usr/local/lib /usr/local/lib/libomp.dylib -# You can also make your code fail to compile if you use deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += main.cpp \ + ../relight/processqueue.cpp \ + ../src/align.cpp \ + ../src/dome.cpp \ + ../src/exif.cpp \ + ../src/image.cpp \ + ../src/lens.cpp \ + ../src/measure.cpp \ + ../src/project.cpp \ + ../src/sphere.cpp \ + ../src/white.cpp \ + imagestab.cpp \ mainwindow.cpp \ + recentprojects.cpp \ + relightapp.cpp \ tabwidget.cpp \ - actions.cpp \ imageframe.cpp \ homeframe.cpp RESOURCES += \ res.qrc -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - -# Additional import path used to resolve QML modules just for Qt Quick Designer -QML_DESIGNER_IMPORT_PATH = - # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin @@ -37,9 +56,21 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin FORMS += HEADERS += \ + ../relight/processqueue.h \ + ../src/align.h \ + ../src/dome.h \ + ../src/exif.h \ + ../src/image.h \ + ../src/lens.h \ + ../src/measure.h \ + ../src/project.h \ + ../src/sphere.h \ + ../src/white.h \ + imagestab.h \ mainwindow.h \ mainwindow.h \ + recentprojects.h \ + relightapp.h \ tabwidget.h \ - actions.h \ imageframe.h \ homeframe.h diff --git a/src/project.cpp b/src/project.cpp index 20890127..de5bcc0b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -43,6 +43,7 @@ void Project::clear() { measures.clear(); crop = QRect(); + needs_saving = false; } bool Project::setDir(QDir folder) { @@ -53,6 +54,7 @@ bool Project::setDir(QDir folder) { } dir = folder; QDir::setCurrent(dir.path()); + needs_saving = true; return true; } @@ -141,7 +143,7 @@ bool Project::scanDir() { images[i].valid &= (lens.focal35() == alllens[i].focal35()); images[i].skip = !images[i].valid; } - + needs_saving = true; return resolutions.size() == 1 && focals.size() == 1; } double mutualInfo(QImage &a, QImage &b) { @@ -187,13 +189,14 @@ double mutualInfo(QImage &a, QImage &b) { } void Project::rotateImages(bool clockwise) { - QTransform rotate; - rotate.rotate(clockwise ? 90 : -90); - for(Image &image: images) { - QImage source(image.filename); - QImage rotated = source.transformed(rotate); - rotated.save(image.filename, "jpg", 100); - } + QTransform rotate; + rotate.rotate(clockwise ? 90 : -90); + for(Image &image: images) { + QImage source(image.filename); + QImage rotated = source.transformed(rotate); + rotated.save(image.filename, "jpg", 100); + } + needs_saving = true; } void Project::rotateImages() { @@ -228,12 +231,11 @@ void Project::rotateImages() { QTransform final = right_mutual > left_mutual ? rot_left : rot_right; //TODO should be libjpeg to rotate. QImage rotated = source.transformed(final); - rotated.save(image.filename, "jpg", 100); + rotated.save(image.filename, "jpg", 100); image.size = imgsize; image.valid = true; image.skip = false; - cout << "Right: " << right_mutual << " Left: " << left_mutual << endl; } } @@ -320,6 +322,7 @@ void Project::load(QString filename) { whites.push_back(_white); } } + needs_saving = false; } void Project::checkMissingImages() { @@ -335,7 +338,7 @@ void Project::checkMissingImages() { } } void Project::checkImages() { - for(Image &image:images) { + for(Image &image:images) { QImageReader reader(image.filename); QSize size = reader.size(); image.valid = (size == imgsize); @@ -423,12 +426,19 @@ void Project::save(QString filename) { QFile file(filename); - file.open(QFile::WriteOnly | QFile::Truncate); + bool opened = file.open(QFile::WriteOnly | QFile::Truncate); + if(!opened) { + QString error = file.errorString(); + throw error; + } file.write(doc.toJson()); + + needs_saving = false; } Measure *Project::newMeasure() { auto m = new Measure(); + needs_saving = true; measures.push_back(m); return m; } @@ -441,21 +451,25 @@ void Project::computePixelSize() { count++; } pixelSize /= count; + needs_saving = true; } Sphere *Project::newSphere() { auto s = new Sphere(images.size()); spheres.push_back(s); + needs_saving = true; return s; } Align *Project::newAlign() { auto s = new Align(images.size()); aligns.push_back(s); + needs_saving = true; return s; } White *Project::newWhite() { auto s = new White(); whites.push_back(s); + needs_saving = true; return s; } @@ -535,7 +549,7 @@ void Project::computeDirections() { v = v.rotate(axis, angle); if(dome.domeDiameter) { - //find intersection between direAlignctions and sphere. + //find intersection between direAlignctions and sphere. for(size_t i = 0; i < sphere->directions.size(); i++) { Vector3f &direction = sphere->directions[i]; direction.normalize(); @@ -570,4 +584,5 @@ void Project::computeDirections() { if(weights[i] > 0) images[i].direction = directions[i]/weights[i]; } + needs_saving = true; } diff --git a/src/project.h b/src/project.h index f89f6349..34907068 100644 --- a/src/project.h +++ b/src/project.h @@ -43,19 +43,21 @@ class Project { QString platform; QDateTime created; QDateTime lastUpdated; + bool needs_saving; Project() { version = RELIGHT_STRINGIFY(RELIGHT_VERSION); auto sysinfo = QSysInfo(); platform = sysinfo.kernelType() + " " + sysinfo.kernelVersion(); created = lastUpdated = QDateTime::currentDateTime(); + needs_saving = false; } ~Project(); void clear(); void load(QString filename); - void save(QString filename); - void saveLP(QString filename, std::vector &directions); + void save(QString filename); //throws QString on error + void saveLP(QString filename, std::vector &directions); //throws QString on error void computeDirections(); void computePixelSize();