29std::function< void( Qt::DockWidgetArea, QDockWidget *,
const QStringList &,
bool ) > QgsDockableWidgetHelper::sAddTabifiedDockWidgetFunction = []( Qt::DockWidgetArea, QDockWidget *,
const QStringList &, bool ) {};
30std::function< QString( ) > QgsDockableWidgetHelper::sAppStylesheetFunction = [] {
return QString(); };
31QMainWindow *QgsDockableWidgetHelper::sOwnerWindow =
nullptr;
33QgsDockableWidgetHelper::QgsDockableWidgetHelper(
bool isDocked,
const QString &windowTitle, QWidget *widget, QMainWindow *ownerWindow,
34 Qt::DockWidgetArea defaultDockArea,
35 const QStringList &tabifyWith,
36 bool raiseTab,
const QString &windowGeometrySettingsKey,
bool usePersistentWidget )
39 , mDialogGeometry( 0, 0, 0, 0 )
40 , mIsDockFloating( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea )
41 , mDockArea( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea ? Qt::DockWidgetArea::RightDockWidgetArea : defaultDockArea )
42 , mWindowTitle( windowTitle )
43 , mOwnerWindow( ownerWindow )
44 , mTabifyWith( tabifyWith )
45 , mRaiseTab( raiseTab )
46 , mWindowGeometrySettingsKey( windowGeometrySettingsKey )
47 , mUuid( QUuid::createUuid().toString() )
48 , mUsePersistentWidget( usePersistentWidget )
50 toggleDockMode( isDocked );
53QgsDockableWidgetHelper::~QgsDockableWidgetHelper()
57 mDockGeometry = mDock->geometry();
58 mIsDockFloating = mDock->isFloating();
60 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
62 mDock->setWidget(
nullptr );
65 mOwnerWindow->removeDockWidget( mDock );
72 mDialogGeometry = mDialog->geometry();
74 if ( !mWindowGeometrySettingsKey.isEmpty() )
79 mDialog->layout()->removeWidget( mWidget );
80 mDialog->deleteLater();
85void QgsDockableWidgetHelper::writeXml( QDomElement &viewDom )
87 viewDom.setAttribute( QStringLiteral(
"isDocked" ), mIsDocked );
91 mDockGeometry = mDock->geometry();
92 mIsDockFloating = mDock->isFloating();
94 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
97 viewDom.setAttribute( QStringLiteral(
"x" ), mDockGeometry.x() );
98 viewDom.setAttribute( QStringLiteral(
"y" ), mDockGeometry.y() );
99 viewDom.setAttribute( QStringLiteral(
"width" ), mDockGeometry.width() );
100 viewDom.setAttribute( QStringLiteral(
"height" ), mDockGeometry.height() );
101 viewDom.setAttribute( QStringLiteral(
"floating" ), mIsDockFloating );
102 viewDom.setAttribute( QStringLiteral(
"area" ), mDockArea );
103 viewDom.setAttribute( QStringLiteral(
"uuid" ), mUuid );
107 const QList<QDockWidget * > tabSiblings = mOwnerWindow ? mOwnerWindow->tabifiedDockWidgets( mDock ) : QList<QDockWidget * >();
108 QDomElement tabSiblingsElement = viewDom.ownerDocument().createElement( QStringLiteral(
"tab_siblings" ) );
109 for ( QDockWidget *dock : tabSiblings )
111 QDomElement siblingElement = viewDom.ownerDocument().createElement( QStringLiteral(
"sibling" ) );
112 siblingElement.setAttribute( QStringLiteral(
"uuid" ), dock->property(
"dock_uuid" ).toString() );
113 siblingElement.setAttribute( QStringLiteral(
"object_name" ), dock->objectName() );
114 tabSiblingsElement.appendChild( siblingElement );
116 viewDom.appendChild( tabSiblingsElement );
120 mDialogGeometry = mDialog->geometry();
122 viewDom.setAttribute( QStringLiteral(
"d_x" ), mDialogGeometry.x() );
123 viewDom.setAttribute( QStringLiteral(
"d_y" ), mDialogGeometry.y() );
124 viewDom.setAttribute( QStringLiteral(
"d_width" ), mDialogGeometry.width() );
125 viewDom.setAttribute( QStringLiteral(
"d_height" ), mDialogGeometry.height() );
128void QgsDockableWidgetHelper::readXml(
const QDomElement &viewDom )
130 mUuid = viewDom.attribute( QStringLiteral(
"uuid" ), mUuid );
133 int x = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
134 int y = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
135 int w = viewDom.attribute( QStringLiteral(
"d_width" ), QStringLiteral(
"200" ) ).toInt();
136 int h = viewDom.attribute( QStringLiteral(
"d_height" ), QStringLiteral(
"200" ) ).toInt();
137 mDialogGeometry = QRect( x, y, w, h );
139 mDialog->setGeometry( mDialogGeometry );
143 int x = viewDom.attribute( QStringLiteral(
"x" ), QStringLiteral(
"0" ) ).toInt();
144 int y = viewDom.attribute( QStringLiteral(
"y" ), QStringLiteral(
"0" ) ).toInt();
145 int w = viewDom.attribute( QStringLiteral(
"width" ), QStringLiteral(
"200" ) ).toInt();
146 int h = viewDom.attribute( QStringLiteral(
"height" ), QStringLiteral(
"200" ) ).toInt();
147 mDockGeometry = QRect( x, y, w, h );
148 mIsDockFloating = viewDom.attribute( QStringLiteral(
"floating" ), QStringLiteral(
"0" ) ).toInt();
149 mDockArea =
static_cast< Qt::DockWidgetArea
>( viewDom.attribute( QStringLiteral(
"area" ), QString::number( Qt::RightDockWidgetArea ) ).toInt() );
151 if ( mDockArea == Qt::DockWidgetArea::NoDockWidgetArea && !mIsDockFloating )
153 mDockArea = Qt::RightDockWidgetArea;
156 QStringList tabSiblings;
157 const QDomElement tabSiblingsElement = viewDom.firstChildElement( QStringLiteral(
"tab_siblings" ) );
158 const QDomNodeList tabSiblingNodes = tabSiblingsElement.childNodes();
159 for (
int i = 0; i < tabSiblingNodes.size(); ++i )
161 const QDomElement tabSiblingElement = tabSiblingNodes.at( i ).toElement();
163 QString tabId = tabSiblingElement.attribute( QStringLiteral(
"uuid" ) );
164 if ( tabId.isEmpty() )
165 tabId = tabSiblingElement.attribute( QStringLiteral(
"object_name" ) );
166 if ( !tabId.isEmpty() )
167 tabSiblings.append( tabId );
170 setupDockWidget( tabSiblings );
175 mDock->setProperty(
"dock_uuid", mUuid );
179void QgsDockableWidgetHelper::setWidget( QWidget *widget )
182 if ( mWidget && mOwnerWindow )
184 mWidget->setParent( mOwnerWindow );
188 mDialog->layout()->removeWidget( mWidget );
192 mDock->setWidget(
nullptr );
196 toggleDockMode( mIsDocked );
204QDialog *QgsDockableWidgetHelper::dialog()
206 return mDialog.data();
209void QgsDockableWidgetHelper::toggleDockMode(
bool docked )
212 if ( mWidget && mOwnerWindow )
214 mWidget->setParent( mOwnerWindow );
220 mDockGeometry = mDock->geometry();
221 mIsDockFloating = mDock->isFloating();
223 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
225 mDock->setWidget(
nullptr );
227 mOwnerWindow->removeDockWidget( mDock );
235 if ( !mWindowGeometrySettingsKey.isEmpty() )
238 mDialogGeometry = mDialog->geometry();
241 mDialog->layout()->removeWidget( mWidget );
257 mDock->setWindowTitle( mWindowTitle );
258 mDock->setWidget( mWidget );
259 mDock->setObjectName( mObjectName );
260 mDock->setProperty(
"dock_uuid", mUuid );
265 mDockGeometry = mDock->geometry();
266 mIsDockFloating = mDock->isFloating();
268 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
272 if ( mUsePersistentWidget )
273 mDock->installEventFilter(
this );
275 connect( mDock, &QgsDockWidget::visibilityChanged,
this, &QgsDockableWidgetHelper::visibilityChanged );
276 mDock->setUserVisible(
true );
277 emit visibilityChanged(
true );
284 if ( mUsePersistentWidget )
285 mDialog =
new QgsNonRejectableDialog(
nullptr, Qt::Window );
287 mDialog =
new QDialog(
nullptr, Qt::Window );
288 mDialog->setStyleSheet( sAppStylesheetFunction() );
290 mDialog->setWindowTitle( mWindowTitle );
291 mDialog->setObjectName( mObjectName );
293 if ( mUsePersistentWidget )
294 mDialog->installEventFilter(
this );
296 QVBoxLayout *vl =
new QVBoxLayout();
297 vl->setContentsMargins( 0, 0, 0, 0 );
298 vl->addWidget( mWidget );
300 if ( !mWindowGeometrySettingsKey.isEmpty() )
303 mDialog->restoreGeometry( settings.
value( mWindowGeometrySettingsKey ).toByteArray() );
307 if ( !mDockGeometry.isEmpty() )
308 mDialog->setGeometry( mDockGeometry );
309 else if ( !mDialogGeometry.isEmpty() )
310 mDialog->setGeometry( mDialogGeometry );
312 mDialog->setLayout( vl );
316 connect( mDialog, &QDialog::finished,
this, [ = ]()
318 mDialogGeometry = mDialog->geometry();
320 emit visibilityChanged(
false );
323 emit visibilityChanged(
true );
325 emit dockModeToggled( docked );
328void QgsDockableWidgetHelper::setUserVisible(
bool visible )
336 mDialog->setWindowState( mDialog->windowState() & ~Qt::WindowMinimized );
337 mDialog->activateWindow();
346 mDock->setUserVisible( visible );
350void QgsDockableWidgetHelper::setWindowTitle(
const QString &title )
352 mWindowTitle = title;
355 mDialog->setWindowTitle( title );
359 mDock->setWindowTitle( title );
363void QgsDockableWidgetHelper::setDockObjectName(
const QString &name )
368 mDialog->setObjectName( name );
372 mDock->setObjectName( name );
376QString QgsDockableWidgetHelper::dockObjectName()
const {
return mObjectName; }
378bool QgsDockableWidgetHelper::isUserVisible()
const
382 return mDialog->isVisible();
386 return mDock->isUserVisible();
391void QgsDockableWidgetHelper::setupDockWidget(
const QStringList &tabSiblings )
396 mDock->setFloating( mIsDockFloating );
397 if ( mDockGeometry.isEmpty() && mOwnerWindow )
399 const QFontMetrics fm( mOwnerWindow->font() );
400 const int initialDockSize = fm.horizontalAdvance(
'0' ) * 50;
401 mDockGeometry = QRect(
static_cast< int >( mOwnerWindow->rect().width() * 0.75 ),
402 static_cast< int >( mOwnerWindow->rect().height() * 0.5 ),
403 initialDockSize, initialDockSize );
405 if ( !tabSiblings.isEmpty() )
407 sAddTabifiedDockWidgetFunction( mDockArea, mDock, tabSiblings,
false );
409 else if ( mRaiseTab )
411 sAddTabifiedDockWidgetFunction( mDockArea, mDock, mTabifyWith, mRaiseTab );
413 else if ( mOwnerWindow )
415 mOwnerWindow->addDockWidget( mDockArea, mDock );
420 QMetaObject::invokeMethod( mDock, [
this] { mDock->setGeometry( mDockGeometry ); }, Qt::QueuedConnection );
423QToolButton *QgsDockableWidgetHelper::createDockUndockToolButton()
425 QToolButton *toggleButton =
new QToolButton;
427 toggleButton->setCheckable(
true );
428 toggleButton->setChecked( mIsDocked );
429 toggleButton->setEnabled(
true );
431 connect( toggleButton, &QToolButton::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
435QAction *QgsDockableWidgetHelper::createDockUndockAction(
const QString &title, QWidget *parent )
437 QAction *toggleAction =
new QAction( title, parent );
439 toggleAction->setCheckable(
true );
440 toggleAction->setChecked( mIsDocked );
441 toggleAction->setEnabled(
true );
443 connect( toggleAction, &QAction::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
447bool QgsDockableWidgetHelper::eventFilter( QObject *watched, QEvent *event )
449 if ( watched == mDialog )
451 if ( event->type() == QEvent::Close )
455 emit visibilityChanged(
false );
459 else if ( watched == mDock )
461 if ( event->type() == QEvent::Close )
465 emit visibilityChanged(
false );
469 return QObject::eventFilter( watched, event );
476QgsNonRejectableDialog::QgsNonRejectableDialog( QWidget *parent, Qt::WindowFlags f )
477 : QDialog( parent, f )
482void 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.