From af5988d4be4d4d7e0d33d039ceddd800aaa5ba37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gs=C3=A4nger?= Date: Sun, 13 Oct 2024 14:15:00 +0200 Subject: [PATCH] Update Viewport handling --- gui/common/guiwrapper.cpp | 14 +--- gui/common/guiwrapper.h | 2 - gui/qt/glwidget.cpp | 4 +- gui/qt/mainwindow.cpp | 134 ++++++++++++++++++-------------------- gui/qt/mainwindow.h | 6 +- gui/qt/viewport.cpp | 53 ++++++--------- gui/qt/viewport.h | 11 ++-- 7 files changed, 98 insertions(+), 126 deletions(-) diff --git a/gui/common/guiwrapper.cpp b/gui/common/guiwrapper.cpp index a745959b..6deb44d7 100644 --- a/gui/common/guiwrapper.cpp +++ b/gui/common/guiwrapper.cpp @@ -147,23 +147,13 @@ void GuiWrapper::drawSel(void *context) void GuiWrapper::setMainStep(Step* step) { curStep = step; - updateMainStep(); -} - -void GuiWrapper::setMainSel(Step::selection* sel) -{ - curSel = sel; - updateMainSelection(); -} - -void GuiWrapper::updateMainStep() -{ mainStep.update(curStep, settings.atRadVdW.val, settings.atRadFac.val, settings.bondRad.val); } -void GuiWrapper::updateMainSelection() +void GuiWrapper::setMainSel(Step::selection* sel) { + curSel = sel; selection.update(curSel, settings.atRadVdW.val, settings.atRadFac.val); } diff --git a/gui/common/guiwrapper.h b/gui/common/guiwrapper.h index cf624dee..0426cda1 100644 --- a/gui/common/guiwrapper.h +++ b/gui/common/guiwrapper.h @@ -36,8 +36,6 @@ class GuiWrapper: protected QOpenGLExtraFunctions{ const Vec& pos, unsigned long width, unsigned long height); void setMainStep(Step* step); void setMainSel(Step::selection* sel); - void updateMainStep(); - void updateMainSelection(); void resizeViewMat(long w, long h); void zoomViewMat(float i); void rotateViewMat(float x, float y, float z); diff --git a/gui/qt/glwidget.cpp b/gui/qt/glwidget.cpp index f2b9a455..eb768400 100644 --- a/gui/qt/glwidget.cpp +++ b/gui/qt/glwidget.cpp @@ -424,7 +424,7 @@ void GLWidget::focusInEvent(QFocusEvent *) { // make sure our viewport is the active one auto vp = static_cast(parentWidget()); - if(!vp->active){ - vp->master->changeViewports(vp, MainWindow::VP_ACTIVE); + if(!vp->isActive()){ + vp->master->setActiveViewport(vp); } } diff --git a/gui/qt/mainwindow.cpp b/gui/qt/mainwindow.cpp index db73e55c..d6ec88ec 100644 --- a/gui/qt/mainwindow.cpp +++ b/gui/qt/mainwindow.cpp @@ -44,7 +44,7 @@ MainWindow::MainWindow(QString path): void MainWindow::setupViewports() { // create first level of splitters and main viewport - viewports.push_back(new ViewPort{this, true}); + viewports.push_back(new ViewPort{this}); vsplit = new QSplitter{this}; vsplit->setOrientation(Qt::Vertical); vsplit->setChildrenCollapsible(false); @@ -53,7 +53,7 @@ void MainWindow::setupViewports() hsplits.back()->addWidget(viewports.front()); setCentralWidget(vsplit); curVP = viewports.front(); - curVP->makeActive(true); + curVP->setFrameShadow(QFrame::Shadow::Sunken); curVP->ui->closeButton->setDisabled(true); } @@ -351,13 +351,14 @@ void MainWindow::setupHelpMenu() void MainWindow::updateWidgets(GUI::change_t change) { + throw Error{"this should not be called anymore"}; // pull in mol/step selection from active viewport - if((change & GUI::molChanged) == GUI::molChanged){ - vApp.setActiveMol(*curVP->curMol); - } - if((change & GUI::stepChanged) == GUI::stepChanged){ - vApp.setActiveStep(*curVP->curStep, *curVP->curSel); - } + // if((change & GUI::molChanged) == GUI::molChanged){ + // vApp.setActiveMol(*curVP->curMol); + // } + // if((change & GUI::stepChanged) == GUI::stepChanged){ + // vApp.setActiveStep(*curVP->curStep, *curVP->curSel); + // } // notify widgets for(auto& w: viewports){ w->updateWidget(change); @@ -367,72 +368,65 @@ void MainWindow::updateWidgets(GUI::change_t change) // } } -void MainWindow::changeViewports(ViewPort *sender, VPChange change) -{ - try{ - switch(change){ - case VP_CLOSE: - { - bool wasActive = sender->active; - auto pos = std::find(viewports.begin(), viewports.end(), sender); - if(pos == viewports.end()){ - throw Error{"Invalid viewport"}; - }else{ - viewports.erase(pos); - delete sender; - // clean-up hsplits if sender was last child - for(auto it = hsplits.begin(); it != hsplits.end(); ++it){ - if(!(*it)->count()){ - delete *it; - hsplits.erase(it); - break; - } - } - } - // make sure we don't close last viewport - if(viewports.size() == 1) - viewports.front()->ui->closeButton->setDisabled(true); - if(wasActive) - viewports.front()->openGLWidget->setFocus(); - } - break; - case VP_VSPLIT: - if(viewports.size() == 1) viewports.front()->ui->closeButton->setEnabled(true); - viewports.push_back(new ViewPort{*sender}); - viewports.back()->updateWidget(GUI::molChanged); - hsplits.push_back(new QSplitter{vsplit}); - hsplits.back()->setChildrenCollapsible(false); - hsplits.back()->addWidget(viewports.back()); - vsplit->addWidget(hsplits.back()); - break; - case VP_HSPLIT: - if(viewports.size() == 1) viewports.front()->ui->closeButton->setEnabled(true); - viewports.push_back(new ViewPort{*sender}); - viewports.back()->updateWidget(GUI::molChanged); - for(auto& h: hsplits){ - for(auto& c: h->children()){ - if (c == sender){ - h->addWidget(viewports.back()); - return; - } - } +void MainWindow::setActiveViewport(ViewPort* sender) { + // deactivate other viewports + for(auto& vp: viewports){ + vp->setFrameShadow(QFrame::Shadow::Raised); + } + sender->setFrameShadow(QFrame::Shadow::Sunken); + // make sender current viewport + curVP = sender; + vApp.setActiveMol(*curVP->curMol); + vApp.setActiveStep(*curVP->curStep, *curVP->curSel); +} + +void MainWindow::splitViewportHoriz(ViewPort* sender) { + viewports.front()->ui->closeButton->setEnabled(true); + viewports.push_back(new ViewPort{*sender}); + viewports.back()->updateWidget(GUI::molChanged); + for(auto& h: hsplits){ + for(auto& c: h->children()){ + if (c == sender){ + h->addWidget(viewports.back()); + return; } - throw Error{"Could not determine horizontal splitter for viewport"}; - case VP_ACTIVE: - // deactivate other viewports - for(auto& vp: viewports){ - vp->makeActive(vp == sender); + } + } + throw Error{"Could not determine horizontal splitter for viewport"}; +} + +void MainWindow::splitViewportVert(ViewPort* sender) { + viewports.front()->ui->closeButton->setEnabled(true); + viewports.push_back(new ViewPort{*sender}); + viewports.back()->updateWidget(GUI::molChanged); + hsplits.push_back(new QSplitter{vsplit}); + hsplits.back()->setChildrenCollapsible(false); + hsplits.back()->addWidget(viewports.back()); + vsplit->addWidget(hsplits.back()); +} + +void MainWindow::closeViewport(ViewPort* sender) { + bool wasActive = sender == curVP; + auto pos = std::find(viewports.begin(), viewports.end(), sender); + if(pos == viewports.end()){ + throw Error{"Invalid viewport"}; + }else{ + viewports.erase(pos); + delete sender; + // clean-up hsplits if sender was last child + for(auto it = hsplits.begin(); it != hsplits.end(); ++it){ + if(!(*it)->count()){ + delete *it; + hsplits.erase(it); + break; } - // make sender current viewport - curVP = sender; - updateWidgets(GUI::molChanged); - break; - default: - throw Error{"Invalid viewport change"}; } - }catch(const Error& e){ - QMessageBox::information(this, "ViewPort Error", e.what()); } + // make sure we don't close last viewport + if(viewports.size() == 1) + viewports.front()->ui->closeButton->setDisabled(true); + if(wasActive) + viewports.front()->openGLWidget->setFocus(); } void MainWindow::newData(IOTuple &&d) diff --git a/gui/qt/mainwindow.h b/gui/qt/mainwindow.h index 0dd3a366..b219a91e 100644 --- a/gui/qt/mainwindow.h +++ b/gui/qt/mainwindow.h @@ -22,8 +22,10 @@ class MainWindow : public QMainWindow // Viewports std::vector viewports; - enum VPChange{VP_CLOSE, VP_VSPLIT, VP_HSPLIT, VP_ACTIVE}; - void changeViewports(ViewPort* sender, VPChange change); + void setActiveViewport(ViewPort* sender); + void splitViewportHoriz(ViewPort* sender); + void splitViewportVert(ViewPort* sender); + void closeViewport(ViewPort* sender); ViewPort* curVP{nullptr}; void updateWidgets(Vipster::GUI::change_t change); void newData(Vipster::IOTuple&& d); diff --git a/gui/qt/viewport.cpp b/gui/qt/viewport.cpp index 46accbb3..dfa91fd7 100644 --- a/gui/qt/viewport.cpp +++ b/gui/qt/viewport.cpp @@ -6,11 +6,10 @@ using namespace Vipster; -ViewPort::ViewPort(MainWindow *parent, bool active) : +ViewPort::ViewPort(MainWindow *parent) : QFrame(parent), ui(new Ui::ViewPort), - master{parent}, - active{active} + master{parent} { ui->setupUi(this); setFocusPolicy(Qt::StrongFocus); @@ -50,12 +49,17 @@ ViewPort::ViewPort(MainWindow *parent, bool active) : [&](const Vipster::ConfigState &){ updateState(); }); + + // Viewport management buttons + connect(ui->closeButton, &QPushButton::clicked, this, [&](){master->closeViewport(this);}); + connect(ui->vSplitButton, &QPushButton::clicked, this, [&](){master->splitViewportVert(this);}); + connect(ui->hSplitButton, &QPushButton::clicked, this, [&](){master->splitViewportHoriz(this);}); } ViewPort::ViewPort(const ViewPort &vp) : - ViewPort{vp.master, false} + ViewPort{vp.master} { - //TODO: make this optional? + // synchronize mol/step state moldata = vp.moldata; for(const auto& p: vp.stepdata){ if(p.second.sel){ @@ -66,8 +70,10 @@ ViewPort::ViewPort(const ViewPort &vp) : } } } + + // synchronize/initialize GUI state + updateMoleculeList(vApp.molecules); ui->molList->setCurrentIndex(vp.ui->molList->currentIndex()); - ui->stepEdit->setValue(vp.ui->stepEdit->value()); } ViewPort::~ViewPort() @@ -75,6 +81,10 @@ ViewPort::~ViewPort() delete ui; } +bool ViewPort::isActive() { + return this == master->curVP; +} + void ViewPort::updateState() { // set widget's bond mode accordingly setBondMode(vApp.getState(*curStep).automatic_bonds); @@ -103,7 +113,7 @@ void ViewPort::updateMoleculeList(const std::list &molecules){ ui->molList->addItem(mol.name.c_str()); } - if (active || shrunk) { + if (!curMol || shrunk || isActive()) { setMol(molecules.size()-1); } } @@ -197,7 +207,7 @@ void ViewPort::setMol(int index) setStep(moldata[curMol].curStep, true); // update app state if required - if (active) { + if (isActive()) { vApp.setActiveMol(*curMol); } } @@ -243,7 +253,7 @@ void ViewPort::setStep(int i, bool setMol) updateState(); // Update application state - if(active){ + if(isActive()){ vApp.setActiveStep(*curStep, *curSel); } } @@ -254,8 +264,8 @@ void ViewPort::setMult(int i) if(sender() == ui->xMultBox){ mult[0] = static_cast(i); } else if(sender() == ui->yMultBox){ mult[1] = static_cast(i); } else if(sender() == ui->zMultBox){ mult[2] = static_cast(i); } - // save mult if needed - if (active) moldata[curMol].mult = mult; + moldata[curMol].mult = mult; + // trigger redraw openGLWidget->setMult(mult); } @@ -327,24 +337,3 @@ void ViewPort::on_mouseMode_currentIndexChanged(int i) { openGLWidget->setMouseMode(static_cast(i)); } - -void ViewPort::on_closeButton_clicked() -{ - master->changeViewports(this, MainWindow::VP_CLOSE); -} - -void ViewPort::on_vSplitButton_clicked() -{ - master->changeViewports(this, MainWindow::VP_VSPLIT); -} - -void ViewPort::on_hSplitButton_clicked() -{ - master->changeViewports(this, MainWindow::VP_HSPLIT); -} - -void ViewPort::makeActive(bool a) -{ - active = a; - setFrameShadow(active ? QFrame::Sunken : QFrame::Raised); -} diff --git a/gui/qt/viewport.h b/gui/qt/viewport.h index faf87417..bb97035d 100644 --- a/gui/qt/viewport.h +++ b/gui/qt/viewport.h @@ -25,17 +25,19 @@ class ViewPort : public QFrame friend class MainWindow; friend class GLWidget; public: - explicit ViewPort(MainWindow *parent, bool active=false); + explicit ViewPort(MainWindow *parent); explicit ViewPort(const ViewPort &vp); ~ViewPort() override; + void updateWidget(Vipster::GUI::change_t change); - void makeActive(bool active); + void addExtraData(const std::shared_ptr &dat, bool global); void delExtraData(const std::shared_ptr &dat, bool global); bool hasExtraData(const std::shared_ptr &dat, bool global); struct { std::vector> extras{}; } vpdata{}; + struct MolState{ size_t curStep{0}; Vipster::GUI::PBCVec mult{1,1,1}; @@ -59,13 +61,11 @@ public slots: private slots: void on_mouseMode_currentIndexChanged(int index); - void on_closeButton_clicked(); - void on_vSplitButton_clicked(); - void on_hSplitButton_clicked(); void updateMoleculeList(const std::list &molecules); public: void updateState(); + bool isActive(); Ui::ViewPort *ui; MainWindow *master; @@ -73,7 +73,6 @@ private slots: Vipster::Molecule* curMol{nullptr}; Vipster::Step* curStep{nullptr}; Vipster::Step::selection* curSel{nullptr}; - bool active{true}; QTimer playTimer{}; };