src/app/qgsidentifyresults.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                      qgsidentifyresults.cpp  -  description
00003                               -------------------
00004       begin                : Fri Oct 25 2002
00005       copyright            : (C) 2002 by Gary E.Sherman
00006       email                : sherman at mrcc dot com
00007       Romans 3:23=>Romans 6:23=>Romans 5:8=>Romans 10:9,10=>Romans 12
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 /* $Id: qgsidentifyresults.cpp 9209 2008-08-29 13:29:04Z jef $ */
00019 
00020 #include "qgsidentifyresults.h"
00021 #include "qgscontexthelp.h"
00022 #include "qgsapplication.h"
00023 #include "qgisapp.h"
00024 
00025 #include <QCloseEvent>
00026 #include <QLabel>
00027 #include <QAction>
00028 #include <QTreeWidgetItem>
00029 #include <QPixmap>
00030 #include <QSettings>
00031 #include <QMenu>
00032 
00033 #include <iostream>
00034 
00035 QgsIdentifyResults::QgsIdentifyResults( const QgsAttributeAction& actions,
00036                                         QWidget *parent, Qt::WFlags f )
00037     : QDialog( parent, f ),
00038     mActions( actions ),
00039     mClickedOnValue( 0 ),
00040     mActionPopup( 0 ),
00041     mCurrentFeatureId( 0 )
00042 {
00043   setupUi( this );
00044   lstResults->setColumnCount( 2 );
00045   setColumnText( 0, tr( "Feature" ) );
00046   setColumnText( 1, tr( "Value" ) );
00047 
00048   connect( buttonCancel, SIGNAL( clicked() ),
00049            this, SLOT( close() ) );
00050   connect( lstResults, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
00051            this, SLOT( clicked( QTreeWidgetItem * ) ) );
00052   connect( lstResults, SIGNAL( itemExpanded( QTreeWidgetItem* ) ),
00053            this, SLOT( itemExpanded( QTreeWidgetItem* ) ) );
00054 
00055   connect( lstResults, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
00056            this, SLOT( handleCurrentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
00057 
00058   // The label to use for the Derived node in the identify results
00059   mDerivedLabel = tr( "(Derived)" );
00060 }
00061 
00062 QgsIdentifyResults::~QgsIdentifyResults()
00063 {
00064   delete mActionPopup;
00065 }
00066 
00067 // Call to show the dialog box.
00068 void QgsIdentifyResults::show()
00069 {
00070   // Enfore a few things before showing the dialog box
00071   lstResults->sortItems( 0, Qt::AscendingOrder );
00072   expandColumnsToFit();
00073 
00074   QDialog::show();
00075 }
00076 // Slot called when user clicks the Close button
00077 // (saves the current window size/position)
00078 void QgsIdentifyResults::close()
00079 {
00080   saveWindowLocation();
00081   done( 0 );
00082 }
00083 // Save the current window size/position before closing
00084 // from window menu or X in titlebar
00085 void QgsIdentifyResults::closeEvent( QCloseEvent *e )
00086 {
00087   // We'll close in our own good time thanks...
00088   e->ignore();
00089   close();
00090 }
00091 
00092 // Popup (create if necessary) a context menu that contains a list of
00093 // actions that can be applied to the data in the identify results
00094 // dialog box.
00095 
00096 void QgsIdentifyResults::contextMenuEvent( QContextMenuEvent* event )
00097 {
00098   QTreeWidgetItem* item = lstResults->itemAt( lstResults->viewport()->mapFrom( this, event->pos() ) );
00099   // if the user clicked below the end of the attribute list, just return
00100   if ( item == NULL )
00101     return;
00102 
00103   // The assumption is made that an instance of QgsIdentifyResults is
00104   // created for each new Identify Results dialog box, and that the
00105   // contents of the popup menu doesn't change during the time that
00106   // such a dialog box is around.
00107   if ( mActionPopup == 0 )
00108   {
00109     mActionPopup = new QMenu();
00110     QAction* a = mActionPopup->addAction( tr( "Run action" ) );
00111     a->setEnabled( false );
00112     mActionPopup->addSeparator();
00113 
00114     QgsAttributeAction::aIter iter = mActions.begin();
00115     for ( int j = 0; iter != mActions.end(); ++iter, ++j )
00116     {
00117       QAction* a = mActionPopup->addAction( iter->name() );
00118       // The menu action stores an integer that is used later on to
00119       // associate an menu action with an actual qgis action.
00120       a->setData( QVariant::fromValue( j ) );
00121     }
00122     connect( mActionPopup, SIGNAL( triggered( QAction* ) ),
00123              this, SLOT( popupItemSelected( QAction* ) ) );
00124   }
00125   // Save the attribute values as these are needed for substituting into
00126   // the action.
00127   extractAllItemData( item );
00128 
00129   if ( mActions.size() > 0 )
00130     mActionPopup->popup( event->globalPos() );
00131 }
00132 
00133 // Restore last window position/size and show the window
00134 void QgsIdentifyResults::restorePosition()
00135 {
00136   QSettings settings;
00137   restoreGeometry( settings.value( "/Windows/Identify/geometry" ).toByteArray() );
00138   show();
00139 }
00140 
00141 // Save the current window location (store in ~/.qt/qgisrc)
00142 void QgsIdentifyResults::saveWindowLocation()
00143 {
00144   QSettings settings;
00145   settings.setValue( "/Windows/Identify/geometry", saveGeometry() );
00146 }
00147 
00149 void QgsIdentifyResults::addAttribute( QTreeWidgetItem * fnode, QString field, QString value )
00150 {
00151   QStringList labels;
00152   labels << field << value;
00153   new QTreeWidgetItem( fnode, labels );
00154 }
00155 
00156 void QgsIdentifyResults::addAttribute( QString field, QString value )
00157 {
00158   QStringList labels;
00159   labels << field << value;
00160   new QTreeWidgetItem( lstResults, labels );
00161 }
00162 
00163 void QgsIdentifyResults::addDerivedAttribute( QTreeWidgetItem * fnode, QString field, QString value )
00164 {
00165   QTreeWidgetItem * daRootNode;
00166 
00167   // Determine if this is the first derived attribute for this feature or not
00168   if ( mDerivedAttributeRootNodes.find( fnode ) != mDerivedAttributeRootNodes.end() )
00169   {
00170     // Reuse existing derived-attribute root node
00171     daRootNode = mDerivedAttributeRootNodes[fnode];
00172   }
00173   else
00174   {
00175     // Create new derived-attribute root node
00176     daRootNode = new QTreeWidgetItem( fnode, QStringList( mDerivedLabel ) );
00177     QFont font = daRootNode->font( 0 );
00178     font.setItalic( true );
00179     daRootNode->setFont( 0, font );
00180     mDerivedAttributeRootNodes[fnode] = daRootNode;
00181   }
00182 
00183   QStringList labels;
00184   labels << field << value;
00185   new QTreeWidgetItem( daRootNode, labels );
00186 }
00187 
00188 void QgsIdentifyResults::addEdit( QTreeWidgetItem * fnode, int id )
00189 {
00190   QStringList labels;
00191   labels << "edit" << QString::number( id );
00192   QTreeWidgetItem *item = new QTreeWidgetItem( fnode, labels );
00193 
00194   item->setIcon( 0, QgisApp::getThemeIcon( "/mIconEditable.png" ) );
00195 }
00196 
00197 void QgsIdentifyResults::addAction( QTreeWidgetItem * fnode, int id, QString field, QString value )
00198 {
00199   QStringList labels;
00200   labels << field << value << "action" << QString::number( id );
00201   QTreeWidgetItem *item = new QTreeWidgetItem( fnode, labels );
00202 
00203   item->setIcon( 0, QgisApp::getThemeIcon( "/mAction.png" ) );
00204 }
00205 
00207 QTreeWidgetItem *QgsIdentifyResults::addNode( QString label )
00208 {
00209   return new QTreeWidgetItem( lstResults, QStringList( label ) );
00210 }
00211 
00212 void QgsIdentifyResults::setTitle( QString title )
00213 {
00214   setWindowTitle( tr( "Identify Results - " ) + title );
00215 }
00216 
00217 void QgsIdentifyResults::setColumnText( int column, const QString & label )
00218 {
00219   QTreeWidgetItem* header = lstResults->headerItem();
00220   header->setText( column, label );
00221 }
00222 
00223 // Run the action that was selected in the popup menu
00224 void QgsIdentifyResults::popupItemSelected( QAction* menuAction )
00225 {
00226   int id = menuAction->data().toInt();
00227   mActions.doAction( id, mValues, mClickedOnValue );
00228 }
00229 
00231 void QgsIdentifyResults::showAllAttributes()
00232 {
00233   // Easy now with Qt 4.2...
00234   lstResults->expandAll();
00235 }
00236 
00237 void QgsIdentifyResults::expandColumnsToFit()
00238 {
00239   lstResults->resizeColumnToContents( 0 );
00240   lstResults->resizeColumnToContents( 1 );
00241 }
00242 
00243 void QgsIdentifyResults::clear()
00244 {
00245   mDerivedAttributeRootNodes.clear();
00246   lstResults->clear();
00247 }
00248 
00249 void QgsIdentifyResults::setMessage( QString shortMsg, QString longMsg )
00250 {
00251   QStringList labels;
00252   labels << shortMsg << longMsg;
00253   new QTreeWidgetItem( lstResults, labels );
00254 }
00255 
00256 void QgsIdentifyResults::setActions( const QgsAttributeAction& actions )
00257 {
00258   mActions = actions;
00259 }
00260 
00261 void QgsIdentifyResults::clicked( QTreeWidgetItem *item )
00262 {
00263   if ( !item )
00264     return;
00265 
00266   if ( item->text( 2 ) == "action" )
00267   {
00268     int id = item->text( 3 ).toInt();
00269 
00270     extractAllItemData( item );
00271 
00272     mActions.doAction( id, mValues, mClickedOnValue );
00273   }
00274   else if ( item->text( 0 ) == "edit" )
00275   {
00276     emit editFeature( item->text( 1 ).toInt() );
00277   }
00278 }
00279 void QgsIdentifyResults::on_buttonHelp_clicked()
00280 {
00281   QgsContextHelp::run( context_id );
00282 }
00283 
00284 void QgsIdentifyResults::itemExpanded( QTreeWidgetItem* item )
00285 {
00286   expandColumnsToFit();
00287 }
00288 
00289 void QgsIdentifyResults::handleCurrentItemChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
00290 {
00291   if ( lstResults->model()->rowCount() <= 1 )
00292     return;
00293 
00294   if ( current == NULL )
00295   {
00296     mCurrentFeatureId = 0;
00297     emit selectedFeatureChanged( 0 );
00298     return;
00299   }
00300 
00301   // move to node where is saved feature ID
00302   QTreeWidgetItem* topLevelItem = current;
00303   while ( topLevelItem->parent() != NULL )
00304   {
00305     topLevelItem = topLevelItem->parent();
00306   }
00307 
00308   QVariant fid = topLevelItem->data( 0, Qt::UserRole );
00309 
00310   // no data saved...
00311   if ( fid.type() != QVariant::Int )
00312     return;
00313   int fid2 = fid.toInt();
00314 
00315   if ( fid2 == mCurrentFeatureId )
00316     return;
00317 
00318   mCurrentFeatureId = fid2;
00319   emit selectedFeatureChanged( mCurrentFeatureId );
00320 }
00321 
00322 void QgsIdentifyResults::extractAllItemData( QTreeWidgetItem* item )
00323 {
00324   // Extracts the name/value pairs from the given item. This includes data
00325   // under the (Derived) item.
00326 
00327   // A little bit complicated because the user could of right-clicked
00328   // on any item in the dialog box. We want a toplevel item, so walk upwards
00329   // as far as possible.
00330   // We also want to keep track of which row in the identify results table was
00331   // actually clicked on. This is stored as an index into the mValues vector.
00332 
00333   QTreeWidgetItem* child = item;
00334   QTreeWidgetItem* parent = child->parent();
00335   while ( parent != 0 )
00336   {
00337     child = parent;
00338     parent = parent->parent();
00339   }
00340   parent = child;
00341 
00342   mValues.clear();
00343 
00344   // For the code below we
00345   // need to do the comparison on the text strings rather than the
00346   // pointers because if the user clicked on the parent, we need
00347   // to pick up which child that actually is (the parent in the
00348   // identify results dialog box is just one of the children
00349   // that has been chosen by some method).
00350 
00351   int valuesIndex = 0;
00352 
00353   for ( int j = 0; j < parent->childCount(); ++j )
00354   {
00355     // For derived attributes, build up a virtual name
00356     if ( parent->child( j )->text( 0 ) == mDerivedLabel )
00357     {
00358       for ( int k = 0; k < parent->child( j )->childCount(); ++k )
00359       {
00360         mValues.push_back(
00361           std::make_pair( mDerivedLabel + "."
00362                           + parent->child( j )->child( k )->text( 0 ),
00363                           parent->child( j )->child( k )->text( 1 ) ) );
00364 
00365         if ( item == parent->child( j )->child( k ) )
00366         {
00367           mClickedOnValue = valuesIndex;
00368         }
00369 
00370         valuesIndex++;
00371       }
00372     }
00373     else // do the actual feature attributes
00374     {
00375       mValues.push_back( std::make_pair( parent->child( j )->text( 0 ),
00376                                          parent->child( j )->text( 1 ) ) );
00377 
00378       if ( item == parent->child( j ) )
00379       {
00380         mClickedOnValue = valuesIndex;
00381       }
00382 
00383       valuesIndex++;
00384     }
00385   }
00386 }

Generated on Tue Oct 28 16:51:26 2008 for Quantum GIS API Documentation by  doxygen 1.5.1