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, Qt::DockWidgetArea defaultDockArea,
const QStringList &tabifyWith,
bool raiseTab,
const QString &windowGeometrySettingsKey,
bool usePersistentWidget )
37 , mDialogGeometry( 0, 0, 0, 0 )
38 , mIsDockFloating( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea )
39 , mDockArea( defaultDockArea == Qt::DockWidgetArea::NoDockWidgetArea ? Qt::DockWidgetArea::RightDockWidgetArea : defaultDockArea )
40 , mWindowTitle( windowTitle )
41 , mOwnerWindow( ownerWindow )
42 , mTabifyWith( tabifyWith )
43 , mRaiseTab( raiseTab )
44 , mWindowGeometrySettingsKey( windowGeometrySettingsKey )
45 , mUuid( QUuid::createUuid().toString() )
46 , mUsePersistentWidget( usePersistentWidget )
48 toggleDockMode( isDocked );
51QgsDockableWidgetHelper::~QgsDockableWidgetHelper()
55 mDockGeometry = mDock->geometry();
56 mIsDockFloating = mDock->isFloating();
58 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
60 mDock->setWidget(
nullptr );
63 mOwnerWindow->removeDockWidget( mDock );
70 mDialogGeometry = mDialog->geometry();
72 if ( !mWindowGeometrySettingsKey.isEmpty() )
77 mDialog->layout()->removeWidget( mWidget );
78 mDialog->deleteLater();
83void QgsDockableWidgetHelper::writeXml( QDomElement &viewDom )
85 viewDom.setAttribute( QStringLiteral(
"isDocked" ), mIsDocked );
89 mDockGeometry = mDock->geometry();
90 mIsDockFloating = mDock->isFloating();
92 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
95 viewDom.setAttribute( QStringLiteral(
"x" ), mDockGeometry.x() );
96 viewDom.setAttribute( QStringLiteral(
"y" ), mDockGeometry.y() );
97 viewDom.setAttribute( QStringLiteral(
"width" ), mDockGeometry.width() );
98 viewDom.setAttribute( QStringLiteral(
"height" ), mDockGeometry.height() );
99 viewDom.setAttribute( QStringLiteral(
"floating" ), mIsDockFloating );
100 viewDom.setAttribute( QStringLiteral(
"area" ), mDockArea );
101 viewDom.setAttribute( QStringLiteral(
"uuid" ), mUuid );
105 const QList<QDockWidget *> tabSiblings = mOwnerWindow ? mOwnerWindow->tabifiedDockWidgets( mDock ) : QList<QDockWidget *>();
106 QDomElement tabSiblingsElement = viewDom.ownerDocument().createElement( QStringLiteral(
"tab_siblings" ) );
107 for ( QDockWidget *dock : tabSiblings )
109 QDomElement siblingElement = viewDom.ownerDocument().createElement( QStringLiteral(
"sibling" ) );
110 siblingElement.setAttribute( QStringLiteral(
"uuid" ), dock->property(
"dock_uuid" ).toString() );
111 siblingElement.setAttribute( QStringLiteral(
"object_name" ), dock->objectName() );
112 tabSiblingsElement.appendChild( siblingElement );
114 viewDom.appendChild( tabSiblingsElement );
118 mDialogGeometry = mDialog->geometry();
120 viewDom.setAttribute( QStringLiteral(
"d_x" ), mDialogGeometry.x() );
121 viewDom.setAttribute( QStringLiteral(
"d_y" ), mDialogGeometry.y() );
122 viewDom.setAttribute( QStringLiteral(
"d_width" ), mDialogGeometry.width() );
123 viewDom.setAttribute( QStringLiteral(
"d_height" ), mDialogGeometry.height() );
126void QgsDockableWidgetHelper::readXml(
const QDomElement &viewDom )
128 mUuid = viewDom.attribute( QStringLiteral(
"uuid" ), mUuid );
131 int x = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
132 int y = viewDom.attribute( QStringLiteral(
"d_x" ), QStringLiteral(
"0" ) ).toInt();
133 int w = viewDom.attribute( QStringLiteral(
"d_width" ), QStringLiteral(
"200" ) ).toInt();
134 int h = viewDom.attribute( QStringLiteral(
"d_height" ), QStringLiteral(
"200" ) ).toInt();
135 mDialogGeometry = QRect( x, y, w, h );
137 mDialog->setGeometry( mDialogGeometry );
141 int x = viewDom.attribute( QStringLiteral(
"x" ), QStringLiteral(
"0" ) ).toInt();
142 int y = viewDom.attribute( QStringLiteral(
"y" ), QStringLiteral(
"0" ) ).toInt();
143 int w = viewDom.attribute( QStringLiteral(
"width" ), QStringLiteral(
"200" ) ).toInt();
144 int h = viewDom.attribute( QStringLiteral(
"height" ), QStringLiteral(
"200" ) ).toInt();
145 mDockGeometry = QRect( x, y, w, h );
146 mIsDockFloating = viewDom.attribute( QStringLiteral(
"floating" ), QStringLiteral(
"0" ) ).toInt();
147 mDockArea =
static_cast<Qt::DockWidgetArea
>( viewDom.attribute( QStringLiteral(
"area" ), QString::number( Qt::RightDockWidgetArea ) ).toInt() );
149 if ( mDockArea == Qt::DockWidgetArea::NoDockWidgetArea && !mIsDockFloating )
151 mDockArea = Qt::RightDockWidgetArea;
154 QStringList tabSiblings;
155 const QDomElement tabSiblingsElement = viewDom.firstChildElement( QStringLiteral(
"tab_siblings" ) );
156 const QDomNodeList tabSiblingNodes = tabSiblingsElement.childNodes();
157 for (
int i = 0; i < tabSiblingNodes.size(); ++i )
159 const QDomElement tabSiblingElement = tabSiblingNodes.at( i ).toElement();
161 QString tabId = tabSiblingElement.attribute( QStringLiteral(
"uuid" ) );
162 if ( tabId.isEmpty() )
163 tabId = tabSiblingElement.attribute( QStringLiteral(
"object_name" ) );
164 if ( !tabId.isEmpty() )
165 tabSiblings.append( tabId );
168 setupDockWidget( tabSiblings );
173 mDock->setProperty(
"dock_uuid", mUuid );
177void QgsDockableWidgetHelper::setWidget( QWidget *widget )
180 if ( mWidget && mOwnerWindow )
182 mWidget->setParent( mOwnerWindow );
186 mDialog->layout()->removeWidget( mWidget );
190 mDock->setWidget(
nullptr );
194 toggleDockMode( mIsDocked );
202QDialog *QgsDockableWidgetHelper::dialog()
204 return mDialog.data();
207void QgsDockableWidgetHelper::toggleDockMode(
bool docked )
210 if ( mWidget && mOwnerWindow )
212 mWidget->setParent( mOwnerWindow );
218 mDockGeometry = mDock->geometry();
219 mIsDockFloating = mDock->isFloating();
221 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
223 mDock->setWidget(
nullptr );
225 mOwnerWindow->removeDockWidget( mDock );
233 if ( !mWindowGeometrySettingsKey.isEmpty() )
236 mDialogGeometry = mDialog->geometry();
239 mDialog->layout()->removeWidget( mWidget );
255 mDock->setWindowTitle( mWindowTitle );
256 mDock->setWidget( mWidget );
257 mDock->setObjectName( mObjectName );
258 mDock->setProperty(
"dock_uuid", mUuid );
262 mDockGeometry = mDock->geometry();
263 mIsDockFloating = mDock->isFloating();
265 mDockArea = mOwnerWindow->dockWidgetArea( mDock );
269 if ( mUsePersistentWidget )
270 mDock->installEventFilter(
this );
272 connect( mDock, &QgsDockWidget::visibilityChanged,
this, &QgsDockableWidgetHelper::visibilityChanged );
273 mDock->setUserVisible(
true );
274 emit visibilityChanged(
true );
281 if ( mUsePersistentWidget )
282 mDialog =
new QgsNonRejectableDialog(
nullptr, Qt::Window );
284 mDialog =
new QDialog(
nullptr, Qt::Window );
285 mDialog->setStyleSheet( sAppStylesheetFunction() );
287 mDialog->setWindowTitle( mWindowTitle );
288 mDialog->setObjectName( mObjectName );
290 if ( mUsePersistentWidget )
291 mDialog->installEventFilter(
this );
293 QVBoxLayout *vl =
new QVBoxLayout();
294 vl->setContentsMargins( 0, 0, 0, 0 );
295 vl->addWidget( mWidget );
297 if ( !mWindowGeometrySettingsKey.isEmpty() )
300 mDialog->restoreGeometry( settings.
value( mWindowGeometrySettingsKey ).toByteArray() );
304 if ( !mDockGeometry.isEmpty() )
305 mDialog->setGeometry( mDockGeometry );
306 else if ( !mDialogGeometry.isEmpty() )
307 mDialog->setGeometry( mDialogGeometry );
309 mDialog->setLayout( vl );
313 connect( mDialog, &QDialog::finished,
this, [=]() {
314 mDialogGeometry = mDialog->geometry();
316 emit visibilityChanged(
false );
319 emit visibilityChanged(
true );
321 emit dockModeToggled( docked );
324void QgsDockableWidgetHelper::setUserVisible(
bool visible )
332 mDialog->setWindowState( mDialog->windowState() & ~Qt::WindowMinimized );
333 mDialog->activateWindow();
342 mDock->setUserVisible( visible );
346void QgsDockableWidgetHelper::setWindowTitle(
const QString &title )
348 mWindowTitle = title;
351 mDialog->setWindowTitle( title );
355 mDock->setWindowTitle( title );
359void QgsDockableWidgetHelper::setDockObjectName(
const QString &name )
364 mDialog->setObjectName( name );
368 mDock->setObjectName( name );
372QString QgsDockableWidgetHelper::dockObjectName()
const {
return mObjectName; }
374bool QgsDockableWidgetHelper::isUserVisible()
const
378 return mDialog->isVisible();
382 return mDock->isUserVisible();
387void QgsDockableWidgetHelper::setupDockWidget(
const QStringList &tabSiblings )
392 mDock->setFloating( mIsDockFloating );
393 if ( mDockGeometry.isEmpty() && mOwnerWindow )
395 const QFontMetrics fm( mOwnerWindow->font() );
396 const int initialDockSize = fm.horizontalAdvance(
'0' ) * 75;
397 mDockGeometry = QRect(
static_cast<int>( mOwnerWindow->rect().width() * 0.75 ),
static_cast<int>( mOwnerWindow->rect().height() * 0.5 ), initialDockSize, initialDockSize );
399 if ( !tabSiblings.isEmpty() )
401 sAddTabifiedDockWidgetFunction( mDockArea, mDock, tabSiblings,
false );
403 else if ( mRaiseTab )
405 sAddTabifiedDockWidgetFunction( mDockArea, mDock, mTabifyWith, mRaiseTab );
407 else if ( mOwnerWindow )
409 mOwnerWindow->addDockWidget( mDockArea, mDock );
414 QMetaObject::invokeMethod( mDock, [
this] { mDock->setGeometry( mDockGeometry ); }, Qt::QueuedConnection );
417QToolButton *QgsDockableWidgetHelper::createDockUndockToolButton()
419 QToolButton *toggleButton =
new QToolButton;
421 toggleButton->setCheckable(
true );
422 toggleButton->setChecked( mIsDocked );
423 toggleButton->setEnabled(
true );
425 connect( toggleButton, &QToolButton::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
429QAction *QgsDockableWidgetHelper::createDockUndockAction(
const QString &title, QWidget *parent )
431 QAction *toggleAction =
new QAction( title, parent );
433 toggleAction->setCheckable(
true );
434 toggleAction->setChecked( mIsDocked );
435 toggleAction->setEnabled(
true );
437 connect( toggleAction, &QAction::toggled,
this, &QgsDockableWidgetHelper::toggleDockMode );
441bool QgsDockableWidgetHelper::eventFilter( QObject *watched, QEvent *event )
443 if ( watched == mDialog )
445 if ( event->type() == QEvent::Close )
449 emit visibilityChanged(
false );
453 else if ( watched == mDock )
455 if ( event->type() == QEvent::Close )
459 emit visibilityChanged(
false );
463 return QObject::eventFilter( watched, event );
470QgsNonRejectableDialog::QgsNonRejectableDialog( QWidget *parent, Qt::WindowFlags f )
471 : QDialog( parent, f )
475void 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.