Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c2d1891a2 | ||
|
|
998fe9fa11 | ||
|
|
28dc374fc2 | ||
|
|
1b6e449b4a | ||
|
|
0e88467f94 | ||
|
|
d0f4ce3248 | ||
|
|
542618fd4e | ||
|
|
661d0c4356 | ||
|
|
dceaa155c4 | ||
|
|
c541f2c69b | ||
|
|
37d305e50d | ||
|
|
4adef2b774 | ||
|
|
1c2383f8eb | ||
|
|
6c687d28de | ||
|
|
708add3ff5 | ||
|
|
e85b4167bd | ||
|
|
59c783831a | ||
|
|
4cb1931ace | ||
|
|
fe10b570d3 | ||
|
|
f3c5d51380 | ||
|
|
34cb2ae917 | ||
|
|
8cc9cc25ad | ||
|
|
c90fb9413c | ||
|
|
dec170ed24 | ||
|
|
3ffbbfb6d0 | ||
|
|
e8332575f8 | ||
|
|
8c12d912b4 | ||
|
|
fd28f0f751 | ||
|
|
3f09d5c6ea | ||
|
|
3407945f19 | ||
|
|
ce01e6b4a6 | ||
|
|
3428a4b8b4 | ||
|
|
2b9377b5ee | ||
|
|
d4a18003d9 | ||
|
|
2c15d5dacd | ||
|
|
f236de3277 | ||
|
|
93394577d0 | ||
|
|
f387c6aebc | ||
|
|
41173d067b | ||
|
|
5b60e39ed3 | ||
|
|
1916bd726d | ||
|
|
3efc5f2ada | ||
|
|
3eba02597c | ||
|
|
65eeffd5e1 | ||
|
|
ff1439c719 | ||
|
|
7ba20f37b7 |
@@ -42,6 +42,7 @@ set(ads_SRCS
|
||||
src/FloatingDockContainer.cpp
|
||||
src/FloatingDragPreview.cpp
|
||||
src/IconProvider.cpp
|
||||
src/DockComponentsFactory.cpp
|
||||
src/ads.qrc
|
||||
src/linux/FloatingWidgetTitleBar.cpp
|
||||
)
|
||||
@@ -61,6 +62,7 @@ set(ads_INSTALL_INCLUDE
|
||||
src/FloatingDockContainer.h
|
||||
src/FloatingDragPreview.h
|
||||
src/IconProvider.h
|
||||
src/DockComponentsFactory.h
|
||||
src/linux/FloatingWidgetTitleBar.h
|
||||
)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
|
||||
21
README.md
21
README.md
@@ -48,6 +48,9 @@ of his docking system project.
|
||||
- [KDDockWidgets](#kddockwidgets)
|
||||
- [QtitanDocking](#qtitandocking)
|
||||
- [Donation](#donation)
|
||||
- [Showcase](#showcase)
|
||||
- [Qt Design Studio](#qt-design-studio)
|
||||
- [QmixElements](#qmixelements)
|
||||
|
||||
### Docking everywhere - no central widget
|
||||
|
||||
@@ -273,3 +276,21 @@ If this project help you reduce time to develop or if you just like it, you can
|
||||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=85R64TMMSY9T6">
|
||||
<img src="doc/donate.png" alt="Donate with PayPal" width="160"/>
|
||||
</a>
|
||||
|
||||
## Showcase
|
||||
|
||||
### [Qt Design Studio](https://www.qt.io/ui-design-tools)
|
||||
|
||||
Taken from the [Qt Blog](https://www.qt.io/blog/qt-design-studio-1.5-beta-released):
|
||||
|
||||
> The most obvious change in [Qt Design Studio 1.5](https://www.qt.io/blog/qt-design-studio-1.5-beta-released) is the integration of dock widgets using the Qt Advanced Docking System. This allows the user to fully customize the workspace and also to undock any view into its own top level window. This especially improves the usability when using multiple screens.
|
||||
|
||||

|
||||
|
||||
### [QmixElements](https://www.cetoni.com/products/qmixelements/)
|
||||
|
||||
The QmixElements software from [CETONI](https://www.cetoni.com) is a comprehensive,
|
||||
plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. This [blog post](https://www.cetoni.com/blog/qmixelements-advanced-docking-system/) gives a nice overview about the use of the Qt
|
||||
Advanced Docking System in the QmixElements sofware.
|
||||
|
||||

|
||||
|
||||
316
demo.py
316
demo.py
@@ -1,316 +0,0 @@
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from PyQt5.QtCore import (QCoreApplication, QDir, Qt, QSettings, QSignalBlocker,
|
||||
QRect)
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtWidgets import (QCalendarWidget, QFileSystemModel, QFrame, QLabel,
|
||||
QMenu, QTreeView, QAction, QWidgetAction,
|
||||
QComboBox, QStyle, QSizePolicy, QInputDialog)
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from PyQtAds import QtAds
|
||||
|
||||
|
||||
class _State:
|
||||
label_count = 0
|
||||
calendar_count = 0
|
||||
file_system_count = 0
|
||||
|
||||
|
||||
def create_long_text_label_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
'''
|
||||
Create long text label dock widget
|
||||
|
||||
Parameters
|
||||
----------
|
||||
view_menu : QMenu
|
||||
|
||||
Returns
|
||||
-------
|
||||
value : QtAds.CDockWidget
|
||||
'''
|
||||
label = QLabel()
|
||||
label.setWordWrap(True)
|
||||
label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||
label.setText('''\
|
||||
Label {} {} - Lorem ipsum dolor sit amet, consectetuer
|
||||
adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum
|
||||
sociis natoque penatibus et magnis dis parturient montes, nascetur
|
||||
ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium
|
||||
quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla
|
||||
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut,
|
||||
imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis
|
||||
pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.
|
||||
Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu,
|
||||
consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra
|
||||
quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet.
|
||||
'''.format(_State.label_count, str(datetime.datetime.now())))
|
||||
_State.label_count += 1
|
||||
|
||||
dock_widget = QtAds.CDockWidget("Label {}".format(_State.label_count))
|
||||
dock_widget.setWidget(label)
|
||||
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_calendar_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
'''
|
||||
Create calendar dock widget
|
||||
|
||||
Parameters
|
||||
----------
|
||||
view_menu : QMenu
|
||||
|
||||
Returns
|
||||
-------
|
||||
value : QtAds.CDockWidget
|
||||
'''
|
||||
widget = QCalendarWidget()
|
||||
|
||||
dock_widget = QtAds.CDockWidget("Calendar {}".format(_State.calendar_count))
|
||||
_State.calendar_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
dock_widget.setToggleViewActionMode(QtAds.CDockWidget.ActionModeShow)
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_file_system_tree_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
'''
|
||||
Create file system tree dock widget
|
||||
|
||||
Parameters
|
||||
----------
|
||||
view_menu : QMenu
|
||||
|
||||
Returns
|
||||
-------
|
||||
value : QtAds.CDockWidget
|
||||
'''
|
||||
widget = QTreeView()
|
||||
widget.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
m = QFileSystemModel(widget)
|
||||
m.setRootPath(QDir.currentPath())
|
||||
widget.setModel(m)
|
||||
|
||||
dock_widget = QtAds.CDockWidget("Filesystem {}".format(_State.file_system_count))
|
||||
_State.file_system_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
save_perspective_action: QAction
|
||||
perspective_list_action: QWidgetAction
|
||||
perspective_combo_box: QComboBox
|
||||
dock_manager: QtAds.CDockManager
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.save_perspective_action = None
|
||||
self.perspective_list_action = None
|
||||
self.perspective_combo_box = None
|
||||
self.dock_manager = None
|
||||
|
||||
self.setup_ui()
|
||||
|
||||
self.dock_manager = QtAds.CDockManager(self)
|
||||
self.perspective_combo_box.activated[str].connect(self.dock_manager.openPerspective)
|
||||
self.create_content()
|
||||
self.resize(800, 600)
|
||||
self.restore_state()
|
||||
self.restore_perspectives()
|
||||
|
||||
def setup_ui(self):
|
||||
self.setObjectName("MainWindow")
|
||||
self.resize(400, 300)
|
||||
self.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks)
|
||||
self.centralWidget = QtWidgets.QWidget(self)
|
||||
self.centralWidget.setObjectName("centralWidget")
|
||||
self.setCentralWidget(self.centralWidget)
|
||||
self.status_bar = QtWidgets.QStatusBar(self)
|
||||
self.status_bar.setObjectName("statusBar")
|
||||
self.setStatusBar(self.status_bar)
|
||||
self.menu_bar = QtWidgets.QMenuBar(self)
|
||||
self.menu_bar.setGeometry(QRect(0, 0, 400, 21))
|
||||
self.menu_bar.setObjectName("menuBar")
|
||||
self.menu_file = QtWidgets.QMenu(self.menu_bar)
|
||||
self.menu_file.setObjectName("menuFile")
|
||||
self.menu_view = QtWidgets.QMenu(self.menu_bar)
|
||||
self.menu_view.setObjectName("menuView")
|
||||
self.menu_about = QtWidgets.QMenu(self.menu_bar)
|
||||
self.menu_about.setObjectName("menuAbout")
|
||||
self.setMenuBar(self.menu_bar)
|
||||
self.tool_bar = QtWidgets.QToolBar(self)
|
||||
self.tool_bar.setObjectName("toolBar")
|
||||
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
|
||||
self.action_exit = QtWidgets.QAction(self)
|
||||
self.action_exit.setObjectName("actionExit")
|
||||
self.action_save_state = QtWidgets.QAction(self)
|
||||
self.action_save_state.setObjectName("actionSaveState")
|
||||
self.action_save_state.triggered.connect(self.saveState)
|
||||
|
||||
self.action_restore_state = QtWidgets.QAction(self)
|
||||
self.action_restore_state.setObjectName("actionRestoreState")
|
||||
self.action_restore_state.triggered.connect(self.restore_state)
|
||||
|
||||
self.menu_file.addAction(self.action_exit)
|
||||
self.menu_file.addAction(self.action_save_state)
|
||||
self.menu_file.addAction(self.action_restore_state)
|
||||
self.menu_bar.addAction(self.menu_file.menuAction())
|
||||
self.menu_bar.addAction(self.menu_view.menuAction())
|
||||
self.menu_bar.addAction(self.menu_about.menuAction())
|
||||
|
||||
self.setWindowTitle("MainWindow")
|
||||
self.menu_file.setTitle("File")
|
||||
self.menu_view.setTitle("View")
|
||||
self.menu_about.setTitle("About")
|
||||
self.tool_bar.setWindowTitle("toolBar")
|
||||
self.action_exit.setText("Exit")
|
||||
self.action_save_state.setText("Save State")
|
||||
self.action_restore_state.setText("Restore State")
|
||||
self.create_actions()
|
||||
|
||||
def create_actions(self):
|
||||
'''
|
||||
Creates the toolbar actions
|
||||
'''
|
||||
self.tool_bar.addAction(self.action_save_state)
|
||||
self.action_save_state.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton))
|
||||
self.tool_bar.addAction(self.action_restore_state)
|
||||
self.action_restore_state.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
|
||||
self.save_perspective_action = QAction("Save Perspective", self)
|
||||
self.save_perspective_action.triggered.connect(self.save_perspective)
|
||||
|
||||
self.perspective_list_action = QWidgetAction(self)
|
||||
self.perspective_combo_box = QComboBox(self)
|
||||
self.perspective_combo_box.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
||||
self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
||||
self.perspective_list_action.setDefaultWidget(self.perspective_combo_box)
|
||||
self.tool_bar.addSeparator()
|
||||
self.tool_bar.addAction(self.perspective_list_action)
|
||||
self.tool_bar.addAction(self.save_perspective_action)
|
||||
|
||||
def create_content(self):
|
||||
'''
|
||||
Fill the dock manager with dock widgets
|
||||
'''
|
||||
# Test container docking
|
||||
view_menu = self.menu_view
|
||||
dock_widget = create_calendar_dock_widget(view_menu)
|
||||
dock_widget.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
|
||||
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
|
||||
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, create_long_text_label_dock_widget(view_menu))
|
||||
file_system_widget = create_file_system_tree_dock_widget(view_menu)
|
||||
tool_bar = file_system_widget.createDefaultToolBar()
|
||||
tool_bar.addAction(self.action_save_state)
|
||||
tool_bar.addAction(self.action_restore_state)
|
||||
self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea, file_system_widget)
|
||||
file_system_widget = create_file_system_tree_dock_widget(view_menu)
|
||||
tool_bar = file_system_widget.createDefaultToolBar()
|
||||
tool_bar.addAction(self.action_save_state)
|
||||
tool_bar.addAction(self.action_restore_state)
|
||||
file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable, False)
|
||||
top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget)
|
||||
dock_widget = create_calendar_dock_widget(view_menu)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
|
||||
dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
|
||||
self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, top_dock_area)
|
||||
|
||||
# Test dock area docking
|
||||
right_dock_area = self.dock_manager.addDockWidget(
|
||||
QtAds.RightDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), top_dock_area)
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.TopDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
|
||||
bottom_dock_area = self.dock_manager.addDockWidget(
|
||||
QtAds.BottomDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.RightDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.CenterDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), bottom_dock_area)
|
||||
|
||||
def save_state(self):
|
||||
'''
|
||||
Saves the dock manager state and the main window geometry
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
settings.setValue("mainWindow/Geometry", self.saveGeometry())
|
||||
settings.setValue("mainWindow/State", self.saveState())
|
||||
settings.setValue("mainWindow/DockingState", self.dock_manager.saveState())
|
||||
|
||||
def save_perspectives(self):
|
||||
'''
|
||||
Save the list of perspectives
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
self.dock_manager.savePerspectives(settings)
|
||||
|
||||
def restore_state(self):
|
||||
'''
|
||||
Restores the dock manager state
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
geom = settings.value("mainWindow/Geometry")
|
||||
if geom is not None:
|
||||
self.restoreGeometry(geom)
|
||||
|
||||
state = settings.value("mainWindow/State")
|
||||
if state is not None:
|
||||
self.restoreState(state)
|
||||
|
||||
state = settings.value("mainWindow/DockingState")
|
||||
if state is not None:
|
||||
self.dock_manager.restore_state(state)
|
||||
|
||||
def restore_perspectives(self):
|
||||
'''
|
||||
Restore the perspective listo of the dock manager
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
self.dock_manager.loadPerspectives(settings)
|
||||
self.perspective_combo_box.clear()
|
||||
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
|
||||
|
||||
def save_perspective(self):
|
||||
perspective_name, ok = QInputDialog.getText(self, 'Save perspective', 'Enter unique name:')
|
||||
if ok and perspective_name:
|
||||
self.dock_manager.addPerspective(perspective_name)
|
||||
_ = QSignalBlocker(self.perspective_combo_box)
|
||||
self.perspective_combo_box.clear()
|
||||
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
|
||||
self.perspective_combo_box.setCurrentText(perspective_name)
|
||||
self.save_perspectives()
|
||||
|
||||
|
||||
def main(app_):
|
||||
main_window = MainWindow()
|
||||
main_window.show()
|
||||
state = main_window.dock_manager.saveState()
|
||||
# print('This is what the saved state looks like in XML:')
|
||||
# print(str(state, 'utf-8'))
|
||||
# print()
|
||||
# main_window.dock_manager.restore_state(state)
|
||||
return main_window
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# logging.basicConfig(level='DEBUG')
|
||||
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
|
||||
QGuiApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
app = QtWidgets.QApplication([])
|
||||
window = main(app)
|
||||
window.show()
|
||||
app.exec_()
|
||||
@@ -73,6 +73,8 @@
|
||||
#include "DockAreaTitleBar.h"
|
||||
#include "DockAreaTabBar.h"
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockComponentsFactory.h"
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
@@ -142,6 +144,25 @@ static QIcon svgIcon(const QString& File)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
class CCustomComponentsFactory : public ads::CDockComponentsFactory
|
||||
{
|
||||
public:
|
||||
using Super = ads::CDockComponentsFactory;
|
||||
ads::CDockAreaTitleBar* createDockAreaTitleBar(ads::CDockAreaWidget* DockArea) const override
|
||||
{
|
||||
auto TitleBar = new ads::CDockAreaTitleBar(DockArea);
|
||||
auto CustomButton = new QToolButton(DockArea);
|
||||
CustomButton->setToolTip(QObject::tr("Help"));
|
||||
CustomButton->setIcon(svgIcon(":/adsdemo/images/help_outline.svg"));
|
||||
CustomButton->setAutoRaise(true);
|
||||
int Index = TitleBar->indexOf(TitleBar->button(ads::TitleBarButtonTabsMenu));
|
||||
TitleBar->insertWidget(Index + 1, CustomButton);
|
||||
return TitleBar;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
|
||||
{
|
||||
@@ -202,28 +223,46 @@ static ads::CDockWidget* createEditorWidget(QMenu* ViewMenu)
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
/**
|
||||
* Custom QTableWidget with a minimum size hint to test CDockWidget
|
||||
* setMinimumSizeHintMode() function of CDockWidget
|
||||
*/
|
||||
class CMinSizeTableWidget : public QTableWidget
|
||||
{
|
||||
public:
|
||||
using QTableWidget::QTableWidget;
|
||||
virtual QSize minimumSizeHint() const override
|
||||
{
|
||||
return QSize(300, 100);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
static ads::CDockWidget* createTableWidget(QMenu* ViewMenu)
|
||||
{
|
||||
static int TableCount = 0;
|
||||
QTableWidget* w = new QTableWidget();
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Table %1").arg(TableCount++));
|
||||
static int colCount = 5;
|
||||
static int rowCount = 30;
|
||||
w->setColumnCount(colCount);
|
||||
w->setRowCount(rowCount);
|
||||
for (int col = 0; col < colCount; ++col)
|
||||
{
|
||||
w->setHorizontalHeaderItem(col, new QTableWidgetItem(QString("Col %1").arg(col+1)));
|
||||
for (int row = 0; row < rowCount; ++row)
|
||||
{
|
||||
w->setItem(row, col, new QTableWidgetItem(QString("T %1-%2").arg(row + 1).arg(col+1)));
|
||||
}
|
||||
}
|
||||
DockWidget->setWidget(w);
|
||||
DockWidget->setIcon(svgIcon(":/adsdemo/images/grid_on.svg"));
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
static int TableCount = 0;
|
||||
auto w = new CMinSizeTableWidget();
|
||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Table %1").arg(TableCount++));
|
||||
static int colCount = 5;
|
||||
static int rowCount = 30;
|
||||
w->setColumnCount(colCount);
|
||||
w->setRowCount(rowCount);
|
||||
for (int col = 0; col < colCount; ++col)
|
||||
{
|
||||
w->setHorizontalHeaderItem(col, new QTableWidgetItem(QString("Col %1").arg(col+1)));
|
||||
for (int row = 0; row < rowCount; ++row)
|
||||
{
|
||||
w->setItem(row, col, new QTableWidgetItem(QString("T %1-%2").arg(row + 1).arg(col+1)));
|
||||
}
|
||||
}
|
||||
DockWidget->setWidget(w);
|
||||
DockWidget->setIcon(svgIcon(":/adsdemo/images/grid_on.svg"));
|
||||
DockWidget->setMinimumSizeHintMode(ads::CDockWidget::MinimumSizeHintFromContent);
|
||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||
return DockWidget;
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +348,8 @@ void MainWindowPrivate::createContent()
|
||||
auto ToolBar = FileSystemWidget->createDefaultToolBar();
|
||||
ToolBar->addAction(ui.actionSaveState);
|
||||
ToolBar->addAction(ui.actionRestoreState);
|
||||
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetFloatable, false);
|
||||
appendFeaturStringToWindowTitle(FileSystemWidget);
|
||||
DockManager->addDockWidget(ads::BottomDockWidgetArea, FileSystemWidget);
|
||||
|
||||
FileSystemWidget = createFileSystemTreeDockWidget(ViewMenu);
|
||||
@@ -318,9 +359,13 @@ void MainWindowPrivate::createContent()
|
||||
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
|
||||
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetFloatable, false);
|
||||
appendFeaturStringToWindowTitle(FileSystemWidget);
|
||||
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
||||
|
||||
// We create a calender widget and clear all flags to prevent the dock area
|
||||
// Test custom factory - we inject a help button into the title bar
|
||||
ads::CDockComponentsFactory::setFactory(new CCustomComponentsFactory());
|
||||
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
||||
ads::CDockComponentsFactory::resetDefaultFactory();
|
||||
|
||||
// We create a calendar widget and clear all flags to prevent the dock area
|
||||
// from closing
|
||||
DockWidget = createCalendarDockWidget(ViewMenu);
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
|
||||
@@ -458,9 +503,9 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
||||
// a QToolButton instead of a QPushButton
|
||||
// CDockManager::setConfigFlags(CDockManager::configFlags() | CDockManager::TabCloseButtonIsToolButton);
|
||||
|
||||
// comment the following line if you want to use opaque undocking and
|
||||
// uncomment the following line if you want to use opaque undocking and
|
||||
// opaque splitter resizing
|
||||
CDockManager::setConfigFlags(CDockManager::DefaultNonOpaqueConfig);
|
||||
// CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
|
||||
|
||||
// uncomment the following line if you want a fixed tab width that does
|
||||
// not change if the visibility of the close button changes
|
||||
@@ -481,6 +526,12 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
||||
// uncomment the following line if you want to show tabs menu button on DockArea's title bar only when there are more than one tab and at least of them has elided title
|
||||
//CDockManager::setConfigFlag(CDockManager::DockAreaDynamicTabsMenuButtonVisibility, true);
|
||||
|
||||
// uncomment the following line if you want floating container to always show application title instead of active dock widget's title
|
||||
//CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetTitle, false);
|
||||
|
||||
// uncomment the following line if you want floating container to show active dock widget's icon instead of always showing application icon
|
||||
//CDockManager::setConfigFlag(CDockManager::FloatingContainerHasWidgetIcon, true);
|
||||
|
||||
// Now create the dock manager and its content
|
||||
d->DockManager = new CDockManager(this);
|
||||
|
||||
|
||||
505
demo/demo.py
Normal file
505
demo/demo.py
Normal file
@@ -0,0 +1,505 @@
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import (QCoreApplication, QDir, Qt, QSettings, QSignalBlocker,
|
||||
QRect, QPoint, qDebug, qInstallMessageHandler,
|
||||
QtDebugMsg, QtInfoMsg, QtWarningMsg,
|
||||
QtCriticalMsg, QtFatalMsg)
|
||||
from PyQt5.QtGui import (QGuiApplication, QIcon, QCloseEvent)
|
||||
from PyQt5.QtWidgets import (QCalendarWidget, QFileSystemModel, QFrame, QLabel,
|
||||
QMenu, QTreeView, QAction, QWidgetAction,
|
||||
QComboBox, QStyle, QSizePolicy, QInputDialog, QMenu,
|
||||
QToolButton, QWidget, QPlainTextEdit,
|
||||
QTableWidget, QTableWidgetItem, QApplication,
|
||||
QMessageBox)
|
||||
try:
|
||||
from PyQt5.QAxContainer import QAxWidget
|
||||
except ImportError:
|
||||
ACTIVEX_AVAILABLE = False
|
||||
else:
|
||||
ACTIVEX_AVAILABLE = True
|
||||
|
||||
from PyQtAds import QtAds
|
||||
|
||||
import rc # pyrcc5 demo.qrc -o rc.py
|
||||
|
||||
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
|
||||
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
|
||||
|
||||
|
||||
class _State:
|
||||
label_count = 0
|
||||
calendar_count = 0
|
||||
file_system_count = 0
|
||||
editor_count = 0
|
||||
table_count = 0
|
||||
activex_count = 0
|
||||
|
||||
|
||||
def features_string(dock_widget: QtAds.CDockWidget) -> str:
|
||||
'''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+'''
|
||||
|
||||
f = dock_widget.features()
|
||||
closable = f & QtAds.CDockWidget.DockWidgetClosable
|
||||
movable = f & QtAds.CDockWidget.DockWidgetMovable
|
||||
floatable = f &QtAds.CDockWidget.DockWidgetFloatable
|
||||
|
||||
return "c{} m{} f{}".format("+" if closable else "-",
|
||||
"+" if movable else "-",
|
||||
"+" if floatable else "-")
|
||||
|
||||
|
||||
def append_feature_string_to_window_title(dock_widget: QtAds.CDockWidget):
|
||||
'''Appends the string returned by features_string() to the window title of
|
||||
the given DockWidget'''
|
||||
|
||||
dock_widget.setWindowTitle(dock_widget.windowTitle() + " ({})".format(features_string(dock_widget)))
|
||||
|
||||
|
||||
def svg_icon(filename: str):
|
||||
'''Helper function to create an SVG icon'''
|
||||
# This is a workaround, because because in item views SVG icons are not
|
||||
# properly scaled an look blurry or pixelate
|
||||
icon = QIcon(filename)
|
||||
icon.addPixmap(icon.pixmap(92))
|
||||
return icon
|
||||
|
||||
|
||||
def create_long_text_label_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
label = QLabel()
|
||||
label.setWordWrap(True)
|
||||
label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||
label.setText('''\
|
||||
Label {} {} - Lorem ipsum dolor sit amet, consectetuer
|
||||
adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum
|
||||
sociis natoque penatibus et magnis dis parturient montes, nascetur
|
||||
ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium
|
||||
quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla
|
||||
vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut,
|
||||
imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis
|
||||
pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.
|
||||
Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu,
|
||||
consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra
|
||||
quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet.
|
||||
'''.format(_State.label_count, datetime.datetime.now().strftime("%H:%M:%S:%f")))
|
||||
dock_widget = QtAds.CDockWidget("Label {}".format(_State.label_count))
|
||||
_State.label_count += 1
|
||||
dock_widget.setWidget(label)
|
||||
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_calendar_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
widget = QCalendarWidget()
|
||||
|
||||
dock_widget = QtAds.CDockWidget("Calendar {}".format(_State.calendar_count))
|
||||
_State.calendar_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
dock_widget.setToggleViewActionMode(QtAds.CDockWidget.ActionModeShow)
|
||||
dock_widget.setIcon(svg_icon(":/adsdemo/images/date_range.svg"))
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_file_system_tree_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
widget = QTreeView()
|
||||
widget.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
m = QFileSystemModel(widget)
|
||||
m.setRootPath(QDir.currentPath())
|
||||
widget.setModel(m)
|
||||
|
||||
dock_widget = QtAds.CDockWidget("Filesystem {}".format(_State.file_system_count))
|
||||
_State.file_system_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_editor_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
widget = QPlainTextEdit()
|
||||
widget.setPlaceholderText("This is an editor. If you close the editor, it will be "
|
||||
"deleted. Enter your text here.")
|
||||
widget.setStyleSheet("border: none")
|
||||
dock_widget = QtAds.CDockWidget("Editor {}".format(_State.editor_count))
|
||||
_State.editor_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
dock_widget.setIcon(svg_icon(":/adsdemo/images/edit.svg"))
|
||||
dock_widget.setFeature(QtAds.CDockWidget.CustomCloseHandling, True)
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
|
||||
options_menu = QMenu(dock_widget)
|
||||
options_menu.setTitle("Options")
|
||||
options_menu.setToolTip(options_menu.title())
|
||||
options_menu.setIcon(svg_icon(":/adsdemo/images/custom-menu-button.svg"))
|
||||
menu_action = options_menu.menuAction()
|
||||
# The object name of the action will be set for the QToolButton that
|
||||
# is created in the dock area title bar. You can use this name for CSS
|
||||
# styling
|
||||
menu_action.setObjectName("options_menu")
|
||||
dock_widget.setTitleBarActions([options_menu.menuAction()])
|
||||
a = options_menu.addAction("Clear Editor")
|
||||
a.triggered.connect(widget.clear)
|
||||
|
||||
return dock_widget
|
||||
|
||||
|
||||
def create_table_widget(view_menu: QMenu) -> QtAds.CDockWidget:
|
||||
widget = QTableWidget()
|
||||
dock_widget = QtAds.CDockWidget("Table {}".format(_State.table_count))
|
||||
_State.table_count += 1
|
||||
COLCOUNT = 5
|
||||
ROWCOUNT = 30
|
||||
widget.setColumnCount(COLCOUNT)
|
||||
widget.setRowCount(ROWCOUNT)
|
||||
for col in range(ROWCOUNT):
|
||||
widget.setHorizontalHeaderItem(col, QTableWidgetItem("Col {}".format(col+1)))
|
||||
for row in range(ROWCOUNT):
|
||||
widget.setItem(row, col, QTableWidgetItem("T {:}-{:}".format(row+1, col+1)))
|
||||
|
||||
dock_widget.setWidget(widget)
|
||||
dock_widget.setIcon(svg_icon(":/adsdemo/images/grid_on.svg"))
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
if ACTIVEX_AVAILABLE:
|
||||
def create_activex_widget(view_menu: QMenu, parent: QWidget = None) -> QtAds.CDockWidget:
|
||||
widget = QAxWidget("{6bf52a52-394a-11d3-b153-00c04f79faa6}", parent)
|
||||
dock_widget = QtAds.CDockWidget("Active X {}".format(_State.activex_count))
|
||||
_State.activex_count += 1
|
||||
dock_widget.setWidget(widget)
|
||||
view_menu.addAction(dock_widget.toggleViewAction())
|
||||
return dock_widget
|
||||
|
||||
|
||||
class CustomComponentsFactory(QtAds.CDockComponentsFactory):
|
||||
|
||||
def createDockAreaTitleBar(self, dock_area: QtAds.CDockAreaWidget) -> QtAds.CDockAreaTitleBar:
|
||||
title_bar = QtAds.CDockAreaTitleBar(dock_area)
|
||||
custom_button = QToolButton(dock_area)
|
||||
custom_button.setToolTip("Help")
|
||||
custom_button.setIcon(svg_icon(":/adsdemo/images/help_outline.svg"))
|
||||
custom_button.setAutoRaise(True)
|
||||
index = title_bar.indexOf(title_bar.button(QtAds.TitleBarButtonTabsMenu))
|
||||
title_bar.insertWidget(index + 1, custom_button)
|
||||
return title_bar
|
||||
|
||||
|
||||
|
||||
class MainWindow(MainWindowUI, MainWindowBase):
|
||||
save_perspective_action: QAction
|
||||
perspective_list_action: QWidgetAction
|
||||
perspective_combo_box: QComboBox
|
||||
dock_manager: QtAds.CDockManager
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.save_perspective_action = None
|
||||
self.perspective_list_action = None
|
||||
self.perspective_combo_box = None
|
||||
self.dock_manager = None
|
||||
|
||||
self.setupUi(self)
|
||||
self.create_actions()
|
||||
|
||||
# uncomment the following line if the tab close button should be
|
||||
# a QToolButton instead of a QPushButton
|
||||
# QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.configFlags() | QtAds.CDockManager.TabCloseButtonIsToolButton)
|
||||
|
||||
# uncomment the following line if you want a fixed tab width that does
|
||||
# not change if the visibility of the close button changes
|
||||
# QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.RetainTabSizeWhenCloseButtonHidden, True)
|
||||
|
||||
# uncomment the follwing line if you want to use non opaque undocking and splitter
|
||||
# movements
|
||||
# QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DefaultNonOpaqueConfig)
|
||||
|
||||
# Now create the dock manager and its content
|
||||
self.dock_manager = QtAds.CDockManager(self)
|
||||
|
||||
# Uncomment the following line to have the old style where the dock
|
||||
# area close button closes the active tab
|
||||
# QtAds.CDockManager.setConfigFlags(QtAds.CDockManager.DockAreaHasCloseButton
|
||||
# | QtAds.CDockManager.DockAreaCloseButtonClosesTab)
|
||||
self.perspective_combo_box.activated[str].connect(self.dock_manager.openPerspective)
|
||||
|
||||
self.create_content()
|
||||
# Default window geometry - center on screen
|
||||
self.resize(1280, 720)
|
||||
self.setGeometry(QStyle.alignedRect(
|
||||
Qt.LeftToRight, Qt.AlignCenter, self.frameSize(),
|
||||
QGuiApplication.primaryScreen().availableGeometry()))
|
||||
|
||||
# self.restore_state()
|
||||
self.restore_perspectives()
|
||||
|
||||
def create_content(self):
|
||||
# Test container docking
|
||||
view_menu = self.menuView
|
||||
dock_widget = create_calendar_dock_widget(view_menu)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable, False)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable, False)
|
||||
special_dock_area = self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
|
||||
|
||||
# For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified):
|
||||
special_dock_area.setAllowedAreas(QtAds.OuterDockAreas)
|
||||
# special_dock_area.setAllowedAreas(QtAds.LeftDockWidgetArea | QtAds.RightDockWidgetArea) # just for testing
|
||||
|
||||
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, create_long_text_label_dock_widget(view_menu))
|
||||
file_system_widget = create_file_system_tree_dock_widget(view_menu)
|
||||
tool_bar = file_system_widget.createDefaultToolBar()
|
||||
tool_bar.addAction(self.actionSaveState)
|
||||
tool_bar.addAction(self.actionRestoreState)
|
||||
file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable, False)
|
||||
append_feature_string_to_window_title(file_system_widget)
|
||||
self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea, file_system_widget)
|
||||
|
||||
file_system_widget = create_file_system_tree_dock_widget(view_menu)
|
||||
tool_bar = file_system_widget.createDefaultToolBar()
|
||||
tool_bar.addAction(self.actionSaveState)
|
||||
tool_bar.addAction(self.actionRestoreState)
|
||||
file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable, False)
|
||||
file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable, False)
|
||||
append_feature_string_to_window_title(file_system_widget)
|
||||
|
||||
# Test custom factory - we inject a help button into the title bar
|
||||
self.factory = CustomComponentsFactory()
|
||||
QtAds.CDockComponentsFactory.setFactory(self.factory)
|
||||
top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget)
|
||||
QtAds.CDockComponentsFactory.resetDefaultFactory()
|
||||
|
||||
|
||||
# We create a calendar widget and clear all flags to prevent the dock area
|
||||
# from closing
|
||||
dock_widget = create_calendar_dock_widget(view_menu)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable, False)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetFloatable, False)
|
||||
dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
|
||||
dock_area = self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, top_dock_area)
|
||||
|
||||
# Now we add a custom button to the dock area title bar that will create
|
||||
# new editor widgets when clicked
|
||||
custom_button = QToolButton(dock_area)
|
||||
custom_button.setToolTip("Create Editor")
|
||||
custom_button.setIcon(svg_icon(":/adsdemo/images/plus.svg"))
|
||||
custom_button.setAutoRaise(True)
|
||||
title_bar = dock_area.titleBar()
|
||||
index = title_bar.indexOf(title_bar.tabBar())
|
||||
title_bar.insertWidget(index + 1, custom_button)
|
||||
def on_button_clicked():
|
||||
dock_widget = create_editor_widget(self.menuView)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
|
||||
self.dock_manager.addDockWidgetTabToArea(dock_widget, dock_area)
|
||||
dock_widget.closeRequested.connect(self.on_editor_close_requested)
|
||||
custom_button.clicked.connect(on_button_clicked)
|
||||
|
||||
# Test dock area docking
|
||||
right_dock_area = self.dock_manager.addDockWidget(
|
||||
QtAds.RightDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), top_dock_area)
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.TopDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
|
||||
bottom_dock_area = self.dock_manager.addDockWidget(
|
||||
QtAds.BottomDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.CenterDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), right_dock_area)
|
||||
self.dock_manager.addDockWidget(
|
||||
QtAds.CenterDockWidgetArea,
|
||||
create_long_text_label_dock_widget(view_menu), bottom_dock_area)
|
||||
|
||||
action = self.menuView.addAction("Set {} floating".format(dock_widget.windowTitle()))
|
||||
action.triggered.connect(dock_widget.setFloating)
|
||||
|
||||
if ACTIVEX_AVAILABLE:
|
||||
flags = self.dock_manager.configFlags()
|
||||
if flags & QtAds.CDockManager.OpaqueUndocking:
|
||||
self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea,
|
||||
create_activex_widget(view_menu), right_dock_area)
|
||||
|
||||
for dock_widget in self.dock_manager.dockWidgetsMap().values():
|
||||
dock_widget.viewToggled.connect(self.on_view_toggled)
|
||||
dock_widget.visibilityChanged.connect(self.on_view_visibility_changed)
|
||||
|
||||
def create_actions(self):
|
||||
self.toolBar.addAction(self.actionSaveState)
|
||||
self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
self.actionSaveState.setIcon(svg_icon(":/adsdemo/images/save.svg"))
|
||||
self.toolBar.addAction(self.actionRestoreState)
|
||||
self.actionRestoreState.setIcon(svg_icon(":/adsdemo/images/restore.svg"))
|
||||
|
||||
self.save_perspective_action = QAction("Create Perspective", self)
|
||||
self.save_perspective_action.setIcon(svg_icon(":/adsdemo/images/picture_in_picture.svg"))
|
||||
self.save_perspective_action.triggered.connect(self.save_perspective)
|
||||
self.perspective_list_action = QWidgetAction(self)
|
||||
self.perspective_combo_box = QComboBox(self)
|
||||
self.perspective_combo_box.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
||||
self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
||||
self.perspective_list_action.setDefaultWidget(self.perspective_combo_box)
|
||||
self.toolBar.addSeparator()
|
||||
self.toolBar.addAction(self.perspective_list_action)
|
||||
self.toolBar.addAction(self.save_perspective_action)
|
||||
|
||||
a = self.toolBar.addAction("Create Editor")
|
||||
a.setToolTip("Creates floating dynamic dockable editor windows that are deleted on close")
|
||||
a.setIcon(svg_icon(":/adsdemo/images/note_add.svg"))
|
||||
a.triggered.connect(self.create_editor)
|
||||
|
||||
a = self.toolBar.addAction("Create Table")
|
||||
a.setToolTip("Creates floating dynamic dockable table with millions of entries")
|
||||
a.setIcon(svg_icon(":/adsdemo/images/grid_on.svg"))
|
||||
a.triggered.connect(self.create_table)
|
||||
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
self.save_state()
|
||||
super().closeEvent(event)
|
||||
|
||||
def on_action_save_state_triggered(state: bool):
|
||||
qDebug("MainWindow::on_action_save_state_triggered")
|
||||
self.save_state()
|
||||
|
||||
def on_action_restore_state_triggered(state: bool):
|
||||
qDebug("MainWindow::on_action_restore_state_triggered")
|
||||
self.restore_state()
|
||||
|
||||
def save_perspective(self):
|
||||
perspective_name, ok = QInputDialog.getText(self, "Save perspective",
|
||||
"Enter unique name:")
|
||||
|
||||
if ok and perspective_name:
|
||||
self.dock_manager.addPerspective(perspective_name)
|
||||
_ = QSignalBlocker(self.perspective_combo_box)
|
||||
self.perspective_combo_box.clear()
|
||||
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
|
||||
self.perspective_combo_box.setCurrentText(perspective_name)
|
||||
|
||||
self.save_perspectives()
|
||||
|
||||
def on_view_toggled(self, open: bool):
|
||||
dock_widget = self.sender()
|
||||
if dock_widget is None:
|
||||
return
|
||||
|
||||
qDebug("{} view_toggled({})".format(dock_widget.objectName(), open))
|
||||
|
||||
def on_view_visibility_changed(self, visible: bool):
|
||||
dock_widget = self.sender()
|
||||
if dock_widget is None:
|
||||
return
|
||||
|
||||
qDebug("{} visibility_changed({})".format(dock_widget.objectName(), visible))
|
||||
|
||||
def create_editor(self):
|
||||
dock_widget = create_editor_widget(self.menuView)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
|
||||
floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
|
||||
floating_widget.move(QPoint(20, 20))
|
||||
dock_widget.closeRequested.connect(self.on_editor_close_requested)
|
||||
|
||||
def on_editor_close_requested(self):
|
||||
dock_widget = self.sender()
|
||||
result = QMessageBox.question(self, "Close Editor",
|
||||
"Editor {} contains unsaved changes? Would you like to close it?".format(dock_widget.windowTitle()))
|
||||
if result == QMessageBox.Yes:
|
||||
dock_widget.closeDockWidget()
|
||||
|
||||
def create_table(self):
|
||||
dock_widget = create_table_widget(self.menuView)
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
|
||||
floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
|
||||
floating_widget.move(QPoint(40, 40))
|
||||
|
||||
def save_state(self):
|
||||
'''
|
||||
Saves the dock manager state and the main window geometry
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
settings.setValue("mainWindow/Geometry", self.saveGeometry())
|
||||
settings.setValue("mainWindow/State", self.saveState())
|
||||
settings.setValue("mainWindow/DockingState", self.dock_manager.saveState())
|
||||
|
||||
def restore_state(self):
|
||||
'''
|
||||
Restores the dock manager state
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
geom = settings.value("mainWindow/Geometry")
|
||||
if geom is not None:
|
||||
self.restoreGeometry(geom)
|
||||
|
||||
state = settings.value("mainWindow/State")
|
||||
if state is not None:
|
||||
self.restoreState(state)
|
||||
|
||||
state = settings.value("mainWindow/DockingState")
|
||||
if state is not None:
|
||||
self.dock_manager.restore_state(state)
|
||||
|
||||
def save_perspectives(self):
|
||||
'''
|
||||
Save the list of perspectives
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
self.dock_manager.savePerspectives(settings)
|
||||
|
||||
def restore_perspectives(self):
|
||||
'''
|
||||
Restore the perspective listo of the dock manager
|
||||
'''
|
||||
settings = QSettings("Settings.ini", QSettings.IniFormat)
|
||||
self.dock_manager.loadPerspectives(settings)
|
||||
self.perspective_combo_box.clear()
|
||||
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
|
||||
|
||||
def save_perspective(self):
|
||||
perspective_name, ok = QInputDialog.getText(self, 'Save perspective', 'Enter unique name:')
|
||||
if ok and perspective_name:
|
||||
self.dock_manager.addPerspective(perspective_name)
|
||||
_ = QSignalBlocker(self.perspective_combo_box)
|
||||
self.perspective_combo_box.clear()
|
||||
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
|
||||
self.perspective_combo_box.setCurrentText(perspective_name)
|
||||
self.save_perspectives()
|
||||
|
||||
|
||||
def my_message_output(type, context, msg):
|
||||
if type == QtDebugMsg:
|
||||
print("Debug: {} ({}:{}, {})".format(msg, context.file, context.line, context.function))
|
||||
elif type == QtInfoMsg:
|
||||
print("Info: {} ({}:{}, {})".format(msg, context.file, context.line, context.function))
|
||||
elif type == QtWarningMsg:
|
||||
print("Warning: {} ({}:{}, {})".format(msg, context.file, context.line, context.function))
|
||||
elif type == QtCriticalMsg:
|
||||
print("Critical: {} ({}:{}, {})".format(msg, context.file, context.line, context.function))
|
||||
elif type == QtFatalMsg:
|
||||
print("Fatal: {} ({}:{}, {})".format(msg, context.file, context.line, context.function))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
|
||||
QGuiApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
||||
app = QApplication(sys.argv)
|
||||
app.setQuitOnLastWindowClosed(True)
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), "app.css"), "r") as style_sheet_file:
|
||||
app.setStyleSheet(style_sheet_file.read())
|
||||
|
||||
qInstallMessageHandler(my_message_output)
|
||||
qDebug("Message handler test")
|
||||
|
||||
mw = MainWindow()
|
||||
mw.show()
|
||||
app.exec_()
|
||||
@@ -12,5 +12,6 @@
|
||||
<file>images/custom-menu-button.svg</file>
|
||||
<file>app.css</file>
|
||||
<file>images/plus.svg</file>
|
||||
<file>images/help_outline.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
6
demo/images/help_outline.svg
Normal file
6
demo/images/help_outline.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,1024,1024">
|
||||
<desc>help_outline icon - Licensed under Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - Created with Iconfu.com - Derivative work of Material icons (Copyright Google Inc.)</desc>
|
||||
<g fill="#03b8e5" fill-rule="nonzero" style="mix-blend-mode: normal">
|
||||
<path d="M938.67,512c0,235.52 -191.15,426.67 -426.67,426.67c-235.52,0 -426.67,-191.15 -426.67,-426.67c0,-235.52 191.15,-426.67 426.67,-426.67c235.52,0 426.67,191.15 426.67,426.67zM853.33,512c0,-188.16 -153.17,-341.33 -341.33,-341.33c-188.16,0 -341.33,153.17 -341.33,341.33c0,188.16 153.17,341.33 341.33,341.33c188.16,0 341.33,-153.17 341.33,-341.33zM682.67,426.67c0,106.67 -128,117.33 -128,213.33h-85.34c0,-138.67 128,-128 128,-213.33c0,-46.93 -38.4,-85.34 -85.33,-85.34c-46.93,0 -85.33,38.41 -85.33,85.34h-85.34c0,-94.29 76.38,-170.67 170.67,-170.67c94.29,0 170.67,76.38 170.67,170.67zM469.33,682.67h85.34v85.33h-85.34z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
doc/qmix_elements.png
Normal file
BIN
doc/qmix_elements.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 539 KiB |
BIN
doc/qt_design_studio.png
Normal file
BIN
doc/qt_design_studio.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 157 KiB |
52
example/example.py
Normal file
52
example/example.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QApplication, QLabel
|
||||
|
||||
from PyQtAds import QtAds
|
||||
|
||||
UI_FILE = os.path.join(os.path.dirname(__file__), 'MainWindow.ui')
|
||||
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
|
||||
|
||||
|
||||
class MainWindow(MainWindowUI, MainWindowBase):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
# Create the dock manager. Because the parent parameter is a QMainWindow
|
||||
# the dock manager registers itself as the central widget.
|
||||
self.dock_manager = QtAds.CDockManager(self)
|
||||
|
||||
# Create example content label - this can be any application specific
|
||||
# widget
|
||||
l = QLabel()
|
||||
l.setWordWrap(True)
|
||||
l.setAlignment(Qt.AlignTop | Qt.AlignLeft);
|
||||
l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
|
||||
|
||||
# Create a dock widget with the title Label 1 and set the created label
|
||||
# as the dock widget content
|
||||
dock_widget = QtAds.CDockWidget("Label 1")
|
||||
dock_widget.setWidget(l)
|
||||
|
||||
# Add the toggleViewAction of the dock widget to the menu to give
|
||||
# the user the possibility to show the dock widget if it has been closed
|
||||
self.menuView.addAction(dock_widget.toggleViewAction())
|
||||
|
||||
# Add the dock widget to the top dock widget area
|
||||
self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
w = MainWindow()
|
||||
w.show()
|
||||
app.exec_()
|
||||
@@ -1,41 +0,0 @@
|
||||
{% set data = load_setup_py_data() %}
|
||||
|
||||
package:
|
||||
name: pyqtads
|
||||
version: {{ data.get('version') }}
|
||||
|
||||
source:
|
||||
path: ../
|
||||
|
||||
build:
|
||||
number: 0
|
||||
script: python setup.py install --single-version-externally-managed --record=record.txt --conda-recipe
|
||||
|
||||
requirements:
|
||||
build:
|
||||
- python
|
||||
- setuptools
|
||||
- pyqt>=5.9
|
||||
- sip>=4.19
|
||||
run:
|
||||
- python
|
||||
- pyqt>=5.9
|
||||
- sip>=4.19
|
||||
- pywin32 [win]
|
||||
|
||||
test:
|
||||
imports:
|
||||
- PyQtAds
|
||||
|
||||
about:
|
||||
home: {{ data.get('url') }}
|
||||
license: {{ data.get('license') }}
|
||||
license_family: LGPL
|
||||
license_file: 'LICENSE.md'
|
||||
summary: {{ data.get('description') }}
|
||||
description: {{ data.get('description') }}
|
||||
doc_url: ''
|
||||
dev_url: {{ data.get('url') }}
|
||||
|
||||
extra:
|
||||
recipe-maintainers: 'nicolas.elie@cnrs.fr'
|
||||
20
setup.py
20
setup.py
@@ -198,16 +198,32 @@ class build_ext(sipdistutils.build_ext):
|
||||
|
||||
dir_util.mkpath(self.build_temp, dry_run=self.dry_run)
|
||||
|
||||
def get_moc_args(out_file, source):
|
||||
if sys.platform.startswith('linux'):
|
||||
return ["moc", "-D", "Q_OS_LINUX=1", "-o", out_file, source]
|
||||
if sys.platform.startswith('darwin'):
|
||||
return ["moc", "-D", "Q_OS_MACOS=1", "-o", out_file, source]
|
||||
if sys.platform.startswith('win'):
|
||||
return ["moc", "-D", "Q_OS_WIN=1", "-o", out_file, source]
|
||||
return ["moc", "-o", out_file, source]
|
||||
|
||||
# Run moc on all header files.
|
||||
for source in cppsources:
|
||||
# *.cpp -> *.moc
|
||||
moc_file = os.path.basename(source).replace(".cpp", ".moc")
|
||||
out_file = os.path.join(self.build_temp, moc_file)
|
||||
|
||||
if newer(source, out_file) or self.force:
|
||||
spawn.spawn(get_moc_args(out_file, source), dry_run=self.dry_run)
|
||||
|
||||
header = source.replace(".cpp", ".h")
|
||||
if os.path.exists(header):
|
||||
# *.h -> moc_*.cpp
|
||||
moc_file = "moc_" + os.path.basename(header).replace(".h", ".cpp")
|
||||
out_file = os.path.join(self.build_temp, moc_file)
|
||||
|
||||
if newer(header, out_file) or self.force:
|
||||
call_arg = ["moc", "-o", out_file, header]
|
||||
spawn.spawn(call_arg, dry_run=self.dry_run)
|
||||
spawn.spawn(get_moc_args(out_file, header), dry_run=self.dry_run)
|
||||
|
||||
if os.path.getsize(out_file) > 0:
|
||||
ext.sources.append(out_file)
|
||||
|
||||
82
simple.py
82
simple.py
@@ -1,82 +0,0 @@
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQtAds import QtAds
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setup_ui()
|
||||
self.dock_manager = QtAds.CDockManager(self)
|
||||
|
||||
self.dock_widgets = []
|
||||
|
||||
for label_text, area in (
|
||||
('1 Top', QtAds.TopDockWidgetArea),
|
||||
('2 Bottom', QtAds.BottomDockWidgetArea),
|
||||
('3 Left', QtAds.LeftDockWidgetArea),
|
||||
('4 Right', QtAds.RightDockWidgetArea),
|
||||
):
|
||||
# Create example content label - this can be any application specific
|
||||
# widget
|
||||
label = QtWidgets.QLabel()
|
||||
label.setWordWrap(True)
|
||||
label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||
label.setText(f"{label_text}: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
|
||||
|
||||
# Create a dock widget with the title Label 1 and set the created label
|
||||
# as the dock widget content
|
||||
dock_widget = QtAds.CDockWidget(label_text)
|
||||
dock_widget.setWidget(label)
|
||||
self.dock_widgets.append(dock_widget)
|
||||
|
||||
# Add the toggleViewAction of the dock widget to the menu to give
|
||||
# the user the possibility to show the dock widget if it has been closed
|
||||
self.menu_view.addAction(dock_widget.toggleViewAction())
|
||||
|
||||
# Add the dock widget to the top dock widget area
|
||||
self.dock_manager.addDockWidget(area, dock_widget)
|
||||
|
||||
def setup_ui(self):
|
||||
self.setWindowTitle("MainWindow")
|
||||
self.setObjectName("MainWindow")
|
||||
self.resize(400, 300)
|
||||
self.central_widget = QtWidgets.QWidget(self)
|
||||
self.central_widget.setObjectName("central_widget")
|
||||
self.setCentralWidget(self.central_widget)
|
||||
|
||||
self.menu_bar = QtWidgets.QMenuBar(self)
|
||||
self.menu_bar.setGeometry(QtCore.QRect(0, 0, 400, 21))
|
||||
self.menu_bar.setObjectName("menuBar")
|
||||
|
||||
self.menu_view = QtWidgets.QMenu(self.menu_bar)
|
||||
self.menu_view.setObjectName("menu_view")
|
||||
self.menu_view.setTitle("View")
|
||||
self.setMenuBar(self.menu_bar)
|
||||
|
||||
self.status_bar = QtWidgets.QStatusBar(self)
|
||||
self.status_bar.setObjectName("statusBar")
|
||||
self.setStatusBar(self.status_bar)
|
||||
self.menu_bar.addAction(self.menu_view.menuAction())
|
||||
|
||||
|
||||
def main(app):
|
||||
main = MainWindow()
|
||||
main.show()
|
||||
state = main.dock_manager.saveState()
|
||||
print('This is what the saved state looks like in XML:')
|
||||
print(state)
|
||||
print()
|
||||
main.dock_manager.restoreState(state)
|
||||
return main
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level='DEBUG')
|
||||
app = QtWidgets.QApplication([])
|
||||
window = main(app)
|
||||
window.show()
|
||||
print('shown')
|
||||
app.exec_()
|
||||
@@ -13,14 +13,6 @@ class CDockAreaTabBar : QScrollArea
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent* Event);
|
||||
virtual void mousePressEvent(QMouseEvent* ev);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void startFloating(const QPoint& Offset);
|
||||
ads::IFloatingWidget* makeAreaFloating(const QPoint& Offset,
|
||||
ads::eDragState DragState);
|
||||
ads::eDragState dragState() const;
|
||||
|
||||
public:
|
||||
CDockAreaTabBar(ads::CDockAreaWidget* parent /TransferThis/);
|
||||
@@ -35,6 +27,7 @@ public:
|
||||
bool isTabOpen(int Index) const;
|
||||
virtual QSize minimumSizeHint() const;
|
||||
virtual QSize sizeHint() const;
|
||||
void elidedChanged(bool elided);
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(int Index);
|
||||
|
||||
@@ -11,6 +11,13 @@ class CDockAreaTitleBar : QFrame
|
||||
#include <DockAreaTitleBar.h>
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* ev);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent* ev);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
|
||||
public slots:
|
||||
void markTabsMenuOutdated();
|
||||
|
||||
@@ -20,7 +27,10 @@ public:
|
||||
virtual ~CDockAreaTitleBar();
|
||||
ads::CDockAreaTabBar* tabBar() const;
|
||||
QAbstractButton* button(ads::TitleBarButton which) const;
|
||||
void updateDockWidgetActionsButtons();
|
||||
virtual void setVisible(bool Visible);
|
||||
void insertWidget(int index, QWidget *widget /Transfer/ );
|
||||
int indexOf(QWidget *widget) const;
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
@@ -42,12 +42,16 @@ public:
|
||||
int currentIndex() const;
|
||||
int indexOfFirstOpenDockWidget() const;
|
||||
ads::CDockWidget* currentDockWidget() const;
|
||||
void setCurrentDockWidget(ads::CDockWidget* DockWidget /Transfer/);
|
||||
void setCurrentDockWidget(ads::CDockWidget* DockWidget);
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
ads::CDockWidget::DockWidgetFeatures features() const;
|
||||
ads::CDockWidget::DockWidgetFeatures features(ads::eBitwiseOperator Mode = ads::BitwiseAnd) const;
|
||||
QAbstractButton* titleBarButton(ads::TitleBarButton which) const;
|
||||
virtual void setVisible(bool Visible);
|
||||
|
||||
void setAllowedAreas(DockWidgetAreas areas);
|
||||
DockWidgetAreas allowedAreas() const;
|
||||
CDockAreaTitleBar* titleBar() const;
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(int index);
|
||||
void closeArea();
|
||||
|
||||
26
sip/DockComponentsFactory.sip
Normal file
26
sip/DockComponentsFactory.sip
Normal file
@@ -0,0 +1,26 @@
|
||||
%If (Qt_5_0_0 -)
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
class CDockComponentsFactory
|
||||
{
|
||||
|
||||
%TypeHeaderCode
|
||||
#include <DockComponentsFactory.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
virtual ~CDockComponentsFactory();
|
||||
virtual CDockWidgetTab* createDockWidgetTab(CDockWidget* DockWidget /Transfer/ ) const;
|
||||
virtual CDockAreaTabBar* createDockAreaTabBar(CDockAreaWidget* DockArea /Transfer/ ) const;
|
||||
virtual CDockAreaTitleBar* createDockAreaTitleBar(CDockAreaWidget* DockArea /Transfer/ ) const;
|
||||
static const CDockComponentsFactory* factory();
|
||||
static void setFactory(CDockComponentsFactory* Factory);
|
||||
static void resetDefaultFactory();
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
%End
|
||||
@@ -23,13 +23,12 @@ protected:
|
||||
QSplitter* rootSplitter() const;
|
||||
void createRootSplitter();
|
||||
void dropFloatingWidget(ads::CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
||||
void dropWidget(QWidget* widget, const QPoint& TargetPos);
|
||||
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget);
|
||||
void addDockArea(ads::CDockAreaWidget* DockAreaWidget /Transfer/, ads::DockWidgetArea area = ads::CenterDockWidgetArea);
|
||||
void removeDockArea(ads::CDockAreaWidget* area /Transfer/);
|
||||
void removeDockArea(ads::CDockAreaWidget* area /TransferBack/);
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
bool restoreState(CDockingStateReader& Stream, bool Testing);
|
||||
ads::CDockAreaWidget* lastAddedDockAreaWidget(ads::DockWidgetArea area) const;
|
||||
bool hasTopLevelDockWidget() const;
|
||||
ads::CDockWidget* topLevelDockWidget() const;
|
||||
ads::CDockAreaWidget* topLevelDockArea() const;
|
||||
QList<ads::CDockWidget*> dockWidgets() const;
|
||||
@@ -88,6 +87,7 @@ public:
|
||||
* If all dock widgets in a dock area are closed, the dock area will be closed
|
||||
*/
|
||||
QList<ads::CDockAreaWidget*> openedDockAreas() const;
|
||||
bool hasTopLevelDockWidget() const;
|
||||
|
||||
/**
|
||||
* Returns the number of dock areas in this container
|
||||
|
||||
@@ -134,6 +134,8 @@ protected:
|
||||
ads::CDockOverlay* containerOverlay() const;
|
||||
ads::CDockOverlay* dockAreaOverlay() const;
|
||||
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
|
||||
public:
|
||||
enum eViewMenuInsertionOrder
|
||||
{
|
||||
@@ -152,13 +154,22 @@ public:
|
||||
TabCloseButtonIsToolButton,
|
||||
AllTabsHaveCloseButton,
|
||||
RetainTabSizeWhenCloseButtonHidden,
|
||||
OpaqueUndocking,
|
||||
DragPreviewIsDynamic,
|
||||
DragPreviewShowsContentPixmap,
|
||||
DragPreviewHasWindowFrame,
|
||||
DefaultConfig,
|
||||
DefaultNonOpaqueConfig,
|
||||
NonOpaqueWithWindowFrame,
|
||||
OpaqueUndocking,
|
||||
DragPreviewIsDynamic,
|
||||
DragPreviewShowsContentPixmap,
|
||||
DragPreviewHasWindowFrame,
|
||||
AlwaysShowTabs,
|
||||
DockAreaHasUndockButton,
|
||||
DockAreaHasTabsMenuButton,
|
||||
DockAreaHideDisabledButtons,
|
||||
DockAreaDynamicTabsMenuButtonVisibility,
|
||||
FloatingContainerHasWidgetTitle,
|
||||
FloatingContainerHasWidgetIcon,
|
||||
DefaultDockAreaButtons,
|
||||
DefaultBaseConfig,
|
||||
DefaultOpaqueConfig,
|
||||
DefaultNonOpaqueConfig,
|
||||
NonOpaqueWithWindowFrame,
|
||||
};
|
||||
typedef QFlags<ads::CDockManager::eConfigFlag> ConfigFlags;
|
||||
|
||||
@@ -167,6 +178,7 @@ public:
|
||||
static ads::CDockManager::ConfigFlags configFlags();
|
||||
static void setConfigFlags(const ads::CDockManager::ConfigFlags Flags);
|
||||
static void setConfigFlag(ads::CDockManager::eConfigFlag Flag, bool On = true);
|
||||
static bool testConfigFlag(eConfigFlag Flag);
|
||||
static ads::CIconProvider& iconProvider();
|
||||
ads::CDockAreaWidget* addDockWidget(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/,
|
||||
ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0);
|
||||
@@ -180,7 +192,7 @@ public:
|
||||
QMap<QString, ads::CDockWidget*> dockWidgetsMap() const;
|
||||
const QList<ads::CDockContainerWidget*> dockContainers() const;
|
||||
const QList<ads::CFloatingDockContainer*> floatingWidgets() const;
|
||||
virtual unsigned int zOrderIndex() const;
|
||||
unsigned int zOrderIndex() const;
|
||||
QByteArray saveState(int version = 1) const;
|
||||
bool restoreState(const QByteArray &state, int version = 1);
|
||||
void addPerspective(const QString& UniquePrespectiveName);
|
||||
@@ -206,6 +218,7 @@ signals:
|
||||
void stateRestored();
|
||||
void openingPerspective(const QString& PerspectiveName);
|
||||
void perspectiveOpened(const QString& PerspectiveName);
|
||||
void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget);
|
||||
void dockAreaCreated(ads::CDockAreaWidget* DockArea);
|
||||
void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget);
|
||||
void dockWidgetRemoved(ads::CDockWidget* DockWidget);
|
||||
|
||||
@@ -24,9 +24,11 @@ public:
|
||||
void setAllowedAreas(ads::DockWidgetAreas areas);
|
||||
ads::DockWidgetAreas allowedAreas() const;
|
||||
ads::DockWidgetArea dropAreaUnderCursor() const;
|
||||
ads::DockWidgetArea visibleDropAreaUnderCursor() const;
|
||||
ads::DockWidgetArea showOverlay(QWidget* target);
|
||||
void hideOverlay();
|
||||
void enableDropPreview(bool Enable);
|
||||
bool dropPreviewEnabled() const;
|
||||
QRect dropOverlayRect() const;
|
||||
virtual bool event(QEvent *e);
|
||||
|
||||
@@ -58,6 +60,8 @@ protected:
|
||||
void setIconOverlayColor(const QColor& Color);
|
||||
void setIconArrowColor(const QColor& Color);
|
||||
void setIconShadowColor(const QColor& Color);
|
||||
virtual void showEvent(QShowEvent* e);
|
||||
void setAreaWidgets(const QHash<ads::DockWidgetArea, QWidget*>& widgets);
|
||||
|
||||
public:
|
||||
CDockOverlayCross(ads::CDockOverlay* overlay /TransferThis/);
|
||||
|
||||
@@ -16,6 +16,9 @@ public:
|
||||
CDockSplitter(Qt::Orientation orientation, QWidget *parent /TransferThis/ = 0);
|
||||
virtual ~CDockSplitter();
|
||||
bool hasVisibleContent() const;
|
||||
QWidget* firstWidget() const;
|
||||
QWidget* lastWidget() const;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -12,15 +12,16 @@ class CDockWidget : QFrame
|
||||
%End
|
||||
|
||||
protected:
|
||||
void setDockManager(ads::CDockManager* DockManager /Transfer/);
|
||||
void setDockArea(ads::CDockAreaWidget* DockArea /Transfer/);
|
||||
void setToggleViewActionChecked(bool Checked);
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
void flagAsUnassigned();
|
||||
static void emitTopLevelEventForWidget(ads::CDockWidget* TopLevelDockWidget, bool Floating);
|
||||
void emitTopLevelChanged(bool Floating);
|
||||
void setClosedState(bool Closed);
|
||||
void toggleViewInternal(bool Open);
|
||||
void setDockManager(ads::CDockManager* DockManager /Transfer/ );
|
||||
void setDockArea(ads::CDockAreaWidget* DockArea /Transfer/ );
|
||||
void setToggleViewActionChecked(bool Checked);
|
||||
void saveState(QXmlStreamWriter& Stream) const;
|
||||
void flagAsUnassigned();
|
||||
static void emitTopLevelEventForWidget(ads::CDockWidget* TopLevelDockWidget, bool Floating);
|
||||
void emitTopLevelChanged(bool Floating);
|
||||
void setClosedState(bool Closed);
|
||||
void toggleViewInternal(bool Open);
|
||||
bool closeDockWidgetInternal(bool ForceClose = false);
|
||||
|
||||
public:
|
||||
enum DockWidgetFeature
|
||||
@@ -29,7 +30,9 @@ public:
|
||||
DockWidgetMovable,
|
||||
DockWidgetFloatable,
|
||||
DockWidgetDeleteOnClose,
|
||||
AllDockWidgetFeatures,
|
||||
CustomCloseHandling,
|
||||
DefaultDockWidgetFeatures,
|
||||
AllDockWidgetFeatures,
|
||||
NoDockWidgetFeatures
|
||||
};
|
||||
typedef QFlags<ads::CDockWidget::DockWidgetFeature> DockWidgetFeatures;
|
||||
@@ -48,6 +51,12 @@ public:
|
||||
ForceNoScrollArea
|
||||
};
|
||||
|
||||
enum eMinimumSizeHintMode
|
||||
{
|
||||
MinimumSizeHintFromDockWidget,
|
||||
MinimumSizeHintFromContent
|
||||
};
|
||||
|
||||
enum eToggleViewActionMode
|
||||
{
|
||||
ActionModeToggle,
|
||||
@@ -73,15 +82,19 @@ public:
|
||||
bool isClosed() const;
|
||||
QAction* toggleViewAction() const;
|
||||
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
|
||||
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
|
||||
void setIcon(const QIcon& Icon);
|
||||
QIcon icon() const;
|
||||
QToolBar* toolBar() const;
|
||||
QToolBar* createDefaultToolBar();
|
||||
void setToolBar(QToolBar* ToolBar);
|
||||
void setToolBar(QToolBar* ToolBar /Transfer/ );
|
||||
void setToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State);
|
||||
Qt::ToolButtonStyle toolBarStyle(ads::CDockWidget::eState State) const;
|
||||
void setToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State);
|
||||
QSize toolBarIconSize(eState State) const;
|
||||
void setTitleBarActions(QList<QAction*> actions);
|
||||
virtual QList<QAction*> titleBarActions() const;
|
||||
|
||||
void setTabToolTip(const QString &text);
|
||||
|
||||
public:
|
||||
@@ -91,12 +104,14 @@ public slots:
|
||||
void toggleView(bool Open = true);
|
||||
void setFloating();
|
||||
void deleteDockWidget();
|
||||
void closeDockWidget();
|
||||
|
||||
signals:
|
||||
void viewToggled(bool Open);
|
||||
void closed();
|
||||
void titleChanged(const QString& Title);
|
||||
void topLevelChanged(bool topLevel);
|
||||
void closeRequested();
|
||||
void visibilityChanged(bool visible);
|
||||
void featuresChanged(ads::CDockWidget::DockWidgetFeatures features);
|
||||
};
|
||||
|
||||
@@ -23,13 +23,14 @@ public:
|
||||
virtual ~CDockWidgetTab();
|
||||
bool isActiveTab() const;
|
||||
void setActiveTab(bool active);
|
||||
ads::CDockWidget* dockWidget() const;
|
||||
void setDockAreaWidget(ads::CDockAreaWidget* DockArea /Transfer/);
|
||||
ads::CDockAreaWidget* dockAreaWidget() const;
|
||||
ads::CDockWidget* dockWidget() const;
|
||||
void setIcon(const QIcon& Icon);
|
||||
const QIcon& icon() const;
|
||||
QString text() const;
|
||||
void setText(const QString& title);
|
||||
bool isTitleElided() const;
|
||||
bool isClosable() const;
|
||||
virtual bool event(QEvent *e);
|
||||
|
||||
@@ -43,6 +44,7 @@ signals:
|
||||
void closeRequested();
|
||||
void closeOtherTabsRequested();
|
||||
void moved(const QPoint& GlobalPos);
|
||||
void elidedChanged(bool elided);
|
||||
}; // class DockWidgetTab
|
||||
};
|
||||
// namespace ads
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
virtual ~CElidingLabel();
|
||||
Qt::TextElideMode elideMode() const;
|
||||
void setElideMode(Qt::TextElideMode mode);
|
||||
|
||||
bool isElided() const;
|
||||
|
||||
public:
|
||||
virtual QSize minimumSizeHint() const;
|
||||
@@ -33,6 +33,7 @@ public:
|
||||
signals:
|
||||
void clicked();
|
||||
void doubleClicked();
|
||||
void elidedChanged(bool elided);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
// NOTE: there is a separate sip/linux/FloatingDockContainer.sip as the base
|
||||
// class for CFloatingDockContainer changes for Linux.
|
||||
|
||||
%Import QtWidgets/QtWidgetsmod.sip
|
||||
|
||||
%If (Qt_5_0_0 -)
|
||||
|
||||
%If (WS_X11)
|
||||
typedef QDockWidget tFloatingWidgetBase;
|
||||
%End
|
||||
%If (!WS_X11)
|
||||
typedef QWidget tFloatingWidgetBase;
|
||||
%End
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
@@ -20,7 +30,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class CFloatingDockContainer : QWidget, ads::IFloatingWidget
|
||||
class CFloatingDockContainer : tFloatingWidgetBase, ads::IFloatingWidget
|
||||
{
|
||||
|
||||
%TypeHeaderCode
|
||||
@@ -46,7 +56,6 @@ protected:
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
virtual void hideEvent(QHideEvent *event);
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
public:
|
||||
CFloatingDockContainer(ads::CDockManager* DockManager /TransferThis/);
|
||||
|
||||
@@ -12,6 +12,10 @@ class CFloatingDragPreview : QWidget, ads::IFloatingWidget
|
||||
#include <FloatingDragPreview.h>
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual void moveEvent(QMoveEvent *event);
|
||||
virtual void paintEvent(QPaintEvent *e);
|
||||
CFloatingDragPreview(QWidget* Content /TransferThis/, QWidget* parent /TransferThis/);
|
||||
|
||||
public:
|
||||
CFloatingDragPreview(ads::CDockWidget* Content /TransferThis/ );
|
||||
@@ -21,6 +25,7 @@ public:
|
||||
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
|
||||
public: // implements IFloatingWidget
|
||||
virtual void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
||||
ads::eDragState DragState, QWidget* MouseEventHandler);
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
%Module(name=PyQtAds.QtAds.ads, call_super_init=True, keyword_arguments="Optional", use_limited_api=True)
|
||||
%Import QtCore/QtCoremod.sip
|
||||
%DefaultSupertype sip.simplewrapper
|
||||
%Platforms {Linux macOS Windows}
|
||||
|
||||
%Include ads_globals.sip
|
||||
%Include DockWidget.sip
|
||||
%Include DockAreaTabBar.sip
|
||||
%Include DockAreaTitleBar.sip
|
||||
%Include DockAreaWidget.sip
|
||||
%Include DockComponentsFactory.sip
|
||||
%Include DockContainerWidget.sip
|
||||
%Include DockingStateReader.sip
|
||||
%Include DockManager.sip
|
||||
@@ -18,6 +18,6 @@
|
||||
%Include FloatingDockContainer.sip
|
||||
%Include FloatingDragPreview.sip
|
||||
%Include IconProvider.sip
|
||||
%If (Linux)
|
||||
%If (WS_X11)
|
||||
%Include linux/FloatingWidgetTitleBar.sip
|
||||
%End
|
||||
@@ -8,6 +8,13 @@ namespace ads
|
||||
#include <ads_globals.h>
|
||||
%End
|
||||
|
||||
enum eStateFileVersion
|
||||
{
|
||||
InitialVerison,
|
||||
Version1,
|
||||
CurrentVersion
|
||||
};
|
||||
|
||||
enum DockWidgetArea
|
||||
{
|
||||
NoDockWidgetArea,
|
||||
@@ -49,6 +56,12 @@ namespace ads
|
||||
IconCount,
|
||||
};
|
||||
|
||||
enum eBitwiseOperator
|
||||
{
|
||||
BitwiseAnd,
|
||||
BitwiseOr
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
%End
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace ads
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <FloatingWidgetTitleBar.h>
|
||||
#include <linux/FloatingWidgetTitleBar.h>
|
||||
%End
|
||||
|
||||
class CFloatingWidgetTitleBar : QWidget
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <QDebug>
|
||||
#include <QBoxLayout>
|
||||
#include <QApplication>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockAreaWidget.h"
|
||||
@@ -69,6 +70,16 @@ struct DockAreaTabBarPrivate
|
||||
* The function reassigns the stylesheet to update the tabs
|
||||
*/
|
||||
void updateTabs();
|
||||
|
||||
/**
|
||||
* Convenience function to access first tab
|
||||
*/
|
||||
CDockWidgetTab* firstTab() const {return _this->tab(0);}
|
||||
|
||||
/**
|
||||
* Convenience function to access last tab
|
||||
*/
|
||||
CDockWidgetTab* lastTab() const {return _this->tab(_this->count() - 1);}
|
||||
};
|
||||
// struct DockAreaTabBarPrivate
|
||||
|
||||
@@ -366,6 +377,8 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
|
||||
|
||||
int fromIndex = d->TabsLayout->indexOf(MovingTab);
|
||||
auto MousePos = mapFromGlobal(GlobalPos);
|
||||
MousePos.rx() = qMax(d->firstTab()->geometry().left(), MousePos.x());
|
||||
MousePos.rx() = qMin(d->lastTab()->geometry().right(), MousePos.x());
|
||||
int toIndex = -1;
|
||||
// Find tab under mouse
|
||||
for (int i = 0; i < count(); ++i)
|
||||
@@ -381,38 +394,23 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
|
||||
if (toIndex == fromIndex)
|
||||
{
|
||||
toIndex = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (toIndex < 0)
|
||||
{
|
||||
toIndex = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Now check if the mouse is behind the last tab
|
||||
if (toIndex < 0)
|
||||
{
|
||||
if (MousePos.x() > tab(count() - 1)->geometry().right())
|
||||
{
|
||||
ADS_PRINT("after all tabs");
|
||||
toIndex = count() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
toIndex = fromIndex;
|
||||
}
|
||||
}
|
||||
|
||||
d->TabsLayout->removeWidget(MovingTab);
|
||||
d->TabsLayout->insertWidget(toIndex, MovingTab);
|
||||
if (toIndex >= 0)
|
||||
if (toIndex > -1)
|
||||
{
|
||||
d->TabsLayout->removeWidget(MovingTab);
|
||||
d->TabsLayout->insertWidget(toIndex, MovingTab);
|
||||
ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
|
||||
emit tabMoved(fromIndex, toIndex);
|
||||
setCurrentIndex(toIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure that the moved tab is reset to its start position
|
||||
d->TabsLayout->update();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "DockWidgetTab.h"
|
||||
#include "DockAreaTabBar.h"
|
||||
#include "IconProvider.h"
|
||||
#include "DockComponentsFactory.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -234,7 +235,7 @@ void DockAreaTitleBarPrivate::createButtons()
|
||||
#endif
|
||||
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
|
||||
TabsMenuButton->setMenu(TabsMenu);
|
||||
internal::setToolTip(TabsMenuButton, QObject::tr("List all tabs"));
|
||||
internal::setToolTip(TabsMenuButton, QObject::tr("List All Tabs"));
|
||||
TabsMenuButton->setSizePolicy(ButtonSizePolicy);
|
||||
Layout->addWidget(TabsMenuButton, 0);
|
||||
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
||||
@@ -273,7 +274,7 @@ void DockAreaTitleBarPrivate::createButtons()
|
||||
//============================================================================
|
||||
void DockAreaTitleBarPrivate::createTabBar()
|
||||
{
|
||||
TabBar = new CDockAreaTabBar(DockArea);
|
||||
TabBar = componentsFactory()->createDockAreaTabBar(DockArea);
|
||||
TabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
||||
Layout->addWidget(TabBar);
|
||||
_this->connect(TabBar, SIGNAL(tabClosed(int)), SLOT(markTabsMenuOutdated()));
|
||||
@@ -599,7 +600,11 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev)
|
||||
|
||||
// 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))
|
||||
// If we do non opaque undocking, then we can create the floating drag
|
||||
// preview if the dock widget is movable
|
||||
auto Features = d->DockArea->features();
|
||||
if (!Features.testFlag(CDockWidget::DockWidgetFloatable)
|
||||
&& !(Features.testFlag(CDockWidget::DockWidgetMovable) && !CDockManager::testConfigFlag(CDockManager::OpaqueUndocking)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "DockWidgetTab.h"
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QStackedLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QScrollArea>
|
||||
@@ -53,8 +54,8 @@
|
||||
#include "DockAreaTabBar.h"
|
||||
#include "DockSplitter.h"
|
||||
#include "DockAreaTitleBar.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "DockComponentsFactory.h"
|
||||
#include "DockWidgetTab.h"
|
||||
|
||||
|
||||
namespace ads
|
||||
@@ -246,6 +247,7 @@ struct DockAreaWidgetPrivate
|
||||
CDockManager* DockManager = nullptr;
|
||||
bool UpdateTitleBarButtons = false;
|
||||
DockWidgetAreas AllowedAreas = AllDockAreas;
|
||||
QSize MinSizeHint;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -262,7 +264,7 @@ struct DockAreaWidgetPrivate
|
||||
*/
|
||||
CDockWidget* dockWidgetAt(int index)
|
||||
{
|
||||
return dynamic_cast<CDockWidget*>(ContentsLayout->widget(index));
|
||||
return qobject_cast<CDockWidget*>(ContentsLayout->widget(index));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +304,20 @@ struct DockAreaWidgetPrivate
|
||||
* Udpates the enable state of the close and detach button
|
||||
*/
|
||||
void updateTitleBarButtonStates();
|
||||
|
||||
/**
|
||||
* Scans all contained dock widgets for the max. minimum size hint
|
||||
*/
|
||||
void updateMinimumSizeHint()
|
||||
{
|
||||
MinSizeHint = QSize();
|
||||
for (int i = 0; i < ContentsLayout->count(); ++i)
|
||||
{
|
||||
auto Widget = ContentsLayout->widget(i);
|
||||
MinSizeHint.setHeight(qMax(MinSizeHint.height(), Widget->minimumSizeHint().height()));
|
||||
MinSizeHint.setWidth(qMax(MinSizeHint.width(), Widget->minimumSizeHint().width()));
|
||||
}
|
||||
}
|
||||
};
|
||||
// struct DockAreaWidgetPrivate
|
||||
|
||||
@@ -317,7 +333,7 @@ DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
|
||||
//============================================================================
|
||||
void DockAreaWidgetPrivate::createTitleBar()
|
||||
{
|
||||
TitleBar = new CDockAreaTitleBar(_this);
|
||||
TitleBar = componentsFactory()->createDockAreaTitleBar(_this);
|
||||
Layout->addWidget(TitleBar);
|
||||
QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested);
|
||||
QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex);
|
||||
@@ -406,6 +422,8 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
||||
d->tabBar()->blockSignals(false);
|
||||
TabWidget->setVisible(!DockWidget->isClosed());
|
||||
DockWidget->setProperty(INDEX_PROPERTY, index);
|
||||
d->MinSizeHint.setHeight(qMax(d->MinSizeHint.height(), DockWidget->minimumSizeHint().height()));
|
||||
d->MinSizeHint.setWidth(qMax(d->MinSizeHint.width(), DockWidget->minimumSizeHint().width()));
|
||||
if (Activate)
|
||||
{
|
||||
setCurrentIndex(index);
|
||||
@@ -446,6 +464,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
||||
|
||||
d->updateTitleBarButtonStates();
|
||||
updateTitleBarVisibility();
|
||||
d->updateMinimumSizeHint();
|
||||
auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
@@ -496,7 +515,6 @@ void CDockAreaWidget::onTabCloseRequested(int Index)
|
||||
auto* DockWidget = dockWidget(Index);
|
||||
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
||||
{
|
||||
//DockWidget->deleteDockWidget();
|
||||
DockWidget->closeDockWidgetInternal();
|
||||
}
|
||||
else
|
||||
@@ -863,6 +881,13 @@ CDockAreaTitleBar* CDockAreaWidget::titleBar() const
|
||||
{
|
||||
return d->TitleBar;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QSize CDockAreaWidget::minimumSizeHint() const
|
||||
{
|
||||
return d->MinSizeHint.isValid() ? d->MinSizeHint : Super::minimumSizeHint();
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -164,6 +164,13 @@ public:
|
||||
*/
|
||||
CDockContainerWidget* dockContainer() const;
|
||||
|
||||
/**
|
||||
* Returns the largest minimumSizeHint() of the dock widgets in this
|
||||
* area.
|
||||
* The minimum size hint is updated if a dock widget is removed or added.
|
||||
*/
|
||||
virtual QSize minimumSizeHint() const override;
|
||||
|
||||
/**
|
||||
* Returns the rectangle of the title area
|
||||
*/
|
||||
|
||||
69
src/DockComponentsFactory.cpp
Normal file
69
src/DockComponentsFactory.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//============================================================================
|
||||
/// \file DockComponentsFactory.cpp
|
||||
/// \author Uwe Kindler
|
||||
/// \date 10.02.2020
|
||||
/// \brief Implementation of DockComponentsFactory
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <DockComponentsFactory.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "DockWidgetTab.h"
|
||||
#include "DockAreaTabBar.h"
|
||||
#include "DockAreaTitleBar.h"
|
||||
#include "DockWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
static std::unique_ptr<CDockComponentsFactory> DefaultFactory(new CDockComponentsFactory());
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidgetTab* CDockComponentsFactory::createDockWidgetTab(CDockWidget* DockWidget) const
|
||||
{
|
||||
return new CDockWidgetTab(DockWidget);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockAreaTabBar* CDockComponentsFactory::createDockAreaTabBar(CDockAreaWidget* DockArea) const
|
||||
{
|
||||
return new CDockAreaTabBar(DockArea);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockAreaTitleBar* CDockComponentsFactory::createDockAreaTitleBar(CDockAreaWidget* DockArea) const
|
||||
{
|
||||
return new CDockAreaTitleBar(DockArea);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
const CDockComponentsFactory* CDockComponentsFactory::factory()
|
||||
{
|
||||
return DefaultFactory.get();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockComponentsFactory::setFactory(CDockComponentsFactory* Factory)
|
||||
{
|
||||
DefaultFactory.reset(Factory);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockComponentsFactory::resetDefaultFactory()
|
||||
{
|
||||
DefaultFactory.reset(new CDockComponentsFactory());
|
||||
}
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF DockComponentsFactory.cpp
|
||||
90
src/DockComponentsFactory.h
Normal file
90
src/DockComponentsFactory.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef DockComponentsFactoryH
|
||||
#define DockComponentsFactoryH
|
||||
//============================================================================
|
||||
/// \file DockComponentsFactory.h
|
||||
/// \author Uwe Kindler
|
||||
/// \date 10.02.2020
|
||||
/// \brief Declaration of DockComponentsFactory
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include "ads_globals.h"
|
||||
|
||||
namespace ads
|
||||
{
|
||||
class CDockWidgetTab;
|
||||
class CDockAreaTitleBar;
|
||||
class CDockAreaTabBar;
|
||||
class CDockAreaWidget;
|
||||
class CDockWidget;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Factory for creation of certain GUI elements for the docking framework.
|
||||
* A default unique instance provided by CDockComponentsFactory is used for
|
||||
* creation of all supported components. To inject your custom components,
|
||||
* you can create your own derived dock components factory and register
|
||||
* it via setDefaultFactory() function.
|
||||
* \code
|
||||
* CDockComponentsFactory::setDefaultFactory(new MyComponentsFactory()));
|
||||
* \endcode
|
||||
*/
|
||||
class ADS_EXPORT CDockComponentsFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Force virtual destructor
|
||||
*/
|
||||
virtual ~CDockComponentsFactory() {}
|
||||
|
||||
/**
|
||||
* This default implementation just creates a dock widget tab with
|
||||
* new CDockWidgetTab(DockWIdget).
|
||||
*/
|
||||
virtual CDockWidgetTab* createDockWidgetTab(CDockWidget* DockWidget) const;
|
||||
|
||||
/**
|
||||
* This default implementation just creates a dock area tab bar with
|
||||
* new CDockAreaTabBar(DockArea).
|
||||
*/
|
||||
virtual CDockAreaTabBar* createDockAreaTabBar(CDockAreaWidget* DockArea) const;
|
||||
|
||||
/**
|
||||
* This default implementation just creates a dock area title bar with
|
||||
* new CDockAreaTitleBar(DockArea).
|
||||
*/
|
||||
virtual CDockAreaTitleBar* createDockAreaTitleBar(CDockAreaWidget* DockArea) const;
|
||||
|
||||
/**
|
||||
* Returns the default components factory
|
||||
*/
|
||||
static const CDockComponentsFactory* factory();
|
||||
|
||||
/**
|
||||
* Sets a new default factory for creation of GUI elements.
|
||||
* This function takes ownership of the given Factory.
|
||||
*/
|
||||
static void setFactory(CDockComponentsFactory* Factory);
|
||||
|
||||
/**
|
||||
* Resets the current factory to the
|
||||
*/
|
||||
static void resetDefaultFactory();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convenience function to ease factory instance access
|
||||
*/
|
||||
inline const CDockComponentsFactory* componentsFactory()
|
||||
{
|
||||
return CDockComponentsFactory::factory();
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif // DockComponentsFactoryH
|
||||
@@ -679,6 +679,23 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea
|
||||
}
|
||||
else
|
||||
{
|
||||
// We check, if we insert the dropped widget into the same place that
|
||||
// it already has and do nothing, if it is the same place. It would
|
||||
// also work without this check, but it looks nicer with the check
|
||||
// because there will be no layout updates
|
||||
auto Splitter = internal::findParent<CDockSplitter*>(DroppedDockArea);
|
||||
auto InsertParam = internal::dockAreaInsertParameters(area);
|
||||
if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation())
|
||||
{
|
||||
if (InsertParam.append() && Splitter->lastWidget() == DroppedDockArea)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (!InsertParam.append() && Splitter->firstWidget() == DroppedDockArea)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
|
||||
NewDockArea = DroppedDockArea;
|
||||
}
|
||||
@@ -736,7 +753,7 @@ void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> N
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidget* Widget)
|
||||
{
|
||||
QSplitter* Splitter = dynamic_cast<QSplitter*>(Widget);
|
||||
QSplitter* Splitter = qobject_cast<QSplitter*>(Widget);
|
||||
if (Splitter)
|
||||
{
|
||||
s.writeStartElement("Splitter");
|
||||
@@ -759,7 +776,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidge
|
||||
}
|
||||
else
|
||||
{
|
||||
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(Widget);
|
||||
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(Widget);
|
||||
if (DockArea)
|
||||
{
|
||||
DockArea->saveState(s);
|
||||
@@ -1046,7 +1063,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
|
||||
void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
||||
{
|
||||
#if defined(QT_DEBUG)
|
||||
QSplitter* Splitter = dynamic_cast<QSplitter*>(widget);
|
||||
QSplitter* Splitter = qobject_cast<QSplitter*>(widget);
|
||||
QByteArray buf;
|
||||
buf.fill(' ', level * 4);
|
||||
if (Splitter)
|
||||
@@ -1069,7 +1086,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
||||
}
|
||||
else
|
||||
{
|
||||
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(widget);
|
||||
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(widget);
|
||||
if (!DockArea)
|
||||
{
|
||||
return;
|
||||
@@ -1285,7 +1302,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
||||
}
|
||||
|
||||
QWidget* widget = Splitter->widget(0);
|
||||
QSplitter* ChildSplitter = dynamic_cast<QSplitter*>(widget);
|
||||
QSplitter* ChildSplitter = qobject_cast<QSplitter*>(widget);
|
||||
// If the one and only content widget of the splitter is not a splitter
|
||||
// then we are finished
|
||||
if (!ChildSplitter)
|
||||
@@ -1436,41 +1453,16 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos)
|
||||
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget)
|
||||
{
|
||||
ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
|
||||
CDockWidget* SingleDockWidget = topLevelDockWidget();
|
||||
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
|
||||
auto dropArea = InvalidDockWidgetArea;
|
||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||
|
||||
if (DockArea)
|
||||
if (TargetAreaWidget)
|
||||
{
|
||||
auto dropOverlay = d->DockManager->dockAreaOverlay();
|
||||
dropOverlay->setAllowedAreas(DockArea->allowedAreas());
|
||||
dropArea = dropOverlay->showOverlay(DockArea);
|
||||
if (ContainerDropArea != InvalidDockWidgetArea &&
|
||||
ContainerDropArea != dropArea)
|
||||
{
|
||||
dropArea = InvalidDockWidgetArea;
|
||||
}
|
||||
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
ADS_PRINT("Dock Area Drop Content: " << dropArea);
|
||||
d->moveToNewSection(Widget, DockArea, dropArea);
|
||||
}
|
||||
d->moveToNewSection(Widget, TargetAreaWidget, DropArea);
|
||||
}
|
||||
|
||||
// mouse is over container
|
||||
if (InvalidDockWidgetArea == dropArea)
|
||||
else
|
||||
{
|
||||
dropArea = ContainerDropArea;
|
||||
ADS_PRINT("Container Drop Content: " << dropArea);
|
||||
if (dropArea != InvalidDockWidgetArea)
|
||||
{
|
||||
d->moveToContainer(Widget, dropArea);
|
||||
}
|
||||
d->moveToContainer(Widget, DropArea);
|
||||
}
|
||||
|
||||
// If there was a top level widget before the drop, then it is not top
|
||||
@@ -1573,7 +1565,7 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
|
||||
|
||||
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
|
||||
QSplitter* OldRoot = d->RootSplitter;
|
||||
d->RootSplitter = dynamic_cast<QSplitter*>(NewRootSplitter);
|
||||
d->RootSplitter = qobject_cast<QSplitter*>(NewRootSplitter);
|
||||
OldRoot->deleteLater();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -96,9 +96,13 @@ protected:
|
||||
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
|
||||
|
||||
/**
|
||||
* Drop a dock area or a dock widget given in widget parameter
|
||||
* Drop a dock area or a dock widget given in widget parameter.
|
||||
* If the TargetAreaWidget is a nullptr, then the DropArea indicates
|
||||
* the drop area for the container. If the given TargetAreaWidget is not
|
||||
* a nullptr, then the DropArea indicates the drop area in the given
|
||||
* TargetAreaWidget
|
||||
*/
|
||||
void dropWidget(QWidget* Widget, const QPoint& TargetPos);
|
||||
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget);
|
||||
|
||||
/**
|
||||
* Adds the given dock area to this container widget
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
namespace ads
|
||||
{
|
||||
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultOpaqueConfig;
|
||||
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultNonOpaqueConfig;
|
||||
|
||||
/**
|
||||
* Private data class of CDockManager class (pimpl)
|
||||
@@ -411,7 +411,7 @@ CDockManager::CDockManager(QWidget *parent) :
|
||||
d(new DockManagerPrivate(this))
|
||||
{
|
||||
createRootSplitter();
|
||||
QMainWindow* MainWindow = dynamic_cast<QMainWindow*>(parent);
|
||||
QMainWindow* MainWindow = qobject_cast<QMainWindow*>(parent);
|
||||
if (MainWindow)
|
||||
{
|
||||
MainWindow->setCentralWidget(this);
|
||||
@@ -440,6 +440,7 @@ CDockManager::~CDockManager()
|
||||
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
||||
{
|
||||
d->FloatingWidgets.append(FloatingWidget);
|
||||
emit floatingWidgetCreated(FloatingWidget);
|
||||
ADS_PRINT("d->FloatingWidgets.count() " << d->FloatingWidgets.count());
|
||||
}
|
||||
|
||||
@@ -777,6 +778,10 @@ QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction,
|
||||
d->addActionToMenu(GroupMenu->menuAction(), d->ViewMenu, AlphabeticallySorted);
|
||||
d->ViewMenuGroups.insert(Group, GroupMenu);
|
||||
}
|
||||
else if (GroupMenu->icon().isNull() && !GroupIcon.isNull())
|
||||
{
|
||||
GroupMenu->setIcon(GroupIcon);
|
||||
}
|
||||
|
||||
d->addActionToMenu(ToggleViewAction, GroupMenu, AlphabeticallySorted);
|
||||
return GroupMenu->menuAction();
|
||||
|
||||
@@ -30,18 +30,11 @@
|
||||
//============================================================================
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <ads_globals.h>
|
||||
#include <DockContainerWidget.h>
|
||||
#include <DockWidget.h>
|
||||
#include <FloatingDockContainer.h>
|
||||
#include <qbytearray.h>
|
||||
#include <qflags.h>
|
||||
#include <qlist.h>
|
||||
#include <qmap.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qstring.h>
|
||||
#include <qstringlist.h>
|
||||
#include <QtGui/qicon.h>
|
||||
#include "ads_globals.h"
|
||||
#include "DockContainerWidget.h"
|
||||
#include "DockWidget.h"
|
||||
#include "FloatingDockContainer.h"
|
||||
|
||||
|
||||
class QSettings;
|
||||
class QMenu;
|
||||
@@ -59,6 +52,7 @@ class CDockWidgetTab;
|
||||
struct DockWidgetTabPrivate;
|
||||
struct DockAreaWidgetPrivate;
|
||||
class CIconProvider;
|
||||
class CDockComponentsFactory;
|
||||
|
||||
/**
|
||||
* The central dock manager that maintains the complete docking system.
|
||||
@@ -141,6 +135,7 @@ public:
|
||||
/**
|
||||
* These global configuration flags configure some global dock manager
|
||||
* settings.
|
||||
* Set the dock manager flags, before you create the dock manager instance.
|
||||
*/
|
||||
enum eConfigFlag
|
||||
{
|
||||
@@ -162,6 +157,8 @@ public:
|
||||
DockAreaHasTabsMenuButton = 0x8000, //!< If the flag is set each dock area has a tabs menu button
|
||||
DockAreaHideDisabledButtons = 0x10000, //!< If the flag is set disabled dock area buttons will not appear on the tollbar at all (enabling them will bring them back)
|
||||
DockAreaDynamicTabsMenuButtonVisibility = 0x20000, //!< If the flag is set dock area will disable a tabs menu button when there is only one tab in the area
|
||||
FloatingContainerHasWidgetTitle = 0x40000,
|
||||
FloatingContainerHasWidgetIcon = 0x80000,
|
||||
|
||||
|
||||
DefaultDockAreaButtons = DockAreaHasCloseButton
|
||||
@@ -170,7 +167,8 @@ public:
|
||||
|
||||
DefaultBaseConfig = DefaultDockAreaButtons
|
||||
| ActiveTabHasCloseButton
|
||||
| XmlCompressionEnabled,///< default base configuration settings
|
||||
| XmlCompressionEnabled
|
||||
| FloatingContainerHasWidgetTitle,///< default base configuration settings
|
||||
|
||||
DefaultOpaqueConfig = DefaultBaseConfig
|
||||
| OpaqueSplitterResize
|
||||
@@ -191,12 +189,12 @@ public:
|
||||
* Before you create any dock widgets, you should properly setup the
|
||||
* configuration flags via setConfigFlags().
|
||||
*/
|
||||
CDockManager(QWidget* parent = 0);
|
||||
CDockManager(QWidget* parent = nullptr);
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~CDockManager();
|
||||
virtual ~CDockManager() override;
|
||||
|
||||
/**
|
||||
* This function returns the global configuration flags
|
||||
@@ -205,12 +203,14 @@ public:
|
||||
|
||||
/**
|
||||
* Sets the global configuration flags for the whole docking system.
|
||||
* Call this function before you create your first dock widget.
|
||||
* Call this function before you create the dock manager and before
|
||||
* your create the first dock widget.
|
||||
*/
|
||||
static void setConfigFlags(const ConfigFlags Flags);
|
||||
|
||||
/**
|
||||
* Set a certain config flag
|
||||
* Set a certain config flag.
|
||||
* \see setConfigFlags()
|
||||
*/
|
||||
static void setConfigFlag(eConfigFlag Flag, bool On = true);
|
||||
|
||||
@@ -446,10 +446,17 @@ signals:
|
||||
|
||||
/**
|
||||
* This signal is emitted if the dock manager finished opening a
|
||||
* perspective
|
||||
* perspective.
|
||||
*/
|
||||
void perspectiveOpened(const QString& PerspectiveName);
|
||||
|
||||
/**
|
||||
* This signal is emitted, if a new floating widget has been created.
|
||||
* An application can use this signal to e.g. subscribe to events of
|
||||
* the newly created window.
|
||||
*/
|
||||
void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted, if a new DockArea has been created.
|
||||
* An application can use this signal to set custom icons or custom
|
||||
|
||||
@@ -380,7 +380,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
|
||||
return Result;
|
||||
}
|
||||
|
||||
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(d->TargetWidget.data());
|
||||
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->TargetWidget.data());
|
||||
if (!DockArea)
|
||||
{
|
||||
return Result;
|
||||
@@ -396,6 +396,20 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
|
||||
{
|
||||
if (isHidden() || !d->DropPreviewEnabled)
|
||||
{
|
||||
return InvalidDockWidgetArea;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dropAreaUnderCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
|
||||
{
|
||||
@@ -632,7 +646,7 @@ void CDockOverlayCross::updateOverlayIcons()
|
||||
{
|
||||
d->updateDropIndicatorIcon(Widget);
|
||||
}
|
||||
#if QT_VESION >= 0x050600
|
||||
#if QT_VERSION >= 0x050600
|
||||
d->LastDevicePixelRatio = devicePixelRatioF();
|
||||
#else
|
||||
d->LastDevicePixelRatio = devicePixelRatio();
|
||||
|
||||
@@ -81,6 +81,13 @@ public:
|
||||
*/
|
||||
DockWidgetArea dropAreaUnderCursor() const;
|
||||
|
||||
/**
|
||||
* This function returns the same like dropAreaUnderCursor() if this
|
||||
* overlay is not hidden and if drop preview is enabled and returns
|
||||
* InvalidDockWidgetArea if it is hidden or drop preview is disabled.
|
||||
*/
|
||||
DockWidgetArea visibleDropAreaUnderCursor() const;
|
||||
|
||||
/**
|
||||
* Show the drop overly for the given target widget
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,20 @@ bool CDockSplitter::hasVisibleContent() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QWidget* CDockSplitter::firstWidget() const
|
||||
{
|
||||
return (count() > 0) ? widget(0) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QWidget* CDockSplitter::lastWidget() const
|
||||
{
|
||||
return (count() > 0) ? widget(count() - 1) : nullptr;
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -61,6 +61,16 @@ public:
|
||||
* Returns true, if any of the internal widgets is visible
|
||||
*/
|
||||
bool hasVisibleContent() const;
|
||||
|
||||
/**
|
||||
* Returns first widget or nullptr if splitter is empty
|
||||
*/
|
||||
QWidget* firstWidget() const;
|
||||
|
||||
/**
|
||||
* Returns last widget of nullptr is splitter is empty
|
||||
*/
|
||||
QWidget* lastWidget() const;
|
||||
}; // class CDockSplitter
|
||||
|
||||
} // namespace ads
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "DockManager.h"
|
||||
#include "FloatingDockContainer.h"
|
||||
#include "DockSplitter.h"
|
||||
#include "DockComponentsFactory.h"
|
||||
#include "ads_globals.h"
|
||||
|
||||
|
||||
@@ -81,6 +82,7 @@ struct DockWidgetPrivate
|
||||
QSize ToolBarIconSizeFloating = QSize(24, 24);
|
||||
bool IsFloatingTopLevel = false;
|
||||
QList<QAction*> TitleBarActions;
|
||||
CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -172,6 +174,12 @@ void DockWidgetPrivate::updateParentDockArea()
|
||||
return;
|
||||
}
|
||||
|
||||
// we don't need to change the current tab if the
|
||||
// current dock widget is not the one being closed
|
||||
if (DockArea->currentDockWidget() != _this){
|
||||
return;
|
||||
}
|
||||
|
||||
auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
|
||||
if (NextDockWidget)
|
||||
{
|
||||
@@ -220,7 +228,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
|
||||
setWindowTitle(title);
|
||||
setObjectName(title);
|
||||
|
||||
d->TabWidget = new CDockWidgetTab(this);
|
||||
d->TabWidget = componentsFactory()->createDockWidgetTab(this);
|
||||
d->ToggleViewAction = new QAction(title, this);
|
||||
d->ToggleViewAction->setCheckable(true);
|
||||
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
|
||||
@@ -417,6 +425,13 @@ void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
|
||||
{
|
||||
d->MinimumSizeHintMode = Mode;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::toggleView(bool Open)
|
||||
{
|
||||
@@ -746,7 +761,14 @@ void CDockWidget::setClosedState(bool Closed)
|
||||
//============================================================================
|
||||
QSize CDockWidget::minimumSizeHint() const
|
||||
{
|
||||
return QSize(60, 40);
|
||||
if (d->MinimumSizeHintMode == CDockWidget::MinimumSizeHintFromDockWidget || !d->Widget)
|
||||
{
|
||||
return QSize(60, 40);
|
||||
}
|
||||
else
|
||||
{
|
||||
return d->Widget->minimumSizeHint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -808,6 +830,7 @@ bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
|
||||
}
|
||||
}
|
||||
deleteDockWidget();
|
||||
emit closed();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -189,6 +189,23 @@ public:
|
||||
ForceNoScrollArea
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The mode of the minimumSizeHint() that is returned by the DockWidget
|
||||
* minimumSizeHint() function.
|
||||
* To ensure, that a dock widget does not block resizing, the dock widget
|
||||
* reimplements minimumSizeHint() function to return a very small minimum
|
||||
* size hint. If you would like to adhere the minimumSizeHint() from the
|
||||
* content widget, the set the minimumSizeHintMode() to
|
||||
* MinimumSizeHintFromContent.
|
||||
*/
|
||||
enum eMinimumSizeHintMode
|
||||
{
|
||||
MinimumSizeHintFromDockWidget,
|
||||
MinimumSizeHintFromContent
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This mode configures the behavior of the toggle view action.
|
||||
* If the mode if ActionModeToggle, then the toggle view action is
|
||||
@@ -225,7 +242,8 @@ public:
|
||||
virtual ~CDockWidget();
|
||||
|
||||
/**
|
||||
* We return a fixed minimum size hint for all dock widgets
|
||||
* We return a fixed minimum size hint or the size hint of the content
|
||||
* widget if minimum size hint mode is MinimumSizeHintFromContent
|
||||
*/
|
||||
virtual QSize minimumSizeHint() const override;
|
||||
|
||||
@@ -334,6 +352,13 @@ public:
|
||||
*/
|
||||
void setToggleViewActionMode(eToggleViewActionMode Mode);
|
||||
|
||||
/**
|
||||
* Configures the minimum size hint that is returned by the
|
||||
* minimumSizeHint() function.
|
||||
* \see eMinimumSizeHintMode for a detailed description
|
||||
*/
|
||||
void setMinimumSizeHintMode(eMinimumSizeHintMode Mode);
|
||||
|
||||
/**
|
||||
* Sets the dock widget icon that is shown in tabs and in toggle view
|
||||
* actions
|
||||
@@ -346,13 +371,10 @@ public:
|
||||
QIcon icon() const;
|
||||
|
||||
/**
|
||||
* If the WithToolBar layout flag is enabled, then this function returns
|
||||
* the dock widget toolbar. If the flag is disabled, the function returns
|
||||
* a nullptr.
|
||||
* This function returns the dock widget top tool bar.
|
||||
* If no toolbar is assigned, this function returns nullptr. To get a vaild
|
||||
* toolbar you either need to create a default empty toolbar via
|
||||
* createDefaultToolBar() function or you need to assign you custom
|
||||
* createDefaultToolBar() function or you need to assign your custom
|
||||
* toolbar via setToolBar().
|
||||
*/
|
||||
QToolBar* toolBar() const;
|
||||
|
||||
@@ -68,6 +68,7 @@ struct DockWidgetTabPrivate
|
||||
QLabel* IconLabel = nullptr;
|
||||
tTabLabel* TitleLabel;
|
||||
QPoint GlobalDragStartMousePosition;
|
||||
QPoint DragStartMousePosition;
|
||||
bool IsActiveTab = false;
|
||||
CDockAreaWidget* DockArea = nullptr;
|
||||
eDragState DragState = DraggingInactive;
|
||||
@@ -150,6 +151,15 @@ struct DockWidgetTabPrivate
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the drag start position in global and local coordinates
|
||||
*/
|
||||
void saveDragStartMousePosition(const QPoint& GlobalPos)
|
||||
{
|
||||
GlobalDragStartMousePosition = GlobalPos;
|
||||
DragStartMousePosition = _this->mapFromGlobal(GlobalPos);
|
||||
}
|
||||
};
|
||||
// struct DockWidgetTabPrivate
|
||||
|
||||
@@ -205,6 +215,8 @@ void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
|
||||
QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition;
|
||||
Distance.setY(0);
|
||||
auto TargetPos = Distance + TabDragStartPosition;
|
||||
TargetPos.rx() = qMax(TargetPos.x(), 0);
|
||||
TargetPos.rx() = qMin(_this->parentWidget()->rect().right() - _this->width() + 1, TargetPos.rx());
|
||||
_this->move(TargetPos);
|
||||
_this->raise();
|
||||
}
|
||||
@@ -229,7 +241,6 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
||||
|
||||
ADS_PRINT("startFloating");
|
||||
DragState = DraggingState;
|
||||
auto DragStartMousePosition = _this->mapFromGlobal(GlobalDragStartMousePosition);
|
||||
QSize Size = DockArea->size();
|
||||
IFloatingWidget* FloatingWidget = nullptr;
|
||||
bool OpaqueUndocking = CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking) ||
|
||||
@@ -287,7 +298,7 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
d->GlobalDragStartMousePosition = ev->globalPos();
|
||||
d->saveDragStartMousePosition(ev->globalPos());
|
||||
d->DragState = DraggingMousePressed;
|
||||
emit clicked();
|
||||
return;
|
||||
@@ -304,6 +315,7 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
auto CurrentDragState = d->DragState;
|
||||
d->GlobalDragStartMousePosition = QPoint();
|
||||
d->DragStartMousePosition = QPoint();
|
||||
d->DragState = DraggingInactive;
|
||||
|
||||
switch (CurrentDragState)
|
||||
@@ -354,9 +366,11 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
d->moveTab(ev);
|
||||
}
|
||||
|
||||
auto MappedPos = mapToParent(ev->pos());
|
||||
bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right());
|
||||
// Maybe a fixed drag distance is better here ?
|
||||
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y());
|
||||
if (DragDistanceY >= CDockManager::startDragDistance())
|
||||
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
|
||||
{
|
||||
// If this is the last dock area in a dock container with only
|
||||
// one single dock widget it does not make sense to move it to a new
|
||||
@@ -368,14 +382,19 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
return;
|
||||
}
|
||||
|
||||
// Floating is only allowed for widgets that are movable
|
||||
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||
|
||||
// Floating is only allowed for widgets that are floatable
|
||||
// If we do non opaque undocking, then can create the drag preview
|
||||
// if the widget is movable.
|
||||
auto Features = d->DockWidget->features();
|
||||
if (Features.testFlag(CDockWidget::DockWidgetFloatable)
|
||||
|| (Features.testFlag(CDockWidget::DockWidgetMovable) && !CDockManager::testConfigFlag(CDockManager::OpaqueUndocking)))
|
||||
{
|
||||
// If we undock, we need to restore the initial position of this
|
||||
// tab because it looks strange if it remains on its dragged position
|
||||
if (d->isDraggingState(DraggingTab) && !CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking))
|
||||
{
|
||||
this->move(d->TabDragStartPosition);
|
||||
parentWidget()->layout()->update();
|
||||
}
|
||||
d->startFloating();
|
||||
}
|
||||
@@ -407,7 +426,7 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
|
||||
return;
|
||||
}
|
||||
|
||||
d->GlobalDragStartMousePosition = ev->globalPos();
|
||||
d->saveDragStartMousePosition(ev->globalPos());
|
||||
QMenu Menu(this);
|
||||
|
||||
const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable);
|
||||
@@ -537,7 +556,7 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
||||
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||
{
|
||||
d->GlobalDragStartMousePosition = event->globalPos();
|
||||
d->saveDragStartMousePosition(event->globalPos());
|
||||
d->startFloating(DraggingInactive);
|
||||
}
|
||||
|
||||
@@ -580,7 +599,8 @@ void CDockWidgetTab::detachDockWidget()
|
||||
{
|
||||
return;
|
||||
}
|
||||
d->GlobalDragStartMousePosition = QCursor::pos();
|
||||
|
||||
d->saveDragStartMousePosition(QCursor::pos());
|
||||
d->startFloating(DraggingInactive);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,11 +94,6 @@ public:
|
||||
*/
|
||||
void setActiveTab(bool active);
|
||||
|
||||
/**
|
||||
* Returns the dock widget this title widget belongs to
|
||||
*/
|
||||
CDockWidget* dockWidget() const;
|
||||
|
||||
/**
|
||||
* Sets the dock area widget the dockWidget returned by dockWidget()
|
||||
* function belongs to.
|
||||
@@ -112,6 +107,11 @@ public:
|
||||
*/
|
||||
CDockAreaWidget* dockAreaWidget() const;
|
||||
|
||||
/**
|
||||
* Returns the dock widget this title widget belongs to
|
||||
*/
|
||||
CDockWidget* dockWidget() const;
|
||||
|
||||
/**
|
||||
* Sets the icon to show in title bar
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <QDebug>
|
||||
#include <QAbstractButton>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTime>
|
||||
|
||||
#include "DockContainerWidget.h"
|
||||
#include "DockAreaWidget.h"
|
||||
@@ -66,6 +67,7 @@ struct FloatingDockContainerPrivate
|
||||
QPoint DragStartMousePosition;
|
||||
CDockContainerWidget *DropContainer = nullptr;
|
||||
CDockAreaWidget *SingleDockArea = nullptr;
|
||||
QPoint DragStartPos;
|
||||
#ifdef Q_OS_LINUX
|
||||
QWidget* MouseEventHandler = nullptr;
|
||||
CFloatingWidgetTitleBar* TitleBar = nullptr;
|
||||
@@ -79,6 +81,14 @@ struct FloatingDockContainerPrivate
|
||||
void titleMouseReleaseEvent();
|
||||
void updateDropOverlays(const QPoint &GlobalPos);
|
||||
|
||||
/**
|
||||
* Returns true if the given config flag is set
|
||||
*/
|
||||
static bool testConfigFlag(CDockManager::eConfigFlag Flag)
|
||||
{
|
||||
return CDockManager::configFlags().testFlag(Flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests is a certain state is active
|
||||
*/
|
||||
@@ -100,6 +110,40 @@ struct FloatingDockContainerPrivate
|
||||
_this->setWindowTitle(Text);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Reflect the current dock widget title in the floating widget windowTitle()
|
||||
* depending on the CDockManager::FloatingContainerHasWidgetTitle flag
|
||||
*/
|
||||
void reflectCurrentWidget(CDockWidget* CurrentWidget)
|
||||
{
|
||||
// reflect CurrentWidget's title if configured to do so, otherwise display application name as window title
|
||||
if (testConfigFlag(CDockManager::FloatingContainerHasWidgetTitle))
|
||||
{
|
||||
setWindowTitle(CurrentWidget->windowTitle());
|
||||
}
|
||||
else
|
||||
{
|
||||
setWindowTitle(qApp->applicationDisplayName());
|
||||
}
|
||||
|
||||
// reflect CurrentWidget's icon if configured to do so, otherwise display application icon as window icon
|
||||
QIcon CurrentWidgetIcon = CurrentWidget->icon();
|
||||
if (testConfigFlag(CDockManager::FloatingContainerHasWidgetIcon)
|
||||
&& !CurrentWidgetIcon.isNull())
|
||||
{
|
||||
_this->setWindowIcon(CurrentWidget->icon());
|
||||
}
|
||||
else
|
||||
{
|
||||
_this->setWindowIcon(QApplication::windowIcon());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles escape key press when dragging around the floating widget
|
||||
*/
|
||||
void handleEscapeKey();
|
||||
};
|
||||
// struct FloatingDockContainerPrivate
|
||||
|
||||
@@ -231,6 +275,17 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void FloatingDockContainerPrivate::handleEscapeKey()
|
||||
{
|
||||
ADS_PRINT("FloatingDockContainerPrivate::handleEscapeKey()");
|
||||
setState(DraggingInactive);
|
||||
DockManager->containerOverlay()->hideOverlay();
|
||||
DockManager->dockAreaOverlay()->hideOverlay();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
|
||||
tFloatingWidgetBase(DockManager),
|
||||
@@ -330,6 +385,9 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
switch (d->DraggingState)
|
||||
{
|
||||
case DraggingMousePressed:
|
||||
#ifdef Q_OS_WIN
|
||||
qApp->installEventFilter(this);
|
||||
#endif
|
||||
d->setState(DraggingFloatingWidget);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
break;
|
||||
@@ -347,6 +405,8 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
@@ -410,6 +470,7 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||
Super::showEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::event(QEvent *e)
|
||||
{
|
||||
@@ -425,21 +486,17 @@ bool CFloatingDockContainer::event(QEvent *e)
|
||||
// It is really great to work around the whole NonClientMouseArea
|
||||
// bugs
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
|
||||
if (e->type()
|
||||
== QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
|
||||
{
|
||||
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
if (e->type() == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
|
||||
#else
|
||||
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
|
||||
#endif
|
||||
{
|
||||
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
||||
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
||||
d->DragStartPos = pos();
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case DraggingMousePressed:
|
||||
switch (e->type())
|
||||
@@ -482,12 +539,49 @@ bool CFloatingDockContainer::event(QEvent *e)
|
||||
}
|
||||
|
||||
#if (ADS_DEBUG_LEVEL > 0)
|
||||
qDebug() << "CFloatingDockContainer::event " << e->type();
|
||||
qDebug() << QTime::currentTime() << "CFloatingDockContainer::event " << e->type();
|
||||
#endif
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *e)
|
||||
{
|
||||
Q_UNUSED(watched);
|
||||
// I have not found a way to detect non client area key press events to
|
||||
// handle escape key presses. On Windows, if the escape key is pressed while
|
||||
// dragging around a widget, the widget position is reset to its start position
|
||||
// which in turn generates a QEvent::NonClientAreaMouseButtonRelease event
|
||||
// if the mouse is outside of the widget after the move to its initial position
|
||||
// or a QEvent::MouseButtonRelease event, if the mouse is inside of teh widget
|
||||
// after the position has been reset.
|
||||
// So we can install an event filter on the application to get these events
|
||||
// here to properly cancel dragging and hide the overlays.
|
||||
// If we are in DraggingFloatingWidget state, it means the widget
|
||||
// has been dragged already but if the position is the same like
|
||||
// the start position, then this is an indication that the escape
|
||||
// key has been pressed.
|
||||
if (e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::NonClientAreaMouseButtonRelease)
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::eventFilter QEvent::MouseButtonRelease or"
|
||||
"QEvent::NonClientAreaMouseButtonRelease" << "d->DragggingState " << d->DraggingState);
|
||||
qApp->removeEventFilter(this);
|
||||
if (d->DragStartPos == pos())
|
||||
{
|
||||
d->handleEscapeKey();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if (ADS_DEBUG_LEVEL > 0)
|
||||
qDebug() << QTime::currentTime() << "CFloatingDockContainer::eventFilter " << e->type();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
|
||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
||||
@@ -537,8 +631,8 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
||||
if (TopLevelDockArea)
|
||||
{
|
||||
d->SingleDockArea = TopLevelDockArea;
|
||||
d->setWindowTitle(
|
||||
d->SingleDockArea->currentDockWidget()->windowTitle());
|
||||
CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
|
||||
d->reflectCurrentWidget(CurrentWidget);
|
||||
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
|
||||
SLOT(onDockAreaCurrentChanged(int)));
|
||||
}
|
||||
@@ -551,6 +645,7 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
||||
d->SingleDockArea = nullptr;
|
||||
}
|
||||
d->setWindowTitle(qApp->applicationDisplayName());
|
||||
setWindowIcon(QApplication::windowIcon());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,11 +655,13 @@ void CFloatingDockContainer::updateWindowTitle()
|
||||
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
||||
if (TopLevelDockArea)
|
||||
{
|
||||
d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
|
||||
CDockWidget* CurrentWidget = TopLevelDockArea->currentDockWidget();
|
||||
d->reflectCurrentWidget(CurrentWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
d->setWindowTitle(qApp->applicationDisplayName());
|
||||
setWindowIcon(QApplication::windowIcon());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,7 +669,8 @@ void CFloatingDockContainer::updateWindowTitle()
|
||||
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
|
||||
{
|
||||
Q_UNUSED(Index);
|
||||
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
|
||||
CDockWidget* CurrentWidget = d->SingleDockArea->currentDockWidget();
|
||||
d->reflectCurrentWidget(CurrentWidget);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
@@ -180,6 +180,7 @@ protected: // reimplements QWidget
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
virtual void hideEvent(QHideEvent *event) override;
|
||||
virtual void showEvent(QShowEvent *event) override;
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
public:
|
||||
using Super = QWidget;
|
||||
|
||||
@@ -40,6 +40,7 @@ struct FloatingDragPreviewPrivate
|
||||
qreal WindowOpacity;
|
||||
bool Hidden = false;
|
||||
QPixmap ContentPreviewPixmap;
|
||||
bool Canceled = false;
|
||||
|
||||
|
||||
/**
|
||||
@@ -59,6 +60,7 @@ struct FloatingDragPreviewPrivate
|
||||
*/
|
||||
void cancelDragging()
|
||||
{
|
||||
Canceled = true;
|
||||
emit _this->draggingCanceled();
|
||||
DockManager->containerOverlay()->hideOverlay();
|
||||
DockManager->dockAreaOverlay()->hideOverlay();
|
||||
@@ -85,11 +87,6 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (DockContainer == ContainerWidget)
|
||||
{
|
||||
continue;
|
||||
}*/
|
||||
|
||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
|
||||
if (ContainerWidget->rect().contains(MappedPos))
|
||||
{
|
||||
@@ -148,6 +145,14 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
else
|
||||
{
|
||||
DockAreaOverlay->hideOverlay();
|
||||
// If there is only one single visible dock area in a container, then
|
||||
// it does not make sense to show a dock overlay because the dock area
|
||||
// would be removed and inserted at the same position
|
||||
if (VisibleDockAreas <= 1)
|
||||
{
|
||||
ContainerOverlay->hide();
|
||||
}
|
||||
|
||||
if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea)
|
||||
{
|
||||
DropContainer = nullptr;
|
||||
@@ -207,9 +212,9 @@ CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) :
|
||||
connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
|
||||
SLOT(onApplicationStateChanged(Qt::ApplicationState)));
|
||||
|
||||
// We need to install an event filter for the given Content
|
||||
// widget to receive the escape key press
|
||||
Content->installEventFilter(this);
|
||||
// The only safe way to receive escape key presses is to install an event
|
||||
// filter for the application object
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -281,35 +286,46 @@ void CFloatingDragPreview::moveEvent(QMoveEvent *event)
|
||||
void CFloatingDragPreview::finishDragging()
|
||||
{
|
||||
ADS_PRINT("CFloatingDragPreview::finishDragging");
|
||||
auto DockDropArea = d->DockManager->dockAreaOverlay()->dropAreaUnderCursor();
|
||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||
bool DropPossible = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea);
|
||||
if (d->DropContainer && DropPossible)
|
||||
auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor();
|
||||
auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor();
|
||||
if (d->DropContainer && (DockDropArea != InvalidDockWidgetArea))
|
||||
{
|
||||
d->DropContainer->dropWidget(d->Content, QCursor::pos());
|
||||
d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos()));
|
||||
}
|
||||
else if (d->DropContainer && (ContainerDropArea != InvalidDockWidgetArea))
|
||||
{
|
||||
d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDockWidget* DockWidget = qobject_cast<CDockWidget*>(d->Content);
|
||||
CFloatingDockContainer* FloatingWidget;
|
||||
if (DockWidget)
|
||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||
|
||||
if (DockWidget && DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||
{
|
||||
FloatingWidget = new CFloatingDockContainer(DockWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(d->Content);
|
||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
||||
if (DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||
{
|
||||
FloatingWidget = new CFloatingDockContainer(DockArea);
|
||||
}
|
||||
}
|
||||
FloatingWidget->setGeometry(this->geometry());
|
||||
FloatingWidget->show();
|
||||
if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame))
|
||||
|
||||
if (FloatingWidget)
|
||||
{
|
||||
QApplication::processEvents();
|
||||
int FrameHeight = FloatingWidget->frameGeometry().height() - FloatingWidget->geometry().height();
|
||||
QRect FixedGeometry = this->geometry();
|
||||
FixedGeometry.adjust(0, FrameHeight, 0, 0);
|
||||
FloatingWidget->setGeometry(FixedGeometry);
|
||||
FloatingWidget->setGeometry(this->geometry());
|
||||
FloatingWidget->show();
|
||||
if (!CDockManager::configFlags().testFlag(CDockManager::DragPreviewHasWindowFrame))
|
||||
{
|
||||
QApplication::processEvents();
|
||||
int FrameHeight = FloatingWidget->frameGeometry().height() - FloatingWidget->geometry().height();
|
||||
QRect FixedGeometry = this->geometry();
|
||||
FixedGeometry.adjust(0, FrameHeight, 0, 0);
|
||||
FloatingWidget->setGeometry(FixedGeometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,12 +384,12 @@ void CFloatingDragPreview::onApplicationStateChanged(Qt::ApplicationState state)
|
||||
bool CFloatingDragPreview::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(watched);
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
if (!d->Canceled && event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent* e = static_cast<QKeyEvent*>(event);
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
d->Content->removeEventFilter(this);
|
||||
watched->removeEventFilter(this);
|
||||
d->cancelDragging();
|
||||
}
|
||||
}
|
||||
@@ -383,7 +399,6 @@ bool CFloatingDragPreview::eventFilter(QObject *watched, QEvent *event)
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -43,7 +43,8 @@ HEADERS += \
|
||||
DockSplitter.h \
|
||||
DockAreaTitleBar.h \
|
||||
ElidingLabel.h \
|
||||
IconProvider.h
|
||||
IconProvider.h \
|
||||
DockComponentsFactory.h
|
||||
|
||||
|
||||
SOURCES += \
|
||||
@@ -61,7 +62,8 @@ SOURCES += \
|
||||
DockSplitter.cpp \
|
||||
DockAreaTitleBar.cpp \
|
||||
ElidingLabel.cpp \
|
||||
IconProvider.cpp
|
||||
IconProvider.cpp \
|
||||
DockComponentsFactory.cpp
|
||||
|
||||
|
||||
unix {
|
||||
|
||||
Reference in New Issue
Block a user