|
QGIS API Documentation
master-59fd5e0
|
00001 /*************************************************************************** 00002 qgscategorizedsymbolrendererv2widget.cpp 00003 --------------------- 00004 begin : November 2009 00005 copyright : (C) 2009 by Martin Dobias 00006 email : wonder dot sk at gmail dot com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "qgscategorizedsymbolrendererv2widget.h" 00017 00018 #include "qgscategorizedsymbolrendererv2.h" 00019 00020 #include "qgssymbolv2.h" 00021 #include "qgssymbollayerv2utils.h" 00022 #include "qgsvectorcolorrampv2.h" 00023 #include "qgsstylev2.h" 00024 00025 #include "qgssymbolv2selectordialog.h" 00026 00027 #include "qgsvectorlayer.h" 00028 00029 #include "qgsproject.h" 00030 00031 #include <QMenu> 00032 #include <QMessageBox> 00033 #include <QStandardItemModel> 00034 #include <QStandardItem> 00035 #include <QPen> 00036 #include <QPainter> 00037 00038 QgsCategorizedSymbolRendererV2Model::QgsCategorizedSymbolRendererV2Model( QObject * parent ) : QAbstractItemModel( parent ) 00039 , mRenderer( 0 ) 00040 , mMimeFormat( "application/x-qgscategorizedsymbolrendererv2model" ) 00041 { 00042 } 00043 00044 void QgsCategorizedSymbolRendererV2Model::setRenderer( QgsCategorizedSymbolRendererV2* renderer ) 00045 { 00046 if ( mRenderer ) 00047 { 00048 beginRemoveRows( QModelIndex(), 0, mRenderer->categories().size() - 1 ); 00049 mRenderer = 0; 00050 endRemoveRows(); 00051 } 00052 if ( renderer ) 00053 { 00054 beginInsertRows( QModelIndex(), 0, renderer->categories().size() - 1 ); 00055 mRenderer = renderer; 00056 endInsertRows(); 00057 } 00058 } 00059 00060 void QgsCategorizedSymbolRendererV2Model::addCategory( const QgsRendererCategoryV2 &cat ) 00061 { 00062 if ( !mRenderer ) return; 00063 int idx = mRenderer->categories().size(); 00064 beginInsertRows( QModelIndex(), idx, idx ); 00065 mRenderer->addCategory( cat ); 00066 endInsertRows(); 00067 } 00068 00069 00070 Qt::ItemFlags QgsCategorizedSymbolRendererV2Model::flags( const QModelIndex & index ) const 00071 { 00072 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; 00073 if ( index.column() == 1 || index.column() == 2 ) 00074 { 00075 flags |= Qt::ItemIsEditable; 00076 } 00077 return flags; 00078 } 00079 00080 Qt::DropActions QgsCategorizedSymbolRendererV2Model::supportedDropActions() const 00081 { 00082 return Qt::MoveAction; 00083 } 00084 00085 QVariant QgsCategorizedSymbolRendererV2Model::data( const QModelIndex &index, int role ) const 00086 { 00087 if ( !index.isValid() || !mRenderer ) return QVariant(); 00088 00089 const QgsRendererCategoryV2 category = mRenderer->categories().value( index.row() ); 00090 00091 if ( role == Qt::DisplayRole || role == Qt::ToolTipRole ) 00092 { 00093 switch ( index.column() ) 00094 { 00095 case 1: return category.value().toString(); 00096 case 2: return category.label(); 00097 default: return QVariant(); 00098 } 00099 } 00100 else if ( role == Qt::DecorationRole && index.column() == 0 && category.symbol() ) 00101 { 00102 return QgsSymbolLayerV2Utils::symbolPreviewIcon( category.symbol(), QSize( 16, 16 ) ); 00103 } 00104 else if ( role == Qt::TextAlignmentRole ) 00105 { 00106 return ( index.column() == 0 ) ? Qt::AlignHCenter : Qt::AlignLeft; 00107 } 00108 else if ( role == Qt::EditRole ) 00109 { 00110 switch ( index.column() ) 00111 { 00112 case 1: return category.value(); 00113 case 2: return category.label(); 00114 default: return QVariant(); 00115 } 00116 } 00117 00118 return QVariant(); 00119 } 00120 00121 bool QgsCategorizedSymbolRendererV2Model::setData( const QModelIndex & index, const QVariant & value, int role ) 00122 { 00123 if ( !index.isValid() || role != Qt::EditRole ) 00124 return false; 00125 00126 switch ( index.column() ) 00127 { 00128 case 1: // value 00129 { 00130 // try to preserve variant type for this value 00131 QVariant val; 00132 switch ( mRenderer->categories().value( index.row() ).value().type() ) 00133 { 00134 case QVariant::Int: 00135 val = value.toInt(); 00136 break; 00137 case QVariant::Double: 00138 val = value.toDouble(); 00139 break; 00140 default: 00141 val = value.toString(); 00142 break; 00143 } 00144 mRenderer->updateCategoryValue( index.row(), val ); 00145 break; 00146 } 00147 case 2: // label 00148 mRenderer->updateCategoryLabel( index.row(), value.toString() ); 00149 break; 00150 default: 00151 return false; 00152 } 00153 00154 emit dataChanged( index, index ); 00155 return true; 00156 } 00157 00158 QVariant QgsCategorizedSymbolRendererV2Model::headerData( int section, Qt::Orientation orientation, int role ) const 00159 { 00160 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 3 ) 00161 { 00162 QStringList lst; lst << tr( "Symbol" ) << tr( "Value" ) << tr( "Label" ); 00163 return lst.value( section ); 00164 } 00165 return QVariant(); 00166 } 00167 00168 int QgsCategorizedSymbolRendererV2Model::rowCount( const QModelIndex &parent ) const 00169 { 00170 if ( parent.column() > 0 || !mRenderer ) return 0; 00171 return mRenderer->categories().size(); 00172 } 00173 00174 int QgsCategorizedSymbolRendererV2Model::columnCount( const QModelIndex & index ) const 00175 { 00176 Q_UNUSED( index ); 00177 return 3; 00178 } 00179 00180 QModelIndex QgsCategorizedSymbolRendererV2Model::index( int row, int column, const QModelIndex &parent ) const 00181 { 00182 if ( hasIndex( row, column, parent ) ) 00183 { 00184 return createIndex( row, column, 0 ); 00185 } 00186 return QModelIndex(); 00187 } 00188 00189 QModelIndex QgsCategorizedSymbolRendererV2Model::parent( const QModelIndex &index ) const 00190 { 00191 Q_UNUSED( index ); 00192 return QModelIndex(); 00193 } 00194 00195 QStringList QgsCategorizedSymbolRendererV2Model::mimeTypes() const 00196 { 00197 QStringList types; 00198 types << mMimeFormat; 00199 return types; 00200 } 00201 00202 QMimeData *QgsCategorizedSymbolRendererV2Model::mimeData( const QModelIndexList &indexes ) const 00203 { 00204 QMimeData *mimeData = new QMimeData(); 00205 QByteArray encodedData; 00206 00207 QDataStream stream( &encodedData, QIODevice::WriteOnly ); 00208 00209 // Create list of rows 00210 foreach ( const QModelIndex &index, indexes ) 00211 { 00212 if ( !index.isValid() || index.column() != 0 ) 00213 continue; 00214 00215 stream << index.row(); 00216 } 00217 mimeData->setData( mMimeFormat, encodedData ); 00218 return mimeData; 00219 } 00220 00221 bool QgsCategorizedSymbolRendererV2Model::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) 00222 { 00223 Q_UNUSED( row ); 00224 Q_UNUSED( column ); 00225 if ( action != Qt::MoveAction ) return true; 00226 00227 if ( !data->hasFormat( mMimeFormat ) ) return false; 00228 00229 QByteArray encodedData = data->data( mMimeFormat ); 00230 QDataStream stream( &encodedData, QIODevice::ReadOnly ); 00231 00232 QVector<int> rows; 00233 while ( !stream.atEnd() ) 00234 { 00235 int r; 00236 stream >> r; 00237 rows.append( r ); 00238 } 00239 00240 int to = parent.row(); 00241 // to is -1 if dragged outside items, i.e. below any item, 00242 // then move to the last position 00243 if ( to == -1 ) to = mRenderer->categories().size(); // out of rang ok, will be decreased 00244 for ( int i = rows.size() - 1; i >= 0; i-- ) 00245 { 00246 QgsDebugMsg( QString( "move %1 to %2" ).arg( rows[i] ).arg( to ) ); 00247 int t = to; 00248 // moveCategory first removes and then inserts 00249 if ( rows[i] < to ) t--; 00250 mRenderer->moveCategory( rows[i], t ); 00251 // current moved under another, shift its index up 00252 for ( int j = 0; j < i; j++ ) 00253 { 00254 if ( to < rows[j] && rows[i] > rows[j] ) rows[j] += 1; 00255 } 00256 // removed under 'to' so the target shifted down 00257 if ( rows[i] < to ) to--; 00258 } 00259 emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) ); 00260 emit rowsMoved(); 00261 return false; 00262 } 00263 00264 void QgsCategorizedSymbolRendererV2Model::deleteRows( QList<int> rows ) 00265 { 00266 for ( int i = rows.size() - 1; i >= 0; i-- ) 00267 { 00268 beginRemoveRows( QModelIndex(), rows[i], rows[i] ); 00269 mRenderer->deleteCategory( rows[i] ); 00270 endRemoveRows(); 00271 } 00272 } 00273 00274 void QgsCategorizedSymbolRendererV2Model::removeAllRows( ) 00275 { 00276 beginRemoveRows( QModelIndex(), 0, mRenderer->categories().size() - 1 ); 00277 mRenderer->deleteAllCategories(); 00278 endRemoveRows(); 00279 } 00280 00281 void QgsCategorizedSymbolRendererV2Model::sort( int column, Qt::SortOrder order ) 00282 { 00283 QgsDebugMsg( "Entered" ); 00284 if ( column == 0 ) 00285 { 00286 return; 00287 } 00288 if ( column == 1 ) 00289 { 00290 mRenderer->sortByValue( order ); 00291 } 00292 else if ( column == 2 ) 00293 { 00294 mRenderer->sortByLabel( order ); 00295 } 00296 emit dataChanged( createIndex( 0, 0, 0 ), createIndex( mRenderer->categories().size(), 0 ) ); 00297 QgsDebugMsg( "Done" ); 00298 } 00299 00300 // ------------------------------ View style -------------------------------- 00301 QgsCategorizedSymbolRendererV2ViewStyle::QgsCategorizedSymbolRendererV2ViewStyle( QStyle* style ) 00302 : QProxyStyle( style ) 00303 {} 00304 00305 void QgsCategorizedSymbolRendererV2ViewStyle::drawPrimitive( PrimitiveElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget ) const 00306 { 00307 if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() ) 00308 { 00309 QStyleOption opt( *option ); 00310 opt.rect.setLeft( 0 ); 00311 // draw always as line above, because we move item to that index 00312 opt.rect.setHeight( 0 ); 00313 if ( widget ) opt.rect.setRight( widget->width() ); 00314 QProxyStyle::drawPrimitive( element, &opt, painter, widget ); 00315 return; 00316 } 00317 QProxyStyle::drawPrimitive( element, option, painter, widget ); 00318 } 00319 00320 // ------------------------------ Widget ------------------------------------ 00321 QgsRendererV2Widget* QgsCategorizedSymbolRendererV2Widget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) 00322 { 00323 return new QgsCategorizedSymbolRendererV2Widget( layer, style, renderer ); 00324 } 00325 00326 QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) 00327 : QgsRendererV2Widget( layer, style ) 00328 , mRenderer( 0 ) 00329 , mModel( 0 ) 00330 { 00331 00332 // try to recognize the previous renderer 00333 // (null renderer means "no previous renderer") 00334 if ( !renderer || renderer->type() != "categorizedSymbol" ) 00335 { 00336 // we're not going to use it - so let's delete the renderer 00337 delete renderer; 00338 00339 mRenderer = new QgsCategorizedSymbolRendererV2( "", QgsCategoryList() ); 00340 } 00341 else 00342 { 00343 mRenderer = static_cast<QgsCategorizedSymbolRendererV2*>( renderer ); 00344 } 00345 00346 QString attrName = mRenderer->classAttribute(); 00347 mOldClassificationAttribute = attrName; 00348 00349 // setup user interface 00350 setupUi( this ); 00351 00352 populateColumns(); 00353 00354 cboCategorizedColorRamp->populate( mStyle ); 00355 00356 // set project default color ramp 00357 QString defaultColorRamp = QgsProject::instance()->readEntry( "DefaultStyles", "/ColorRamp", "" ); 00358 if ( defaultColorRamp != "" ) 00359 { 00360 int index = cboCategorizedColorRamp->findText( defaultColorRamp, Qt::MatchCaseSensitive ); 00361 if ( index >= 0 ) 00362 cboCategorizedColorRamp->setCurrentIndex( index ); 00363 } 00364 00365 mModel = new QgsCategorizedSymbolRendererV2Model( this ); 00366 mModel->setRenderer( mRenderer ); 00367 viewCategories->setModel( mModel ); 00368 viewCategories->resizeColumnToContents( 0 ); 00369 viewCategories->resizeColumnToContents( 1 ); 00370 viewCategories->resizeColumnToContents( 2 ); 00371 00372 viewCategories->setStyle( new QgsCategorizedSymbolRendererV2ViewStyle( viewCategories->style() ) ); 00373 00374 mCategorizedSymbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() ); 00375 00376 connect( mModel, SIGNAL( rowsMoved() ), this, SLOT( rowsMoved() ) ); 00377 00378 connect( cboCategorizedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( categoryColumnChanged() ) ); 00379 00380 connect( viewCategories, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( categoriesDoubleClicked( const QModelIndex & ) ) ); 00381 connect( viewCategories, SIGNAL( customContextMenuRequested( const QPoint& ) ), this, SLOT( contextMenuViewCategories( const QPoint& ) ) ); 00382 00383 connect( btnChangeCategorizedSymbol, SIGNAL( clicked() ), this, SLOT( changeCategorizedSymbol() ) ); 00384 connect( btnAddCategories, SIGNAL( clicked() ), this, SLOT( addCategories() ) ); 00385 connect( btnDeleteCategories, SIGNAL( clicked() ), this, SLOT( deleteCategories() ) ); 00386 connect( btnDeleteAllCategories, SIGNAL( clicked() ), this, SLOT( deleteAllCategories() ) ); 00387 connect( btnAddCategory, SIGNAL( clicked() ), this, SLOT( addCategory() ) ); 00388 00389 // update GUI from renderer 00390 updateUiFromRenderer(); 00391 00392 // menus for data-defined rotation/size 00393 QMenu* advMenu = new QMenu; 00394 00395 advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) ); 00396 00397 mDataDefinedMenus = new QgsRendererV2DataDefinedMenus( advMenu, mLayer->pendingFields(), 00398 mRenderer->rotationField(), mRenderer->sizeScaleField(), mRenderer->scaleMethod() ); 00399 connect( mDataDefinedMenus, SIGNAL( rotationFieldChanged( QString ) ), this, SLOT( rotationFieldChanged( QString ) ) ); 00400 connect( mDataDefinedMenus, SIGNAL( sizeScaleFieldChanged( QString ) ), this, SLOT( sizeScaleFieldChanged( QString ) ) ); 00401 connect( mDataDefinedMenus, SIGNAL( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ), this, SLOT( scaleMethodChanged( QgsSymbolV2::ScaleMethod ) ) ); 00402 btnAdvanced->setMenu( advMenu ); 00403 } 00404 00405 QgsCategorizedSymbolRendererV2Widget::~QgsCategorizedSymbolRendererV2Widget() 00406 { 00407 if ( mRenderer ) delete mRenderer; 00408 if ( mModel ) delete mModel; 00409 } 00410 00411 void QgsCategorizedSymbolRendererV2Widget::updateUiFromRenderer() 00412 { 00413 updateCategorizedSymbolIcon(); 00414 00415 //mModel->setRenderer ( mRenderer ); // necessary? 00416 00417 // set column 00418 disconnect( cboCategorizedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( categoryColumnChanged() ) ); 00419 QString attrName = mRenderer->classAttribute(); 00420 mOldClassificationAttribute = attrName; 00421 int idx = cboCategorizedColumn->findText( attrName, Qt::MatchExactly ); 00422 cboCategorizedColumn->setCurrentIndex( idx >= 0 ? idx : 0 ); 00423 connect( cboCategorizedColumn, SIGNAL( currentIndexChanged( int ) ), this, SLOT( categoryColumnChanged() ) ); 00424 00425 // set source symbol 00426 if ( mRenderer->sourceSymbol() ) 00427 { 00428 delete mCategorizedSymbol; 00429 mCategorizedSymbol = mRenderer->sourceSymbol()->clone(); 00430 updateCategorizedSymbolIcon(); 00431 } 00432 00433 // set source color ramp 00434 if ( mRenderer->sourceColorRamp() ) 00435 { 00436 cboCategorizedColorRamp->setSourceColorRamp( mRenderer->sourceColorRamp() ); 00437 } 00438 00439 } 00440 00441 QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2Widget::renderer() 00442 { 00443 return mRenderer; 00444 } 00445 00446 void QgsCategorizedSymbolRendererV2Widget::changeSelectedSymbols() 00447 { 00448 QList<int> selectedCats = selectedCategories(); 00449 00450 if ( selectedCats.size() > 0 ) 00451 { 00452 QgsSymbolV2* newSymbol = mCategorizedSymbol->clone(); 00453 QgsSymbolV2SelectorDialog dlg( newSymbol, mStyle, mLayer, this ); 00454 if ( !dlg.exec() ) 00455 { 00456 delete newSymbol; 00457 return; 00458 } 00459 00460 foreach ( const int idx, selectedCats ) 00461 { 00462 QgsRendererCategoryV2 category = mRenderer->categories().value( idx ); 00463 00464 QgsSymbolV2* newCatSymbol = newSymbol->clone(); 00465 newCatSymbol->setColor( mRenderer->categories()[idx].symbol()->color() ); 00466 mRenderer->updateCategorySymbol( idx, newCatSymbol ); 00467 } 00468 } 00469 } 00470 00471 void QgsCategorizedSymbolRendererV2Widget::changeCategorizedSymbol() 00472 { 00473 // When there is a slection, change the selected symbols alone 00474 QItemSelectionModel* m = viewCategories->selectionModel(); 00475 QModelIndexList i = m->selectedRows(); 00476 00477 if ( m && i.size() > 0 ) 00478 { 00479 changeSelectedSymbols(); 00480 return; 00481 } 00482 00483 // When there is no selection, change the base mCategorizedSymbol 00484 QgsSymbolV2* newSymbol = mCategorizedSymbol->clone(); 00485 00486 QgsSymbolV2SelectorDialog dlg( newSymbol, mStyle, mLayer, this ); 00487 if ( !dlg.exec() ) 00488 { 00489 delete newSymbol; 00490 return; 00491 } 00492 00493 mCategorizedSymbol = newSymbol; 00494 updateCategorizedSymbolIcon(); 00495 00496 mRenderer->updateSymbols( mCategorizedSymbol ); 00497 } 00498 00499 void QgsCategorizedSymbolRendererV2Widget::updateCategorizedSymbolIcon() 00500 { 00501 QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( mCategorizedSymbol, btnChangeCategorizedSymbol->iconSize() ); 00502 btnChangeCategorizedSymbol->setIcon( icon ); 00503 } 00504 00505 void QgsCategorizedSymbolRendererV2Widget::populateCategories() 00506 { 00507 00508 } 00509 00510 void QgsCategorizedSymbolRendererV2Widget::populateColumns() 00511 { 00512 cboCategorizedColumn->clear(); 00513 const QgsFields& flds = mLayer->pendingFields(); 00514 for ( int idx = 0; idx < flds.count(); ++idx ) 00515 { 00516 cboCategorizedColumn->addItem( flds[idx].name() ); 00517 } 00518 } 00519 00520 void QgsCategorizedSymbolRendererV2Widget::categoryColumnChanged() 00521 { 00522 mRenderer->setClassAttribute( cboCategorizedColumn->currentText() ); 00523 } 00524 00525 void QgsCategorizedSymbolRendererV2Widget::categoriesDoubleClicked( const QModelIndex & idx ) 00526 { 00527 if ( idx.isValid() && idx.column() == 0 ) 00528 changeCategorySymbol(); 00529 } 00530 00531 void QgsCategorizedSymbolRendererV2Widget::changeCategorySymbol() 00532 { 00533 int catIdx = currentCategoryRow(); 00534 QgsRendererCategoryV2 category = mRenderer->categories().value( currentCategoryRow() ); 00535 00536 QgsSymbolV2 *symbol = category.symbol(); 00537 if ( symbol ) 00538 { 00539 symbol = symbol->clone(); 00540 } 00541 else 00542 { 00543 symbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() ); 00544 } 00545 00546 QgsSymbolV2SelectorDialog dlg( symbol, mStyle, mLayer, this ); 00547 if ( !dlg.exec() ) 00548 { 00549 delete symbol; 00550 return; 00551 } 00552 00553 mRenderer->updateCategorySymbol( catIdx, symbol ); 00554 } 00555 00556 static void _createCategories( QgsCategoryList& cats, QList<QVariant>& values, QgsSymbolV2* symbol, QgsVectorColorRampV2* ramp ) 00557 { 00558 // sort the categories first 00559 QgsSymbolLayerV2Utils::sortVariantList( values, Qt::AscendingOrder ); 00560 00561 int num = values.count(); 00562 00563 bool hasNull = false; 00564 00565 for ( int i = 0; i < num; i++ ) 00566 { 00567 QVariant value = values[i]; 00568 if ( value.toString().isNull() ) 00569 { 00570 hasNull = true; 00571 } 00572 double x = i / ( double ) num; 00573 QgsSymbolV2* newSymbol = symbol->clone(); 00574 newSymbol->setColor( ramp->color( x ) ); 00575 00576 cats.append( QgsRendererCategoryV2( value, newSymbol, value.toString() ) ); 00577 } 00578 00579 // add null (default) value if not exists 00580 if ( !hasNull ) 00581 { 00582 QgsSymbolV2* newSymbol = symbol->clone(); 00583 newSymbol->setColor( ramp->color( 1 ) ); 00584 cats.append( QgsRendererCategoryV2( QVariant( "" ), newSymbol, QString() ) ); 00585 } 00586 } 00587 00588 void QgsCategorizedSymbolRendererV2Widget::addCategories() 00589 { 00590 QString attrName = cboCategorizedColumn->currentText(); 00591 int idx = mLayer->fieldNameIndex( attrName ); 00592 QList<QVariant> unique_vals; 00593 mLayer->uniqueValues( idx, unique_vals ); 00594 00595 // ask to abort if too many classes 00596 if ( unique_vals.size() >= 1000 ) 00597 { 00598 int res = QMessageBox::warning( 0, tr( "High number of classes!" ), 00599 tr( "Classification would yield %1 entries which might not be expected. Continue?" ).arg( unique_vals.size() ), 00600 QMessageBox::Ok | QMessageBox::Cancel, 00601 QMessageBox::Cancel ); 00602 if ( res == QMessageBox::Cancel ) 00603 { 00604 return; 00605 } 00606 } 00607 00608 //DlgAddCategories dlg(mStyle, createDefaultSymbol(), unique_vals, this); 00609 //if (!dlg.exec()) 00610 // return; 00611 00612 QgsVectorColorRampV2* ramp = cboCategorizedColorRamp->currentColorRamp(); 00613 00614 if ( ramp == NULL ) 00615 { 00616 if ( cboCategorizedColorRamp->count() == 0 ) 00617 QMessageBox::critical( this, tr( "Error" ), tr( "There are no available color ramps. You can add them in Style Manager." ) ); 00618 else 00619 QMessageBox::critical( this, tr( "Error" ), tr( "The selected color ramp is not available." ) ); 00620 return; 00621 } 00622 00623 QgsCategoryList cats; 00624 _createCategories( cats, unique_vals, mCategorizedSymbol, ramp ); 00625 00626 bool deleteExisting = false; 00627 00628 if ( !mOldClassificationAttribute.isEmpty() && 00629 attrName != mOldClassificationAttribute && 00630 mRenderer->categories().count() > 0 ) 00631 { 00632 int res = QMessageBox::question( this, 00633 tr( "Confirm Delete" ), 00634 tr( "The classification field was changed from '%1' to '%2'.\n" 00635 "Should the existing classes be deleted before classification?" ) 00636 .arg( mOldClassificationAttribute ).arg( attrName ), 00637 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel ); 00638 if ( res == QMessageBox::Cancel ) 00639 { 00640 return; 00641 } 00642 00643 deleteExisting = ( res == QMessageBox::Yes ); 00644 } 00645 00646 if ( !deleteExisting ) 00647 { 00648 QgsCategoryList prevCats = mRenderer->categories(); 00649 for ( int i = 0; i < cats.size(); ++i ) 00650 { 00651 bool contains = false; 00652 QVariant value = cats.at( i ).value(); 00653 for ( int j = 0; j < prevCats.size() && !contains; ++j ) 00654 { 00655 if ( prevCats.at( j ).value() == value ) 00656 { 00657 contains = true; 00658 break; 00659 } 00660 } 00661 00662 if ( !contains ) 00663 prevCats.append( cats.at( i ) ); 00664 } 00665 cats = prevCats; 00666 } 00667 00668 mOldClassificationAttribute = attrName; 00669 00670 // TODO: if not all categories are desired, delete some! 00671 /* 00672 if (not dlg.readAllCats.isChecked()) 00673 { 00674 cats2 = {} 00675 for item in dlg.listCategories.selectedItems(): 00676 for k,c in cats.iteritems(): 00677 if item.text() == k.toString(): 00678 break 00679 cats2[k] = c 00680 cats = cats2 00681 } 00682 */ 00683 00684 // recreate renderer 00685 QgsCategorizedSymbolRendererV2 *r = new QgsCategorizedSymbolRendererV2( attrName, cats ); 00686 r->setSourceSymbol( mCategorizedSymbol->clone() ); 00687 r->setSourceColorRamp( ramp->clone() ); 00688 r->setScaleMethod( mRenderer->scaleMethod() ); 00689 r->setSizeScaleField( mRenderer->sizeScaleField() ); 00690 r->setRotationField( mRenderer->rotationField() ); 00691 00692 if ( mModel ) 00693 { 00694 mModel->setRenderer( r ); 00695 } 00696 delete mRenderer; 00697 mRenderer = r; 00698 } 00699 00700 int QgsCategorizedSymbolRendererV2Widget::currentCategoryRow() 00701 { 00702 QModelIndex idx = viewCategories->selectionModel()->currentIndex(); 00703 if ( !idx.isValid() ) 00704 return -1; 00705 return idx.row(); 00706 } 00707 00708 QList<int> QgsCategorizedSymbolRendererV2Widget::selectedCategories() 00709 { 00710 QList<int> rows; 00711 QModelIndexList selectedRows = viewCategories->selectionModel()->selectedRows(); 00712 00713 foreach ( QModelIndex r, selectedRows ) 00714 { 00715 if ( r.isValid() ) 00716 { 00717 rows.append( r.row() ); 00718 } 00719 } 00720 return rows; 00721 } 00722 00723 void QgsCategorizedSymbolRendererV2Widget::deleteCategories() 00724 { 00725 QList<int> categoryIndexes = selectedCategories(); 00726 mModel->deleteRows( categoryIndexes ); 00727 } 00728 00729 void QgsCategorizedSymbolRendererV2Widget::deleteAllCategories() 00730 { 00731 mModel->removeAllRows(); 00732 } 00733 00734 void QgsCategorizedSymbolRendererV2Widget::addCategory() 00735 { 00736 if ( !mModel ) return; 00737 QgsSymbolV2 *symbol = QgsSymbolV2::defaultSymbol( mLayer->geometryType() ); 00738 QgsRendererCategoryV2 cat( QString(), symbol, QString() ); 00739 mModel->addCategory( cat ); 00740 } 00741 00742 void QgsCategorizedSymbolRendererV2Widget::rotationFieldChanged( QString fldName ) 00743 { 00744 mRenderer->setRotationField( fldName ); 00745 } 00746 00747 void QgsCategorizedSymbolRendererV2Widget::sizeScaleFieldChanged( QString fldName ) 00748 { 00749 mRenderer->setSizeScaleField( fldName ); 00750 } 00751 00752 void QgsCategorizedSymbolRendererV2Widget::scaleMethodChanged( QgsSymbolV2::ScaleMethod scaleMethod ) 00753 { 00754 mRenderer->setScaleMethod( scaleMethod ); 00755 } 00756 00757 QList<QgsSymbolV2*> QgsCategorizedSymbolRendererV2Widget::selectedSymbols() 00758 { 00759 QList<QgsSymbolV2*> selectedSymbols; 00760 00761 QItemSelectionModel* m = viewCategories->selectionModel(); 00762 QModelIndexList selectedIndexes = m->selectedRows( 1 ); 00763 00764 if ( m && selectedIndexes.size() > 0 ) 00765 { 00766 const QgsCategoryList& categories = mRenderer->categories(); 00767 QModelIndexList::const_iterator indexIt = selectedIndexes.constBegin(); 00768 for ( ; indexIt != selectedIndexes.constEnd(); ++indexIt ) 00769 { 00770 int row = ( *indexIt ).row(); 00771 QgsSymbolV2* s = categories[row].symbol(); 00772 if ( s ) 00773 { 00774 selectedSymbols.append( s ); 00775 } 00776 } 00777 } 00778 return selectedSymbols; 00779 } 00780 00781 void QgsCategorizedSymbolRendererV2Widget::showSymbolLevels() 00782 { 00783 showSymbolLevelsDialog( mRenderer ); 00784 } 00785 00786 void QgsCategorizedSymbolRendererV2Widget::rowsMoved() 00787 { 00788 viewCategories->selectionModel()->clear(); 00789 }