Skip to content

Commit e58f25d

Browse files
committedMay 30, 2017
Create new QgsOpacityWidget widget
Allows consistent behavior and appearance across all opacity controls
1 parent a326224 commit e58f25d

File tree

11 files changed

+433
-0
lines changed

11 files changed

+433
-0
lines changed
 

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
%Include qgsnewnamedialog.sip
129129
%Include qgsnewvectorlayerdialog.sip
130130
%Include qgsnewgeopackagelayerdialog.sip
131+
%Include qgsopacitywidget.sip
131132
%Include qgsoptionsdialogbase.sip
132133
%Include qgsoptionswidgetfactory.sip
133134
%Include qgsorderbydialog.sip

‎python/gui/qgsopacitywidget.sip

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/qgsopacitywidget.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsOpacityWidget : QWidget
13+
{
14+
%Docstring
15+
A widget for setting an opacity value.
16+
.. versionadded:: 3.0
17+
%End
18+
19+
%TypeHeaderCode
20+
#include "qgsopacitywidget.h"
21+
%End
22+
public:
23+
24+
explicit QgsOpacityWidget( QWidget *parent /TransferThis/ = 0 );
25+
%Docstring
26+
Constructor for QgsOpacityWidget.
27+
%End
28+
29+
double opacity() const;
30+
%Docstring
31+
Returns the current opacity selected in the widget, where opacity ranges from 0.0 (transparent)
32+
to 1.0 (opaque).
33+
.. seealso:: setOpacity()
34+
.. seealso:: opacityChanged()
35+
:rtype: float
36+
%End
37+
38+
public slots:
39+
40+
void setOpacity( double opacity );
41+
%Docstring
42+
Sets the current ``opacity`` to show in the widget, where ``opacity`` ranges from 0.0 (transparent)
43+
to 1.0 (opaque).
44+
.. seealso:: opacity()
45+
.. seealso:: opacityChanged()
46+
%End
47+
48+
signals:
49+
50+
void opacityChanged( double opacity );
51+
%Docstring
52+
Emitted when the ``opacity`` is changed in the widget, where ``opacity`` ranges from 0.0 (transparent)
53+
to 1.0 (opaque).
54+
.. seealso:: setOpacity()
55+
.. seealso:: opacity()
56+
%End
57+
58+
};
59+
60+
/************************************************************************
61+
* This file has been generated automatically from *
62+
* *
63+
* src/gui/qgsopacitywidget.h *
64+
* *
65+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
66+
************************************************************************/

