mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-18 00:04:02 -04:00
Merge pull request #4299 from alexbruy/checkable-combobox
[FEATURE] New custom widget checkable combobox
This commit is contained in:
commit
78d02b7fab
@ -37,6 +37,7 @@
|
||||
%Include qgscodeeditorcss.sip
|
||||
%End
|
||||
%Include qgscharacterselectdialog.sip
|
||||
%Include qgscheckablecombobox.sip
|
||||
%Include qgscolorbrewercolorrampdialog.sip
|
||||
%Include qgscolorbutton.sip
|
||||
%Include qgscolorrampbutton.sip
|
||||
|
153
python/gui/qgscheckablecombobox.sip
Normal file
153
python/gui/qgscheckablecombobox.sip
Normal file
@ -0,0 +1,153 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgscheckablecombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsCheckableComboBox : QComboBox
|
||||
{
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgscheckablecombobox.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsCheckableComboBox( QWidget *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsCheckableComboBox.
|
||||
%End
|
||||
|
||||
QString separator() const;
|
||||
%Docstring
|
||||
Returns separator used to separate items in the display text.
|
||||
\see setSeparator()
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
void setSeparator( const QString &separator );
|
||||
%Docstring
|
||||
Set separator used to separate items in the display text.
|
||||
\param separator separator to use
|
||||
\see separator()
|
||||
%End
|
||||
|
||||
QString defaultText() const;
|
||||
%Docstring
|
||||
Returns default text which will be displayed in the widget
|
||||
when no items selected.
|
||||
\see setDefaultText()
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
void setDefaultText( const QString &text );
|
||||
%Docstring
|
||||
Set default text which will be displayed in the widget when
|
||||
no items selected.
|
||||
\param text default text
|
||||
\see defaultText()
|
||||
%End
|
||||
|
||||
QStringList checkedItems() const;
|
||||
%Docstring
|
||||
Returns currently checked items.
|
||||
\see setCheckedItems()
|
||||
:rtype: list of str
|
||||
%End
|
||||
|
||||
Qt::CheckState itemCheckState( int index ) const;
|
||||
%Docstring
|
||||
Returns the checked state of the item identified by index
|
||||
\param index item index
|
||||
\see setItemCheckState()
|
||||
\see toggleItemCheckState()
|
||||
:rtype: Qt.CheckState
|
||||
%End
|
||||
|
||||
void setItemCheckState( int index, Qt::CheckState state );
|
||||
%Docstring
|
||||
Sets the item check state to state
|
||||
\param index item index
|
||||
\param state check state
|
||||
\see itemCheckState()
|
||||
\see toggleItemCheckState()
|
||||
%End
|
||||
|
||||
void toggleItemCheckState( int index );
|
||||
%Docstring
|
||||
Toggles the item check state
|
||||
\param index item index
|
||||
\see itemCheckState()
|
||||
\see setItemCheckState()
|
||||
%End
|
||||
|
||||
virtual void hidePopup();
|
||||
%Docstring
|
||||
Hides the list of items in the combobox if it is currently
|
||||
visible and resets the internal state.
|
||||
%End
|
||||
|
||||
virtual bool eventFilter( QObject *object, QEvent *event );
|
||||
%Docstring
|
||||
Filters events to enable context menu
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void checkedItemsChanged( const QStringList &items );
|
||||
%Docstring
|
||||
This signal is emitted whenever the checked items list changed.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void setCheckedItems( const QStringList &items );
|
||||
%Docstring
|
||||
Set items which should be checked/selected.
|
||||
\param items items to select
|
||||
\see checkedItems()
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
virtual void resizeEvent( QResizeEvent *event );
|
||||
%Docstring
|
||||
Handler for widget resizing
|
||||
%End
|
||||
|
||||
protected slots:
|
||||
|
||||
void showContextMenu( const QPoint &pos );
|
||||
%Docstring
|
||||
Display context menu which allows to select/deselect
|
||||
all items at once.
|
||||
%End
|
||||
|
||||
void selectAllOptions();
|
||||
%Docstring
|
||||
Selects all items.
|
||||
%End
|
||||
|
||||
void deselectAllOptions();
|
||||
%Docstring
|
||||
Removes selection from all items.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgscheckablecombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -14,6 +14,7 @@ SET (QGIS_CUSTOMWIDGETS_SRCS
|
||||
qgiscustomwidgets.cpp
|
||||
qgscollapsiblegroupboxplugin.cpp
|
||||
qgscolorbuttonplugin.cpp
|
||||
qgscheckablecomboboxplugin.cpp
|
||||
qgsdatetimeeditplugin.cpp
|
||||
qgsdockwidgetplugin.cpp
|
||||
qgsdoublespinboxplugin.cpp
|
||||
@ -40,6 +41,7 @@ SET (QGIS_CUSTOMWIDGETS_MOC_HDRS
|
||||
qgiscustomwidgets.h
|
||||
qgscollapsiblegroupboxplugin.h
|
||||
qgscolorbuttonplugin.h
|
||||
qgscheckablecomboboxplugin.h
|
||||
qgsdatetimeeditplugin.h
|
||||
qgsdockwidgetplugin.h
|
||||
qgsdoublespinboxplugin.h
|
||||
|
97
src/customwidgets/qgscheckablecomboboxplugin.cpp
Normal file
97
src/customwidgets/qgscheckablecomboboxplugin.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/***************************************************************************
|
||||
qgscheckablecomboboxplugin.cpp
|
||||
--------------------------------------
|
||||
Date : March 22, 2017
|
||||
Copyright : (C) 2017 Alexander Bruy
|
||||
Email : alexander dot bruy 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 "qgiscustomwidgets.h"
|
||||
#include "qgscheckablecombobox.h"
|
||||
#include "qgscheckablecomboboxplugin.h"
|
||||
|
||||
|
||||
QgsCheckableComboBoxPlugin::QgsCheckableComboBoxPlugin( QObject *parent )
|
||||
: QObject( parent )
|
||||
, mInitialized( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::name() const
|
||||
{
|
||||
return "QgsCheckableComboBox";
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::group() const
|
||||
{
|
||||
return QgisCustomWidgets::groupName();
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::includeFile() const
|
||||
{
|
||||
return "qgscheckablecombobox.h";
|
||||
}
|
||||
|
||||
QIcon QgsCheckableComboBoxPlugin::icon() const
|
||||
{
|
||||
return QIcon( ":/images/icons/qgis-icon-60x60.png" );
|
||||
}
|
||||
|
||||
bool QgsCheckableComboBoxPlugin::isContainer() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QWidget *QgsCheckableComboBoxPlugin::createWidget( QWidget *parent )
|
||||
{
|
||||
return new QgsCheckableComboBox( parent );
|
||||
}
|
||||
|
||||
bool QgsCheckableComboBoxPlugin::isInitialized() const
|
||||
{
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
void QgsCheckableComboBoxPlugin::initialize( QDesignerFormEditorInterface *core )
|
||||
{
|
||||
Q_UNUSED( core );
|
||||
if ( mInitialized )
|
||||
return;
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::toolTip() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::whatsThis() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBoxPlugin::domXml() const
|
||||
{
|
||||
return QString( "<ui language=\"c++\">\n"
|
||||
" <widget class=\"%1\" name=\"mComboBox\">\n"
|
||||
" <property name=\"geometry\">\n"
|
||||
" <rect>\n"
|
||||
" <x>0</x>\n"
|
||||
" <y>0</y>\n"
|
||||
" <width>160</width>\n"
|
||||
" <height>27</height>\n"
|
||||
" </rect>\n"
|
||||
" </property>\n"
|
||||
" </widget>\n"
|
||||
"</ui>\n" )
|
||||
.arg( name() );
|
||||
}
|
51
src/customwidgets/qgscheckablecomboboxplugin.h
Normal file
51
src/customwidgets/qgscheckablecomboboxplugin.h
Normal file
@ -0,0 +1,51 @@
|
||||
/***************************************************************************
|
||||
qgscheckablecomboboxplugin.h
|
||||
--------------------------------------
|
||||
Date : March 22, 2017
|
||||
Copyright : (C) 2017 Alexander Bruy
|
||||
Email : alexander dot bruy 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSCHECKABLECOMBOBOXPLUGIN_H
|
||||
#define QGSCHECKABLECOMBOBOXPLUGIN_H
|
||||
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
|
||||
#include <QtUiPlugin/QDesignerExportWidget>
|
||||
#include "qgis_customwidgets.h"
|
||||
|
||||
|
||||
class CUSTOMWIDGETS_EXPORT QgsCheckableComboBoxPlugin : public QObject, public QDesignerCustomWidgetInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( QDesignerCustomWidgetInterface )
|
||||
|
||||
public:
|
||||
explicit QgsCheckableComboBoxPlugin( QObject *parent = 0 );
|
||||
|
||||
private:
|
||||
bool mInitialized = false;
|
||||
|
||||
// QDesignerCustomWidgetInterface interface
|
||||
public:
|
||||
QString name() const override;
|
||||
QString group() const override;
|
||||
QString includeFile() const override;
|
||||
QIcon icon() const override;
|
||||
bool isContainer() const override;
|
||||
QWidget *createWidget( QWidget *parent ) override;
|
||||
bool isInitialized() const override;
|
||||
void initialize( QDesignerFormEditorInterface *core ) override;
|
||||
QString toolTip() const override;
|
||||
QString whatsThis() const override;
|
||||
QString domXml() const override;
|
||||
};
|
||||
#endif // QGSCHECKABLECOMBOBOXPLUGIN_H
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
qgsfilterlineeditplugin.cpp
|
||||
qgspasswordlineeditplugin.cpp
|
||||
--------------------------------------
|
||||
Date : March 13, 2017
|
||||
Copyright : (C) 2017 Alexander Bruy
|
||||
|
@ -172,6 +172,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgsbrowsertreeview.cpp
|
||||
qgsbusyindicatordialog.cpp
|
||||
qgscharacterselectdialog.cpp
|
||||
qgscheckablecombobox.cpp
|
||||
qgscodeeditor.cpp
|
||||
qgscodeeditorcss.cpp
|
||||
qgscodeeditorhtml.cpp
|
||||
@ -329,6 +330,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
qgsbrowsertreeview.h
|
||||
qgsbusyindicatordialog.h
|
||||
qgscharacterselectdialog.h
|
||||
qgscheckablecombobox.h
|
||||
qgscodeeditor.h
|
||||
qgscodeeditorcss.h
|
||||
qgscodeeditorhtml.h
|
||||
|
266
src/gui/qgscheckablecombobox.cpp
Normal file
266
src/gui/qgscheckablecombobox.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
/***************************************************************************
|
||||
qgscheckablecombobox.cpp
|
||||
------------------------
|
||||
begin : March 21, 2017
|
||||
copyright : (C) 2017 by Alexander Bruy
|
||||
email : alexander dot bruy 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 "qgscheckablecombobox.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QPoint>
|
||||
#include <QAbstractItemView>
|
||||
|
||||
|
||||
QgsCheckableItemModel::QgsCheckableItemModel( QObject *parent )
|
||||
: QStandardItemModel( 0, 1, parent )
|
||||
{
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsCheckableItemModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
return QStandardItemModel::flags( index ) | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
QVariant QgsCheckableItemModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
QVariant value = QStandardItemModel::data( index, role );
|
||||
|
||||
if ( index.isValid() && role == Qt::CheckStateRole && !value.isValid() )
|
||||
{
|
||||
value = Qt::Unchecked;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool QgsCheckableItemModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
bool ok = QStandardItemModel::setData( index, value, role );
|
||||
|
||||
if ( ok && role == Qt::CheckStateRole )
|
||||
{
|
||||
emit dataChanged( index, index );
|
||||
emit itemCheckStateChanged();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
QgsCheckBoxDelegate::QgsCheckBoxDelegate( QObject *parent )
|
||||
: QStyledItemDelegate( parent )
|
||||
{
|
||||
}
|
||||
|
||||
void QgsCheckBoxDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
|
||||
{
|
||||
QStyleOptionViewItem &nonConstOpt = const_cast<QStyleOptionViewItem &>( option );
|
||||
nonConstOpt.showDecorationSelected = false;
|
||||
QStyledItemDelegate::paint( painter, nonConstOpt, index );
|
||||
}
|
||||
|
||||
|
||||
QgsCheckableComboBox::QgsCheckableComboBox( QWidget *parent )
|
||||
: QComboBox( parent )
|
||||
, mSeparator( ", " )
|
||||
{
|
||||
setModel( new QgsCheckableItemModel( this ) );
|
||||
setItemDelegate( new QgsCheckBoxDelegate( this ) );
|
||||
|
||||
QLineEdit *lineEdit = new QLineEdit( this );
|
||||
lineEdit->setReadOnly( true );
|
||||
setLineEdit( lineEdit );
|
||||
|
||||
mContextMenu = new QMenu( this );
|
||||
mSelectAllAction = mContextMenu->addAction( tr( "Select all" ) );
|
||||
mDeselectAllAction = mContextMenu->addAction( tr( "Deselect all" ) );
|
||||
connect( mSelectAllAction, &QAction::triggered, this, &QgsCheckableComboBox::selectAllOptions );
|
||||
connect( mDeselectAllAction, &QAction::triggered, this, &QgsCheckableComboBox::deselectAllOptions );
|
||||
|
||||
view()->viewport()->installEventFilter( this );
|
||||
view()->setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
connect( view(), &QAbstractItemView::customContextMenuRequested, this, &QgsCheckableComboBox::showContextMenu );
|
||||
|
||||
QgsCheckableItemModel *myModel = qobject_cast<QgsCheckableItemModel *>( model() );
|
||||
connect( myModel, &QgsCheckableItemModel::itemCheckStateChanged, this, &QgsCheckableComboBox::updateCheckedItems );
|
||||
connect( model(), &QStandardItemModel::rowsInserted, this, [ = ]( const QModelIndex &, int, int ) { updateCheckedItems(); } );
|
||||
connect( model(), &QStandardItemModel::rowsRemoved, this, [ = ]( const QModelIndex &, int, int ) { updateCheckedItems(); } );
|
||||
|
||||
connect( this, static_cast< void ( QComboBox::* )( int ) >( &QComboBox::activated ), this, &QgsCheckableComboBox::toggleItemCheckState );
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBox::separator() const
|
||||
{
|
||||
return mSeparator;
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::setSeparator( const QString &separator )
|
||||
{
|
||||
if ( mSeparator != separator )
|
||||
{
|
||||
mSeparator = separator;
|
||||
updateDisplayText();
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsCheckableComboBox::defaultText() const
|
||||
{
|
||||
return mDefaultText;
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::setDefaultText( const QString &text )
|
||||
{
|
||||
if ( mDefaultText != text )
|
||||
{
|
||||
mDefaultText = text;
|
||||
updateDisplayText();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList QgsCheckableComboBox::checkedItems() const
|
||||
{
|
||||
QStringList items;
|
||||
|
||||
if ( model() )
|
||||
{
|
||||
QModelIndex index = model()->index( 0, modelColumn(), rootModelIndex() );
|
||||
QModelIndexList indexes = model()->match( index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly );
|
||||
Q_FOREACH ( const QModelIndex &index, indexes )
|
||||
{
|
||||
items += index.data().toString();
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
Qt::CheckState QgsCheckableComboBox::itemCheckState( int index ) const
|
||||
{
|
||||
return static_cast<Qt::CheckState>( itemData( index, Qt::CheckStateRole ).toInt() );
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::setItemCheckState( int index, Qt::CheckState state )
|
||||
{
|
||||
setItemData( index, state, Qt::CheckStateRole );
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::toggleItemCheckState( int index )
|
||||
{
|
||||
QVariant value = itemData( index, Qt::CheckStateRole );
|
||||
if ( value.isValid() )
|
||||
{
|
||||
Qt::CheckState state = static_cast<Qt::CheckState>( value.toInt() );
|
||||
setItemData( index, ( state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked ), Qt::CheckStateRole );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::hidePopup()
|
||||
{
|
||||
if ( !mSkipHide )
|
||||
{
|
||||
QComboBox::hidePopup();
|
||||
}
|
||||
mSkipHide = false;
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::showContextMenu( const QPoint &pos )
|
||||
{
|
||||
Q_UNUSED( pos );
|
||||
|
||||
mContextMenu->exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::selectAllOptions()
|
||||
{
|
||||
blockSignals( true );
|
||||
for ( int i = 0; i < count(); i++ )
|
||||
{
|
||||
setItemData( i, Qt::Checked, Qt::CheckStateRole );
|
||||
}
|
||||
blockSignals( false );
|
||||
updateCheckedItems();
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::deselectAllOptions()
|
||||
{
|
||||
blockSignals( true );
|
||||
for ( int i = 0; i < count(); i++ )
|
||||
{
|
||||
setItemData( i, Qt::Unchecked, Qt::CheckStateRole );
|
||||
}
|
||||
blockSignals( false );
|
||||
updateCheckedItems();
|
||||
}
|
||||
|
||||
bool QgsCheckableComboBox::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if ( ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease )
|
||||
&& object == view()->viewport() )
|
||||
{
|
||||
mSkipHide = true;
|
||||
}
|
||||
|
||||
if ( event->type() == QEvent::MouseButtonRelease )
|
||||
{
|
||||
if ( static_cast<QMouseEvent *>( event )->button() == Qt::RightButton )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::setCheckedItems( const QStringList &items )
|
||||
{
|
||||
Q_FOREACH ( const QString &text, items )
|
||||
{
|
||||
const int index = findText( text );
|
||||
setItemCheckState( index, index != -1 ? Qt::Checked : Qt::Unchecked );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::resizeEvent( QResizeEvent *event )
|
||||
{
|
||||
QComboBox::resizeEvent( event );
|
||||
updateDisplayText();
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::updateCheckedItems()
|
||||
{
|
||||
QStringList items = checkedItems();
|
||||
updateDisplayText();
|
||||
emit checkedItemsChanged( items );
|
||||
}
|
||||
|
||||
void QgsCheckableComboBox::updateDisplayText()
|
||||
{
|
||||
QString text;
|
||||
QStringList items = checkedItems();
|
||||
if ( items.isEmpty() )
|
||||
{
|
||||
text = mDefaultText;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = items.join( mSeparator );
|
||||
}
|
||||
|
||||
QRect rect = lineEdit()->rect();
|
||||
QFontMetrics fontMetrics( font() );
|
||||
text = fontMetrics.elidedText( text, Qt::ElideRight, rect.width() );
|
||||
setEditText( text );
|
||||
}
|
||||
|
238
src/gui/qgscheckablecombobox.h
Normal file
238
src/gui/qgscheckablecombobox.h
Normal file
@ -0,0 +1,238 @@
|
||||
/***************************************************************************
|
||||
qgscheckablecombobox.h
|
||||
------------------------
|
||||
begin : March 21, 2017
|
||||
copyright : (C) 2017 by Alexander Bruy
|
||||
email : alexander dot bruy 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSCHECKABLECOMBOBOX_H
|
||||
#define QGSCHECKABLECOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QMenu>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
class QEvent;
|
||||
|
||||
/** \class QgsCheckableItemModel
|
||||
* \ingroup gui
|
||||
* QStandardItemModel subclass which makes all items checkable
|
||||
* by default.
|
||||
* \since QGIS 3.0
|
||||
* \note not available in Python bindings
|
||||
**/
|
||||
#ifndef SIP_RUN
|
||||
class QgsCheckableItemModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsCheckableItemModel.
|
||||
* \param parent parent object
|
||||
*/
|
||||
QgsCheckableItemModel( QObject *parent = nullptr );
|
||||
|
||||
/** Returns a combination of the item flags: items are enabled
|
||||
* (ItemIsEnabled), selectable (ItemIsSelectable) and checkable
|
||||
* (ItemIsUserCheckable).
|
||||
* \param index item index
|
||||
*/
|
||||
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||
|
||||
/** Returns the data stored under the given role for the item
|
||||
* referred to by the index.
|
||||
* \param index item index
|
||||
* \param role data role
|
||||
*/
|
||||
virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const;
|
||||
|
||||
/** Sets the role data for the item at index to value.
|
||||
* \param index item index
|
||||
* \param value data value
|
||||
* \param role data role
|
||||
* \returns true on success, false otherwise
|
||||
*/
|
||||
virtual bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole );
|
||||
|
||||
signals:
|
||||
|
||||
/** This signal is emitted whenever the items checkstate has changed.
|
||||
*/
|
||||
void itemCheckStateChanged();
|
||||
};
|
||||
|
||||
|
||||
/** \class QgsCheckBoxDelegate
|
||||
* \ingroup gui
|
||||
* QStyledItemDelegate subclass for QgsCheckableComboBox. Needed for
|
||||
* correct drawing of the checkable items on Mac and GTK.
|
||||
* \since QGIS 3.0
|
||||
* \note not available in Python bindings
|
||||
**/
|
||||
|
||||
class QgsCheckBoxDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsCheckBoxDelegate.
|
||||
* \param parent parent object
|
||||
*/
|
||||
QgsCheckBoxDelegate( QObject *parent = nullptr );
|
||||
|
||||
/** Renders the delegate using the given painter and style option
|
||||
* for the item specified by index.
|
||||
* \param painter painter to use
|
||||
* \param option style option
|
||||
* \param index item index
|
||||
*/
|
||||
virtual void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** \class QgsCheckableComboBox
|
||||
* \ingroup gui
|
||||
* QComboBox subclass which allows selecting multiple items.
|
||||
* \since QGIS 3.0
|
||||
**/
|
||||
|
||||
class GUI_EXPORT QgsCheckableComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString separator READ separator WRITE setSeparator )
|
||||
Q_PROPERTY( QString defaultText READ defaultText WRITE setDefaultText )
|
||||
Q_PROPERTY( QStringList checkedItems READ checkedItems WRITE setCheckedItems )
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsCheckableComboBox.
|
||||
*/
|
||||
QgsCheckableComboBox( QWidget *parent SIP_TRANSFERTHIS = nullptr );
|
||||
|
||||
/** Returns separator used to separate items in the display text.
|
||||
* \see setSeparator()
|
||||
*/
|
||||
QString separator() const;
|
||||
|
||||
/** Set separator used to separate items in the display text.
|
||||
* \param separator separator to use
|
||||
* \see separator()
|
||||
*/
|
||||
void setSeparator( const QString &separator );
|
||||
|
||||
/** Returns default text which will be displayed in the widget
|
||||
* when no items selected.
|
||||
* \see setDefaultText()
|
||||
*/
|
||||
QString defaultText() const;
|
||||
|
||||
/** Set default text which will be displayed in the widget when
|
||||
* no items selected.
|
||||
* \param text default text
|
||||
* \see defaultText()
|
||||
*/
|
||||
void setDefaultText( const QString &text );
|
||||
|
||||
/** Returns currently checked items.
|
||||
* \see setCheckedItems()
|
||||
*/
|
||||
QStringList checkedItems() const;
|
||||
|
||||
/** Returns the checked state of the item identified by index
|
||||
* \param index item index
|
||||
* \see setItemCheckState()
|
||||
* \see toggleItemCheckState()
|
||||
*/
|
||||
Qt::CheckState itemCheckState( int index ) const;
|
||||
|
||||
/** Sets the item check state to state
|
||||
* \param index item index
|
||||
* \param state check state
|
||||
* \see itemCheckState()
|
||||
* \see toggleItemCheckState()
|
||||
*/
|
||||
void setItemCheckState( int index, Qt::CheckState state );
|
||||
|
||||
/** Toggles the item check state
|
||||
* \param index item index
|
||||
* \see itemCheckState()
|
||||
* \see setItemCheckState()
|
||||
*/
|
||||
void toggleItemCheckState( int index );
|
||||
|
||||
/** Hides the list of items in the combobox if it is currently
|
||||
* visible and resets the internal state.
|
||||
*/
|
||||
virtual void hidePopup() override;
|
||||
|
||||
/** Filters events to enable context menu
|
||||
*/
|
||||
virtual bool eventFilter( QObject *object, QEvent *event ) override;
|
||||
|
||||
signals:
|
||||
|
||||
/** This signal is emitted whenever the checked items list changed.
|
||||
*/
|
||||
void checkedItemsChanged( const QStringList &items );
|
||||
|
||||
public slots:
|
||||
|
||||
/** Set items which should be checked/selected.
|
||||
* \param items items to select
|
||||
* \see checkedItems()
|
||||
*/
|
||||
void setCheckedItems( const QStringList &items );
|
||||
|
||||
protected:
|
||||
|
||||
/** Handler for widget resizing
|
||||
*/
|
||||
virtual void resizeEvent( QResizeEvent *event ) override;
|
||||
|
||||
protected slots:
|
||||
|
||||
/** Display context menu which allows to select/deselect
|
||||
* all items at once.
|
||||
*/
|
||||
void showContextMenu( const QPoint &pos );
|
||||
|
||||
/** Selects all items.
|
||||
*/
|
||||
void selectAllOptions();
|
||||
|
||||
/** Removes selection from all items.
|
||||
*/
|
||||
void deselectAllOptions();
|
||||
|
||||
private:
|
||||
void updateCheckedItems();
|
||||
void updateDisplayText();
|
||||
|
||||
QString mSeparator;
|
||||
QString mDefaultText;
|
||||
|
||||
bool mSkipHide = false;
|
||||
|
||||
QMenu *mContextMenu = nullptr;
|
||||
QAction *mSelectAllAction = nullptr;
|
||||
QAction *mDeselectAllAction = nullptr;
|
||||
};
|
||||
|
||||
#endif // QGSCHECKABLECOMBOBOX_H
|
@ -20,6 +20,7 @@ ADD_PYTHON_TEST(PyQgsAttributeTableModel test_qgsattributetablemodel.py)
|
||||
ADD_PYTHON_TEST(PyQgsBearingUtils test_qgsbearingutils.py)
|
||||
ADD_PYTHON_TEST(PyQgsBlendModes test_qgsblendmodes.py)
|
||||
ADD_PYTHON_TEST(PyQgsCategorizedSymbolRenderer test_qgscategorizedsymbolrenderer.py)
|
||||
ADD_PYTHON_TEST(PyQgsCheckableComboBox test_qgscheckablecombobox.py)
|
||||
ADD_PYTHON_TEST(PyQgsColorButton test_qgscolorbutton.py)
|
||||
ADD_PYTHON_TEST(PyQgsColorScheme test_qgscolorscheme.py)
|
||||
ADD_PYTHON_TEST(PyQgsColorSchemeRegistry test_qgscolorschemeregistry.py)
|
||||
|
63
tests/src/python/test_qgscheckablecombobox.py
Normal file
63
tests/src/python/test_qgscheckablecombobox.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsCheckableComboBox
|
||||
|
||||
.. note:: 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.
|
||||
"""
|
||||
__author__ = 'Alexander Bruy'
|
||||
__date__ = '22/03/2017'
|
||||
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.PyQt.QtCore import Qt
|
||||
from qgis.PyQt.QtTest import QSignalSpy
|
||||
|
||||
from qgis.gui import QgsCheckableComboBox
|
||||
from qgis.testing import start_app, unittest
|
||||
|
||||
start_app()
|
||||
|
||||
|
||||
class TestQgsCheckableComboBox(unittest.TestCase):
|
||||
|
||||
def testGettersSetters(self):
|
||||
""" test widget getters/setters """
|
||||
w = qgis.gui.QgsCheckableComboBox()
|
||||
|
||||
w.setSeparator('|')
|
||||
self.assertEqual(w.separator(), '|')
|
||||
w.setDefaultText('Select items...')
|
||||
self.assertEqual(w.defaultText(), 'Select items...')
|
||||
|
||||
w.addItems(['One', 'Two', 'Three'])
|
||||
|
||||
w.setCheckedItems(['Two'])
|
||||
self.assertEqual(len(w.checkedItems()), 1)
|
||||
self.assertEqual(w.checkedItems(), ['Two'])
|
||||
w.setCheckedItems(['Three'])
|
||||
self.assertEqual(len(w.checkedItems()), 2)
|
||||
self.assertEqual(w.checkedItems(), ['Two', 'Three'])
|
||||
|
||||
w.setItemCheckState(2, Qt.Unchecked)
|
||||
self.assertEqual(w.itemCheckState(2), Qt.Unchecked)
|
||||
|
||||
def test_ChangedSignals(self):
|
||||
""" test that signals are correctly emitted when clearing"""
|
||||
|
||||
w = qgis.gui.QgsCheckableComboBox()
|
||||
|
||||
w.addItems(['One', 'Two', 'Three'])
|
||||
|
||||
checkedItemsChanged_spy = QSignalSpy(w.checkedItemsChanged)
|
||||
w.setCheckedItems(['Two'])
|
||||
|
||||
self.assertEqual(len(checkedItemsChanged_spy), 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user