35 #include <QMessageBox> 36 #include <QStandardItemModel> 37 #include <QStandardItem> 43 , mMimeFormat(
"application/x-qgscategorizedsymbolrendererv2model" )
51 beginRemoveRows( QModelIndex(), 0, mRenderer->
categories().size() - 1 );
57 beginInsertRows( QModelIndex(), 0, renderer->
categories().size() - 1 );
65 if ( !mRenderer )
return;
67 beginInsertRows( QModelIndex(), idx, idx );
79 int row = index.row();
80 if ( row >= catList.size() )
84 return catList.at( row );
90 if ( !index.isValid() )
92 return Qt::ItemIsDropEnabled;
95 Qt::ItemFlags
flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable;
96 if ( index.column() == 1 || index.column() == 2 )
98 flags |= Qt::ItemIsEditable;
105 return Qt::MoveAction;
110 if ( !index.isValid() || !mRenderer )
115 if ( role == Qt::CheckStateRole && index.column() == 0 )
117 return category.
renderState() ? Qt::Checked : Qt::Unchecked;
119 else if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
121 switch ( index.column() )
123 case 1:
return category.
value().toString();
124 case 2:
return category.
label();
125 default:
return QVariant();
128 else if ( role == Qt::DecorationRole && index.column() == 0 && category.
symbol() )
132 else if ( role == Qt::TextAlignmentRole )
134 return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft;
136 else if ( role == Qt::EditRole )
138 switch ( index.column() )
140 case 1:
return category.
value();
141 case 2:
return category.
label();
142 default:
return QVariant();
151 if ( !index.isValid() )
154 if ( index.column() == 0 && role == Qt::CheckStateRole )
157 emit dataChanged( index, index );
161 if ( role != Qt::EditRole )
164 switch ( index.column() )
170 switch ( mRenderer->
categories().value( index.row() ).value().type() )
175 case QVariant::Double:
176 val = value.toDouble();
179 val = value.toString();
192 emit dataChanged( index, index );
198 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 )
200 QStringList lst; lst <<
tr(
"Symbol" ) <<
tr(
"Value" ) <<
tr(
"Legend" );
201 return lst.value( section );
208 if ( parent.isValid() || !mRenderer )
223 if ( hasIndex( row, column, parent ) )
225 return createIndex( row, column );
227 return QModelIndex();
233 return QModelIndex();
239 types << mMimeFormat;
245 QMimeData *
mimeData =
new QMimeData();
246 QByteArray encodedData;
248 QDataStream stream( &encodedData, QIODevice::WriteOnly );
251 foreach (
const QModelIndex &
index, indexes )
253 if ( !index.isValid() || index.column() != 0 )
256 stream << index.row();
258 mimeData->setData( mMimeFormat, encodedData );
266 if ( action != Qt::MoveAction )
return true;
268 if ( !data->hasFormat( mMimeFormat ) )
return false;
270 QByteArray encodedData = data->data( mMimeFormat );
271 QDataStream stream( &encodedData, QIODevice::ReadOnly );
274 while ( !stream.atEnd() )
281 int to = parent.row();
284 if ( to == -1 ) to = mRenderer->
categories().size();
285 for (
int i = rows.size() - 1; i >= 0; i-- )
287 QgsDebugMsg( QString(
"move %1 to %2" ).arg( rows[i] ).arg( to ) );
290 if ( rows[i] < t ) t--;
293 for (
int j = 0; j < i; j++ )
295 if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1;
298 if ( rows[i] < to ) to--;
300 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->
categories().size(), 0 ) );
307 for (
int i = rows.size() - 1; i >= 0; i-- )
309 beginRemoveRows( QModelIndex(), rows[i], rows[i] );
317 beginRemoveRows( QModelIndex(), 0, mRenderer->
categories().size() - 1 );
333 else if ( column == 2 )
337 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->
categories().size(), 0 ) );
343 emit dataChanged( createIndex( 0, 0 ), createIndex( mRenderer->
categories().size(), 0 ) );
348 : QProxyStyle( style )
353 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
355 QStyleOption opt( *option );
356 opt.rect.setLeft( 0 );
358 opt.rect.setHeight( 0 );
359 if ( widget ) opt.rect.setRight( widget->width() );
360 QProxyStyle::drawPrimitive( element, &opt, painter, widget );
363 QProxyStyle::drawPrimitive( element, option, painter, widget );
390 mOldClassificationAttribute = attrName;
395 mExpressionWidget->setLayer(
mLayer );
397 cboCategorizedColorRamp->populate(
mStyle );
398 int randomIndex = cboCategorizedColorRamp->findText(
tr(
"Random colors" ) );
399 if ( randomIndex != -1 )
401 cboCategorizedColorRamp->setCurrentIndex( randomIndex );
406 if ( defaultColorRamp !=
"" )
408 int index = cboCategorizedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive );
410 cboCategorizedColorRamp->setCurrentIndex( index );
421 viewCategories->setModel( mModel );
422 viewCategories->resizeColumnToContents( 0 );
423 viewCategories->resizeColumnToContents( 1 );
424 viewCategories->resizeColumnToContents( 2 );
430 connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ),
this, SLOT(
categoryColumnChanged( QString ) ) );
432 connect( viewCategories, SIGNAL( doubleClicked(
const QModelIndex & ) ),
this, SLOT(
categoriesDoubleClicked(
const QModelIndex & ) ) );
433 connect( viewCategories, SIGNAL( customContextMenuRequested(
const QPoint& ) ),
this, SLOT(
contextMenuViewCategories(
const QPoint& ) ) );
436 connect( btnAddCategories, SIGNAL( clicked() ),
this, SLOT(
addCategories() ) );
437 connect( btnDeleteCategories, SIGNAL( clicked() ),
this, SLOT(
deleteCategories() ) );
438 connect( btnDeleteAllCategories, SIGNAL( clicked() ),
this, SLOT(
deleteAllCategories() ) );
439 connect( btnAddCategory, SIGNAL( clicked() ),
this, SLOT(
addCategory() ) );
440 connect( cbxInvertedColorRamp, SIGNAL( toggled(
bool ) ),
this, SLOT(
applyColorRamp() ) );
441 connect( cboCategorizedColorRamp, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT(
applyColorRamp() ) );
444 QMenu* advMenu =
new QMenu;
453 btnAdvanced->setMenu( advMenu );
474 mExpressionWidget->setField( attrName );
502 if ( selectedCats.size() > 0 )
512 foreach (
const int idx, selectedCats )
526 QItemSelectionModel* m = viewCategories->selectionModel();
527 QModelIndexList i = m->selectedRows();
529 if ( m && i.size() > 0 )
554 btnChangeCategorizedSymbol->setIcon( icon );
568 if ( idx.isValid() && idx.column() == 0 )
580 symbol = symbol->
clone();
602 int num = values.count();
604 bool hasNull =
false;
606 for (
int i = 0; i < num; i++ )
608 QVariant value = values[i];
609 if ( value.toString().isNull() )
631 if ( cboCategorizedColorRamp->count() == 0 )
632 QMessageBox::critical(
this,
tr(
"Error" ),
tr(
"There are no available color ramps. You can add them in Style Manager." ) );
633 else if ( !cboCategorizedColorRamp->createNewColorRampSelected() )
634 QMessageBox::critical(
this,
tr(
"Error" ),
tr(
"The selected color ramp is not available." ) );
642 QString attrName = mExpressionWidget->currentField();
644 QList<QVariant> unique_vals;
654 QVariant value = expression->
evaluate( feature );
655 if ( unique_vals.contains( value ) )
657 unique_vals << value;
666 if ( unique_vals.size() >= 1000 )
668 int res = QMessageBox::warning( 0,
tr(
"High number of classes!" ),
669 tr(
"Classification would yield %1 entries which might not be expected. Continue?" ).arg( unique_vals.size() ),
670 QMessageBox::Ok | QMessageBox::Cancel,
671 QMessageBox::Cancel );
672 if ( res == QMessageBox::Cancel )
679 DlgAddCategories dlg(
mStyle, createDefaultSymbol(), unique_vals,
this );
686 bool deleteExisting =
false;
688 if ( !mOldClassificationAttribute.isEmpty() &&
689 attrName != mOldClassificationAttribute &&
692 int res = QMessageBox::question(
this,
693 tr(
"Confirm Delete" ),
694 tr(
"The classification field was changed from '%1' to '%2'.\n" 695 "Should the existing classes be deleted before classification?" )
696 .arg( mOldClassificationAttribute ).arg( attrName ),
697 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel );
698 if ( res == QMessageBox::Cancel )
703 deleteExisting = ( res == QMessageBox::Yes );
707 bool keepExistingColors =
false;
708 if ( !deleteExisting )
711 keepExistingColors = prevCats.size() > 0;
712 for (
int i = 0; i < cats.size(); ++i )
714 bool contains =
false;
715 QVariant value = cats.at( i ).value();
716 for (
int j = 0; j < prevCats.size() && !contains; ++j )
718 if ( prevCats.at( j ).value() == value )
726 prevCats.append( cats.at( i ) );
731 mOldClassificationAttribute = attrName;
778 QModelIndex idx = viewCategories->selectionModel()->currentIndex();
779 if ( !idx.isValid() )
787 QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows();
789 foreach ( QModelIndex r, selectedRows )
793 rows.append( r.row() );
837 QItemSelectionModel* m = viewCategories->selectionModel();
838 QModelIndexList selectedIndexes = m->selectedRows( 1 );
840 if ( m && selectedIndexes.size() > 0 )
843 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
844 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
846 int row = ( *indexIt ).row();
850 selectedSymbols.append( s );
861 QItemSelectionModel* m = viewCategories->selectionModel();
862 QModelIndexList selectedIndexes = m->selectedRows( 1 );
864 if ( m && selectedIndexes.size() > 0 )
866 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin();
867 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt )
882 viewCategories->selectionModel()->clear();
892 if ( event->key() == Qt::Key_C &&
event->modifiers() == Qt::ControlModifier )
897 else if ( event->key() == Qt::Key_V &&
event->modifiers() == Qt::ControlModifier )
899 QgsCategoryList::const_iterator rIt = mCopyBuffer.constBegin();
900 for ( ; rIt != mCopyBuffer.constEnd(); ++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.
QgsRendererCategoryV2 category(const QModelIndex &index)
const QgsCategoryList & categories() const
QgsVectorColorRampV2 * sourceColorRamp()
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
QVariant data(const QModelIndex &index, int role) const override
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
void setSourceSymbol(QgsSymbolV2 *sym)
QStringList mimeTypes() const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
virtual QgsSymbolV2 * clone() const =0
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
bool updateCategoryRenderState(int catIndex, bool render)
void addCategory(const QgsRendererCategoryV2 &cat)
void moveCategory(int from, int to)
Moves the category at index position from to index position to.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
void setSizeScaleField(QString fieldOrExpression)
void setSourceColorRamp(QgsVectorColorRampV2 *ramp)
QString rotationField() const override
return rotation field name (or empty string if not set or not supported by renderer) ...
void sortByLabel(Qt::SortOrder order=Qt::AscendingOrder)
void updateSymbols(QgsSymbolV2 *sym)
void setColor(const QColor &color)
void deleteAllCategories()
QList< QgsRendererCategoryV2 > QgsCategoryList
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
virtual QgsVectorColorRampV2 * clone() const =0
QMimeData * mimeData(const QModelIndexList &indexes) const override
QgsCategorizedSymbolRendererV2Model(QObject *parent=0)
void setClassAttribute(QString attr)
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QgsCategorizedSymbolRendererV2ViewStyle(QStyle *style=0)
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)
bool updateCategoryLabel(int catIndex, QString label)
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget=0) const override
QgsSymbolV2 * sourceSymbol()
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=0) const
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void setRenderer(QgsCategorizedSymbolRendererV2 *renderer)
bool updateCategoryValue(int catIndex, const QVariant &value)
bool deleteCategory(int catIndex)
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
static QgsProject * instance()
access to canonical QgsProject instance
QModelIndex parent(const QModelIndex &index) const override
QString sizeScaleField() const
bool updateCategorySymbol(int catIndex, QgsSymbolV2 *symbol)
Qt::DropActions supportedDropActions() const override
QString classAttribute() const
int columnCount(const QModelIndex &=QModelIndex()) const override
void setRotationField(QString fieldOrExpression) override
sets rotation field of renderer (if supported by the renderer)
void deleteRows(QList< int > rows)
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsSymbolV2::ScaleMethod scaleMethod() const
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
bool nextFeature(QgsFeature &f)
Qt::ItemFlags flags(const QModelIndex &index) const override
void addCategory(const QgsRendererCategoryV2 &category)
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 sortByValue(Qt::SortOrder order=Qt::AscendingOrder)
QgsSymbolV2 * symbol() const
void setInvertedColorRamp(bool inverted)