36 #include <QMessageBox> 37 #include <QStandardItemModel> 38 #include <QStandardItem> 41 #include <QFileDialog> 45 QgsCategorizedSymbolRendererV2Model::QgsCategorizedSymbolRendererV2Model(
QObject * parent ) :
QAbstractItemModel( parent )
46 , mRenderer( nullptr )
47 , mMimeFormat(
"application/x-qgscategorizedsymbolrendererv2model" )
55 beginRemoveRows(
QModelIndex(), 0, mRenderer->categories().size() - 1 );
69 if ( !mRenderer )
return;
70 int idx = mRenderer->categories().size();
72 mRenderer->addCategory( cat );
83 int row = index.
row();
84 if ( row >= catList.
size() )
88 return catList.
at( row );
96 return Qt::ItemIsDropEnabled;
99 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
102 flags |= Qt::ItemIsEditable;
107 Qt::DropActions QgsCategorizedSymbolRendererV2Model::supportedDropActions()
const 109 return Qt::MoveAction;
112 QVariant QgsCategorizedSymbolRendererV2Model::data(
const QModelIndex &index,
int role )
const 114 if ( !index.
isValid() || !mRenderer )
119 if ( role == Qt::CheckStateRole && index.
column() == 0 )
121 return category.
renderState() ? Qt::Checked : Qt::Unchecked;
123 else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
130 return category.
label();
135 else if ( role == Qt::DecorationRole && index.
column() == 0 && category.
symbol() )
139 else if ( role == Qt::TextAlignmentRole )
141 return ( index.
column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
143 else if ( role == Qt::EditRole )
148 return category.
value();
150 return category.
label();
159 bool QgsCategorizedSymbolRendererV2Model::setData(
const QModelIndex & index,
const QVariant & value,
int role )
164 if ( index.
column() == 0 && role == Qt::CheckStateRole )
166 mRenderer->updateCategoryRenderState( index.
row(), value == Qt::Checked );
167 emit dataChanged( index, index );
171 if ( role != Qt::EditRole )
180 switch ( mRenderer->categories().value( index.
row() ).value().
type() )
185 case QVariant::Double:
192 mRenderer->updateCategoryValue( index.
row(), val );
196 mRenderer->updateCategoryLabel( index.
row(), value.
toString() );
202 emit dataChanged( index, index );
206 QVariant QgsCategorizedSymbolRendererV2Model::headerData(
int section, Qt::Orientation orientation,
int role )
const 208 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
211 lst <<
tr(
"Symbol" ) <<
tr(
"Value" ) <<
tr(
"Legend" );
212 return lst.
value( section );
217 int QgsCategorizedSymbolRendererV2Model::rowCount(
const QModelIndex &
parent )
const 219 if ( parent.
isValid() || !mRenderer )
223 return mRenderer->categories().size();
226 int QgsCategorizedSymbolRendererV2Model::columnCount(
const QModelIndex & index )
const 234 if ( hasIndex( row, column, parent ) )
236 return createIndex( row, column );
247 QStringList QgsCategorizedSymbolRendererV2Model::mimeTypes()
const 250 types << mMimeFormat;
254 QMimeData *QgsCategorizedSymbolRendererV2Model::mimeData(
const QModelIndexList &indexes )
const 259 QDataStream stream( &encodedData, QIODevice::WriteOnly );
267 stream << index.
row();
269 mimeData->
setData( mMimeFormat, encodedData );
273 bool QgsCategorizedSymbolRendererV2Model::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
277 if ( action != Qt::MoveAction )
return true;
279 if ( !data->
hasFormat( mMimeFormat ) )
return false;
282 QDataStream stream( &encodedData, QIODevice::ReadOnly );
285 while ( !stream.atEnd() )
292 int to = parent.
row();
295 if ( to == -1 ) to = mRenderer->categories().size();
296 for (
int i = rows.
size() - 1; i >= 0; i-- )
301 if ( rows[i] < t ) t--;
302 mRenderer->moveCategory( rows[i], t );
304 for (
int j = 0; j < i; j++ )
306 if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
309 if ( rows[i] < to ) to--;
311 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) );
316 void QgsCategorizedSymbolRendererV2Model::deleteRows(
QList<int> rows )
319 for (
int i = rows.
size() - 1; i >= 0; i-- )
321 beginRemoveRows(
QModelIndex(), rows[i], rows[i] );
322 mRenderer->deleteCategory( rows[i] );
327 void QgsCategorizedSymbolRendererV2Model::removeAllRows()
329 beginRemoveRows(
QModelIndex(), 0, mRenderer->categories().size() - 1 );
330 mRenderer->deleteAllCategories();
334 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 );
445 if ( defaultColorRamp !=
"" )
447 int index = cboCategorizedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive );
449 cboCategorizedColorRamp->setCurrentIndex( index );
454 mModel =
new QgsCategorizedSymbolRendererV2Model(
this );
460 viewCategories->setModel( mModel );
461 viewCategories->resizeColumnToContents( 0 );
462 viewCategories->resizeColumnToContents( 1 );
463 viewCategories->resizeColumnToContents( 2 );
465 viewCategories->setStyle(
new QgsCategorizedSymbolRendererV2ViewStyle( viewCategories->style() ) );
480 connect( cboCategorizedColorRamp, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT(
applyColorRamp() ) );
482 connect( mButtonEditRamp, SIGNAL( clicked() ), cboCategorizedColorRamp, SLOT( editSourceRamp() ) );
491 btnAdvanced->setMenu( advMenu );
515 mExpressionWidget->setField( attrName );
554 Q_FOREACH (
int idx, selectedCats )
571 if ( m && !i.isEmpty() )
582 if ( !dlg.
exec() || !newSymbol )
598 btnChangeCategorizedSymbol->setIcon( icon );
624 symbol = symbol->
clone();
647 int num = values.
count();
649 bool hasNull =
false;
651 for (
int i = 0; i < num; i++ )
676 if ( cboCategorizedColorRamp->count() == 0 )
677 QMessageBox::critical(
this,
tr(
"Error" ),
tr(
"There are no available color ramps. You can add them in Style Manager." ) );
678 else if ( !cboCategorizedColorRamp->createNewColorRampSelected() )
687 QString attrName = mExpressionWidget->currentField();
700 expression->
prepare( &context );
707 if ( unique_vals.
contains( value ) )
709 unique_vals << value;
718 if ( unique_vals.
size() >= 1000 )
721 tr(
"Classification would yield %1 entries which might not be expected. Continue?" ).arg( unique_vals.
size() ),
722 QMessageBox::Ok | QMessageBox::Cancel,
723 QMessageBox::Cancel );
724 if ( res == QMessageBox::Cancel )
731 DlgAddCategories dlg(
mStyle, createDefaultSymbol(), unique_vals,
this );
738 bool deleteExisting =
false;
740 if ( !mOldClassificationAttribute.
isEmpty() &&
741 attrName != mOldClassificationAttribute &&
745 tr(
"Confirm Delete" ),
746 tr(
"The classification field was changed from '%1' to '%2'.\n" 747 "Should the existing classes be deleted before classification?" )
748 .arg( mOldClassificationAttribute, attrName ),
749 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel );
750 if ( res == QMessageBox::Cancel )
755 deleteExisting = ( res == QMessageBox::Yes );
759 bool keepExistingColors =
false;
760 if ( !deleteExisting )
763 keepExistingColors = !prevCats.
isEmpty();
764 for (
int i = 0; i < cats.
size(); ++i )
766 bool contains =
false;
768 for (
int j = 0; j < prevCats.
size() && !contains; ++j )
770 if ( prevCats.
at( j ).value() == value )
783 mOldClassificationAttribute = attrName;
825 mModel->updateSymbology();
830 QModelIndex idx = viewCategories->selectionModel()->currentIndex();
839 QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
854 mModel->deleteRows( categoryIndexes );
867 mModel->addCategory( cat );
887 if ( m && !selectedIndexes.isEmpty() )
890 QModelIndexList::const_iterator indexIt = selectedIndexes.
constBegin();
891 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
893 int row = ( *indexIt ).row();
897 selectedSymbols.
append( s );
911 if ( m && !selectedIndexes.isEmpty() )
913 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
914 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
929 viewCategories->selectionModel()->clear();
938 tr(
"Matched %1 categories to symbols." ).arg( matched ) );
943 tr(
"No categories could be matched to symbols in library." ) );
966 mModel->updateSymbology();
976 tr(
"XML files (*.xml *XML)" ) );
986 if ( !importedStyle.
importXML( fileName ) )
989 tr(
"An error occurred reading file:\n%1" ).arg( importedStyle.
errorString() ) );
997 tr(
"Matched %1 categories to symbols from file." ).arg( matched ) );
1002 tr(
"No categories could be matched to symbols in file." ) );
1013 if ( event->
key() == Qt::Key_C &&
event->modifiers() == Qt::ControlModifier )
1015 mCopyBuffer.
clear();
1018 else if ( event->
key() == Qt::Key_V &&
event->modifiers() == Qt::ControlModifier )
1021 for ( ; rIt != mCopyBuffer.
constEnd(); ++rIt )
1023 mModel->addCategory( *rIt );
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
const QgsCategoryList & categories() 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)
Returns unique values for column.
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.
const T & at(int i) const
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
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)
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) 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
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
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
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()
access to canonical QgsProject instance
QString sizeScaleField() const
bool updateCategorySymbol(int catIndex, QgsSymbolV2 *symbol)
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QString classAttribute() const
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...
QgsSymbolV2::ScaleMethod scaleMethod() const
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.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
void setSizeScaleField(const QString &fieldOrExpression)
QString errorString()
return last error from load/save operation
QgsSymbolV2 * symbol() const
void setInvertedColorRamp(bool inverted)