37 #include <QMessageBox> 38 #include <QStandardItemModel> 39 #include <QStandardItem> 42 #include <QFileDialog> 46 QgsCategorizedSymbolRendererV2Model::QgsCategorizedSymbolRendererV2Model(
QObject * parent ) :
QAbstractItemModel( parent )
47 , mRenderer( nullptr )
48 , mMimeFormat(
"application/x-qgscategorizedsymbolrendererv2model" )
56 beginRemoveRows(
QModelIndex(), 0, mRenderer->categories().size() - 1 );
70 if ( !mRenderer )
return;
71 int idx = mRenderer->categories().size();
73 mRenderer->addCategory( cat );
84 int row = index.
row();
85 if ( row >= catList.
size() )
89 return catList.
at( row );
97 return Qt::ItemIsDropEnabled;
100 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
103 flags |= Qt::ItemIsEditable;
108 Qt::DropActions QgsCategorizedSymbolRendererV2Model::supportedDropActions()
const 110 return Qt::MoveAction;
113 QVariant QgsCategorizedSymbolRendererV2Model::data(
const QModelIndex &index,
int role )
const 115 if ( !index.
isValid() || !mRenderer )
120 if ( role == Qt::CheckStateRole && index.
column() == 0 )
122 return category.
renderState() ? Qt::Checked : Qt::Unchecked;
124 else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
131 return category.
label();
136 else if ( role == Qt::DecorationRole && index.
column() == 0 && category.
symbol() )
140 else if ( role == Qt::TextAlignmentRole )
142 return ( index.
column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
144 else if ( role == Qt::EditRole )
149 return category.
value();
151 return category.
label();
160 bool QgsCategorizedSymbolRendererV2Model::setData(
const QModelIndex & index,
const QVariant & value,
int role )
165 if ( index.
column() == 0 && role == Qt::CheckStateRole )
167 mRenderer->updateCategoryRenderState( index.
row(), value == Qt::Checked );
168 emit dataChanged( index, index );
172 if ( role != Qt::EditRole )
181 switch ( mRenderer->categories().value( index.
row() ).value().
type() )
186 case QVariant::Double:
193 mRenderer->updateCategoryValue( index.
row(), val );
197 mRenderer->updateCategoryLabel( index.
row(), value.
toString() );
203 emit dataChanged( index, index );
207 QVariant QgsCategorizedSymbolRendererV2Model::headerData(
int section, Qt::Orientation orientation,
int role )
const 209 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
212 lst <<
tr(
"Symbol" ) <<
tr(
"Value" ) <<
tr(
"Legend" );
213 return lst.
value( section );
218 int QgsCategorizedSymbolRendererV2Model::rowCount(
const QModelIndex &
parent )
const 220 if ( parent.
isValid() || !mRenderer )
224 return mRenderer->categories().size();
227 int QgsCategorizedSymbolRendererV2Model::columnCount(
const QModelIndex & index )
const 235 if ( hasIndex( row, column, parent ) )
237 return createIndex( row, column );
248 QStringList QgsCategorizedSymbolRendererV2Model::mimeTypes()
const 251 types << mMimeFormat;
255 QMimeData *QgsCategorizedSymbolRendererV2Model::mimeData(
const QModelIndexList &indexes )
const 260 QDataStream stream( &encodedData, QIODevice::WriteOnly );
268 stream << index.
row();
270 mimeData->
setData( mMimeFormat, encodedData );
274 bool QgsCategorizedSymbolRendererV2Model::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
278 if ( action != Qt::MoveAction )
return true;
280 if ( !data->
hasFormat( mMimeFormat ) )
return false;
283 QDataStream stream( &encodedData, QIODevice::ReadOnly );
286 while ( !stream.atEnd() )
293 int to = parent.
row();
296 if ( to == -1 ) to = mRenderer->categories().size();
297 for (
int i = rows.
size() - 1; i >= 0; i-- )
302 if ( rows[i] < t ) t--;
303 mRenderer->moveCategory( rows[i], t );
305 for (
int j = 0; j < i; j++ )
307 if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
310 if ( rows[i] < to ) to--;
312 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
317 void QgsCategorizedSymbolRendererV2Model::deleteRows(
QList<int> rows )
320 for (
int i = rows.
size() - 1; i >= 0; i-- )
322 beginRemoveRows(
QModelIndex(), rows[i], rows[i] );
323 mRenderer->deleteCategory( rows[i] );
328 void QgsCategorizedSymbolRendererV2Model::removeAllRows()
330 beginRemoveRows(
QModelIndex(), 0, mRenderer->categories().size() - 1 );
331 mRenderer->deleteAllCategories();
335 void QgsCategorizedSymbolRendererV2Model::sort(
int column, Qt::SortOrder order )
343 mRenderer->sortByValue( order );
345 else if ( column == 2 )
347 mRenderer->sortByLabel( order );
349 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
353 void QgsCategorizedSymbolRendererV2Model::updateSymbology()
355 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
359 QgsCategorizedSymbolRendererV2ViewStyle::QgsCategorizedSymbolRendererV2ViewStyle(
QStyle*
style )
363 void QgsCategorizedSymbolRendererV2ViewStyle::drawPrimitive( PrimitiveElement element,
const QStyleOption * option,
QPainter * painter,
const QWidget * widget )
const 365 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
368 opt.rect.setLeft( 0 );
370 opt.rect.setHeight( 0 );
371 if ( widget ) opt.rect.setRight( widget->
width() );
413 , mRenderer( nullptr )
429 mOldClassificationAttribute = attrName;
434 mExpressionWidget->setLayer(
mLayer );
436 cboCategorizedColorRamp->populate(
mStyle );
437 int randomIndex = cboCategorizedColorRamp->findText(
tr(
"Random colors" ) );
438 if ( randomIndex != -1 )
440 cboCategorizedColorRamp->setCurrentIndex( randomIndex );
441 mButtonEditRamp->setEnabled(
false );
446 if ( defaultColorRamp !=
"" )
448 int index = cboCategorizedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive );
450 cboCategorizedColorRamp->setCurrentIndex( index );
455 mModel =
new QgsCategorizedSymbolRendererV2Model(
this );
461 viewCategories->setModel( mModel );
462 viewCategories->resizeColumnToContents( 0 );
463 viewCategories->resizeColumnToContents( 1 );
464 viewCategories->resizeColumnToContents( 2 );
466 viewCategories->setStyle(
new QgsCategorizedSymbolRendererV2ViewStyle( viewCategories->style() ) );
482 connect( cboCategorizedColorRamp, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT(
applyColorRamp() ) );
484 connect( mButtonEditRamp, SIGNAL( clicked() ), cboCategorizedColorRamp, SLOT( editSourceRamp() ) );
493 btnAdvanced->setMenu( advMenu );
517 mExpressionWidget->setField( attrName );
534 if ( cboCategorizedColorRamp->currentText() ==
tr(
"Random colors" ) )
535 mButtonEditRamp->setEnabled(
false );
537 mButtonEditRamp->setEnabled(
true );
560 Q_FOREACH (
int idx, selectedCats )
586 btnChangeCategorizedSymbol->setIcon( icon );
612 symbol = symbol->
clone();
620 dlg->setDockMode( this->
dockMode() );
632 int num = values.
count();
633 for (
int i = 0; i < num; i++ )
652 if ( cboCategorizedColorRamp->count() == 0 )
653 QMessageBox::critical(
this,
tr(
"Error" ),
tr(
"There are no available color ramps. You can add them in Style Manager." ) );
654 else if ( !cboCategorizedColorRamp->createNewColorRampSelected() )
663 QString attrName = mExpressionWidget->currentField();
676 expression->
prepare( &context );
683 if ( unique_vals.
contains( value ) )
685 unique_vals << value;
694 if ( unique_vals.
size() >= 1000 )
697 tr(
"Classification would yield %1 entries which might not be expected. Continue?" ).arg( unique_vals.
size() ),
698 QMessageBox::Ok | QMessageBox::Cancel,
699 QMessageBox::Cancel );
700 if ( res == QMessageBox::Cancel )
707 DlgAddCategories dlg(
mStyle, createDefaultSymbol(), unique_vals,
this );
714 bool deleteExisting =
false;
716 if ( !mOldClassificationAttribute.
isEmpty() &&
717 attrName != mOldClassificationAttribute &&
721 tr(
"Confirm Delete" ),
722 tr(
"The classification field was changed from '%1' to '%2'.\n" 723 "Should the existing classes be deleted before classification?" )
724 .arg( mOldClassificationAttribute, attrName ),
725 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel );
726 if ( res == QMessageBox::Cancel )
731 deleteExisting = ( res == QMessageBox::Yes );
735 bool keepExistingColors =
false;
736 if ( !deleteExisting )
739 keepExistingColors = !prevCats.
isEmpty();
740 for (
int i = 0; i < cats.
size(); ++i )
742 bool contains =
false;
744 for (
int j = 0; j < prevCats.
size() && !contains; ++j )
746 if ( prevCats.
at( j ).value() == value )
759 mOldClassificationAttribute = attrName;
797 if ( cboCategorizedColorRamp->currentText() ==
tr(
"Random colors" ) )
798 mButtonEditRamp->setEnabled(
false );
800 mButtonEditRamp->setEnabled(
true );
807 mModel->updateSymbology();
812 QModelIndex idx = viewCategories->selectionModel()->currentIndex();
821 QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
836 mModel->deleteRows( categoryIndexes );
851 mModel->addCategory( cat );
874 if ( m && !selectedIndexes.isEmpty() )
877 QModelIndexList::const_iterator indexIt = selectedIndexes.
constBegin();
878 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
880 int row = ( *indexIt ).row();
884 selectedSymbols.
append( s );
898 if ( m && !selectedIndexes.isEmpty() )
900 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
901 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
922 viewCategories->selectionModel()->clear();
931 tr(
"Matched %1 categories to symbols." ).arg( matched ) );
936 tr(
"No categories could be matched to symbols in library." ) );
959 mModel->updateSymbology();
969 tr(
"XML files (*.xml *XML)" ) );
979 if ( !importedStyle.
importXML( fileName ) )
982 tr(
"An error occurred reading file:\n%1" ).arg( importedStyle.
errorString() ) );
990 tr(
"Matched %1 categories to symbols from file." ).arg( matched ) );
995 tr(
"No categories could be matched to symbols in file." ) );
999 void QgsCategorizedSymbolRendererV2Widget::cleanUpSymbolSelector(
QgsPanelWidget *container )
1008 void QgsCategorizedSymbolRendererV2Widget::updateSymbolsFromWidget()
1020 if ( m && !i.isEmpty() )
1024 if ( !selectedCats.
isEmpty() )
1026 Q_FOREACH (
int idx, selectedCats )
1029 if ( selectedCats.
count() > 1 )
1052 if ( event->
key() == Qt::Key_C &&
event->modifiers() == Qt::ControlModifier )
1054 mCopyBuffer.
clear();
1057 else if ( event->
key() == Qt::Key_V &&
event->modifiers() == Qt::ControlModifier )
1060 for ( ; rIt != mCopyBuffer.
constEnd(); ++rIt )
1062 mModel->addCategory( *rIt );
const QgsCategoryList & categories() const
static void sortVariantList(QList< QVariant > &list, Qt::SortOrder order)
Sorts the passed list in requested order.
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
QByteArray data(const QString &mimeType) const
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) const
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
bool importXML(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file...
QgsVectorColorRampV2 * sourceColorRamp()
Returns the source color ramp, from which each categories' color is derived.
void append(const T &value)
static QgsExpressionContextScope * atlasScope(const QgsAtlasComposition *atlas)
Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Calculates a list of unique values contained within an attribute in the layer.
void setSourceSymbol(QgsSymbolV2 *sym)
Sets the source symbol for the renderer, which is the base symbol used for the each categories' symbo...
virtual QgsSymbolV2 * clone() const =0
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QString sizeScaleField() const
const T & at(int i) const
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QString tr(const char *sourceText, const char *disambiguation, int n)
void setClassAttribute(const QString &attr)
void setSourceColorRamp(QgsVectorColorRampV2 *ramp)
Sets the source color ramp.
The QgsMapSettings class contains configuration for rendering of the map.
void setValue(const QString &key, const QVariant &value)
void updateSymbols(QgsSymbolV2 *sym)
Update all the symbols but leave categories and colors.
void setColor(const QColor &color)
QgsSymbolV2::ScaleMethod scaleMethod() const
QList< QgsRendererCategoryV2 > QgsCategoryList
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
int count(const T &value) const
void append(const T &value)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
int toInt(bool *ok) const
StandardButton question(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
virtual QgsVectorColorRampV2 * clone() const =0
Creates a clone of the color ramp.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QgsStyleV2 * defaultStyle()
return default application-wide style
QModelIndexList selectedRows(int column) const
QString classAttribute() const
QGis::GeometryType geometryType() const
Returns point, line or polygon.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
static QgsCategorizedSymbolRendererV2 * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsCategorizedSymbolRendererV2 from an existing renderer.
void updateColorRamp(QgsVectorColorRampV2 *ramp, bool inverted=false)
Update the color ramp used and all symbols colors.
QgsSymbolV2 * symbol(const QString &name)
return a NEW copy of symbol
bool contains(const T &value) const
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
QVariant value(const QString &key, const QVariant &defaultValue) const
QgsSymbolV2 * sourceSymbol()
Returns the renderer's source symbol, which is the base symbol used for the each categories' symbol b...
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object...
QgsExpressionContextScope & expressionContextScope()
Returns a reference to the expression context scope for the map canvas.
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
static QgsProject * instance()
Returns the QgsProject singleton instance.
bool updateCategorySymbol(int catIndex, QgsSymbolV2 *symbol)
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
QgsSymbolV2 * symbol() const
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
double toDouble(bool *ok) const
void setData(const QString &mimeType, const QByteArray &data)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
const_iterator constEnd() const
bool nextFeature(QgsFeature &f)
const_iterator constBegin() const
QString absolutePath() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
Abstract base class for color ramps.
void setSizeScaleField(const QString &fieldOrExpression)
QString errorString()
return last error from load/save operation
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
void setInvertedColorRamp(bool inverted)