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