1 /*************************************************************************** 2 qgsgrassmoduleinput.h 3 ------------------- 4 begin : September, 2015 5 copyright : (C) 2015 by Radim Blazek 6 email : radim.blazek@gmail.com 7 ***************************************************************************/ 8 /*************************************************************************** 9 * * 10 * This program is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 ***************************************************************************/ 16 #ifndef QGSGRASSMODULEINPUT_H 17 #define QGSGRASSMODULEINPUT_H 18 19 #include <QAbstractProxyModel> 20 #include <QCheckBox> 21 #include <QComboBox> 22 #include <QCompleter> 23 #include <QFileSystemModel> 24 #include <QFileSystemWatcher> 25 #include <QGroupBox> 26 #include <QListView> 27 #include <QMap> 28 #include <QSortFilterProxyModel> 29 #include <QStandardItem> 30 #include <QStandardItemModel> 31 #include <QStyledItemDelegate> 32 #include <QTreeView> 33 34 #include "qgis.h" 35 36 #include "qgsgrass.h" 37 #include "qgsgrassmodule.h" 38 #include "qgsgrassmoduleparam.h" 39 #include "qgsgrassplugin.h" 40 #include "qgsgrassprovider.h" 41 #include "qgsgrassvector.h" 42 43 extern "C" 44 { 45 #include <grass/vector.h> 46 } 47 48 class QgsGrassModuleInputModel : public QStandardItemModel 49 { 50 Q_OBJECT 51 52 public: 53 enum Role 54 { 55 MapRole = Qt::UserRole, 56 MapsetRole = Qt::UserRole + 1, 57 TypeRole = Qt::UserRole + 2 // QgsGrassObject::Type 58 }; 59 60 explicit QgsGrassModuleInputModel( QObject *parent = nullptr ); 61 62 //! Gets singleton instance of this class. 63 static QgsGrassModuleInputModel *instance(); 64 65 QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; 66 67 68 public slots: 69 //! Reload current mapset 70 void reload(); 71 72 void onMapsetChanged(); 73 74 void onDirectoryChanged( const QString &path ); 75 void onFileChanged( const QString &path ); 76 void onMapsetSearchPathChanged(); 77 78 private: 79 void addMapset( const QString &mapset ); 80 void refreshMapset( QStandardItem *mapsetItem, const QString &mapset, const QList<QgsGrassObject::Type> &types = QList<QgsGrassObject::Type>() ); 81 // Add to watched paths if exists and if not yet watched 82 void watch( const QString &path ); 83 QString mLocationPath; 84 // mapset watched dirs watchedDirs()85 QStringList watchedDirs() { QStringList l; l << QStringLiteral( "cellhd" ) << QStringLiteral( "vector" ) << QStringLiteral( "tgis" ); return l; } 86 // names of 87 QStringList locationDirNames(); 88 QFileSystemWatcher *mWatcher = nullptr; 89 90 QgsGrassModuleInputModel( const QgsGrassModuleInputModel & ) = delete; 91 QgsGrassModuleInputModel &operator = ( const QgsGrassModuleInputModel & ) = delete; 92 }; 93 94 // Filter maps by type 95 class QgsGrassModuleInputProxy : public QSortFilterProxyModel 96 { 97 Q_OBJECT 98 99 public: 100 explicit QgsGrassModuleInputProxy( QgsGrassModuleInputModel *sourceModel, QgsGrassObject::Type type, QObject *parent = nullptr ); 101 102 protected: 103 bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override; 104 bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; 105 106 private: 107 QgsGrassModuleInputModel *mSourceModel = nullptr; 108 QgsGrassObject::Type mType; 109 }; 110 111 class QgsGrassModuleInputTreeView : public QTreeView 112 { 113 Q_OBJECT 114 public: 115 explicit QgsGrassModuleInputTreeView( QWidget *parent = nullptr ); 116 117 void resetState(); 118 }; 119 120 class QgsGrassModuleInputPopup : public QTreeView 121 { 122 Q_OBJECT 123 public: 124 explicit QgsGrassModuleInputPopup( QWidget *parent = nullptr ); 125 126 void setModel( QAbstractItemModel *model ) override; 127 }; 128 129 // Flattens tree to list of maps for completer 130 class QgsGrassModuleInputCompleterProxy : public QAbstractProxyModel 131 { 132 Q_OBJECT 133 public: 134 explicit QgsGrassModuleInputCompleterProxy( QObject *parent = nullptr ); 135 136 int columnCount( const QModelIndex &parent = QModelIndex() ) const override { Q_UNUSED( parent ) return 1; } 137 int rowCount( const QModelIndex &parent = QModelIndex() ) const override; 138 QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override; 139 QModelIndex parent( const QModelIndex &index ) const override; 140 141 142 void setSourceModel( QAbstractItemModel *sourceModel ) override; 143 144 QModelIndex mapFromSource( const QModelIndex &sourceIndex ) const override; 145 QModelIndex mapToSource( const QModelIndex &proxyIndex ) const override; 146 147 private: 148 void refreshMapping(); 149 void map( const QModelIndex &parent, int level = 0 ); 150 QMap<int, QModelIndex> mIndexes; 151 QMap<QModelIndex, int> mRows; 152 }; 153 154 class QgsGrassModuleInputCompleter : public QCompleter 155 { 156 Q_OBJECT 157 158 public: 159 explicit QgsGrassModuleInputCompleter( QAbstractItemModel *model, QWidget *parent = nullptr ); 160 161 bool eventFilter( QObject *watched, QEvent *event ) override; 162 }; 163 164 class QgsGrassModuleInputComboBox : public QComboBox 165 { 166 Q_OBJECT 167 168 public: 169 explicit QgsGrassModuleInputComboBox( QgsGrassObject::Type type, QWidget *parent = nullptr ); 170 171 bool eventFilter( QObject *watched, QEvent *event ) override; 172 void showPopup() override; 173 void hidePopup() override; 174 175 // set current index 176 void setCurrent( const QModelIndex &proxyIndex ); 177 178 // set current item to map/mapset if exists 179 bool setCurrent( const QString &map, const QString &mapset = QString() ); 180 181 // set to first map if exists 182 bool setFirst(); 183 184 protected: 185 QgsGrassObject::Type mType; 186 QgsGrassModuleInputModel *mModel = nullptr; 187 QgsGrassModuleInputProxy *mProxy = nullptr; 188 QgsGrassModuleInputTreeView *mTreeView = nullptr; 189 // Skip next hidePopup 190 bool mSkipHide; 191 }; 192 193 class QgsGrassModuleInputSelectedDelegate : public QStyledItemDelegate 194 { 195 Q_OBJECT 196 public: 197 explicit QgsGrassModuleInputSelectedDelegate( QObject *parent = nullptr ); 198 199 void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override; 200 201 public slots: 202 void handlePressed( const QModelIndex &index ); 203 204 private: 205 mutable QModelIndex mPressedIndex; 206 }; 207 208 class QgsGrassModuleInputSelectedView : public QTreeView 209 { 210 Q_OBJECT 211 public: 212 explicit QgsGrassModuleInputSelectedView( QWidget *parent = nullptr ); 213 214 void setModel( QAbstractItemModel *model ) override; 215 216 signals: 217 void deleteItem( const QModelIndex &index ); 218 219 protected: 220 bool eventFilter( QObject *obj, QEvent *event ) override; 221 222 private: 223 QgsGrassModuleInputSelectedDelegate *mDelegate = nullptr; 224 }; 225 226 227 /** 228 * \class QgsGrassModuleInput 229 * \brief Class representing raster or vector module input 230 */ 231 class QgsGrassModuleInput : public QgsGrassModuleGroupBoxItem 232 { 233 Q_OBJECT 234 235 public: 236 237 /** 238 * \brief Constructor 239 * \param qdesc option element in QGIS module description XML file 240 * \param gdesc GRASS module XML description file 241 */ 242 QgsGrassModuleInput( QgsGrassModule *module, 243 QgsGrassModuleStandardOptions *options, QString key, 244 QDomElement &qdesc, QDomElement &gdesc, QDomNode &gnode, 245 bool direct, QWidget *parent = nullptr ); 246 247 //! Returns list of options which will be passed to module 248 QStringList options() override; 249 250 //! Return vector of attribute fields of current vector 251 QgsFields currentFields(); 252 253 //! Returns pointer to currently selected layer or null 254 255 QgsGrassObject currentGrassObject(); 256 257 QString currentMap(); 258 259 QgsGrassVectorLayer *currentLayer(); 260 261 QStringList currentGeometryTypeNames(); 262 263 QString ready() override; 264 265 //! Does this options causes use of region? 266 // Raster input/output uses region by default 267 // Use of region can be forced by 'region' attribute in qgm usesRegion()268 bool usesRegion() { return mUsesRegion; } 269 270 //! Should be used region of this input 271 bool useRegion(); 272 type()273 QgsGrassObject::Type type() { return mType; } 274 setGeometryTypeOption(const QString & optionName)275 void setGeometryTypeOption( const QString &optionName ) { mGeometryTypeOption = optionName; } geometryTypeOption()276 QString geometryTypeOption() const { return mGeometryTypeOption; } 277 278 // list of selected layers in <field>_<type> form, used by QgsGrassModuleSelection 279 QStringList currentLayerCodes(); 280 281 public slots: 282 void onActivated( const QString &text ); 283 284 void onChanged( const QString &text ); 285 286 void onLayerChanged(); 287 288 void deleteSelectedItem( const QModelIndex &index ); 289 290 signals: 291 // emitted when value changed/selected 292 void valueChanged(); 293 294 private: 295 //! Input type 296 QgsGrassObject::Type mType; 297 298 // Module options 299 QgsGrassModuleStandardOptions *mModuleStandardOptions = nullptr; 300 301 //! Vector type mask read from option defined by "typeoption" tag, used for QGIS layers in combo 302 // + type mask defined in configuration file 303 int mGeometryTypeMask; 304 305 //! Name of vector type option associated with this input 306 QString mGeometryTypeOption; 307 308 //! Name of vector layer option associated with this input 309 QString mVectorLayerOption; 310 311 //! Model used in combo 312 QgsGrassModuleInputModel *mModel = nullptr; 313 314 //! Model containing currently selected maps 315 QStandardItemModel *mSelectedModel = nullptr; 316 317 //! Combo box with GRASS layers 318 QgsGrassModuleInputComboBox *mComboBox = nullptr; 319 320 //! Region button 321 QPushButton *mRegionButton = nullptr; 322 323 //! Vector sublayer label 324 QLabel *mLayerLabel = nullptr; 325 326 //! Vector sublayer combo 327 QComboBox *mLayerComboBox = nullptr; 328 329 //! List of multiple selected maps 330 QgsGrassModuleInputSelectedView *mSelectedTreeView = nullptr; 331 332 // Vector type checkboxes 333 QMap<int, QCheckBox *> mTypeCheckBoxes; 334 335 //! Optional map option id, if defined, only the layers from the 336 // map currently selected in that option are available. 337 // This is used by nodes layer option for networks. 338 QString mMapId; 339 340 // Currently selected vector 341 QgsGrassVector *mVector = nullptr; 342 343 // List of vector layers matching mGeometryTypes for currently selected vector 344 QList<QgsGrassVectorLayer *> mLayers; 345 346 //! The input map will be updated -> must be from current mapset 347 // TODO 348 bool mUpdate; 349 350 //! Uses region 351 bool mUsesRegion; 352 353 QgsGrassModuleInput( const QgsGrassModuleInput & ) = delete; 354 QgsGrassModuleInput &operator = ( const QgsGrassModuleInput & ) = delete; 355 }; 356 357 358 #endif // QGSGRASSMODULEINPUT_H 359