diff --git a/avogadro/mainwindow.cpp b/avogadro/mainwindow.cpp index f3e35853..d2676c64 100644 --- a/avogadro/mainwindow.cpp +++ b/avogadro/mainwindow.cpp @@ -15,6 +15,7 @@ ******************************************************************************/ #include "mainwindow.h" + #include "aboutdialog.h" #include "avogadroappconfig.h" #include "backgroundfileformat.h" @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +207,7 @@ using QtGui::ExtensionPlugin; using QtGui::ExtensionPluginFactory; using QtGui::FileFormatDialog; using QtGui::Molecule; +using QtGui::MultiViewWidget; using QtGui::RWMolecule; using QtGui::ScenePlugin; using QtGui::ScenePluginFactory; @@ -224,6 +227,8 @@ MainWindow::MainWindow(const QStringList& fileNames, bool disableSettings) : m_molecule(nullptr) , m_rwMolecule(nullptr) , m_moleculeModel(nullptr) + , m_layerModel(nullptr) + , m_activeScenePlugin(nullptr) , m_queuedFilesStarted(false) , m_menuBuilder(new MenuBuilder) , m_fileReadThread(nullptr) @@ -347,19 +352,21 @@ void MainWindow::setupInterface() addDockWidget(Qt::LeftDockWidgetArea, m_toolDock); // Our scene/view dock. - QDockWidget* sceneDock = new QDockWidget(tr("Display Types"), this); - m_sceneTreeView = new QTreeView(sceneDock); + m_sceneDock = new QDockWidget(tr("Display Types"), this); + m_sceneDock->setFeatures(m_sceneDock->features() & + ~QDockWidget::AllDockWidgetFeatures); + + m_sceneTreeView = new QTreeView(m_sceneDock); m_sceneTreeView->setIndentation(0); m_sceneTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); m_sceneTreeView->setSelectionMode(QAbstractItemView::SingleSelection); - sceneDock->setWidget(m_sceneTreeView); - addDockWidget(Qt::LeftDockWidgetArea, sceneDock); - + m_sceneDock->setWidget(m_sceneTreeView); + addDockWidget(Qt::LeftDockWidgetArea, m_sceneDock); // Our view dock. m_viewDock = new QDockWidget(tr("View Configuration"), this); addDockWidget(Qt::LeftDockWidgetArea, m_viewDock); - // put display types on top of view config - tabifyDockWidget(m_viewDock, sceneDock); + m_viewDock->setFeatures(m_viewDock->features() & + ~QDockWidget::AllDockWidgetFeatures); // Our molecule dock. QDockWidget* moleculeDock = new QDockWidget(tr("Molecules"), this); @@ -370,6 +377,17 @@ void MainWindow::setupInterface() moleculeDock->setWidget(m_moleculeTreeView); addDockWidget(Qt::LeftDockWidgetArea, moleculeDock); + // Our molecule dock. + QDockWidget* layerDock = new QDockWidget(tr("Layers"), this); + m_layerTreeView = new QTreeView(layerDock); + m_layerTreeView->setIndentation(0); + m_layerTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_layerTreeView->setSelectionMode(QAbstractItemView::SingleSelection); + layerDock->setWidget(m_layerTreeView); + addDockWidget(Qt::LeftDockWidgetArea, layerDock); + + tabifyDockWidget(moleculeDock, layerDock); + // Switch to our fallback icons if there are no platform-specific icons. if (!QIcon::hasThemeIcon("document-new")) QIcon::setThemeName("fallback"); @@ -409,6 +427,24 @@ void MainWindow::setupInterface() connect(m_moleculeTreeView, &QAbstractItemView::clicked, this, &MainWindow::moleculeActivated); + m_layerModel = new QtGui::LayerModel(this); + m_layerTreeView->setModel(m_layerModel); + m_layerTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_layerTreeView->setAlternatingRowColors(true); + m_layerTreeView->header()->setStretchLastSection(false); + m_layerTreeView->header()->setVisible(false); + m_layerTreeView->header()->setSectionResizeMode(0, QHeaderView::Stretch); + for (int i = 1; i < m_layerModel->columnCount(QModelIndex()); ++i) { + m_layerTreeView->header()->setSectionResizeMode(i, QHeaderView::Fixed); + m_layerTreeView->header()->resizeSection(i, 25); + } + connect(m_layerTreeView, &QAbstractItemView::activated, this, + &MainWindow::layerActivated); + connect(m_layerTreeView, &QAbstractItemView::clicked, this, + &MainWindow::layerActivated); + connect(m_sceneTreeView, &QAbstractItemView::clicked, m_layerModel, + &QtGui::LayerModel::updateRows); + viewActivated(glWidget); buildTools(); // Connect to the invalid context signal, check whether GL is initialized. @@ -479,16 +515,33 @@ void setWidgetMolecule(T* glWidget, M* mol) glWidget->resetCamera(); } +void setDefaultViews(MultiViewWidget* viewWidget) +{ + QSettings settings; + // save the enabled scene / render plugins + if (GLWidget* glWidget = + qobject_cast(viewWidget->activeWidget())) { + + const ScenePluginModel* sceneModel = &glWidget->sceneModel(); + for (auto plugin : sceneModel->scenePlugins()) { + QString settingsKey("MainWindow/" + plugin->objectName()); + bool enabled = settings.value(settingsKey, plugin->isEnabled()).toBool(); + plugin->setEnabled(enabled); + } + } +} void MainWindow::setMolecule(Molecule* mol) { if (!mol) return; // Set the new molecule, ensure both molecules are in the model. - if (m_molecule && !m_moleculeModel->molecules().contains(m_molecule)) + if (m_molecule && !m_moleculeModel->molecules().contains(m_molecule)) { m_moleculeModel->addItem(m_molecule); - if (!m_moleculeModel->molecules().contains(mol)) + } + if (!m_moleculeModel->molecules().contains(mol)) { m_moleculeModel->addItem(mol); + } Molecule* oldMolecule(m_molecule); m_molecule = mol; @@ -507,6 +560,14 @@ void MainWindow::setMolecule(Molecule* mol) markMoleculeClean(); updateWindowTitle(); m_moleculeModel->setActiveMolecule(m_molecule); + m_layerModel->addMolecule(m_molecule); + // only set the default values if there is nothing setup + // 1 layer (layerCount) and 1ยบ layer + add items + if (m_layerModel->layerCount() == 1 && m_layerModel->items() == 2) { + setDefaultViews(m_multiViewWidget); + refreshDisplayTypes(); + } + ActiveObjects::instance().setActiveMolecule(m_molecule); if (oldMolecule) @@ -533,6 +594,18 @@ void MainWindow::markMoleculeDirty() } } +void MainWindow::refreshDisplayTypes() +{ + m_layerModel->updateRows(); + // force m_sceneTreeView update (update doesn't update the checkbox) + m_sceneTreeView->setFocus(); + if (m_activeScenePlugin != nullptr) { + m_viewDock->setWidget(m_activeScenePlugin->setupWidget()); + } + // reset focus to m_layerTreeView + m_layerTreeView->setFocus(); +} + void MainWindow::markMoleculeClean() { if (m_moleculeDirty) { @@ -867,6 +940,52 @@ void MainWindow::rendererInvalid() QTimer::singleShot(500, this, &QWidget::close); } +void MainWindow::layerActivated(const QModelIndex& idx) +{ + m_layerModel->updateRows(); + if (idx.row() == m_layerModel->items() - 1) { + m_layerModel->addLayer(m_molecule->undoMolecule()); + } else { + bool updateGL = false; + if (idx.column() == QtGui::LayerModel::ColumnType::Name) { + m_layerModel->setActiveLayer(idx.row(), m_molecule->undoMolecule()); + } else if (idx.column() == QtGui::LayerModel::ColumnType::Remove) { + if (m_layerModel->layerCount() > 1) { + m_layerModel->removeItem(idx.row(), m_molecule->undoMolecule()); + updateGL = true; + } + } else if (idx.column() == QtGui::LayerModel::ColumnType::Lock) { + m_layerModel->flipLocked(idx.row()); + } else if (idx.column() == QtGui::LayerModel::ColumnType::Visible) { + m_layerModel->flipVisible(idx.row()); + updateGL = true; + } else if (idx.column() == QtGui::LayerModel::ColumnType::Menu) { + m_layerModel->setActiveLayer(idx.row(), m_molecule->undoMolecule()); + if (m_sceneDock->isHidden()) { + m_sceneDock->show(); + m_viewDock->show(); + resizeDocks({ m_sceneDock, m_viewDock }, { 250, 50 }, Qt::Vertical); + } else { + m_sceneDock->hide(); + m_viewDock->hide(); + } + } + + if (updateGL) { + QWidget* w = m_multiViewWidget->activeWidget(); + if (GLWidget* glWidget = qobject_cast(w)) { + glWidget->updateScene(); + } +#ifdef AVO_USE_VTK + else if (vtkGLWidget* vtkWidget = qobject_cast(w)) { + vtkWidget->updateScene(); + } +#endif + } + } + refreshDisplayTypes(); +} + void MainWindow::moleculeActivated(const QModelIndex& idx) { QObject* obj = static_cast(idx.internalPointer()); @@ -897,8 +1016,10 @@ void MainWindow::sceneItemActivated(const QModelIndex& idx) if (!idx.isValid()) return; QObject* obj = static_cast(idx.internalPointer()); - if (ScenePlugin* scene = qobject_cast(obj)) + if (ScenePlugin* scene = qobject_cast(obj)) { m_viewDock->setWidget(scene->setupWidget()); + m_activeScenePlugin = scene; + } } bool populatePluginModel(ScenePluginModel& model, bool editOnly = false) @@ -913,8 +1034,7 @@ bool populatePluginModel(ScenePluginModel& model, bool editOnly = false) foreach (ScenePluginFactory* factory, scenePluginFactories) { ScenePlugin* scenePlugin = factory->createInstance(); if (editOnly && scenePlugin) { - if (scenePlugin->objectName() == "BallStick" || - scenePlugin->objectName() == "OverlayAxes") { + if (scenePlugin->objectName() == "BallStick") { model.addItem(scenePlugin); } else { delete scenePlugin; @@ -922,10 +1042,6 @@ bool populatePluginModel(ScenePluginModel& model, bool editOnly = false) } else if (scenePlugin) { model.addItem(scenePlugin); } - - QString settingsKey("MainWindow/" + scenePlugin->objectName()); - bool enabled = settings.value(settingsKey, scenePlugin->isEnabled()).toBool(); - scenePlugin->setEnabled(enabled); } return true; } @@ -967,15 +1083,13 @@ void MainWindow::viewActivated(QWidget* widget) glWidget->updateScene(); } else { m_moleculeModel->setActiveMolecule(glWidget->molecule()); + m_layerModel->addMolecule(m_molecule); // Figure out the active tool - reflect this in the toolbar. ToolPlugin* tool = glWidget->activeTool(); if (tool) { QString name = tool->objectName(); foreach (QAction* action, m_toolToolBar->actions()) { - if (action->data().toString() == name) - action->setChecked(true); - else - action->setChecked(false); + action->setChecked(action->data().toString() == name); } } } @@ -984,6 +1098,7 @@ void MainWindow::viewActivated(QWidget* widget) m_molecule = glWidget->molecule(); emit moleculeChanged(m_molecule); m_moleculeModel->setActiveMolecule(m_molecule); + m_layerModel->addMolecule(m_molecule); } ActiveObjects::instance().setActiveGLWidget(glWidget); } @@ -997,12 +1112,14 @@ void MainWindow::viewActivated(QWidget* widget) vtkWidget->updateScene(); } else { m_moleculeModel->setActiveMolecule(vtkWidget->molecule()); + m_layerModel->addMolecule(m_molecule); } if (m_molecule != vtkWidget->molecule() && vtkWidget->molecule()) { m_rwMolecule = nullptr; m_molecule = vtkWidget->molecule(); emit moleculeChanged(m_molecule); m_moleculeModel->setActiveMolecule(m_molecule); + m_layerModel->addMolecule(m_molecule); } } #endif @@ -1369,6 +1486,7 @@ void MainWindow::undoEdit() if (m_molecule) { m_molecule->undoMolecule()->undoStack().undo(); m_molecule->emitChanged(Molecule::Atoms | Molecule::Added); + m_layerModel->updateRows(); activeMoleculeEdited(); } } @@ -1378,6 +1496,7 @@ void MainWindow::redoEdit() if (m_molecule) { m_molecule->undoMolecule()->undoStack().redo(); m_molecule->emitChanged(Molecule::Atoms | Molecule::Added); + m_layerModel->updateRows(); activeMoleculeEdited(); } } diff --git a/avogadro/mainwindow.h b/avogadro/mainwindow.h index 36a1dbf9..314a3074 100644 --- a/avogadro/mainwindow.h +++ b/avogadro/mainwindow.h @@ -55,6 +55,7 @@ class Molecule; class MoleculeModel; class MultiViewWidget; class RWMolecule; +class LayerModel; } /** @@ -130,8 +131,8 @@ public slots: void closeEvent(QCloseEvent* event); // Handle drag and drop -- accept files dragged on the window - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); protected slots: /** @@ -226,6 +227,7 @@ protected slots: void undoEdit(); void redoEdit(); void activeMoleculeEdited(); + void refreshDisplayTypes(); #ifdef QTTESTING protected slots: @@ -299,6 +301,11 @@ private slots: */ void moleculeActivated(const QModelIndex& index); + /** + * @brief Change the active layer + */ + void layerActivated(const QModelIndex& index); + /** * @brief Change the configuration dialog to reflect active scene item. */ @@ -321,6 +328,8 @@ private slots: QtGui::Molecule* m_molecule; QtGui::RWMolecule* m_rwMolecule; QtGui::MoleculeModel* m_moleculeModel; + QtGui::LayerModel* m_layerModel; + QtGui::ScenePlugin* m_activeScenePlugin; bool m_queuedFilesStarted; QStringList m_queuedFiles; @@ -344,9 +353,11 @@ private slots: QtGui::MultiViewWidget* m_multiViewWidget; QTreeView* m_sceneTreeView; + QTreeView* m_layerTreeView; QTreeView* m_moleculeTreeView; QDockWidget* m_toolDock; QDockWidget* m_viewDock; + QDockWidget* m_sceneDock; QList m_tools; QList m_extensions;