QGIS API Documentation  master-59fd5e0
src/gui/symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines