Skip to content

Commit

Permalink
Fix style dock button not synced to dock state (fix #14862)
Browse files Browse the repository at this point in the history
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 cb4dacf
Show file tree
Hide file tree
Showing 9 changed files with 402 additions and 4 deletions.
1 change: 1 addition & 0 deletions python/gui/gui.sip
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 61 additions & 0 deletions python/gui/qgsdockwidget.sip
Original file line number Diff line number Diff line change
@@ -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 );

};
7 changes: 4 additions & 3 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -5800,7 +5801,7 @@ void QgisApp::setMapStyleDockLayer( QgsMapLayer* layer )

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

Expand Down
3 changes: 2 additions & 1 deletion src/app/qgisapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class QgsStatusBarMagnifierWidget;
class QgsStatusBarScaleWidget;
class QgsContrastEnhancement;
class QgsCustomLayerOrderWidget;
class QgsDockWidget;
class QgsDoubleSpinBox;
class QgsFeature;
class QgsGeometry;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ SET(QGIS_GUI_SRCS
qgsdetaileditemwidget.cpp
qgsdial.cpp
qgsdialog.cpp
qgsdockwidget.cpp
qgsencodingfiledialog.cpp
qgserrordialog.cpp
qgsexpressionbuilderdialog.cpp
Expand Down Expand Up @@ -360,6 +361,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsdetaileditemwidget.h
qgsdial.h
qgsdialog.h
qgsdockwidget.h
qgsencodingfiledialog.h
qgserrordialog.h
qgsexpressionbuilderdialog.h
Expand Down
71 changes: 71 additions & 0 deletions src/gui/qgsdockwidget.cpp
Original file line number Diff line number Diff line change
@@ -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;
}

86 changes: 86 additions & 0 deletions src/gui/qgsdockwidget.h
Original file line number Diff line number Diff line change
@@ -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;

};
1 change: 1 addition & 0 deletions tests/src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

2 comments on commit cb4dacf

@nirvn
Copy link
Contributor

@nirvn nirvn commented on cb4dacf Jun 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice. That is a good fix.

Please sign in to comment.