1 /*************************************************************************** 2 qgsattributesformproperties.h 3 --------------------- 4 begin : August 2017 5 copyright : (C) 2017 by David Signer 6 email : david at opengis dot ch 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSATTRIBUTESFORMPROPERTIES_H 17 #define QGSATTRIBUTESFORMPROPERTIES_H 18 19 // We don't want to expose this in the public API 20 #define SIP_NO_FILE 21 22 #include <QMimeData> 23 #include <QPushButton> 24 #include <QTableWidget> 25 #include <QTreeWidget> 26 #include <QWidget> 27 #include <QSpinBox> 28 #include <QTreeWidgetItem> 29 #include <QDropEvent> 30 #include <QTableWidgetItem> 31 #include <QMessageBox> 32 #include <QFileDialog> 33 #include <QHBoxLayout> 34 #include <QFormLayout> 35 #include <QPlainTextEdit> 36 37 #include "ui_qgsattributesformproperties.h" 38 #include "qgis_gui.h" 39 #include "qgsaddattrdialog.h" 40 #include "qgslogger.h" 41 #include "qgsexpressionbuilderdialog.h" 42 #include "qgsfieldcalculator.h" 43 #include "qgsfieldexpressionwidget.h" 44 #include "qgsattributesforminitcode.h" 45 #include "qgsgui.h" 46 #include "qgseditorwidgetfactory.h" 47 #include "qgseditorwidgetregistry.h" 48 #include "qgsrelationmanager.h" 49 50 class QgsAttributesDnDTree; 51 class QgsAttributeFormContainerEdit; 52 class QgsAttributeTypeDialog; 53 class QgsAttributeWidgetEdit; 54 55 class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpressionContextGenerator, private Ui_QgsAttributesFormProperties 56 { 57 Q_OBJECT 58 59 public: 60 61 enum FieldPropertiesRoles 62 { 63 DnDTreeRole = Qt::UserRole, 64 FieldConfigRole, 65 FieldNameRole 66 }; 67 68 struct RelationEditorConfiguration 69 { 70 QgsAttributeEditorRelation::Buttons buttons = QgsAttributeEditorRelation::Button::AllButtons; 71 QVariant nmRelationId; 72 bool forceSuppressFormPopup = false; 73 QString label; 74 }; 75 76 struct QmlElementEditorConfiguration 77 { 78 QString qmlCode; 79 }; 80 81 struct HtmlElementEditorConfiguration 82 { 83 QString htmlCode; 84 }; 85 86 class DnDTreeItemData : public QTreeWidgetItem 87 { 88 public: 89 enum Type 90 { 91 Field, 92 Relation, 93 Container, //!< Container for the form 94 QmlWidget, 95 HtmlWidget, 96 WidgetType //!< In the widget tree, the type of widget 97 }; 98 99 //do we need that 100 DnDTreeItemData() = default; 101 102 DnDTreeItemData( Type type, const QString &name, const QString &displayName, const QColor &backgroundColor = QColor() ) mType(type)103 : mType( type ) 104 , mName( name ) 105 , mDisplayName( displayName ) 106 , mBackgroundColor( backgroundColor ) 107 {} 108 name()109 QString name() const { return mName; } setName(const QString & name)110 void setName( const QString &name ) { mName = name; } 111 displayName()112 QString displayName() const { return mDisplayName; } setDisplayName(const QString & displayName)113 void setDisplayName( const QString &displayName ) { mDisplayName = displayName; } 114 type()115 Type type() const { return mType; } setType(Type type)116 void setType( Type type ) { mType = type; } 117 QVariant()118 operator QVariant() { return QVariant::fromValue<DnDTreeItemData>( *this ); } 119 columnCount()120 int columnCount() const { return mColumnCount; } setColumnCount(int count)121 void setColumnCount( int count ) { mColumnCount = count; } 122 123 bool showAsGroupBox() const; 124 void setShowAsGroupBox( bool showAsGroupBox ); 125 126 bool showLabel() const; 127 void setShowLabel( bool showLabel ); 128 129 QgsOptionalExpression visibilityExpression() const; 130 void setVisibilityExpression( const QgsOptionalExpression &visibilityExpression ); 131 132 RelationEditorConfiguration relationEditorConfiguration() const; 133 void setRelationEditorConfiguration( RelationEditorConfiguration relationEditorConfiguration ); 134 135 QmlElementEditorConfiguration qmlElementEditorConfiguration() const; 136 void setQmlElementEditorConfiguration( QmlElementEditorConfiguration qmlElementEditorConfiguration ); 137 138 HtmlElementEditorConfiguration htmlElementEditorConfiguration() const; 139 void setHtmlElementEditorConfiguration( HtmlElementEditorConfiguration htmlElementEditorConfiguration ); 140 141 QColor backgroundColor() const; 142 void setBackgroundColor( const QColor &backgroundColor ); 143 144 private: 145 Type mType = Field; 146 QString mName; 147 QString mDisplayName; 148 int mColumnCount = 1; 149 bool mShowAsGroupBox = false; 150 bool mShowLabel = true; 151 QgsOptionalExpression mVisibilityExpression; 152 RelationEditorConfiguration mRelationEditorConfiguration; 153 QmlElementEditorConfiguration mQmlElementEditorConfiguration; 154 HtmlElementEditorConfiguration mHtmlElementEditorConfiguration; 155 QColor mBackgroundColor; 156 }; 157 158 159 /** 160 * Holds the configuration for a field 161 */ 162 struct FieldConfig 163 { 164 FieldConfig() = default; 165 FieldConfig( QgsVectorLayer *layer, int idx ); 166 167 bool mEditable = true ; 168 bool mEditableEnabled = true ; 169 bool mLabelOnTop = false ; 170 QgsFieldConstraints mFieldConstraints; 171 QPushButton *mButton = nullptr; 172 QString mEditorWidgetType; 173 QMap<QString, QVariant> mEditorWidgetConfig; 174 QString mAlias; 175 QgsPropertyCollection mDataDefinedProperties; 176 QString mComment; 177 178 operator QVariant(); 179 }; 180 181 public: 182 explicit QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent = nullptr ); 183 184 QgsAttributeEditorElement *createAttributeEditorWidget( QTreeWidgetItem *item, QgsAttributeEditorElement *parent, bool forceGroup = true ); 185 186 void init(); 187 void apply(); 188 189 190 void loadRelations(); 191 192 void initAvailableWidgetsTree(); 193 void initFormLayoutTree(); 194 void initLayoutConfig(); 195 void initInitPython(); 196 void initSuppressCombo(); 197 198 QgsExpressionContext createExpressionContext() const override; 199 200 protected: 201 void updateButtons(); 202 203 //QList<QgsRelation> mRelations; 204 QgsVectorLayer *mLayer = nullptr; 205 206 QgsAttributesDnDTree *mAvailableWidgetsTree = nullptr; 207 QgsAttributesDnDTree *mFormLayoutTree = nullptr; 208 209 QgsAttributeWidgetEdit *mAttributeWidgetEdit = nullptr; 210 QgsAttributeTypeDialog *mAttributeTypeDialog = nullptr; 211 QgsAttributeFormContainerEdit *mAttributeContainerEdit = nullptr; 212 QLabel *mInfoTextWidget = nullptr; 213 214 private slots: 215 216 void onInvertSelectionButtonClicked( bool checked ); 217 void loadAttributeSpecificEditor( QgsAttributesDnDTree *emitter, QgsAttributesDnDTree *receiver ); 218 void onAttributeSelectionChanged(); 219 void onFormLayoutSelectionChanged(); 220 221 private: 222 //! this will clean the right panel 223 void clearAttributeTypeFrame(); 224 225 void loadAttributeWidgetEdit(); 226 void storeAttributeWidgetEdit(); 227 228 void loadAttributeTypeDialog(); 229 void storeAttributeTypeDialog( ); 230 231 void storeAttributeContainerEdit(); 232 void loadAttributeContainerEdit(); 233 234 void loadInfoWidget( const QString &infoText ); 235 236 QgsEditFormConfig::PythonInitCodeSource mInitCodeSource = QgsEditFormConfig::CodeSourceNone; 237 QString mInitFunction; 238 QString mInitFilePath; 239 QString mInitCode; 240 241 QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement *widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree ); 242 243 private slots: 244 void addTabOrGroupButton(); 245 void removeTabOrGroupButton(); 246 void mEditorLayoutComboBox_currentIndexChanged( int index ); 247 void pbnSelectEditForm_clicked(); 248 void mTbInitCode_clicked(); 249 }; 250 251 252 QDataStream &operator<< ( QDataStream &stream, const QgsAttributesFormProperties::DnDTreeItemData &data ); 253 QDataStream &operator>> ( QDataStream &stream, QgsAttributesFormProperties::DnDTreeItemData &data ); 254 255 256 /** 257 * This class overrides mime type handling to be able to work with 258 * the drag and drop attribute editor. 259 * 260 * The mime type is application/x-qgsattributetablefield 261 * 262 * Graphical representation for the attribute editor drag and drop editor 263 */ 264 265 class GUI_EXPORT QgsAttributesDnDTree : public QTreeWidget 266 { 267 Q_OBJECT 268 269 public: 270 explicit QgsAttributesDnDTree( QgsVectorLayer *layer, QWidget *parent = nullptr ); 271 272 /** 273 * Adds a new item to a \a parent. If \a index is -1, the item is added to the end of the parent's existing children. 274 * Otherwise it is inserted at the specified \a index. 275 */ 276 QTreeWidgetItem *addItem( QTreeWidgetItem *parent, QgsAttributesFormProperties::DnDTreeItemData data, int index = -1, const QIcon &icon = QIcon() ); 277 QTreeWidgetItem *addContainer( QTreeWidgetItem *parent, const QString &title, int columnCount ); 278 279 enum Type 280 { 281 Drag, 282 Drop 283 }; 284 285 286 Type type() const; 287 void setType( QgsAttributesDnDTree::Type value ); 288 289 public slots: 290 void selectFirstMatchingItem( const QgsAttributesFormProperties::DnDTreeItemData &data ); 291 292 protected: 293 void dragMoveEvent( QDragMoveEvent *event ) override; 294 void dropEvent( QDropEvent *event ) override; 295 bool dropMimeData( QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action ) override; 296 /* Qt::DropActions supportedDropActions() const;*/ 297 298 // QTreeWidget interface 299 protected: 300 QStringList mimeTypes() const override; 301 QMimeData *mimeData( const QList<QTreeWidgetItem *> items ) const override; 302 303 304 private slots: 305 void onItemDoubleClicked( QTreeWidgetItem *item, int column ); 306 307 private: 308 QgsVectorLayer *mLayer = nullptr; 309 Type mType = QgsAttributesDnDTree::Type::Drag; 310 }; 311 312 313 Q_DECLARE_METATYPE( QgsAttributesFormProperties::FieldConfig ) 314 Q_DECLARE_METATYPE( QgsAttributesFormProperties::DnDTreeItemData ) 315 316 #endif // QGSATTRIBUTESFORMPROPERTIES_H 317