diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index d09cb40..6694e60 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -88,6 +88,32 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu) } +/** + * Function returns a features string with closable (c), movable (m) and floatable (f) + * features. i.e. The following string is for a not closable but movable and floatable + * widget: c- m+ f+ + */ +static QString featuresString(ads::CDockWidget* DockWidget) +{ + auto f = DockWidget->features(); + return QString("c%1 m%2 f%3") + .arg(f.testFlag(ads::CDockWidget::DockWidgetClosable) ? "+" : "-") + .arg(f.testFlag(ads::CDockWidget::DockWidgetMovable) ? "+" : "-") + .arg(f.testFlag(ads::CDockWidget::DockWidgetFloatable) ? "+" : "-"); +} + + +/** + * Appends the string returned by featuresString() to the window title of + * the given DockWidget + */ +static void appendFeaturStringToWindowTitle(ads::CDockWidget* DockWidget) +{ + DockWidget->setWindowTitle(DockWidget->windowTitle() + + QString(" (%1)").arg(featuresString(DockWidget))); +} + + //============================================================================ static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu) { @@ -110,7 +136,8 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu) QFileSystemModel* m = new QFileSystemModel(w); m->setRootPath(QDir::currentPath()); w->setModel(m); - ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++)); + ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1") + .arg(FileSystemCount++)); DockWidget->setWidget(w); ViewMenu->addAction(DockWidget->toggleViewAction()); return DockWidget; @@ -185,6 +212,8 @@ void MainWindowPrivate::createContent() ToolBar->addAction(ui.actionSaveState); ToolBar->addAction(ui.actionRestoreState); FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false); + FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetFloatable, false); + appendFeaturStringToWindowTitle(FileSystemWidget); auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget); DockWidget = createCalendarDockWidget(ViewMenu); DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false); diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 031a193..648b67d 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -205,6 +205,13 @@ void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev) return; } + // If one single dock widget in this area is not floatable then the whole + // area is not floatable + if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) + { + return; + } + int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength(); if (DragDistance >= CDockManager::startDragDistance()) { @@ -228,6 +235,11 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event) { return; } + + if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) + { + return; + } makeAreaFloating(event->pos(), DraggingInactive); } diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 021060b..99c81ee 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -291,7 +291,10 @@ void CDockAreaTitleBar::onCloseButtonClicked() //============================================================================ void CDockAreaTitleBar::onUndockButtonClicked() { - d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive); + if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) + { + d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive); + } } @@ -346,9 +349,10 @@ void CDockAreaTitleBar::setVisible(bool Visible) void CDockAreaTitleBar::showContextMenu(const QPoint& pos) { QMenu Menu(this); - Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked())); + auto Action = Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked())); + Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)); Menu.addSeparator(); - auto Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked())); + Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked())); Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable)); Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas())); Menu.exec(mapToGlobal(pos)); diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 292d54b..c2d6e6c 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -241,7 +241,7 @@ struct DockAreaWidgetPrivate DockAreaLayout* ContentsLayout = nullptr; CDockAreaTitleBar* TitleBar = nullptr; CDockManager* DockManager = nullptr; - bool UpdateCloseButton = false; + bool UpdateTitleBarButtons = false; /** * Private data constructor @@ -295,9 +295,9 @@ struct DockAreaWidgetPrivate } /** - * Udpates the enable state of the close button + * Udpates the enable state of the close and detach button */ - void updateCloseButtonState(); + void updateTitleBarButtonStates(); }; // struct DockAreaWidgetPrivate @@ -322,17 +322,19 @@ void DockAreaWidgetPrivate::createTitleBar() //============================================================================ -void DockAreaWidgetPrivate::updateCloseButtonState() +void DockAreaWidgetPrivate::updateTitleBarButtonStates() { if (_this->isHidden()) { - UpdateCloseButton = true; + UpdateTitleBarButtons = true; return; } TitleBar->button(TitleBarButtonClose)->setEnabled( _this->features().testFlag(CDockWidget::DockWidgetClosable)); - UpdateCloseButton = false; + TitleBar->button(TitleBarButtonUndock)->setEnabled( + _this->features().testFlag(CDockWidget::DockWidgetFloatable)); + UpdateTitleBarButtons = false; } @@ -400,7 +402,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, setCurrentIndex(index); } DockWidget->setDockArea(this); - d->updateCloseButtonState(); + d->updateTitleBarButtonStates(); } @@ -433,7 +435,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) hideAreaWithNoVisibleContent(); } - d->updateCloseButtonState(); + d->updateTitleBarButtonStates(); updateTitleBarVisibility(); auto TopLevelDockWidget = DockContainer->topLevelDockWidget(); if (TopLevelDockWidget) @@ -765,9 +767,9 @@ void CDockAreaWidget::toggleView(bool Open) void CDockAreaWidget::setVisible(bool Visible) { Super::setVisible(Visible); - if (d->UpdateCloseButton) + if (d->UpdateTitleBarButtons) { - d->updateCloseButtonState(); + d->updateTitleBarButtonStates(); } } diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 7a66686..ca0ef1e 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -340,8 +340,9 @@ void DockManagerPrivate::emitTopLevelEvents() //============================================================================ -bool DockManagerPrivate::restoreState(const QByteArray &state, int version) +bool DockManagerPrivate::restoreState(const QByteArray& State, int version) { + QByteArray state = State.startsWith("ConfigFlags.testFlag(XmlAutoFormattingEnabled)); s.writeStartDocument(); s.writeStartElement("QtAdvancedDockingSystem"); s.writeAttribute("Version", QString::number(version)); @@ -510,7 +511,7 @@ QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const s.writeEndElement(); s.writeEndDocument(); - return xmldata; + return d->ConfigFlags.testFlag(XmlCompressionEnabled) ? qCompress(xmldata, 9) : xmldata; } diff --git a/src/DockManager.h b/src/DockManager.h index 72ab026..4a6dfdc 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -51,7 +51,9 @@ struct DockWidgetTabPrivate; struct DockAreaWidgetPrivate; /** - * The central dock manager that maintains the complete docking system + * The central dock manager that maintains the complete docking system. + * With the configuration flags you can globally control the functionality + * of the docking system. **/ class ADS_EXPORT CDockManager : public CDockContainerWidget { @@ -108,12 +110,6 @@ public: MenuAlphabeticallySorted }; - enum eXmlMode - { - XmlAutoFormattingDisabled, - XmlAutoFormattingEnabled - }; - /** * These global configuration flags configure some global dock manager * settings. @@ -124,7 +120,9 @@ public: DockAreaHasCloseButton = 0x02, //!< If the flag is set each dock area has a close button DockAreaCloseButtonClosesTab = 0x04,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area OpaqueSplitterResize = 0x08, //!< See QSplitter::setOpaqueResize() documentation - DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize, ///< the default configuration + XmlAutoFormattingEnabled = 0x10,//!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace). + XmlCompressionEnabled = 0x20,//!< If enabled, the XML output will be compressed and is not human readable anymore + DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize | XmlCompressionEnabled, ///< the default configuration }; Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag) @@ -228,7 +226,7 @@ public: * The XmlMode XmlAutoFormattingDisabled is better if you would like to have * a more compact XML output - i.e. for storage in ini files. */ - QByteArray saveState(eXmlMode XmlMode = XmlAutoFormattingDisabled, int version = 0) const; + QByteArray saveState(int version = 0) const; /** * Restores the state of this dockmanagers dockwidgets. diff --git a/src/DockWidget.h b/src/DockWidget.h index 658372f..32152db 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -141,7 +141,7 @@ public: enum DockWidgetFeature { DockWidgetClosable = 0x01, - DockWidgetMovable = 0x02, + DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored DockWidgetFloatable = 0x04, AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable, NoDockWidgetFeatures = 0x00 diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 6e05086..069eb84 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -328,7 +328,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev) } // Floating is only allowed for widgets that are movable - if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable)) + if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) { d->startFloating(); } @@ -352,9 +352,10 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev) d->DragStartMousePosition = ev->pos(); QMenu Menu(this); - Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered())); + auto Action = Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered())); + Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)); Menu.addSeparator(); - auto Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); + Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); Action->setEnabled(isClosable()); Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); Menu.exec(mapToGlobal(ev->pos())); @@ -469,7 +470,8 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event) // If this is the last dock area in a dock container it does not make // sense to move it to a new floating widget and leave this one // empty - if (!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1) + if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1) + && d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) { d->DragStartMousePosition = event->pos(); d->startFloating(DraggingInactive); @@ -505,13 +507,15 @@ bool CDockWidgetTab::isClosable() const //=========================================================================== void CDockWidgetTab::onDetachActionTriggered() { + if (!d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) + { + return; + } d->DragStartMousePosition = mapFromGlobal(QCursor::pos()); d->startFloating(DraggingInactive); } - - //============================================================================ bool CDockWidgetTab::event(QEvent *e) {