|
Quantum GIS API Documentation
master-693a1fe
|
00001 /*************************************************************************** 00002 qgsstylev2exportimportdialog.cpp 00003 --------------------- 00004 begin : Jan 2011 00005 copyright : (C) 2011 by Alexander Bruy 00006 email : alexander dot bruy at gmail dot com 00007 00008 *************************************************************************** 00009 * * 00010 * This program is free software; you can redistribute it and/or modify * 00011 * it under the terms of the GNU General Public License as published by * 00012 * the Free Software Foundation; either version 2 of the License, or * 00013 * (at your option) any later version. * 00014 * * 00015 ***************************************************************************/ 00016 #include "qgsstylev2exportimportdialog.h" 00017 00018 #include "qgsstylev2.h" 00019 #include "qgssymbolv2.h" 00020 #include "qgssymbollayerv2utils.h" 00021 #include "qgsvectorcolorrampv2.h" 00022 #include "qgslogger.h" 00023 00024 #include <QInputDialog> 00025 #include <QCloseEvent> 00026 #include <QFileDialog> 00027 #include <QMessageBox> 00028 #include <QPushButton> 00029 #include <QStandardItemModel> 00030 00031 QgsStyleV2ExportImportDialog::QgsStyleV2ExportImportDialog( QgsStyleV2* style, QWidget *parent, Mode mode ) 00032 : QDialog( parent ) 00033 , mDialogMode( mode ) 00034 , mQgisStyle( style ) 00035 { 00036 setupUi( this ); 00037 00038 // additional buttons 00039 QPushButton *pb; 00040 pb = new QPushButton( tr( "Select all" ) ); 00041 buttonBox->addButton( pb, QDialogButtonBox::ActionRole ); 00042 connect( pb, SIGNAL( clicked() ), this, SLOT( selectAll() ) ); 00043 00044 pb = new QPushButton( tr( "Clear selection" ) ); 00045 buttonBox->addButton( pb, QDialogButtonBox::ActionRole ); 00046 connect( pb, SIGNAL( clicked() ), this, SLOT( clearSelection() ) ); 00047 00048 QStandardItemModel* model = new QStandardItemModel( listItems ); 00049 listItems->setModel( model ); 00050 00051 mTempStyle = new QgsStyleV2(); 00052 // TODO validate 00053 mFileName = ""; 00054 mProgressDlg = NULL; 00055 mTempFile = NULL; 00056 mNetManager = new QNetworkAccessManager( this ); 00057 mNetReply = NULL; 00058 00059 if ( mDialogMode == Import ) 00060 { 00061 setWindowTitle( tr( "Import style(s)" ) ); 00062 // populate the import types 00063 importTypeCombo->addItem( "file specified below", QVariant( "file" ) ); 00064 // importTypeCombo->addItem( "official QGIS repo online", QVariant( "official" ) ); 00065 importTypeCombo->addItem( "URL specified below", QVariant( "url" ) ); 00066 connect( importTypeCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( importTypeChanged( int ) ) ); 00067 00068 QStringList groups = mQgisStyle->groupNames(); 00069 groupCombo->addItem( "imported", QVariant( "new" ) ); 00070 foreach ( QString gName, groups ) 00071 { 00072 groupCombo->addItem( gName ); 00073 } 00074 00075 btnBrowse->setText( "Browse" ); 00076 connect( btnBrowse, SIGNAL( clicked() ), this, SLOT( browse() ) ); 00077 00078 label->setText( tr( "Select symbols to import" ) ); 00079 buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Import" ) ); 00080 } 00081 else 00082 { 00083 setWindowTitle( tr( "Export style(s)" ) ); 00084 // hide import specific controls when exporting 00085 btnBrowse->setHidden( true ); 00086 fromLabel->setHidden( true ); 00087 importTypeCombo->setHidden( true ); 00088 locationLabel->setHidden( true ); 00089 locationLineEdit->setHidden( true ); 00090 groupLabel->setHidden( true ); 00091 groupCombo->setHidden( true ); 00092 00093 buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Export" ) ); 00094 if ( !populateStyles( mQgisStyle ) ) 00095 { 00096 QApplication::postEvent( this, new QCloseEvent() ); 00097 } 00098 } 00099 00100 // use Ok button for starting import and export operations 00101 disconnect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) ); 00102 connect( buttonBox, SIGNAL( accepted() ), this, SLOT( doExportImport() ) ); 00103 } 00104 00105 void QgsStyleV2ExportImportDialog::doExportImport() 00106 { 00107 QModelIndexList selection = listItems->selectionModel()->selectedIndexes(); 00108 if ( selection.isEmpty() ) 00109 { 00110 QMessageBox::warning( this, tr( "Export/import error" ), 00111 tr( "You should select at least one symbol/color ramp." ) ); 00112 return; 00113 } 00114 00115 if ( mDialogMode == Export ) 00116 { 00117 QString fileName = QFileDialog::getSaveFileName( this, tr( "Save styles" ), ".", 00118 tr( "XML files (*.xml *.XML)" ) ); 00119 if ( fileName.isEmpty() ) 00120 { 00121 return; 00122 } 00123 00124 // ensure the user never ommited the extension from the file name 00125 if ( !fileName.toLower().endsWith( ".xml" ) ) 00126 { 00127 fileName += ".xml"; 00128 } 00129 00130 mFileName = fileName; 00131 00132 moveStyles( &selection, mQgisStyle, mTempStyle ); 00133 if ( !mTempStyle->exportXML( mFileName ) ) 00134 { 00135 QMessageBox::warning( this, tr( "Export/import error" ), 00136 tr( "Error when saving selected symbols to file:\n%1" ) 00137 .arg( mTempStyle->errorString() ) ); 00138 return; 00139 } 00140 } 00141 else // import 00142 { 00143 moveStyles( &selection, mTempStyle, mQgisStyle ); 00144 00145 // clear model 00146 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() ); 00147 model->clear(); 00148 accept(); 00149 } 00150 00151 mFileName = ""; 00152 mTempStyle->clear(); 00153 } 00154 00155 bool QgsStyleV2ExportImportDialog::populateStyles( QgsStyleV2* style ) 00156 { 00157 // load symbols and color ramps from file 00158 if ( mDialogMode == Import ) 00159 { 00160 // NOTE mTempStyle is style here 00161 if ( !style->importXML( mFileName ) ) 00162 { 00163 QMessageBox::warning( this, tr( "Import error" ), 00164 tr( "An error occured during import:\n%1" ).arg( style->errorString() ) ); 00165 return false; 00166 } 00167 } 00168 00169 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() ); 00170 model->clear(); 00171 00172 // populate symbols 00173 QStringList styleNames = style->symbolNames(); 00174 QString name; 00175 00176 for ( int i = 0; i < styleNames.count(); ++i ) 00177 { 00178 name = styleNames[i]; 00179 QgsSymbolV2* symbol = style->symbol( name ); 00180 QStandardItem* item = new QStandardItem( name ); 00181 QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( symbol, listItems->iconSize() ); 00182 item->setIcon( icon ); 00183 model->appendRow( item ); 00184 delete symbol; 00185 } 00186 00187 // and color ramps 00188 styleNames = style->colorRampNames(); 00189 00190 for ( int i = 0; i < styleNames.count(); ++i ) 00191 { 00192 name = styleNames[i]; 00193 QgsVectorColorRampV2* ramp = style->colorRamp( name ); 00194 00195 QStandardItem* item = new QStandardItem( name ); 00196 QIcon icon = QgsSymbolLayerV2Utils::colorRampPreviewIcon( ramp, listItems->iconSize() ); 00197 item->setIcon( icon ); 00198 model->appendRow( item ); 00199 delete ramp; 00200 } 00201 return true; 00202 } 00203 00204 void QgsStyleV2ExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyleV2* src, QgsStyleV2* dst ) 00205 { 00206 QString symbolName; 00207 QgsSymbolV2* symbol; 00208 QgsVectorColorRampV2 *ramp = 0; 00209 QModelIndex index; 00210 bool isSymbol = true; 00211 bool prompt = true; 00212 bool overwrite = true; 00213 int groupid = 0; 00214 00215 // get the groupid when going for import 00216 if ( mDialogMode == Import ) 00217 { 00218 int index = groupCombo->currentIndex(); 00219 QString name = groupCombo->itemText( index ); 00220 if ( name.isEmpty() ) 00221 { 00222 // get name of the group 00223 bool nameInvalid = true; 00224 while ( nameInvalid ) 00225 { 00226 bool ok; 00227 name = QInputDialog::getText( this, tr( "Group Name" ), 00228 tr( "Please enter a name for new group:" ), 00229 QLineEdit::Normal, 00230 tr( "imported" ), 00231 &ok ); 00232 if ( !ok ) 00233 { 00234 QMessageBox::warning( this, tr( "New Group" ), 00235 tr( "New group cannot be created without a name. Kindly enter a name." ) ); 00236 continue; 00237 } 00238 // validate name 00239 if ( name.isEmpty() ) 00240 { 00241 QMessageBox::warning( this, tr( "New group" ), 00242 tr( "Cannot create a group without name. Enter a name." ) ); 00243 } 00244 else 00245 { 00246 // valid name 00247 nameInvalid = false; 00248 } 00249 } 00250 groupid = dst->addGroup( name ); 00251 } 00252 else if ( dst->groupNames().contains( name ) ) 00253 { 00254 groupid = dst->groupId( name ); 00255 } 00256 else 00257 { 00258 groupid = dst->addGroup( name ); 00259 } 00260 } 00261 00262 for ( int i = 0; i < selection->size(); ++i ) 00263 { 00264 index = selection->at( i ); 00265 symbolName = index.model()->data( index, 0 ).toString(); 00266 symbol = src->symbol( symbolName ); 00267 if ( symbol == NULL ) 00268 { 00269 isSymbol = false; 00270 ramp = src->colorRamp( symbolName ); 00271 } 00272 00273 if ( isSymbol ) 00274 { 00275 if ( dst->symbolNames().contains( symbolName ) && prompt ) 00276 { 00277 int res = QMessageBox::warning( this, tr( "Duplicate names" ), 00278 tr( "Symbol with name '%1' already exists.\nOverwrite?" ) 00279 .arg( symbolName ), 00280 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel ); 00281 switch ( res ) 00282 { 00283 case QMessageBox::Cancel: 00284 return; 00285 case QMessageBox::No: 00286 continue; 00287 case QMessageBox::Yes: 00288 dst->addSymbol( symbolName, symbol ); 00289 if ( mDialogMode == Import ) 00290 dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); 00291 continue; 00292 case QMessageBox::YesToAll: 00293 prompt = false; 00294 overwrite = true; 00295 break; 00296 case QMessageBox::NoToAll: 00297 prompt = false; 00298 overwrite = false; 00299 break; 00300 } 00301 } 00302 00303 if ( dst->symbolNames().contains( symbolName ) && overwrite ) 00304 { 00305 dst->addSymbol( symbolName, symbol ); 00306 if ( mDialogMode == Import ) 00307 dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); 00308 } 00309 else if ( dst->symbolNames().contains( symbolName ) && !overwrite ) 00310 { 00311 continue; 00312 } 00313 else 00314 { 00315 dst->addSymbol( symbolName, symbol ); 00316 if ( mDialogMode == Import ) 00317 dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); 00318 } 00319 } 00320 else 00321 { 00322 if ( dst->colorRampNames().contains( symbolName ) && prompt ) 00323 { 00324 int res = QMessageBox::warning( this, tr( "Duplicate names" ), 00325 tr( "Color ramp with name '%1' already exists.\nOverwrite?" ) 00326 .arg( symbolName ), 00327 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel ); 00328 switch ( res ) 00329 { 00330 case QMessageBox::Cancel: 00331 return; 00332 case QMessageBox::No: 00333 continue; 00334 case QMessageBox::Yes: 00335 dst->addColorRamp( symbolName, ramp ); 00336 if ( mDialogMode == Import ) 00337 dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); 00338 continue; 00339 case QMessageBox::YesToAll: 00340 prompt = false; 00341 overwrite = true; 00342 break; 00343 case QMessageBox::NoToAll: prompt = false; 00344 overwrite = false; 00345 break; 00346 } 00347 } 00348 00349 if ( dst->colorRampNames().contains( symbolName ) && overwrite ) 00350 { 00351 dst->addColorRamp( symbolName, ramp ); 00352 if ( mDialogMode == Import ) 00353 dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); 00354 } 00355 else if ( dst->colorRampNames().contains( symbolName ) && !overwrite ) 00356 { 00357 continue; 00358 } 00359 else 00360 { 00361 dst->addColorRamp( symbolName, ramp ); 00362 if ( mDialogMode == Import ) 00363 dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); 00364 } 00365 } 00366 } 00367 } 00368 00369 QgsStyleV2ExportImportDialog::~QgsStyleV2ExportImportDialog() 00370 { 00371 delete mTempFile; 00372 delete mTempStyle; 00373 } 00374 00375 void QgsStyleV2ExportImportDialog::selectAll() 00376 { 00377 listItems->selectAll(); 00378 } 00379 00380 void QgsStyleV2ExportImportDialog::clearSelection() 00381 { 00382 listItems->clearSelection(); 00383 } 00384 00385 void QgsStyleV2ExportImportDialog::importTypeChanged( int index ) 00386 { 00387 QString type = importTypeCombo->itemData( index ).toString(); 00388 00389 locationLineEdit->setText( "" ); 00390 00391 if ( type == "file" ) 00392 { 00393 locationLineEdit->setEnabled( true ); 00394 btnBrowse->setText( "Browse" ); 00395 } 00396 else if ( type == "official" ) 00397 { 00398 btnBrowse->setText( "Fetch Symbols" ); 00399 locationLineEdit->setEnabled( false ); 00400 } 00401 else 00402 { 00403 btnBrowse->setText( "Fetch Symbols" ); 00404 locationLineEdit->setEnabled( true ); 00405 } 00406 } 00407 00408 void QgsStyleV2ExportImportDialog::browse() 00409 { 00410 QString type = importTypeCombo->itemData( importTypeCombo->currentIndex() ).toString(); 00411 00412 if ( type == "file" ) 00413 { 00414 mFileName = QFileDialog::getOpenFileName( this, tr( "Load styles" ), ".", 00415 tr( "XML files (*.xml *XML)" ) ); 00416 if ( mFileName.isEmpty() ) 00417 { 00418 return; 00419 } 00420 QFileInfo pathInfo( mFileName ); 00421 QString groupName = pathInfo.fileName().replace( ".xml", "" ); 00422 groupCombo->setItemText( 0, groupName ); 00423 locationLineEdit->setText( mFileName ); 00424 populateStyles( mTempStyle ); 00425 } 00426 else if ( type == "official" ) 00427 { 00428 // TODO set URL 00429 // downloadStyleXML( QUrl( "http://...." ) ); 00430 } 00431 else 00432 { 00433 downloadStyleXML( QUrl( locationLineEdit->text() ) ); 00434 } 00435 } 00436 00437 void QgsStyleV2ExportImportDialog::downloadStyleXML( QUrl url ) 00438 { 00439 // XXX Try to move this code to some core Network interface, 00440 // HTTP downloading is a generic functionality that might be used elsewhere 00441 00442 mTempFile = new QTemporaryFile(); 00443 if ( mTempFile->open() ) 00444 { 00445 mFileName = mTempFile->fileName(); 00446 00447 if ( mProgressDlg ) 00448 { 00449 QProgressDialog *dummy = mProgressDlg; 00450 mProgressDlg = NULL; 00451 delete dummy; 00452 } 00453 mProgressDlg = new QProgressDialog(); 00454 mProgressDlg->setLabelText( tr( "Downloading style ... " ) ); 00455 mProgressDlg->setAutoClose( true ); 00456 00457 connect( mProgressDlg, SIGNAL( canceled() ), this, SLOT( downloadCanceled() ) ); 00458 00459 // open the network connection and connect the respective slots 00460 if ( mNetReply ) 00461 { 00462 QNetworkReply *dummyReply = mNetReply; 00463 mNetReply = NULL; 00464 delete dummyReply; 00465 } 00466 mNetReply = mNetManager->get( QNetworkRequest( url ) ); 00467 00468 connect( mNetReply, SIGNAL( finished() ), this, SLOT( httpFinished() ) ); 00469 connect( mNetReply, SIGNAL( readyRead() ), this, SLOT( fileReadyRead() ) ); 00470 connect( mNetReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( updateProgress( qint64, qint64 ) ) ); 00471 } 00472 } 00473 00474 void QgsStyleV2ExportImportDialog::httpFinished() 00475 { 00476 if ( mNetReply->error() ) 00477 { 00478 mTempFile->remove(); 00479 mFileName = ""; 00480 mProgressDlg->hide(); 00481 QMessageBox::information( this, tr( "HTTP Error!" ), 00482 tr( "Download failed: %1." ).arg( mNetReply->errorString() ) ); 00483 return; 00484 } 00485 else 00486 { 00487 mTempFile->flush(); 00488 mTempFile->close(); 00489 populateStyles( mTempStyle ); 00490 } 00491 } 00492 00493 void QgsStyleV2ExportImportDialog::fileReadyRead() 00494 { 00495 mTempFile->write( mNetReply->readAll() ); 00496 } 00497 00498 void QgsStyleV2ExportImportDialog::updateProgress( qint64 bytesRead, qint64 bytesTotal ) 00499 { 00500 mProgressDlg->setMaximum( bytesTotal ); 00501 mProgressDlg->setValue( bytesRead ); 00502 } 00503 00504 void QgsStyleV2ExportImportDialog::downloadCanceled() 00505 { 00506 mNetReply->abort(); 00507 mTempFile->remove(); 00508 mFileName = ""; 00509 }