Split symbol list off to its own reusable widget

This commit is contained in:
Nyall Dawson 2019-06-19 18:21:12 +10:00
parent e0446a7165
commit 4ea55fceaa
10 changed files with 976 additions and 625 deletions

View File

@ -0,0 +1,100 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsstyleitemslistwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsStyleItemsListWidget : QWidget
{
%Docstring
A reusable widget for showing a filtered list of entities from a QgsStyle database.
.. versionadded:: 3.10
%End
%TypeHeaderCode
#include "qgsstyleitemslistwidget.h"
%End
public:
QgsStyleItemsListWidget( QWidget *parent /TransferThis/ );
%Docstring
Constructor for QgsStyleItemsListWidget, with the specified ``parent`` widget.
%End
void setStyle( QgsStyle *style );
%Docstring
Sets the ``style`` database associated with the widget.
Ownership of ``style`` is not transferred, and the caller is responsible for ensuring that
it exists for the lifetime of the widget.
%End
void setEntityType( QgsStyle::StyleEntity type );
%Docstring
Sets the ``type`` of style entity to show in the widget.
.. seealso:: :py:func:`setSymbolType`
%End
void setSymbolType( QgsSymbol::SymbolType type );
%Docstring
Sets the ``type`` of symbols to show in the widget.
.. seealso:: :py:func:`setEntityType`
%End
QString currentItemName() const;
%Docstring
Returns the name of the item currently selected in the widget.
.. seealso:: :py:func:`currentEntityType`
%End
QgsStyle::StyleEntity currentEntityType() const;
%Docstring
Returns the type of the item currently selected in the widget.
.. seealso:: :py:func:`currentItemName`
%End
signals:
void selectionChanged( const QString &name, QgsStyle::StyleEntity type );
%Docstring
Emitted when the selected item is changed in the widget.
:param name: Newly selected item name
:param type: Newly selected item type
%End
void saveEntity();
%Docstring
Emitted when the user has opted to save a new entity to the style
database, by clicking the "Save" button in the widget.
It is the caller's responsibility to handle this in an appropriate
manner given the context of the widget.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsstyleitemslistwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -11,7 +11,6 @@
class QgsSymbolsListWidget : QWidget
{
@ -63,20 +62,11 @@ Returns the vector layer associated with the widget.
public slots:
void setSymbolFromStyle( const QModelIndex &index );
void setSymbolColor( const QColor &color );
void setMarkerAngle( double angle );
void setMarkerSize( double size );
void setLineWidth( double width );
void addSymbolToStyle();
void saveSymbol();
void populateGroups();
%Docstring
Pupulates the groups combo box with available tags and smartgroups
%End
void openStyleManager();
void clipFeaturesToggled( bool checked );
void updateDataDefinedMarkerSize();

View File

@ -204,6 +204,7 @@
%Include auto_generated/qgsslider.sip
%Include auto_generated/qgssnaptogridcanvasitem.sip
%Include auto_generated/qgsstatusbar.sip
%Include auto_generated/qgsstyleitemslistwidget.sip
%Include auto_generated/qgssublayersdialog.sip
%Include auto_generated/qgssubstitutionlistwidget.sip
%Include auto_generated/qgssymbolbutton.sip

View File

@ -373,6 +373,7 @@ SET(QGIS_GUI_SRCS
qgsslider.cpp
qgssnapindicator.cpp
qgssnaptogridcanvasitem.cpp
qgsstyleitemslistwidget.cpp
qgssublayersdialog.cpp
qgssubstitutionlistwidget.cpp
qgssqlcomposerdialog.cpp
@ -552,6 +553,7 @@ SET(QGIS_GUI_MOC_HDRS
qgssnaptogridcanvasitem.h
qgssqlcomposerdialog.h
qgsstatusbar.h
qgsstyleitemslistwidget.h
qgssublayersdialog.h
qgssubstitutionlistwidget.h
qgssymbolbutton.h

View File

@ -0,0 +1,376 @@
/***************************************************************************
qgsstyleitemslistwidget.cpp
---------------------------
begin : June 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail.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 "qgsstyleitemslistwidget.h"
#include "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgspanelwidget.h"
#include "qgssettings.h"
#include "qgsgui.h"
#include "qgswindowmanagerinterface.h"
//
// QgsReadOnlyStyleModel
//
///@cond PRIVATE
QgsReadOnlyStyleModel::QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent )
: QgsStyleProxyModel( style, parent )
{
}
Qt::ItemFlags QgsReadOnlyStyleModel::flags( const QModelIndex &index ) const
{
return QgsStyleProxyModel::flags( index ) & ~Qt::ItemIsEditable;
}
QVariant QgsReadOnlyStyleModel::data( const QModelIndex &index, int role ) const
{
if ( role == Qt::FontRole )
{
// drop font size to get reasonable amount of item name shown
QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
f.setPointSize( 9 );
return f;
}
return QgsStyleProxyModel::data( index, role );
}
///@endcond
//
// QgsStyleItemsListWidget
//
QgsStyleItemsListWidget::QgsStyleItemsListWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );
btnAdvanced->hide(); // advanced button is hidden by default
btnAdvanced->setMenu( new QMenu( this ) );
double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10;
viewSymbols->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) ); // ~100, 90 on low dpi
double treeIconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 2;
mSymbolTreeView->setIconSize( QSize( static_cast< int >( treeIconSize ), static_cast< int >( treeIconSize ) ) );
viewSymbols->setSelectionBehavior( QAbstractItemView::SelectRows );
mSymbolTreeView->setSelectionMode( viewSymbols->selectionMode() );
connect( openStyleManagerButton, &QToolButton::clicked, this, &QgsStyleItemsListWidget::openStyleManager );
lblSymbolName->clear();
connect( mButtonIconView, &QToolButton::toggled, this, [ = ]( bool active )
{
if ( active )
{
mSymbolViewStackedWidget->setCurrentIndex( 0 );
// note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui );
}
} );
connect( mButtonListView, &QToolButton::toggled, this, [ = ]( bool active )
{
if ( active )
{
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 1, QgsSettings::Gui );
mSymbolViewStackedWidget->setCurrentIndex( 1 );
}
} );
// restore previous view
QgsSettings settings;
const int currentView = settings.value( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui ).toInt();
if ( currentView == 0 )
mButtonIconView->setChecked( true );
else
mButtonListView->setChecked( true );
mSymbolTreeView->header()->restoreState( settings.value( QStringLiteral( "UI/symbolsList/treeState" ), QByteArray(), QgsSettings::Gui ).toByteArray() );
connect( mSymbolTreeView->header(), &QHeaderView::sectionResized, this, [this]
{
// note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
} );
QgsFilterLineEdit *groupEdit = new QgsFilterLineEdit();
groupEdit->setShowSearchIcon( true );
groupEdit->setShowClearButton( true );
groupEdit->setPlaceholderText( tr( "Filter symbols…" ) );
groupsCombo->setLineEdit( groupEdit );
connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsStyleItemsListWidget::saveEntity );
}
void QgsStyleItemsListWidget::setStyle( QgsStyle *style )
{
mStyle = style;
mModel = new QgsReadOnlyStyleModel( mStyle, this );
mModel->addDesiredIconSize( viewSymbols->iconSize() );
mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
viewSymbols->setModel( mModel );
mSymbolTreeView->setModel( mModel );
connect( mStyle, &QgsStyle::groupsModified, this, &QgsStyleItemsListWidget::populateGroups );
mSymbolTreeView->setSelectionModel( viewSymbols->selectionModel() );
connect( viewSymbols->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsStyleItemsListWidget::onSelectionChanged );
populateGroups();
connect( groupsCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsStyleItemsListWidget::groupsCombo_currentIndexChanged );
connect( groupsCombo, &QComboBox::currentTextChanged, this, &QgsStyleItemsListWidget::updateModelFilters );
}
void QgsStyleItemsListWidget::setEntityType( QgsStyle::StyleEntity type )
{
mModel->setEntityFilterEnabled( true );
mModel->setEntityFilter( type );
const int allGroup = groupsCombo->findData( QVariant( "all" ) );
switch ( type )
{
case QgsStyle::SymbolEntity:
btnSaveSymbol->setText( tr( "Save Symbol…" ) );
btnSaveSymbol->setToolTip( tr( "Save symbol to styles" ) );
if ( allGroup >= 0 )
groupsCombo->setItemText( allGroup, tr( "All Symbols" ) );
break;
case QgsStyle::ColorrampEntity:
btnSaveSymbol->setText( tr( "Save Color Ramp…" ) );
btnSaveSymbol->setToolTip( tr( "Save color ramp to styles" ) );
if ( allGroup >= 0 )
groupsCombo->setItemText( allGroup, tr( "All Color Ramps" ) );
break;
case QgsStyle::TextFormatEntity:
btnSaveSymbol->setText( tr( "Save Format…" ) );
btnSaveSymbol->setToolTip( tr( "Save text format to styles" ) );
if ( allGroup >= 0 )
groupsCombo->setItemText( allGroup, tr( "All Text Formats" ) );
break;
case QgsStyle::TagEntity:
case QgsStyle::SmartgroupEntity:
break;
}
}
void QgsStyleItemsListWidget::setSymbolType( QgsSymbol::SymbolType type )
{
mModel->setSymbolTypeFilterEnabled( true );
mModel->setSymbolType( type );
}
QMenu *QgsStyleItemsListWidget::advancedMenu()
{
return btnAdvanced->menu();
}
void QgsStyleItemsListWidget::setAdvancedMenu( QMenu *menu )
{
if ( menu ) // show it if there is a menu pointer
{
btnAdvanced->show();
btnAdvanced->setMenu( menu );
}
}
void QgsStyleItemsListWidget::showAdvancedButton( bool enabled )
{
btnAdvanced->setVisible( enabled );
}
QString QgsStyleItemsListWidget::currentItemName() const
{
QItemSelection selection = viewSymbols->selectionModel()->selection();
if ( selection.isEmpty() )
return QString();
const QModelIndex index = selection.at( 0 ).topLeft();
return mModel->data( index, QgsStyleModel::Name ).toString();
}
QgsStyle::StyleEntity QgsStyleItemsListWidget::currentEntityType() const
{
QItemSelection selection = viewSymbols->selectionModel()->selection();
if ( selection.isEmpty() )
return QgsStyle::SymbolEntity;
const QModelIndex index = selection.at( 0 ).topLeft();
return static_cast< QgsStyle::StyleEntity >( mModel->data( index, QgsStyleModel::TypeRole ).toInt() );
}
void QgsStyleItemsListWidget::populateGroups()
{
if ( !mStyle )
return;
mUpdatingGroups = true;
groupsCombo->blockSignals( true );
groupsCombo->clear();
groupsCombo->addItem( tr( "Favorites" ), QVariant( "favorite" ) );
QString allText = tr( "All Symbols" );
if ( mModel->entityFilterEnabled() )
{
switch ( mModel->entityFilter() )
{
case QgsStyle::SymbolEntity:
allText = tr( "All Symbols" );
break;
case QgsStyle::ColorrampEntity:
allText = tr( "All Color Ramps" );
break;
case QgsStyle::TextFormatEntity:
allText = tr( "All Text Formats" );
break;
case QgsStyle::TagEntity:
case QgsStyle::SmartgroupEntity:
break;
}
}
groupsCombo->addItem( allText, QVariant( "all" ) );
int index = 2;
QStringList tags = mStyle->tags();
if ( tags.count() > 0 )
{
tags.sort();
groupsCombo->insertSeparator( index );
const auto constTags = tags;
for ( const QString &tag : constTags )
{
groupsCombo->addItem( tag, QVariant( "tag" ) );
index++;
}
}
QStringList groups = mStyle->smartgroupNames();
if ( groups.count() > 0 )
{
groups.sort();
groupsCombo->insertSeparator( index + 1 );
const auto constGroups = groups;
for ( const QString &group : constGroups )
{
groupsCombo->addItem( group, QVariant( "smartgroup" ) );
}
}
groupsCombo->blockSignals( false );
QgsSettings settings;
index = settings.value( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 ).toInt();
groupsCombo->setCurrentIndex( index );
mUpdatingGroups = false;
updateModelFilters();
}
void QgsStyleItemsListWidget::updateModelFilters()
{
if ( mUpdatingGroups || !mModel )
return;
const QString text = groupsCombo->currentText();
const bool isFreeText = text != groupsCombo->itemText( groupsCombo->currentIndex() );
if ( isFreeText )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( groupsCombo->currentText() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
{
mModel->setFavoritesOnly( true );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( mStyle->smartgroupId( text ) );
mModel->setFilterString( QString() );
}
else
{
mModel->setFavoritesOnly( false );
mModel->setTagId( mStyle->tagId( text ) );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
}
void QgsStyleItemsListWidget::openStyleManager()
{
// prefer to use global window manager to open the style manager, if possible!
// this allows reuse of an existing non-modal window instead of opening a new modal window.
// Note that we only use the non-modal dialog if we're open in the panel -- if we're already
// open as part of a modal dialog, then we MUST use another modal dialog or the result will
// not be focusable!
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
if ( !panel || !panel->dockMode()
|| !QgsGui::windowManager()
|| !QgsGui::windowManager()->openStandardDialog( QgsWindowManagerInterface::DialogStyleManager ) )
{
// fallback to modal dialog
QgsStyleManagerDialog dlg( mStyle, this );
dlg.exec();
updateModelFilters(); // probably not needed -- the model should automatically update if any changes were made
}
}
void QgsStyleItemsListWidget::onSelectionChanged( const QModelIndex &index )
{
if ( !mModel )
return;
QString symbolName = mModel->data( mModel->index( index.row(), QgsStyleModel::Name ) ).toString();
lblSymbolName->setText( symbolName );
emit selectionChanged( symbolName, static_cast< QgsStyle::StyleEntity >( mModel->data( index, QgsStyleModel::TypeRole ).toInt() ) );
}
void QgsStyleItemsListWidget::groupsCombo_currentIndexChanged( int index )
{
QgsSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
}

View File

@ -0,0 +1,159 @@
/***************************************************************************
qgsstyleitemslistwidget.h
-------------------------
begin : June 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail.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 QGSSTYLEITEMSLISTWIDGET_H
#define QGSSTYLEITEMSLISTWIDGET_H
#include "ui_qgsstyleitemslistwidgetbase.h"
#include "qgsstylemodel.h"
#include <QWidget>
#include "qgis_gui.h"
class QgsStyle;
class QMenu;
#ifndef SIP_RUN
///@cond PRIVATE
class QgsReadOnlyStyleModel : public QgsStyleProxyModel
{
Q_OBJECT
public:
explicit QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override;
QVariant data( const QModelIndex &index, int role ) const override;
};
#endif
///@endcond
/**
* \ingroup gui
* \class QgsStyleItemsListWidget
* A reusable widget for showing a filtered list of entities from a QgsStyle database.
* \since QGIS 3.10
*/
class GUI_EXPORT QgsStyleItemsListWidget : public QWidget, private Ui::QgsStyleItemsListWidgetBase
{
Q_OBJECT
public:
/**
* Constructor for QgsStyleItemsListWidget, with the specified \a parent widget.
*/
QgsStyleItemsListWidget( QWidget *parent SIP_TRANSFERTHIS );
/**
* Sets the \a style database associated with the widget.
*
* Ownership of \a style is not transferred, and the caller is responsible for ensuring that
* it exists for the lifetime of the widget.
*/
void setStyle( QgsStyle *style );
/**
* Sets the \a type of style entity to show in the widget.
*
* \see setSymbolType()
*/
void setEntityType( QgsStyle::StyleEntity type );
/**
* Sets the \a type of symbols to show in the widget.
*
* \see setEntityType()
*/
void setSymbolType( QgsSymbol::SymbolType type );
#ifndef SIP_RUN
/**
* Returns a pointer to the widget's current advanced menu.
* \see setAdvancedMenu()
* \note Not available in Python bindings.
*/
QMenu *advancedMenu();
/**
* Sets the widget's advanced \a menu, which is shown when the user clicks
* the "Advanced" button in the widget's GUI.
*
* Ownership of \a menu is NOT transferred to the widget.
*
* \see advancedMenu()
* \note Not available in Python bindings.
*/
void setAdvancedMenu( QMenu *menu );
/**
* Sets whether the advanced button should be shown in the widget. By default
* the button is hidden.
*
* \see setAdvancedMenu()
* \note Not available in Python bindings.
*/
void showAdvancedButton( bool enabled );
#endif
/**
* Returns the name of the item currently selected in the widget.
* \see currentEntityType()
*/
QString currentItemName() const;
/**
* Returns the type of the item currently selected in the widget.
* \see currentItemName()
*/
QgsStyle::StyleEntity currentEntityType() const;
signals:
/**
* Emitted when the selected item is changed in the widget.
* \param name Newly selected item name
* \param type Newly selected item type
*/
void selectionChanged( const QString &name, QgsStyle::StyleEntity type );
/**
* Emitted when the user has opted to save a new entity to the style
* database, by clicking the "Save" button in the widget.
*
* It is the caller's responsibility to handle this in an appropriate
* manner given the context of the widget.
*/
void saveEntity();
private slots:
void groupsCombo_currentIndexChanged( int index );
void updateModelFilters();
void onSelectionChanged( const QModelIndex &index );
void populateGroups();
void openStyleManager();
private:
QgsStyle *mStyle = nullptr;
QgsStyleProxyModel *mModel = nullptr;
bool mUpdatingGroups = false;
};
#endif //QGSSTYLEITEMSLISTWIDGET_H

View File

@ -18,73 +18,17 @@
#include "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgssymbol.h"
#include "qgsstyle.h"
#include "qgssymbollayerutils.h"
#include "qgsmarkersymbollayer.h"
#include "qgsmapcanvas.h"
#include "qgsapplication.h"
#include "qgsstyleitemslistwidget.h"
#include "qgsvectorlayer.h"
#include "qgssettings.h"
#include "qgsnewauxiliarylayerdialog.h"
#include "qgsauxiliarystorage.h"
#include "qgsstylemodel.h"
#include "qgsgui.h"
#include "qgswindowmanagerinterface.h"
#include <QAction>
#include <QString>
#include <QStringList>
#include <QPainter>
#include <QIcon>
#include <QStandardItemModel>
#include <QColorDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QMenu>
#include <QPushButton>
//
// QgsReadOnlyStyleModel
//
///@cond PRIVATE
QgsReadOnlyStyleModel::QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent )
: QgsStyleProxyModel( style, parent )
{
}
Qt::ItemFlags QgsReadOnlyStyleModel::flags( const QModelIndex &index ) const
{
return QgsStyleProxyModel::flags( index ) & ~Qt::ItemIsEditable;
}
QVariant QgsReadOnlyStyleModel::data( const QModelIndex &index, int role ) const
{
if ( role == Qt::FontRole )
{
// drop font size to get reasonable amount of item name shown
QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
f.setPointSize( 9 );
return f;
}
return QgsStyleProxyModel::data( index, role );
}
///@endcond
//
// QgsSymbolsListWidget
//
QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer )
: QWidget( parent )
, mSymbol( symbol )
, mStyle( style )
, mAdvancedMenu( menu )
, mLayer( layer )
{
setupUi( this );
@ -94,26 +38,12 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
mSymbolUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mModel = new QgsReadOnlyStyleModel( mStyle, this );
mModel->setEntityFilterEnabled( true );
mModel->setEntityFilter( QgsStyle::SymbolEntity );
mStyleItemsListWidget->setStyle( mStyle );
mStyleItemsListWidget->setEntityType( QgsStyle::SymbolEntity );
if ( mSymbol )
{
mModel->setSymbolTypeFilterEnabled( true );
mModel->setSymbolType( mSymbol->type() );
}
mStyleItemsListWidget->setSymbolType( mSymbol->type() );
mStyleItemsListWidget->setAdvancedMenu( menu );
btnAdvanced->hide(); // advanced button is hidden by default
if ( menu ) // show it if there is a menu pointer
{
mAdvancedMenu = menu;
btnAdvanced->show();
btnAdvanced->setMenu( mAdvancedMenu );
}
else
{
btnAdvanced->setMenu( new QMenu( this ) );
}
mClipFeaturesAction = new QAction( tr( "Clip Features to Canvas Extent" ), this );
mClipFeaturesAction->setCheckable( true );
connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
@ -121,70 +51,6 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
mStandardizeRingsAction->setCheckable( true );
connect( mStandardizeRingsAction, &QAction::toggled, this, &QgsSymbolsListWidget::forceRHRToggled );
double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10;
viewSymbols->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) ); // ~100, 90 on low dpi
double treeIconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 2;
mSymbolTreeView->setIconSize( QSize( static_cast< int >( treeIconSize ), static_cast< int >( treeIconSize ) ) );
mModel->addDesiredIconSize( viewSymbols->iconSize() );
mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
viewSymbols->setModel( mModel );
mSymbolTreeView->setModel( mModel );
viewSymbols->setSelectionBehavior( QAbstractItemView::SelectRows );
mSymbolTreeView->setSelectionModel( viewSymbols->selectionModel() );
mSymbolTreeView->setSelectionMode( viewSymbols->selectionMode() );
connect( viewSymbols->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolsListWidget::setSymbolFromStyle );
connect( mStyle, &QgsStyle::groupsModified, this, &QgsSymbolsListWidget::populateGroups );
connect( openStyleManagerButton, &QToolButton::clicked, this, &QgsSymbolsListWidget::openStyleManager );
lblSymbolName->clear();
connect( mButtonIconView, &QToolButton::toggled, this, [ = ]( bool active )
{
if ( active )
{
mSymbolViewStackedWidget->setCurrentIndex( 0 );
// note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui );
}
} );
connect( mButtonListView, &QToolButton::toggled, this, [ = ]( bool active )
{
if ( active )
{
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 1, QgsSettings::Gui );
mSymbolViewStackedWidget->setCurrentIndex( 1 );
}
} );
// restore previous view
QgsSettings settings;
const int currentView = settings.value( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui ).toInt();
if ( currentView == 0 )
mButtonIconView->setChecked( true );
else
mButtonListView->setChecked( true );
mSymbolTreeView->header()->restoreState( settings.value( QStringLiteral( "UI/symbolsList/treeState" ), QByteArray(), QgsSettings::Gui ).toByteArray() );
connect( mSymbolTreeView->header(), &QHeaderView::sectionResized, this, [this]
{
// note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
QgsSettings().setValue( QStringLiteral( "UI/symbolsList/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
} );
QgsFilterLineEdit *groupEdit = new QgsFilterLineEdit();
groupEdit->setShowSearchIcon( true );
groupEdit->setShowClearButton( true );
groupEdit->setPlaceholderText( tr( "Filter symbols…" ) );
groupsCombo->setLineEdit( groupEdit );
populateGroups();
connect( groupsCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSymbolsListWidget::groupsCombo_currentIndexChanged );
connect( groupsCombo, &QComboBox::currentTextChanged, this, &QgsSymbolsListWidget::updateModelFilters );
if ( mSymbol )
{
updateSymbolInfo();
@ -211,17 +77,19 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style,
btnColor->setAllowOpacity( true );
btnColor->setColorDialogTitle( tr( "Select Color" ) );
btnColor->setContext( QStringLiteral( "symbology" ) );
connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsSymbolsListWidget::saveSymbol );
connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsSymbolsListWidget::opacityChanged );
connect( mStyleItemsListWidget, &QgsStyleItemsListWidget::selectionChanged, this, &QgsSymbolsListWidget::setSymbolFromStyle );
connect( mStyleItemsListWidget, &QgsStyleItemsListWidget::saveEntity, this, &QgsSymbolsListWidget::saveSymbol );
}
QgsSymbolsListWidget::~QgsSymbolsListWidget()
{
// This action was added to the menu by this widget, clean it up
// The menu can be passed in the constructor, so may live longer than this widget
btnAdvanced->menu()->removeAction( mClipFeaturesAction );
btnAdvanced->menu()->removeAction( mStandardizeRingsAction );
mStyleItemsListWidget->advancedMenu()->removeAction( mClipFeaturesAction );
mStyleItemsListWidget->advancedMenu()->removeAction( mStandardizeRingsAction );
}
void QgsSymbolsListWidget::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsSymbolLayer::Property key )
@ -311,96 +179,6 @@ QgsSymbolWidgetContext QgsSymbolsListWidget::context() const
return mContext;
}
void QgsSymbolsListWidget::populateGroups()
{
mUpdatingGroups = true;
groupsCombo->blockSignals( true );
groupsCombo->clear();
groupsCombo->addItem( tr( "Favorites" ), QVariant( "favorite" ) );
groupsCombo->addItem( tr( "All Symbols" ), QVariant( "all" ) );
int index = 2;
QStringList tags = mStyle->tags();
if ( tags.count() > 0 )
{
tags.sort();
groupsCombo->insertSeparator( index );
const auto constTags = tags;
for ( const QString &tag : constTags )
{
groupsCombo->addItem( tag, QVariant( "tag" ) );
index++;
}
}
QStringList groups = mStyle->smartgroupNames();
if ( groups.count() > 0 )
{
groups.sort();
groupsCombo->insertSeparator( index + 1 );
const auto constGroups = groups;
for ( const QString &group : constGroups )
{
groupsCombo->addItem( group, QVariant( "smartgroup" ) );
}
}
groupsCombo->blockSignals( false );
QgsSettings settings;
index = settings.value( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 ).toInt();
groupsCombo->setCurrentIndex( index );
mUpdatingGroups = false;
updateModelFilters();
}
void QgsSymbolsListWidget::updateModelFilters()
{
if ( mUpdatingGroups )
return;
const QString text = groupsCombo->currentText();
const bool isFreeText = text != groupsCombo->itemText( groupsCombo->currentIndex() );
if ( isFreeText )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( groupsCombo->currentText() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
{
mModel->setFavoritesOnly( true );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
{
mModel->setFavoritesOnly( false );
mModel->setTagId( -1 );
mModel->setSmartGroupId( mStyle->smartgroupId( text ) );
mModel->setFilterString( QString() );
}
else
{
mModel->setFavoritesOnly( false );
mModel->setTagId( mStyle->tagId( text ) );
mModel->setSmartGroupId( -1 );
mModel->setFilterString( QString() );
}
}
void QgsSymbolsListWidget::forceRHRToggled( bool checked )
{
if ( !mSymbol )
@ -410,24 +188,39 @@ void QgsSymbolsListWidget::forceRHRToggled( bool checked )
emit changed();
}
void QgsSymbolsListWidget::openStyleManager()
void QgsSymbolsListWidget::saveSymbol()
{
// prefer to use global window manager to open the style manager, if possible!
// this allows reuse of an existing non-modal window instead of opening a new modal window.
// Note that we only use the non-modal dialog if we're open in the panel -- if we're already
// open as part of a modal dialog, then we MUST use another modal dialog or the result will
// not be focusable!
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
if ( !panel || !panel->dockMode()
|| !QgsGui::windowManager()
|| !QgsGui::windowManager()->openStandardDialog( QgsWindowManagerInterface::DialogStyleManager ) )
{
// fallback to modal dialog
QgsStyleManagerDialog dlg( mStyle, this );
dlg.exec();
if ( !mStyle )
return;
updateModelFilters(); // probably not needed -- the model should automatically update if any changes were made
QgsStyleSaveDialog saveDlg( this );
if ( !saveDlg.exec() )
return;
if ( saveDlg.name().isEmpty() )
return;
// check if there is no symbol with same name
if ( mStyle->symbolNames().contains( saveDlg.name() ) )
{
int res = QMessageBox::warning( this, tr( "Save Symbol" ),
tr( "Symbol with name '%1' already exists. Overwrite?" )
.arg( saveDlg.name() ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
{
return;
}
mStyle->removeSymbol( saveDlg.name() );
}
QStringList symbolTags = saveDlg.tags().split( ',' );
// add new symbol to style and re-populate the list
mStyle->addSymbol( saveDlg.name(), mSymbol->clone() );
// make sure the symbol is stored
mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
}
void QgsSymbolsListWidget::clipFeaturesToggled( bool checked )
@ -539,66 +332,6 @@ void QgsSymbolsListWidget::updateAssistantSymbol()
mWidthDDBtn->setSymbol( mAssistantSymbol );
}
void QgsSymbolsListWidget::addSymbolToStyle()
{
bool ok;
QString name = QInputDialog::getText( this, tr( "Save Symbol" ),
tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
if ( !ok || name.isEmpty() )
return;
// check if there is no symbol with same name
if ( mStyle->symbolNames().contains( name ) )
{
int res = QMessageBox::warning( this, tr( "Save Symbol" ),
tr( "Symbol with name '%1' already exists. Overwrite?" )
.arg( name ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
{
return;
}
}
// add new symbol to style and re-populate the list
mStyle->addSymbol( name, mSymbol->clone() );
// make sure the symbol is stored
mStyle->saveSymbol( name, mSymbol->clone(), false, QStringList() );
}
void QgsSymbolsListWidget::saveSymbol()
{
QgsStyleSaveDialog saveDlg( this );
if ( !saveDlg.exec() )
return;
if ( saveDlg.name().isEmpty() )
return;
// check if there is no symbol with same name
if ( mStyle->symbolNames().contains( saveDlg.name() ) )
{
int res = QMessageBox::warning( this, tr( "Save Symbol" ),
tr( "Symbol with name '%1' already exists. Overwrite?" )
.arg( saveDlg.name() ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
{
return;
}
mStyle->removeSymbol( saveDlg.name() );
}
QStringList symbolTags = saveDlg.tags().split( ',' );
// add new symbol to style and re-populate the list
mStyle->addSymbol( saveDlg.name(), mSymbol->clone() );
// make sure the symbol is stored
mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
}
void QgsSymbolsListWidget::mSymbolUnitWidget_changed()
{
if ( mSymbol )
@ -706,41 +439,39 @@ void QgsSymbolsListWidget::updateSymbolInfo()
mOpacityWidget->setOpacity( mSymbol->opacity() );
// Clean up previous advanced symbol actions
const QList<QAction *> actionList( btnAdvanced->menu()->actions() );
const QList<QAction *> actionList( mStyleItemsListWidget->advancedMenu()->actions() );
for ( const auto &action : actionList )
{
if ( mClipFeaturesAction->text() == action->text() )
{
btnAdvanced->menu()->removeAction( action );
mStyleItemsListWidget->advancedMenu()->removeAction( action );
}
else if ( mStandardizeRingsAction->text() == action->text() )
{
btnAdvanced->menu()->removeAction( action );
mStyleItemsListWidget->advancedMenu()->removeAction( action );
}
}
if ( mSymbol->type() == QgsSymbol::Line || mSymbol->type() == QgsSymbol::Fill )
{
//add clip features option for line or fill symbols
btnAdvanced->menu()->addAction( mClipFeaturesAction );
mStyleItemsListWidget->advancedMenu()->addAction( mClipFeaturesAction );
}
if ( mSymbol->type() == QgsSymbol::Fill )
{
btnAdvanced->menu()->addAction( mStandardizeRingsAction );
mStyleItemsListWidget->advancedMenu()->addAction( mStandardizeRingsAction );
}
btnAdvanced->setVisible( mAdvancedMenu || !btnAdvanced->menu()->isEmpty() );
mStyleItemsListWidget->showAdvancedButton( mAdvancedMenu || !mStyleItemsListWidget->advancedMenu()->isEmpty() );
whileBlocking( mClipFeaturesAction )->setChecked( mSymbol->clipFeaturesToExtent() );
whileBlocking( mStandardizeRingsAction )->setChecked( mSymbol->forceRHR() );
}
void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex &index )
void QgsSymbolsListWidget::setSymbolFromStyle( const QString &name, QgsStyle::StyleEntity )
{
QString symbolName = mModel->data( mModel->index( index.row(), QgsStyleModel::Name ) ).toString();
lblSymbolName->setText( symbolName );
// get new instance of symbol from style
std::unique_ptr< QgsSymbol > s( mStyle->symbol( symbolName ) );
std::unique_ptr< QgsSymbol > s( mStyle->symbol( name ) );
if ( !s )
return;
@ -758,9 +489,3 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex &index )
updateSymbolInfo();
emit changed();
}
void QgsSymbolsListWidget::groupsCombo_currentIndexChanged( int index )
{
QgsSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
}

View File

@ -29,21 +29,6 @@ class QgsStyle;
class QMenu;
#ifndef SIP_RUN
///@cond PRIVATE
class QgsReadOnlyStyleModel : public QgsStyleProxyModel
{
Q_OBJECT
public:
explicit QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override;
QVariant data( const QModelIndex &index, int role ) const override;
};
#endif
///@endcond
/**
* \ingroup gui
* \class QgsSymbolsListWidget
@ -90,18 +75,11 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
public slots:
void setSymbolFromStyle( const QModelIndex &index );
void setSymbolColor( const QColor &color );
void setMarkerAngle( double angle );
void setMarkerSize( double size );
void setLineWidth( double width );
void addSymbolToStyle();
void saveSymbol();
//! Pupulates the groups combo box with available tags and smartgroups
void populateGroups();
void openStyleManager();
void clipFeaturesToggled( bool checked );
void updateDataDefinedMarkerSize();
@ -112,13 +90,13 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
void changed();
private slots:
void setSymbolFromStyle( const QString &name, QgsStyle::StyleEntity type );
void mSymbolUnitWidget_changed();
void groupsCombo_currentIndexChanged( int index );
void updateAssistantSymbol();
void opacityChanged( double value );
void createAuxiliaryField();
void updateModelFilters();
void forceRHRToggled( bool checked );
void saveSymbol();
private:
QgsSymbol *mSymbol = nullptr;
@ -129,8 +107,6 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
QAction *mStandardizeRingsAction = nullptr;
QgsVectorLayer *mLayer = nullptr;
QgsMapCanvas *mMapCanvas = nullptr;
QgsStyleProxyModel *mModel = nullptr;
bool mUpdatingGroups = false;
void updateSymbolColor();
void updateSymbolInfo();

View File

@ -0,0 +1,276 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsStyleItemsListWidgetBase</class>
<widget class="QWidget" name="QgsStyleItemsListWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>619</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>4</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QComboBox" name="groupsCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter Symbols</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="openStyleManagerButton">
<property name="toolTip">
<string>Style Manager</string>
</property>
<property name="text">
<string>Open Library…</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionStyleManager.svg</normaloff>:/images/themes/default/mActionStyleManager.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="mButtonIconView">
<property name="toolTip">
<string>Icon View</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionIconView.svg</normaloff>:/images/themes/default/mActionIconView.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="mButtonListView">
<property name="toolTip">
<string>List View</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionOpenTable.svg</normaloff>:/images/themes/default/mActionOpenTable.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblSymbolName">
<property name="text">
<string>Symbol Name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnSaveSymbol">
<property name="toolTip">
<string>Save symbol</string>
</property>
<property name="text">
<string>Save Symbol</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnAdvanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QStackedWidget" name="mSymbolViewStackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="viewSymbols">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="iconSize">
<size>
<width>77</width>
<height>70</height>
</size>
</property>
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="flow">
<enum>QListView::LeftToRight</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="mSymbolTreeView"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>groupsCombo</tabstop>
<tabstop>openStyleManagerButton</tabstop>
<tabstop>btnSaveSymbol</tabstop>
<tabstop>btnAdvanced</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

View File

@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0,1,0">
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,1">
<property name="leftMargin">
<number>0</number>
</property>
@ -36,234 +36,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QComboBox" name="groupsCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter Symbols</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="openStyleManagerButton">
<property name="toolTip">
<string>Style Manager</string>
</property>
<property name="text">
<string>Open Library…</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionStyleManager.svg</normaloff>:/images/themes/default/mActionStyleManager.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QStackedWidget" name="mSymbolViewStackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="viewSymbols">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>2</verstretch>
</sizepolicy>
</property>
<property name="iconSize">
<size>
<width>77</width>
<height>70</height>
</size>
</property>
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="flow">
<enum>QListView::LeftToRight</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="mSymbolTreeView"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="mButtonIconView">
<property name="toolTip">
<string>Icon View</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionIconView.svg</normaloff>:/images/themes/default/mActionIconView.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="mButtonListView">
<property name="toolTip">
<string>List View</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionOpenTable.svg</normaloff>:/images/themes/default/mActionOpenTable.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblSymbolName">
<property name="text">
<string>Symbol Name</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnSaveSymbol">
<property name="toolTip">
<string>Save symbol</string>
</property>
<property name="text">
<string>Save Symbol</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnAdvanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@ -537,6 +309,9 @@
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QgsStyleItemsListWidget" name="mStyleItemsListWidget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
@ -568,6 +343,12 @@
<header>qgsopacitywidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsStyleItemsListWidget</class>
<extends>QWidget</extends>
<header>qgsstyleitemslistwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mOpacityWidget</tabstop>
@ -578,10 +359,6 @@
<tabstop>mRotationDDBtn</tabstop>
<tabstop>spinWidth</tabstop>
<tabstop>mWidthDDBtn</tabstop>
<tabstop>groupsCombo</tabstop>
<tabstop>openStyleManagerButton</tabstop>
<tabstop>btnSaveSymbol</tabstop>
<tabstop>btnAdvanced</tabstop>
<tabstop>spinSize</tabstop>
<tabstop>mSizeDDBtn</tabstop>
<tabstop>spinAngle</tabstop>
@ -589,38 +366,7 @@
<tabstop>spinWidth</tabstop>
<tabstop>mWidthDDBtn</tabstop>
</tabstops>
<resources>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
</resources>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>