File indexing completed on 2024-05-12 16:39:51
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at> 0003 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> 0004 Copyright (C) 2004-2009 Jarosław Staniek <staniek@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #ifndef KFORMDESIGNERWIDGETFACTORY_H 0023 #define KFORMDESIGNERWIDGETFACTORY_H 0024 0025 #include <QVariant> 0026 #include <QRect> 0027 0028 #include <KPluginFactory> 0029 0030 #include <config-kexi.h> 0031 #include "kformdesigner_export.h" 0032 0033 class QWidget; 0034 class QListWidget; 0035 class QMenu; 0036 class QDomElement; 0037 class QDomDocument; 0038 class QVariant; 0039 class KActionCollection; 0040 class KPropertySet; 0041 0042 namespace KFormDesigner 0043 { 0044 0045 class Container; 0046 class ObjectTreeItem; 0047 class Form; 0048 class WidgetLibrary; 0049 class WidgetInfo; 0050 0051 //! Used by WidgetFactory 0052 class KFORMDESIGNER_EXPORT InternalPropertyHandlerInterface 0053 { 0054 protected: 0055 InternalPropertyHandlerInterface(); 0056 0057 virtual ~InternalPropertyHandlerInterface(); 0058 0059 /*! Assigns \a value for internal property \a property for a class \a classname. 0060 Internal properties are not stored within objects, but can be provided 0061 to describe class' details. */ 0062 virtual void setInternalProperty(const QByteArray& classname, const QByteArray& property, const QVariant& value) = 0; 0063 0064 friend class WidgetInfo; 0065 }; 0066 0067 //! The base class for all widget Factories 0068 /*! This is the class you need to inherit to create a new Factory. There are few 0069 virtuals you need to implement, and some other functions 0070 to implement if you want more features.\n \n 0071 0072 <b>Widget Creation</b>\n 0073 To be able to create widgets, you need to implement the create() function, an classes(), 0074 which should return all the widgets supported by this factory.\n \n 0075 0076 <b>GUI Integration</b>\n 0077 The following functions allow you to customize even more the look-n-feel of your widgets inside KFormDesigner. 0078 You can use createMenuActions() to add custom items in widget's context menu. The previewWidget() 0079 is called when the Form gets in Preview mode, and you have a last opportunity to remove all editing-related 0080 stuff (see eg Spring class).\n 0081 You can also choose which properties to show in the Property Editor. 0082 By default, most all properties are shown (see implementation for details), 0083 but you can hide some reimplementing isPropertyVisibleInternal() (don't forget to call superclass' method) 0084 To add new properties, just define new Q_PROPERTY in widget class definition.\n \n 0085 0086 <b>Inline editing</b>\n 0087 KFormDesigner allow you to edit the widget's contents inside Form, without using a dialog. 0088 You can of course customize the behaviour of your widgets, using startInlineEditing(). There are some editing 0089 modes already implemented in WidgetFactroy, but you can create your own if you want: 0090 \li Editing using a line edit (createInlineEditor()): a line edit is created on top of widget, 0091 where the user inputs text. As the text changes, changeInlineText() is called 0092 (where you should set your widget's text and resize widget to fit the text if needed) and resizeEditor() 0093 to update editor's position when widget is moved/resized.\n 0094 \li Editing by disabling event filter: if you call disableFilter(), the event filter 0095 on the object is temporarily disabled, so the widget behaves as usual. This 0096 can be used for more complex widgets, such as spinbox, date/time edit, etc. 0097 \li Other modes: there are 3 other modes, to edit a string list: editList() 0098 (for combo box, listbox), to edit rich text: editRichText() (for labels, etc.)\n \n 0099 0100 <b>Widget saving/loading</b>\n 0101 You can also control how your widget are saved/loaded. You can choose which properties to save 0102 (see autoSaveProperties()), and save/load custom properties, ie 0103 properties that are not Q_PROPERTY but you want to save in the UI file. This is used eg to 0104 save combo box or list widget contents (see saveSpecialProperty() and 0105 readSpecialProperty()). \n \n 0106 0107 <b>Special internal properties</b>\n 0108 Use void WidgetInfo::setInternalProperty(const QByteArray& property, const QVariant& value) 0109 to set values of special internal properties. 0110 Currently these properties are used for customizing popup menu items used for orientation selection. 0111 Customization for class ClassName should look like: 0112 <code> 0113 WidgetInfo *wi = ... 0114 wi->setInternalProperty("orientationSelectionPopup", true); 0115 wi->setInternalProperty("orientationSelectionPopup:horizontalIcon", "myicon"); 0116 </code> 0117 Available internal properties: 0118 * "orientationSelectionPopup" - set it to true if you want a given class to offer orientation selection, 0119 so orientation selection popup will be displayed when needed. 0120 * "orientationSelectionPopup:horizontalIcon" - sets a name of icon for "Horizontal" item 0121 for objects of class 'ClassName'. Set this property only for classes supporting orientations. 0122 * "orientationSelectionPopup:verticalIcon" - the same for "Vertical" item. 0123 Set this property only for classes supporting orientations. 0124 * "orientationSelectionPopup:horizontalText" - sets a i18n'd text for "Horizontal" item 0125 for objects of class 'ClassName', e.g. xi18n("Insert Horizontal Line"). 0126 Set this property only for classes supporting orientations. 0127 * "orientationSelectionPopup:verticalText" - the same for "Vertical" item, 0128 e.g. xi18n("Insert Vertical Line"). Set this property only for classes supporting orientations. 0129 * "dontStartEditingOnInserting" - if true, WidgetFactory::startInlineEditing() will not be executed upon 0130 widget inseting by a user. 0131 * "forceShowAdvancedProperty:{propertyname}" - set it to true for "{propertyname}" advanced property 0132 if you want to force it to be visible even if WidgetLibrary::setAdvancedPropertiesVisible(false) 0133 has been called. For example, setting "forceShowAdvancedProperty:pixmap" to true 0134 unhides "pixmap" property for a given class. 0135 0136 See KexiStandardFormWidgetsFactory::KexiStandardFormWidgetsFactory() for properties like "Line:orientationSelectionPopup:horizontalIcon". 0137 0138 \n\n 0139 See the standard factories in formeditor/factories for an example of factories, 0140 and how to deal with complex widgets (eg tabwidget). 0141 */ 0142 class KFORMDESIGNER_EXPORT WidgetFactory : public QObject, 0143 public InternalPropertyHandlerInterface 0144 { 0145 Q_OBJECT 0146 public: 0147 //! Options used in createWidget() 0148 enum CreateWidgetOption { 0149 NoCreateWidgetOptions = 0, 0150 AnyOrientation = 1, //!< any orientation hint 0151 HorizontalOrientation = 2, //!< horizontal orientation hint 0152 VerticalOrientation = 4, //!< vertical orientation hint 0153 DesignViewMode = 8, //!< create widget in design view mode, otherwise preview mode 0154 DefaultOptions = AnyOrientation | DesignViewMode 0155 }; 0156 Q_DECLARE_FLAGS(CreateWidgetOptions, CreateWidgetOption) 0157 0158 explicit WidgetFactory(QObject *parent); 0159 0160 virtual ~WidgetFactory(); 0161 0162 /*! Adds a new class described by \a w. */ 0163 void addClass(WidgetInfo *w); 0164 0165 /*! This method allows to force a class \a classname to hidden. 0166 It is useful if you do not want a class to be available 0167 (e.g. because it is not implemented well yet for our purposes). 0168 All widget libraries are affected by this setting. */ 0169 void hideClass(const char *classname); 0170 0171 /** 0172 * \return all classes which are provided by this factory 0173 */ 0174 QHash<QByteArray, WidgetInfo*> classes() const; 0175 0176 /** 0177 * Creates a widget (and if needed a KFormDesigner::Container) 0178 * \return the created widget 0179 * \param classname the classname of the widget, which should get created 0180 * \param parent the parent for the created widget 0181 * \param name the name of the created widget 0182 * \param container the toplevel Container (if a container should get created) 0183 * \param options options for the created widget: orientation and view mode (see CreateWidgetOptions) 0184 */ 0185 virtual QWidget* createWidget(const QByteArray &classname, QWidget *parent, const char *name, 0186 KFormDesigner::Container *container, 0187 CreateWidgetOptions options = DefaultOptions) /*Q_REQUIRED_RESULT*/ = 0; 0188 0189 /*! Creates custom actions. Reimplement this if you need to add some 0190 actions coming from the factory. */ 0191 virtual void createCustomActions(KActionCollection *col) { 0192 Q_UNUSED(col); 0193 } 0194 0195 /*! This function can be used to add custom items in widget \a w context 0196 menu \a menu. */ 0197 virtual bool createMenuActions(const QByteArray &classname, QWidget *w, QMenu *menu, 0198 KFormDesigner::Container *container) = 0; 0199 0200 //! Arguments used by Form::createInlineEditor() and startInlineEditing() 0201 /*! @a text is the text to display by default in the line edit. 0202 @a widget is the edited widget, @a geometry is the geometry the new line 0203 edit should have, and @a alignment is Qt::Alignment of the new line edit. 0204 If @a useFrame is false (the default), the line edit has no frame. 0205 if @a multiLine is false (the default), the line edit has single line. 0206 @a background describes line edit's background. 0207 If @a execute is true (the default), createInlineEditor() will be executed. */ 0208 class KFORMDESIGNER_EXPORT InlineEditorCreationArguments { 0209 public: 0210 InlineEditorCreationArguments( 0211 const QByteArray& _classname, QWidget *_widget, Container *_container); 0212 QByteArray classname; 0213 QString text; 0214 QWidget *widget; 0215 Container *container; 0216 QRect geometry; 0217 Qt::Alignment alignment; 0218 bool useFrame; 0219 bool multiLine; 0220 bool execute; 0221 //! true if the inline editor's bakground should be transparent (false by default) 0222 bool transparentBackground; 0223 }; 0224 0225 /*! Sets up (if necessary) aguments for the inline editor used to edit the contents 0226 of the widget directly within the Form, 0227 e.g. creates a line edit to change the text of a label. @a args is 0228 used to pass the arguments back to the caller. 0229 */ 0230 virtual bool startInlineEditing(InlineEditorCreationArguments& args) = 0; 0231 0232 /*! This function is called just before the Form is previewed. It allows widgets 0233 to make changes before switching (ie for a Spring, hiding the cross) */ 0234 virtual bool previewWidget(const QByteArray &classname, QWidget *widget, Container *container) = 0; 0235 0236 virtual bool clearWidgetContent(const QByteArray &classname, QWidget *w); 0237 0238 /*! This function is called when FormIO finds a property, at save time, 0239 that it cannot handle (ie not a normal property). 0240 This way you can save special properties, for example the contents of a listbox. 0241 \sa readSpecialProperty() 0242 */ 0243 virtual bool saveSpecialProperty(const QByteArray &classname, const QString &name, 0244 const QVariant &value, QWidget *w, 0245 QDomElement &parentNode, QDomDocument &parent); 0246 0247 /*! This function is called when FormIO finds a property or an unknown 0248 element in a .ui file. You can this way load a special property, for 0249 example the contents of a listbox. 0250 \sa saveSpecialProperty() 0251 */ 0252 virtual bool readSpecialProperty(const QByteArray &classname, QDomElement &node, 0253 QWidget *w, ObjectTreeItem *item); 0254 0255 /*! This function is used to know whether the \a property for the widget \a w 0256 should be shown or not in the PropertyEditor. If \a multiple is true, 0257 then multiple widgets of the same class are selected, and you should 0258 only show properties shared by widgets (eg font, color). By default, 0259 all properties are shown if multiple == true, and none if multiple == false. */ 0260 bool isPropertyVisible(const QByteArray &classname, QWidget *w, 0261 const QByteArray &property, bool multiple, bool isTopLevel); 0262 0263 /*! \return The i18n'ed name of the property whose name is \a name, 0264 that will be displayed in PropertyEditor. */ 0265 QString propertyDescription(const char* name) const; 0266 0267 /*! \return The i18n'ed name of the property's value whose name is \a name. */ 0268 QString valueDescription(const char* name) const; 0269 0270 /*! This method is called after form's property set was filled with properties 0271 of a widget \a w, of class defined by \a info. 0272 Default implementation does nothing. 0273 Implement this if you need to set options for properties within the set \a set. */ 0274 virtual void setPropertyOptions(KPropertySet& set, const WidgetInfo& info, QWidget *w); 0275 0276 /*! \return internal property \a property for a class \a classname. 0277 Internal properties are not stored within objects, but can be just provided 0278 to describe class' details. */ 0279 QVariant internalProperty(const QByteArray& classname, const QByteArray& property) const; 0280 0281 /*! This function is called when the widget is resized, 0282 and the @a editor size needs to be updated. */ 0283 virtual void resizeEditor(QWidget *editor, QWidget *widget, const QByteArray &classname); 0284 0285 /*! @return selectable item for @a item item. 0286 By default it is equal to @a item but e.g. for pages of QTabWidget, 0287 item for the widget itself is returned. 0288 Used when user clicks on the Widget Tree item or when parent of the current 0289 widget should to be selected. Defaults can be overridden by reimplementing this method. */ 0290 virtual ObjectTreeItem* selectableItem(ObjectTreeItem* item); 0291 0292 /*! Sets the i18n'ed description of a property, which will be shown in PropertyEditor. */ 0293 void setPropertyDescription(const char *property, const QString &description); 0294 0295 /*! Sets the i18n'ed description of a property value, which will be shown in PropertyEditor. */ 0296 void setValueDescription(const char *valueName, const QString &description); 0297 0298 0299 void setAdvancedPropertiesVisible(bool set); 0300 protected: 0301 /*! This function is called when we want to know whether the property should be visible. 0302 Implement it in the factory; don't forget to call implementation in the superclass. 0303 Default implementation hides "windowTitle", "windowIcon", "sizeIncrement" and "windowIconText" properties. */ 0304 virtual bool isPropertyVisibleInternal(const QByteArray &classname, QWidget *w, 0305 const QByteArray &property, bool isTopLevel); 0306 0307 /*! Sometimes property sets should be reloaded when a given property value changed. 0308 Implement it in the factory. Default implementation always returns false. */ 0309 virtual bool propertySetShouldBeReloadedAfterPropertyChange(const QByteArray& classname, QWidget *w, 0310 const QByteArray& property); 0311 0312 /*! This function provides a simple editing mode: it just disables event filtering 0313 for the widget, and it install it again when 0314 the widget loose focus or Enter is pressed. */ 0315 void disableFilter(QWidget *w, Container *container); 0316 0317 /*! This function creates a little dialog (a KEditListBox) to modify the contents 0318 of a list (of strings). It can be used to modify the contents 0319 of a combo box for instance. The modified list is copied 0320 into \a list if the user presses "Ok" and true is returned. 0321 When user presses "Cancel" false is returned. */ 0322 bool editList(QWidget *w, QStringList &list) const; 0323 0324 /*! This function creates a little editor to modify rich text. It supports alignment, 0325 subscript and superscript and all basic formatting properties. 0326 If the user presses "Ok", the edited text is put into @a text and true is returned. 0327 If the user presses "Cancel" false is returned. */ 0328 bool editRichText(QWidget *w, QString &text) const; 0329 0330 #ifdef KEXI_LIST_FORM_WIDGET_SUPPORT 0331 /*! This function creates a dialog to modify the contents of a list widget. You can modify both 0332 columns and list items. The list widget is automatically updated if the user presses "Ok".*/ 0333 void editListWidget(QListWidget *listwidget) const; 0334 #endif 0335 0336 /*! This function is used to modify a property of a widget (eg after editing it). 0337 Please use it instead of w->setProperty() to allow sync inside PropertyEditor. 0338 */ 0339 void changeProperty(Form *form, QWidget *widget, const char *name, const QVariant &value); 0340 0341 /*! \return true if at least one class defined by this factory inherits 0342 a class from other factory. Used in WidgetLibrary::loadFactories() 0343 to load factories in proper order. */ 0344 bool inheritsFactories(); 0345 0346 /*! Assigns \a value for internal property \a property for a class \a classname. 0347 Internal properties are not stored within objects, but can be provided 0348 to describe class' details. */ 0349 void setInternalProperty(const QByteArray& classname, const QByteArray& property, const QVariant& value) override; 0350 0351 WidgetInfo* widgetInfoForClassName(const char* classname); 0352 0353 const QSet<QByteArray>* hiddenClasses() const; 0354 0355 WidgetLibrary* library(); 0356 0357 bool advancedPropertiesVisible() const; 0358 0359 void setLibrary(WidgetLibrary* library); 0360 0361 public Q_SLOTS: 0362 /*! @internal. This slot is called when the editor has lost focus or the user pressed Enter. 0363 It destroys the editor or installs again the event filter on the widget. */ 0364 0365 //! Changes inline text for widget @a widget to @a text 0366 /*! Default implementation changes "text" property of the widget. 0367 You have to reimplement this function for inline editing inside the form @a form if your widget's 0368 property you want to change is not named "text". 0369 This slot is called when the line edit text changes, and you have to make 0370 it really change property of the widget using changeProperty() (text, title, etc.). */ 0371 virtual bool changeInlineText(Form *form, QWidget *widget, 0372 const QString& text, QString *oldText = nullptr); 0373 private: 0374 class Private; 0375 Private* const d; 0376 0377 friend class WidgetLibrary; 0378 }; 0379 0380 Q_DECLARE_OPERATORS_FOR_FLAGS(WidgetFactory::CreateWidgetOptions) 0381 0382 } 0383 #endif