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' ) * 75;
 
  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.