‎src/customwidgets/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ SET (QGIS_CUSTOMWIDGETS_SRCS
2626
qgsfilewidgetplugin.cpp
2727
qgsfilterlineeditplugin.cpp
2828
qgsmaplayercomboboxplugin.cpp
29+
qgsopacitywidgetplugin.cpp
2930
qgspasswordlineeditplugin.cpp
3031
qgsprojectionselectionwidgetplugin.cpp
3132
qgspropertyoverridebuttonplugin.cpp
@@ -54,6 +55,7 @@ SET (QGIS_CUSTOMWIDGETS_MOC_HDRS
5455
qgsfilewidgetplugin.h
5556
qgsfilterlineeditplugin.h
5657
qgsmaplayercomboboxplugin.h
58+
qgsopacitywidgetplugin.h
5759
qgspasswordlineeditplugin.h
5860
qgsprojectionselectionwidgetplugin.h
5961
qgspropertyoverridebuttonplugin.h
@@ -87,6 +89,7 @@ SET(QGIS_CUSTOMWIDGETS_HDRS
8789
qgsfilewidgetplugin.h
8890
qgsfilterlineeditplugin.h
8991
qgsmaplayercomboboxplugin.h
92+
qgsopacitywidgetplugin.h
9093
qgsprojectionselectionwidgetplugin.h
9194
qgspropertyoverridebuttonplugin.h
9295
qgsrasterbandcomboboxplugin.h

‎src/customwidgets/qgiscustomwidgets.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "qgsfilewidgetplugin.h"
2929
#include "qgsfilterlineeditplugin.h"
3030
#include "qgsmaplayercomboboxplugin.h"
31+
#include "qgsopacitywidgetplugin.h"
3132
#include "qgsprojectionselectionwidgetplugin.h"
3233
#include "qgspropertyoverridebuttonplugin.h"
3334
#include "qgsrasterbandcomboboxplugin.h"
@@ -53,6 +54,7 @@ QgisCustomWidgets::QgisCustomWidgets( QObject *parent )
5354
mWidgets.append( new QgsFileWidgetPlugin( this ) );
5455
mWidgets.append( new QgsFilterLineEditPlugin( this ) );
5556
mWidgets.append( new QgsMapLayerComboBoxPlugin( this ) );
57+
mWidgets.append( new QgsOpacityWidgetPlugin( this ) );
5658
mWidgets.append( new QgsProjectionSelectionWidgetPlugin( this ) );
5759
mWidgets.append( new QgsPropertyOverrideButtonPlugin( this ) );
5860
mWidgets.append( new QgsRasterBandComboBoxPlugin( this ) );
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/***************************************************************************
2+
qgsopacitywidgetplugin.cpp
3+
-------------------------
4+
Date : 30.05.2017
5+
Copyright : (C) 2017 Nyall Dawson
6+
Email : nyall.dawson@gmail.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgiscustomwidgets.h"
17+
#include "qgsopacitywidget.h"
18+
#include "qgsopacitywidgetplugin.h"
19+
20+
21+
QgsOpacityWidgetPlugin::QgsOpacityWidgetPlugin( QObject *parent )
22+
: QObject( parent )
23+
, mInitialized( false )
24+
{
25+
}
26+
27+
28+
QString QgsOpacityWidgetPlugin::name() const
29+
{
30+
return "QgsOpacityWidget";
31+
}
32+
33+
QString QgsOpacityWidgetPlugin::group() const
34+
{
35+
return QgisCustomWidgets::groupName();
36+
}
37+
38+
QString QgsOpacityWidgetPlugin::includeFile() const
39+
{
40+
return "qgsopacitywidget.h";
41+
}
42+
43+
QIcon QgsOpacityWidgetPlugin::icon() const
44+
{
45+
return QIcon( ":/images/icons/qgis-icon-60x60.png" );
46+
}
47+
48+
bool QgsOpacityWidgetPlugin::isContainer() const
49+
{
50+
return false;
51+
}
52+
53+
QWidget *QgsOpacityWidgetPlugin::createWidget( QWidget *parent )
54+
{
55+
return new QgsOpacityWidget( parent );
56+
}
57+
58+
bool QgsOpacityWidgetPlugin::isInitialized() const
59+
{
60+
return mInitialized;
61+
}
62+
63+
void QgsOpacityWidgetPlugin::initialize( QDesignerFormEditorInterface *core )
64+
{
65+
Q_UNUSED( core );
66+
if ( mInitialized )
67+
return;
68+
mInitialized = true;
69+
}
70+
71+
72+
QString QgsOpacityWidgetPlugin::toolTip() const
73+
{
74+
return tr( "A widget for specifying an opacity value." );
75+
}
76+
77+
QString QgsOpacityWidgetPlugin::whatsThis() const
78+
{
79+
return tr( "A widget for specifying an opacity value." );
80+
}
81+
82+
QString QgsOpacityWidgetPlugin::domXml() const
83+
{
84+
return QString( "<ui language=\"c++\">\n"
85+
" <widget class=\"%1\" name=\"mOpacityWidget\">\n"
86+
" <property name=\"geometry\">\n"
87+
" <rect>\n"
88+
" <x>0</x>\n"
89+
" <y>0</y>\n"
90+
" <width>160</width>\n"
91+
" <height>27</height>\n"
92+
" </rect>\n"
93+
" </property>\n"
94+
" </widget>\n"
95+
"</ui>\n" )
96+
.arg( name() );
97+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/***************************************************************************
2+
qgsopacitywidgetplugin.h
3+
-----------------------
4+
Date : 30.05.2017
5+
Copyright : (C) 2017 Nyall Dawson
6+
Email : nyall.dawson@gmail.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSOPACITYWIDGETPLUGIN_H
17+
#define QGSOPACITYWIDGETPLUGIN_H
18+
19+
20+
#include <QtGlobal>
21+
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
22+
#include <QtUiPlugin/QDesignerExportWidget>
23+
#include "qgis_customwidgets.h"
24+
25+
26+
class CUSTOMWIDGETS_EXPORT QgsOpacityWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
27+
{
28+
Q_OBJECT
29+
Q_INTERFACES( QDesignerCustomWidgetInterface )
30+
31+
public:
32+
explicit QgsOpacityWidgetPlugin( QObject *parent = 0 );
33+
34+
private:
35+
bool mInitialized;
36+
37+
// QDesignerCustomWidgetInterface interface
38+
public:
39+
QString name() const override;
40+
QString group() const override;
41+
QString includeFile() const override;
42+
QIcon icon() const override;
43+
bool isContainer() const override;
44+
QWidget *createWidget( QWidget *parent ) override;
45+
bool isInitialized() const override;
46+
void initialize( QDesignerFormEditorInterface *core ) override;
47+
QString toolTip() const override;
48+
QString whatsThis() const override;
49+
QString domXml() const override;
50+
};
51+
#endif // QGSOPACITYWIDGETPLUGIN_H

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ SET(QGIS_GUI_SRCS
273273
qgsnewnamedialog.cpp
274274
qgsnewvectorlayerdialog.cpp
275275
qgsnewgeopackagelayerdialog.cpp
276+
qgsopacitywidget.cpp
276277
qgsoptionsdialogbase.cpp
277278
qgsorderbydialog.cpp
278279
qgsowssourceselect.cpp
@@ -421,6 +422,7 @@ SET(QGIS_GUI_MOC_HDRS
421422
qgsnewnamedialog.h
422423
qgsnewvectorlayerdialog.h
423424
qgsnewgeopackagelayerdialog.h
425+
qgsopacitywidget.h
424426
qgsoptionsdialogbase.h
425427
qgsoptionswidgetfactory.h
426428
qgsorderbydialog.h

‎src/gui/qgsopacitywidget.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/***************************************************************************
2+
qgsopacitywidget.cpp
3+
-------------------
4+
Date : May 2017
5+
Copyright : (C) 2017 Nyall Dawson
6+
Email : nyall.dawson@gmail.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsopacitywidget.h"
17+
#include "qgsdoublespinbox.h"
18+
#include <QHBoxLayout>
19+
#include <QSlider>
20+
21+
QgsOpacityWidget::QgsOpacityWidget( QWidget *parent )
22+
: QWidget( parent )
23+
{
24+
QHBoxLayout *layout = new QHBoxLayout();
25+
layout->setContentsMargins( 0, 0, 0, 0 );
26+
layout->setSpacing( 0 );
27+
setLayout( layout );
28+
29+
mSlider = new QSlider();
30+
mSlider->setMinimum( 0 );
31+
mSlider->setMaximum( 1000 );
32+
mSlider->setSingleStep( 10 );
33+
mSlider->setPageStep( 100 );
34+
mSlider->setValue( 1000 );
35+
mSlider->setOrientation( Qt::Horizontal );
36+
layout->addWidget( mSlider, 1 );
37+
38+
mSpinBox = new QgsDoubleSpinBox();
39+
mSpinBox->setMinimum( 0.0 );
40+
mSpinBox->setMaximum( 100.0 );
41+
mSpinBox->setValue( 100.0 );
42+
mSpinBox->setClearValue( 100.0 );
43+
mSpinBox->setMinimumSize( QSize( 100, 0 ) );
44+
mSpinBox->setDecimals( 1 );
45+
mSpinBox->setSuffix( tr( " %" ) );
46+
layout->addWidget( mSpinBox, 0 );
47+
48+
setFocusProxy( mSpinBox );
49+
50+
connect( mSlider, &QSlider::valueChanged, this, [ = ]( int value ) { mSpinBox->setValue( value / 10.0 ); } );
51+
connect( mSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double value ) { whileBlocking( mSlider )->setValue( value * 10 ); } );
52+
connect( mSpinBox, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsOpacityWidget::spinChanged );
53+
}
54+
55+
double QgsOpacityWidget::opacity() const
56+
{
57+
return mSpinBox->value() / 100.0;
58+
}
59+
60+
void QgsOpacityWidget::setOpacity( double opacity )
61+
{
62+
mSpinBox->setValue( opacity * 100.0 );
63+
}
64+
65+
void QgsOpacityWidget::spinChanged( double value )
66+
{
67+
emit opacityChanged( value / 100.0 );
68+
}
69+

‎src/gui/qgsopacitywidget.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/***************************************************************************
2+
qgsopacitywidget.h
3+
-----------------
4+
Date : May 2017
5+
Copyright : (C) 2017 Nyall Dawson
6+
Email : nyall.dawson@gmail.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSOPACITYWIDGET_H
17+
#define QGSOPACITYWIDGET_H
18+
19+
#include <QWidget>
20+
#include "qgis.h"
21+
#include "qgis_gui.h"
22+
23+
class QgsDoubleSpinBox;
24+
class QSlider;
25+
26+
/**
27+
* \class QgsOpacityWidget
28+
* \ingroup gui
29+
* \brief A widget for setting an opacity value.
30+
* \since QGIS 3.0
31+
*/
32+
class GUI_EXPORT QgsOpacityWidget : public QWidget
33+
{
34+
Q_OBJECT
35+
Q_PROPERTY( double opacity READ opacity WRITE setOpacity NOTIFY opacityChanged )
36+
37+
public:
38+
39+
/**
40+
* Constructor for QgsOpacityWidget.
41+
*/
42+
explicit QgsOpacityWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );
43+
44+
/**
45+
* Returns the current opacity selected in the widget, where opacity ranges from 0.0 (transparent)
46+
* to 1.0 (opaque).
47+
* \see setOpacity()
48+
* \see opacityChanged()
49+
*/
50+
double opacity() const;
51+
52+
public slots:
53+
54+
/**
55+
* Sets the current \a opacity to show in the widget, where \a opacity ranges from 0.0 (transparent)
56+
* to 1.0 (opaque).
57+
* \see opacity()
58+
* \see opacityChanged()
59+
*/
60+
void setOpacity( double opacity );
61+
62+
signals:
63+
64+
/**
65+
* Emitted when the \a opacity is changed in the widget, where \a opacity ranges from 0.0 (transparent)
66+
* to 1.0 (opaque).
67+
* \see setOpacity()
68+
* \see opacity()
69+
*/
70+
void opacityChanged( double opacity );
71+
72+
private slots:
73+
74+
void spinChanged( double value );
75+
76+
private:
77+
78+
QgsDoubleSpinBox *mSpinBox = nullptr;
79+
QSlider *mSlider = nullptr;
80+
81+
};
82+
83+
#endif // QGSOPACITYWIDGET_H

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ ADD_PYTHON_TEST(PyQgsNewGeoPackageLayerDialog test_qgsnewgeopackagelayerdialog.p
9191
ADD_PYTHON_TEST(PyQgsNoApplication test_qgsnoapplication.py)
9292
ADD_PYTHON_TEST(PyQgsOGRProviderGpkg test_provider_ogr_gpkg.py)
9393
ADD_PYTHON_TEST(PyQgsOGRProviderSqlite test_provider_ogr_sqlite.py)
94+
ADD_PYTHON_TEST(PyQgsOpacityWidget test_qgsopacitywidget.py)
9495
ADD_PYTHON_TEST(PyQgsOptional test_qgsoptional.py)
9596
ADD_PYTHON_TEST(PyQgsPalLabelingBase test_qgspallabeling_base.py)
9697
ADD_PYTHON_TEST(PyQgsPalLabelingCanvas test_qgspallabeling_canvas.py)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for QgsOpacityWidget
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Nyall Dawson'
10+
__date__ = '30/05/2017'
11+
__copyright__ = 'Copyright 2017, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
from qgis.gui import QgsOpacityWidget
18+
19+
from qgis.PyQt.QtTest import QSignalSpy
20+
from qgis.testing import start_app, unittest
21+
22+
start_app()
23+
24+
25+
class TestQgsOpacityWidget(unittest.TestCase):
26+
27+
def testGettersSetters(self):
28+
""" test widget getters/setters """
29+
w = qgis.gui.QgsOpacityWidget()
30+
31+
w.setOpacity(0.2)
32+
self.assertEqual(w.opacity(), 0.2)
33+
34+
# bad values
35+
w.setOpacity(-0.2)
36+
self.assertEqual(w.opacity(), 0.0)
37+
w.setOpacity(100)
38+
self.assertEqual(w.opacity(), 1.0)
39+
40+
def test_ChangedSignals(self):
41+
""" test that signals are correctly emitted when setting opacity"""
42+
43+
w = qgis.gui.QgsOpacityWidget()
44+
45+
spy = QSignalSpy(w.opacityChanged)
46+
w.setOpacity(0.2)
47+
48+
self.assertEqual(len(spy), 1)
49+
self.assertEqual(spy[0][0], 0.2)
50+
51+
# bad value
52+
w.setOpacity(100)
53+
self.assertEqual(len(spy), 2)
54+
self.assertEqual(spy[1][0], 1.0)
55+
56+
57+
if __name__ == '__main__':
58+
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.