Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit c8ef752b authored by Artur Grunau's avatar Artur Grunau
Browse files

Initial implementation of a main menu

This commit adds a simple main menu to the application. For the time being
it only has 2 submenus, "File" and "Visualizations". The latter is created
by MdiDockArea and lets users manage the visibility and placement of
canvas windows.
parent 348c710e
......@@ -136,6 +136,7 @@ namespace campvis {
ui.logViewerDock->setWidget(_logViewer);
_dcInspectorWidget = new DataContainerInspectorWidget();
this->populateMainMenu();
connect(
this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)),
......@@ -160,6 +161,14 @@ namespace campvis {
_application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
}
void MainWindow::populateMainMenu() {
QMenuBar* menuBar = this->menuBar();
QMenu* fileMenu = menuBar->addMenu(tr("&File"));
fileMenu->addAction(tr("&Quit"), qApp, SLOT(closeAllWindows()), QKeySequence(Qt::CTRL + Qt::Key_Q));
menuBar->addMenu(_mdiArea->menu());
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
if (watched == _pipelinePropertiesWidget && event->type() == QEvent::Resize) {
_pipelinePropertiesScrollArea->setMinimumWidth(_pipelinePropertiesWidget->minimumSizeHint().width() +
......
......@@ -141,12 +141,16 @@ namespace campvis {
*/
void onDataContainersChanged();
/**
* Setup Qt GUI stuff
*/
void setup();
/**
* Create and populate the application's main menu.
*/
void populateMainMenu();
/**
* Adds a widget to the top docking area of the main window.
* This method creates a new dock with the specified name,
......
......@@ -28,23 +28,111 @@
// ================================================================================================
#include "mdidockarea.h"
#include "tgt/assert.h"
#include <QMenu>
#include <QSignalMapper>
namespace campvis {
MdiDockArea::MdiDockArea(QWidget* parent /*= 0*/)
: QMdiArea(parent)
, _menu(0)
, _signalMapper(0)
{
_signalMapper = new QSignalMapper(this);
this->setTabsClosable(true);
this->setTabsMovable(true);
this->setDocumentMode(true);
// Menu setup
_menu = new QMenu(tr("&Visualizations"));
QActionGroup* displayStyleActions = new QActionGroup(this);
QAction* displayTiledAction = displayStyleActions->addAction(tr("Display tiled"));
displayTiledAction->setCheckable(true);
displayTiledAction->setChecked(true);
_menu->addAction(displayTiledAction);
this->connect(displayTiledAction, SIGNAL(triggered()), SLOT(switchToTiledDisplay()));
QAction* displayTabbedAction = displayStyleActions->addAction(tr("Display tabbed"));
displayTabbedAction->setCheckable(true);
_menu->addAction(displayTabbedAction);
this->connect(displayTabbedAction, SIGNAL(triggered()), SLOT(switchToTabbedDisplay()));
_menu->addSeparator();
}
MdiDockedWindow* MdiDockArea::addSubWindow(QWidget* widget, Qt::WindowFlags windowFlags /*= 0*/) {
MdiDockedWindow* dockedWindow = new MdiDockedWindow();
MdiDockedWindow* dockedWindow = new MdiDockedWindow(this, windowFlags);
dockedWindow->setWidget(widget);
QMdiArea::addSubWindow(dockedWindow, windowFlags);
widget->show();
this->tileSubWindows();
this->addDockedWindow(dockedWindow);
connect(dockedWindow, SIGNAL(s_positionChanged(MdiDockedWindow*, const QPoint&)),
this, SLOT(trackMdiSubWindowsPosition(MdiDockedWindow*, const QPoint&)));
// Calling tileSubWindows() in TabbedView mode breaks the tabbed display
if (this->viewMode() == QMdiArea::SubWindowView)
this->tileSubWindows();
QAction* visibilityAction = _menu->addAction(widget->windowTitle());
visibilityAction->setCheckable(true);
visibilityAction->setChecked(true);
visibilityAction->setData(QVariant::fromValue(dynamic_cast<QWidget*>(widget)));
connect(visibilityAction, SIGNAL(triggered()), _signalMapper, SLOT(map()));
_signalMapper->setMapping(visibilityAction, visibilityAction);
connect(_signalMapper, SIGNAL(mapped(QObject*)), SLOT(toggleSubWindowVisibility(QObject*)));
return dockedWindow;
}
QMenu* MdiDockArea::menu() {
return _menu;
}
void MdiDockArea::addDockedWindow(MdiDockedWindow* dockedWindow) {
QMdiArea::addSubWindow(dockedWindow);
dockedWindow->show();
connect(dockedWindow, SIGNAL(s_positionChanged(MdiDockedWindow*, const QPoint&)),
SLOT(trackMdiSubWindowsPosition(MdiDockedWindow*, const QPoint&)));
}
void MdiDockArea::toggleSubWindowVisibility(QObject* actionObject) {
/*
* This static_cast is safe as toggleSubWindowVisibility() is a private slot to which only
* MdiDockArea creates connections, always passing a QAction instance.
*/
QAction* visibilityAction = static_cast<QAction*>(actionObject);
QWidget* windowWidget = visibilityAction->data().value<QWidget*>()->parentWidget();
if (MdiDockedWindow* dockedWindow = dynamic_cast<MdiDockedWindow*>(windowWidget)) {
if (visibilityAction->isChecked())
this->addDockedWindow(dockedWindow);
else
this->removeSubWindow(dockedWindow);
// Calling tileSubWindows() in TabbedView mode breaks the tabbed display
if (this->viewMode() == QMdiArea::SubWindowView)
this->tileSubWindows();
} else if (MdiFloatingWindow* floatingWindow = dynamic_cast<MdiFloatingWindow*>(windowWidget)) {
if (visibilityAction->isChecked())
floatingWindow->show();
else
floatingWindow->hide();
}
else
tgtAssert(false, "Widget's parent is of unsupported type.");
}
void MdiDockArea::switchToTiledDisplay() {
this->setViewMode(QMdiArea::SubWindowView);
this->tileSubWindows();
}
void MdiDockArea::switchToTabbedDisplay() {
this->setViewMode(QMdiArea::TabbedView);
}
void MdiDockArea::trackFloatingWindowsPosition(MdiFloatingWindow* floatingWindow, const QPoint& newPos) {
const QRect& widgetGeometry = floatingWindow->frameGeometry();
const QRect& mdiAreaRect = this->contentsRect();
......@@ -56,13 +144,16 @@ namespace campvis {
if (widgetGeometry.width() * widgetGeometry.height() * 3 <
intersection.width() * intersection.height() * 5) {
floatingWindow->stopWindowDrag();
floatingWindow->hide();
QWidget* widget = floatingWindow->widget();
MdiDockedWindow* dockedWindow = this->addSubWindow(widget);
MdiDockedWindow* dockedWindow = new MdiDockedWindow();
dockedWindow->setWidget(widget);
dockedWindow->setWindowTitle(floatingWindow->windowTitle());
this->addDockedWindow(dockedWindow);
widget->show();
floatingWindow->deleteLater();
dockedWindow->forceWindowDrag();
}
}
......@@ -79,16 +170,16 @@ namespace campvis {
dockedWindow->stopWindowDrag();
dockedWindow->setWidget(0);
removeSubWindow(dockedWindow);
dockedWindow->deleteLater();
tileSubWindows();
MdiFloatingWindow* floatingWindow = new MdiFloatingWindow(widget);
floatingWindow->setWindowTitle(dockedWindow->windowTitle());
floatingWindow->show();
floatingWindow->forceWindowDrag();
connect(floatingWindow, SIGNAL(s_positionChanged(MdiFloatingWindow*, const QPoint&)),
this, SLOT(trackFloatingWindowsPosition(MdiFloatingWindow*, const QPoint&)));
dockedWindow->deleteLater();
tileSubWindows();
floatingWindow->show();
}
}
......
......@@ -35,6 +35,8 @@
#include <QMdiArea>
class QSignalMapper;
namespace campvis {
/**
......@@ -49,6 +51,13 @@ namespace campvis {
Q_OBJECT
public:
/**
* Constructs an empty MDI area.
*
* \param parent the area's parent widget (passed to QMdiArea's constructor)
*/
explicit MdiDockArea(QWidget* parent = 0);
/**
* Wrap \p widget in an MDI window and dock it in the MDI area.
*
......@@ -60,6 +69,8 @@ namespace campvis {
*/
MdiDockedWindow* addSubWindow(QWidget* widget, Qt::WindowFlags windowFlags = 0);
QMenu* menu();
private slots:
/**
* Track the position of a floating MDI window and dock it if necessary.
......@@ -75,6 +86,34 @@ namespace campvis {
*/
void trackMdiSubWindowsPosition(MdiDockedWindow* mdiSubWindow, const QPoint& newPos);
/**
* Display docked windows as sub-windows with window frames.
*/
void switchToTiledDisplay();
/**
* Display docked windows with tabs in a tab bar.
*/
void switchToTabbedDisplay();
/**
* Depending on the state of \p actionObject, show or hide its associated sub-window.
*
* \param actionObject the visibility action whose corresponding sub-window should be shown or hidden
*/
void toggleSubWindowVisibility(QObject* actionObject);
private:
/**
* Add the given MdiDockedWindow to the MDI area.
*
* \param dockedWindow the docked window to add
*/
void addDockedWindow(MdiDockedWindow* dockedWindow);
QMenu* _menu; ///< Menu with actions for controlling the MDI area and its subwindows.
QSignalMapper* _signalMapper; ///< Helper used to pass extra information to toggleSubWindowVisibility.
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment