17#include "moc_qgsdockablewidgethelper.cpp"
30std::function< void( Qt::DockWidgetArea, QDockWidget *,
const QStringList &,
bool ) > QgsDockableWidgetHelper::sAddTabifiedDockWidgetFunction = []( Qt::DockWidgetArea, QDockWidget *,
const QStringList &, bool ) {};
31std::function< QString( ) > QgsDockableWidgetHelper::sAppStylesheetFunction = [] {
return QString(); };
32QMainWindow *QgsDockableWidgetHelper::sOwnerWindow =
nullptr;
34QgsDockableWidgetHelper::QgsDockableWidgetHelper(
bool isDocked,
const QString &windowTitle, QWidget *widget, QMainWindow *ownerWindow,
35 Qt::DockWidgetArea defaultDockArea,
36 const QStringList &tabifyWith,
37 bool raiseTab,
const QString &windowGeometrySettingsKey,
bool usePersistentWidget )
40 , mDialogGeometry( 0, 0, 0, 0 )
41 , mIsDockFloating( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea )
42 , mDockArea( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea ? Qt::DockWidgetArea::RightDockWidgetArea : defaultDockArea )
43 , mWindowTitle( windowTitle )
44 , mOwnerWindow( ownerWindow )
45 , mTabifyWith( tabifyWith )
46 , mRaiseTab( raiseTab )
47 , mWindowGeometrySettingsKey( windowGeometrySettingsKey )
48 , mUuid( QUuid::createUuid().toString() )
49 , mUsePersistentWidget( usePersistentWidget )
51 toggleDockMode( isDocked );
54QgsDockableWidgetHelper::~QgsDockableWidgetHelper()
58 mDockGeometry = mDock->geometry();
59 mIsDockFloating = mDock->isFloating();
61 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
63 mDock->setWidget(
nullptr );
66 mOwnerWindow->removeDockWidget( mDock );
73 mDialogGeometry = mDialog->geometry();
75 if ( !mWindowGeometrySettingsKey.isEmpty() )
80 mDialog->layout()->removeWidget( mWidget );
81 mDialog->deleteLater();
86void QgsDockableWidgetHelper::writeXml( QDomElement &viewDom )
88 viewDom.setAttribute( QStringLiteral(
"isDocked" ), mIsDocked );
92 mDockGeometry = mDock->geometry();
93 mIsDockFloating = mDock->isFloating();
95 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
98 viewDom.setAttribute( QStringLiteral(
"x" ), mDockGeometry.x() );
99 viewDom.setAttribute( QStringLiteral(
"y" ), mDockGeometry.y() );
100 viewDom.setAttribute( QStringLiteral(
"width" ), mDockGeometry.width() );
101 viewDom.setAttribute( QStringLiteral(
"height" ), mDockGeometry.height() );
102 viewDom.setAttribute( QStringLiteral(
"floating" ), mIsDockFloating );
103 viewDom.setAttribute( QStringLiteral(
"area" ), mDockArea );
104 viewDom.setAttribute( QStringLiteral(
"uuid" ), mUuid );
108 const QList<QDockWidget * > tabSiblings = mOwnerWindow ? mOwnerWindow->tabifiedDockWidgets( mDock ) : QList<QDockWidget * >();
109 QDomElement tabSiblingsElement = viewDom.ownerDocument().createElement( QStringLiteral(
"tab_siblings" ) );
110 for ( QDockWidget *dock : tabSiblings )
112 QDomElement siblingElement = viewDom.ownerDocument().createElement( QStringLiteral(
"sibling" ) );
113 siblingElement.setAttribute( QStringLiteral(
"uuid" ), dock->property(
"dock_uuid" ).toString() );
114 siblingElement.setAttribute( QStringLiteral(
"object_name" ), dock->objectName() );
115 tabSiblingsElement.appendChild( siblingElement );
117 viewDom.appendChild( tabSiblingsElement );
121 mDialogGeometry = mDialog->geometry();
123 viewDom.setAttribute( QStringLiteral(
"d_x" ), mDialogGeometry.x() );
124 viewDom.setAttribute( QStringLiteral(
"d_y" ), mDialogGeometry.y() );
125 viewDom.setAttribute( QStringLiteral(
"d_width" ), mDialogGeometry.width() );
126 viewDom.setAttribute( QStringLiteral(
"d_height" ), mDialogGeometry.height() );
129void QgsDockableWidgetHelper::readXml(
const QDomElement &viewDom )
131 mUuid = viewDom.attribute( QStringLiteral(
"uuid" ), mUuid );
134 int x = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
135 int y = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
136 int w = viewDom.attribute( QStringLiteral(
"d_width" ), QStringLiteral(
"200" ) ).toInt();
137 int h = viewDom.attribute( QStringLiteral(
"d_height" ), QStringLiteral(
"200" ) ).toInt();
138 mDialogGeometry = QRect( x, y, w, h );
140 mDialog->setGeometry( mDialogGeometry );
144 int x = viewDom.attribute( QStringLiteral(
"x" ), QStringLiteral(
"0" ) ).toInt();
145 int y = viewDom.attribute( QStringLiteral(
"y" ), QStringLiteral(
"0" ) ).toInt();
146 int w = viewDom.attribute( QStringLiteral(
"width" ), QStringLiteral(
"200" ) ).toInt();
147 int h = viewDom.attribute( QStringLiteral(
"height" ), QStringLiteral(
"200" ) ).toInt();
148 mDockGeometry = QRect( x, y, w, h );
149 mIsDockFloating = viewDom.attribute( QStringLiteral(
"floating" ), QStringLiteral(
"0" ) ).toInt();
150 mDockArea =
static_cast< Qt::DockWidgetArea
>( viewDom.attribute( QStringLiteral(
"area" ), QString::number( Qt::RightDockWidgetArea ) ).toInt() );
152 if ( mDockArea == Qt::DockWidgetArea::NoDockWidgetArea && !mIsDockFloating )
154 mDockArea = Qt::RightDockWidgetArea;
157 QStringList tabSiblings;
158 const QDomElement tabSiblingsElement = viewDom.firstChildElement( QStringLiteral(
"tab_siblings" ) );
159 const QDomNodeList tabSiblingNodes = tabSiblingsElement.childNodes();
160 for (
int i = 0; i < tabSiblingNodes.size(); ++i )
162 const QDomElement tabSiblingElement = tabSiblingNodes.at( i ).toElement();
164 QString tabId = tabSiblingElement.attribute( QStringLiteral(
"uuid" ) );
165 if ( tabId.isEmpty() )
166 tabId = tabSiblingElement.attribute( QStringLiteral(
"object_name" ) );
167 if ( !tabId.isEmpty() )
168 tabSiblings.append( tabId );
171 setupDockWidget( tabSiblings );
176 mDock->setProperty(
"dock_uuid", mUuid );
180void QgsDockableWidgetHelper::setWidget( QWidget *widget )
183 if ( mWidget && mOwnerWindow )
185 mWidget->setParent( mOwnerWindow );
189 mDialog->layout()->removeWidget( mWidget );
193 mDock->setWidget(
nullptr );
197 toggleDockMode( mIsDocked );
205QDialog *QgsDockableWidgetHelper::dialog()
207 return mDialog.data();
210void QgsDockableWidgetHelper::toggleDockMode(
bool docked )
213 if ( mWidget && mOwnerWindow )
215 mWidget->setParent( mOwnerWindow );
221 mDockGeometry = mDock->geometry();
222 mIsDockFloating = mDock->isFloating();
224 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
226 mDock->setWidget(
nullptr );
228 mOwnerWindow->removeDockWidget( mDock );
236 if ( !mWindowGeometrySettingsKey.isEmpty() )
239 mDialogGeometry = mDialog->geometry();
242 mDialog->layout()->removeWidget( mWidget );
258 mDock->setWindowTitle( mWindowTitle );
259 mDock->setWidget( mWidget );
260 mDock->setObjectName( mObjectName );
261 mDock->setProperty(
"dock_uuid", mUuid );
266 mDockGeometry = mDock->geometry();
267 mIsDockFloating = mDock->isFloating();
269 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
273 if ( mUsePersistentWidget )
274 mDock->installEventFilter(
this );
276 connect( mDock, &QgsDockWidget::visibilityChanged,
this, &QgsDockableWidgetHelper::visibilityChanged );
277 mDock->setUserVisible(
true );
278 emit visibilityChanged(
true );
285 if ( mUsePersistentWidget )
286 mDialog =
new QgsNonRejectableDialog(
nullptr, Qt::Window );
288 mDialog =
new QDialog(
nullptr, Qt::Window );
289 mDialog->setStyleSheet( sAppStylesheetFunction() );
291 mDialog->setWindowTitle( mWindowTitle );
292 mDialog->setObjectName( mObjectName );
294 if ( mUsePersistentWidget )
295 mDialog->installEventFilter(
this );
297 QVBoxLayout *vl =
new QVBoxLayout();
298 vl->setContentsMargins( 0, 0, 0, 0 );
299 vl->addWidget( mWidget );
301 if ( !mWindowGeometrySettingsKey.isEmpty() )
304 mDialog->restoreGeometry( settings.
value( mWindowGeometrySettingsKey ).toByteArray() );
308 if ( !mDockGeometry.isEmpty() )
309 mDialog->setGeometry( mDockGeometry );
310 else if ( !mDialogGeometry.isEmpty() )
311 mDialog->setGeometry( mDialogGeometry );
313 mDialog->setLayout( vl );
317 connect( mDialog, &QDialog::finished,
this, [ = ]()
319 mDialogGeometry = mDialog->geometry();
321 emit visibilityChanged(
false );
324 emit visibilityChanged(
true );
326 emit dockModeToggled( docked );
329void QgsDockableWidgetHelper::setUserVisible(
bool visible )
337 mDialog->setWindowState( mDialog->windowState() & ~Qt::WindowMinimized );
338 mDialog->activateWindow();
347 mDock->setUserVisible( visible );
351void QgsDockableWidgetHelper::setWindowTitle(
const QString &title )
353 mWindowTitle = title;
356 mDialog->setWindowTitle( title );
360 mDock->setWindowTitle( title );
364void QgsDockableWidgetHelper::setDockObjectName(
const QString &name )
369 mDialog->setObjectName( name );
373 mDock->setObjectName( name );
377QString QgsDockableWidgetHelper::dockObjectName()
const {
return mObjectName; }
379bool QgsDockableWidgetHelper::isUserVisible()
const
383 return mDialog->isVisible();
387 return mDock->isUserVisible();
392void QgsDockableWidgetHelper::setupDockWidget(
const QStringList &tabSiblings )
397 mDock->setFloating( mIsDockFloating );
398 if ( mDockGeometry.isEmpty() && mOwnerWindow )
400 const QFontMetrics fm( mOwnerWindow->font() );
401 const int initialDockSize = fm.horizontalAdvance(
'0' ) * 75;
402 mDockGeometry = QRect(
static_cast< int >( mOwnerWindow->rect().width() * 0.75 ),
403 static_cast< int >( mOwnerWindow->rect().height() * 0.5 ),
404 initialDockSize, initialDockSize );
406 if ( !tabSiblings.isEmpty() )
408 sAddTabifiedDockWidgetFunction( mDockArea, mDock, tabSiblings,
false );
410 else if ( mRaiseTab )
412 sAddTabifiedDockWidgetFunction( mDockArea, mDock, mTabifyWith, mRaiseTab );
414 else if ( mOwnerWindow )
416 mOwnerWindow->addDockWidget( mDockArea, mDock );
421 QMetaObject::invokeMethod( mDock, [
this] { mDock->setGeometry( mDockGeometry ); }, Qt::QueuedConnection );
424QToolButton *QgsDockableWidgetHelper::createDockUndockToolButton()
426 QToolButton *toggleButton =
new QToolButton;
428 toggleButton->setCheckable(
true );
429 toggleButton->setChecked( mIsDocked );
430 toggleButton->setEnabled(
true );
432 connect( toggleButton, &QToolButton::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
436QAction *QgsDockableWidgetHelper::createDockUndockAction(
const QString &title, QWidget *parent )
438 QAction *toggleAction =
new QAction( title, parent );
440 toggleAction->setCheckable(
true );
441 toggleAction->setChecked( mIsDocked );
442 toggleAction->setEnabled(
true );
444 connect( toggleAction, &QAction::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
448bool QgsDockableWidgetHelper::eventFilter( QObject *watched, QEvent *event )
450 if ( watched == mDialog )
452 if ( event->type() == QEvent::Close )
456 emit visibilityChanged(
false );
460 else if ( watched == mDock )
462 if ( event->type() == QEvent::Close )
466 emit visibilityChanged(
false );
470 return QObject::eventFilter( watched, event );
477QgsNonRejectableDialog::QgsNonRejectableDialog( QWidget *parent, Qt::WindowFlags f )
478 : QDialog( parent, f )
483void QgsNonRejectableDialog::reject()
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.