Skip to content
Permalink
Browse files

Fix style dock button not synced to dock state (fix #14862)

Add a new class QgsDockWidget which has finer control over setting
and retrieving the dock visibility, to account for dock widgets
which are open but hidden by other docks
  • Loading branch information
nyalldawson committed Jun 9, 2016
1 parent a033e81 commit cb4dacfebcc8c53e7fa7e31bf612045aca6bd728
@@ -63,6 +63,7 @@
%Include qgsdetaileditemwidget.sip
%Include qgsdial.sip
%Include qgsdialog.sip
%Include qgsdockwidget.sip
%Include qgsencodingfiledialog.sip
%Include qgserrordialog.sip
%Include qgsexpressionbuilderdialog.sip
@@ -0,0 +1,61 @@
/** \ingroup gui
* \class QgsDockWidget
* QDockWidget subclass with more fine-grained control over how the widget is closed or opened.
* \note added in 2.16
*/

class QgsDockWidget : QDockWidget
{
%TypeHeaderCode
#include <qgsdockwidget.h>
%End

public:

/** Constructor for QgsDockWidget.
* @param parent parent widget
*/
explicit QgsDockWidget( QWidget* parent /TransferThis/ = nullptr );

public slots:

/** Sets the dock widget as visible to a user, ie both shown and raised to the front.
* @param visible set to true to show the dock to the user, or false to hide the dock.
* When setting a dock as user visible, the dock will be opened (if it is not already
* opened) and raised to the front.
* When setting as hidden, the following logic is used:
* - hiding a dock which is open but not raised (ie hidden by another tab) will have no
* effect, and the dock will still be opened and hidden by the other tab
* - hiding a dock which is open and raised (ie, user visible) will cause the dock to
* be closed
* - hiding a dock which is closed has no effect and raises no signals
* @see isUserVisible()
*/
void setUserVisible( bool visible );

/** Returns true if the dock is both opened and raised to the front (ie not hidden by
* any other tabs.
* @see setUserVisible()
*/
bool isUserVisible() const;

protected:

virtual void closeEvent( QCloseEvent * );
virtual void showEvent( QShowEvent* event );

signals:

/** Emitted when dock widget is closed (or opened).
* @param wasClosed will be true if dock widget was closed, or false if dock widget was opened
* @see opened()
*/
void closed( bool wasClosed );

/** Emitted when dock widget is opened (or closed).
* @param wasOpened will be true if dock widget was opened, or false if dock widget was closed
* @see closed()
*/
void opened( bool wasOpened );

};
@@ -135,6 +135,7 @@
#include "qgsdatasourceuri.h"
#include "qgsdatumtransformdialog.h"
#include "qgsdoublespinbox.h"
#include "qgsdockwidget.h"
#include "qgsdxfexport.h"
#include "qgsdxfexportdialog.h"
#include "qgsdecorationcopyright.h"
@@ -769,13 +770,13 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mUndoDock->hide();

startProfile( "Map Style dock" );
mMapStylingDock = new QDockWidget( this );
mMapStylingDock = new QgsDockWidget( this );
mMapStylingDock->setWindowTitle( tr( "Map Styling" ) );
mMapStylingDock->setObjectName( "MapStyling" );
mMapStyleWidget = new QgsMapStylingWidget( mMapCanvas, mMapStylePanelFactories );
mMapStylingDock->setWidget( mMapStyleWidget );
connect( mMapStyleWidget, SIGNAL( styleChanged( QgsMapLayer* ) ), this, SLOT( updateLabelToolButtons() ) );
// connect( mMapStylingDock, SIGNAL( visibilityChanged( bool ) ), mActionStyleDock, SLOT( setChecked( bool ) ) );
connect( mMapStylingDock, SIGNAL( visibilityChanged( bool ) ), mActionStyleDock, SLOT( setChecked( bool ) ) );

addDockWidget( Qt::RightDockWidgetArea, mMapStylingDock );
mMapStylingDock->hide();
@@ -5800,7 +5801,7 @@ void QgisApp::setMapStyleDockLayer( QgsMapLayer* layer )

void QgisApp::mapStyleDock( bool enabled )
{
mMapStylingDock->setVisible( enabled );
mMapStylingDock->setUserVisible( enabled );
setMapStyleDockLayer( activeLayer() );
}

@@ -49,6 +49,7 @@ class QgsStatusBarMagnifierWidget;
class QgsStatusBarScaleWidget;
class QgsContrastEnhancement;
class QgsCustomLayerOrderWidget;
class QgsDockWidget;
class QgsDoubleSpinBox;
class QgsFeature;
class QgsGeometry;
@@ -1730,7 +1731,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsSnappingDialog *mSnappingDialog;

QgsPluginManager *mPluginManager;
QDockWidget *mMapStylingDock;
QgsDockWidget *mMapStylingDock;
QgsMapStylingWidget* mMapStyleWidget;

QgsComposerManager *mComposerManager;
@@ -204,6 +204,7 @@ SET(QGIS_GUI_SRCS
qgsdetaileditemwidget.cpp
qgsdial.cpp
qgsdialog.cpp
qgsdockwidget.cpp
qgsencodingfiledialog.cpp
qgserrordialog.cpp
qgsexpressionbuilderdialog.cpp
@@ -360,6 +361,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsdetaileditemwidget.h
qgsdial.h
qgsdialog.h
qgsdockwidget.h
qgsencodingfiledialog.h
qgserrordialog.h
qgsexpressionbuilderdialog.h
@@ -0,0 +1,71 @@
/***************************************************************************
qgsdockwidget.cpp
-----------------
begin : June 2016
copyright : (C) 2016 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/


#include "qgsdockwidget.h"


QgsDockWidget::QgsDockWidget( QWidget* parent )
: QDockWidget( parent )
, mVisibleAndActive( false )
{
connect( this, SIGNAL( visibilityChanged( bool ) ), this, SLOT( handleVisibilityChanged( bool ) ) );
}

void QgsDockWidget::setUserVisible( bool visible )
{
if ( visible )
{
if ( mVisibleAndActive )
return;

show();
raise();
}
else
{
if ( !mVisibleAndActive )
return;

hide();
}
}

bool QgsDockWidget::isUserVisible() const
{
return mVisibleAndActive;
}

void QgsDockWidget::closeEvent( QCloseEvent* e )
{
emit closed( true );
emit opened( false );

This comment has been minimized.

Copy link
@m-kuhn

m-kuhn Jun 13, 2016

Member

What do you think about just emitting closed() here and opened() below?

That would make it easier to react without custom logic like

connect( dock, SIGNAL( closed() ), dock, SLOT( deleteLater() ) );

We can still introduce a signal openStateChanged( bool open ).

QDockWidget::closeEvent( e );
}

void QgsDockWidget::showEvent( QShowEvent* e )
{
emit closed( false );
emit opened( true );
QDockWidget::showEvent( e );
}

void QgsDockWidget::handleVisibilityChanged( bool visible )
{
mVisibleAndActive = visible;
}

@@ -0,0 +1,86 @@
/***************************************************************************
qgsdockwidget.h
---------------
begin : June 2016
copyright : (C) 2016 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include <QDockWidget>

/** \ingroup gui
* \class QgsDockWidget
* QDockWidget subclass with more fine-grained control over how the widget is closed or opened.
* \note added in 2.16
*/

class GUI_EXPORT QgsDockWidget : public QDockWidget
{
Q_OBJECT

public:

/** Constructor for QgsDockWidget.
* @param parent parent widget
*/
explicit QgsDockWidget( QWidget* parent = nullptr );

public slots:

/** Sets the dock widget as visible to a user, ie both shown and raised to the front.
* @param visible set to true to show the dock to the user, or false to hide the dock.
* When setting a dock as user visible, the dock will be opened (if it is not already
* opened) and raised to the front.
* When setting as hidden, the following logic is used:
* - hiding a dock which is open but not raised (ie hidden by another tab) will have no
* effect, and the dock will still be opened and hidden by the other tab
* - hiding a dock which is open and raised (ie, user visible) will cause the dock to
* be closed
* - hiding a dock which is closed has no effect and raises no signals
* @see isUserVisible()
*/
void setUserVisible( bool visible );

/** Returns true if the dock is both opened and raised to the front (ie not hidden by
* any other tabs.
* @see setUserVisible()
*/
bool isUserVisible() const;

protected:

virtual void closeEvent( QCloseEvent * ) override;
virtual void showEvent( QShowEvent* event ) override;

signals:

/** Emitted when dock widget is closed (or opened).
* @param wasClosed will be true if dock widget was closed, or false if dock widget was opened
* @see opened()
*/
void closed( bool wasClosed );

/** Emitted when dock widget is opened (or closed).
* @param wasOpened will be true if dock widget was opened, or false if dock widget was closed
* @see closed()
*/
void opened( bool wasOpened );

private slots:

void handleVisibilityChanged( bool visible );

private:

bool mVisibleAndActive;

};
@@ -129,6 +129,7 @@ ADD_QGIS_TEST(zoomtest testqgsmaptoolzoom.cpp)
ADD_QGIS_TEST(doublespinbox testqgsdoublespinbox.cpp)
ADD_QGIS_TEST(dualviewtest testqgsdualview.cpp)
ADD_QGIS_TEST(attributeformtest testqgsattributeform.cpp)
ADD_QGIS_TEST(dockwidget testqgsdockwidget.cpp)
ADD_QGIS_TEST(fieldexpressionwidget testqgsfieldexpressionwidget.cpp)
ADD_QGIS_TEST(filewidget testqgsfilewidget.cpp)
ADD_QGIS_TEST(focuswatcher testqgsfocuswatcher.cpp)

2 comments on commit cb4dacf

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn replied Jun 9, 2016

Nice.

It'd be good to seize of the opportunity to refactor the layer panel's toolbar buttons (I'm mostly thinking of the "filter legend by map content" and "filter legend by expression" buttons). Merging those two would make space for the style dock button to be moved there instead of floating to the right.

@NathanW2

This comment has been minimized.

Copy link
Member

@NathanW2 NathanW2 replied Jun 9, 2016

Very nice. That is a good fix.

Please sign in to comment.
You can’t perform that action at this time.