diff --git a/src/core/kexipart.h b/src/core/kexipart.h index daa302aff..2ce1a63a4 100644 --- a/src/core/kexipart.h +++ b/src/core/kexipart.h @@ -1,282 +1,282 @@ /* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2003-2014 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXIPART_H #define KEXIPART_H #include #include #include #include "kexipartbase.h" #include class KActionCollection; class KexiWindow; class KexiWindowData; class KexiView; class KDbQuerySchema; class QAction; class QKeySequence; namespace KexiPart { class Item; class GUIClient; class StaticPartInfo; /*! Official (registered) type IDs for objects like table, query, form... */ enum ObjectType { UnknownObjectType = KDb::UnknownObjectType, //!< -1, helper AnyObjectType = KDb::AnyObjectType, //!< 0, helper TableObjectType = KDb::TableObjectType, //!< 1, like in KDb::ObjectType QueryObjectType = KDb::QueryObjectType, //!< 2, like in KDb::ObjectType FormObjectType = 3, ReportObjectType = 4, ScriptObjectType = 5, WebObjectType = 6, MacroObjectType = 7, LastObjectType = 7, //ALWAYS UPDATE THIS UserObjectType = 100 //!< external types }; //! @return Kexi Part API version: "major.minor" //! @since 3.1 KEXICORE_EXPORT QString version(); //! @short The main class for kexi frontend parts (plugins) like tables, queries, forms and reports /*! Plugins create windows (KexiWindow) for a given type of object. Notes for plugins implementors: This class supports InternalPropertyMap interface, so supported internal properties affecting its behaviour are: - newObjectsAreDirty: True if newly created, unsaved objects are dirty. False by default. - textViewModeCaption: custum i18n'd action text replacing standard "Text View" text. Used in for query's "SQL View". In general: a whole set of i18n'd action names, initialised on KexiPart::Part subclass ctor. The names are useful because the same action can have other name for each part, e.g. "New table" vs "New query" can have different forms for some languages. So this is a flexible way for customizing translatable strings. */ class KEXICORE_EXPORT Part : public PartBase { Q_OBJECT public: virtual ~Part(); //! @todo make it protected, outside world should use KexiProject /*! Try to execute the part. Implementations of this \a Part are able to overwrite this method to offer execution. \param item The \a KexiPart::Item that should be executed. \param sender The sender QObject which likes to execute this \a Part or NULL if there is no sender. The KFormDesigner uses this to pass the actual widget (e.g. the button that was pressed). \return true if execution was successfully else false. */ virtual bool execute(KexiPart::Item* item, QObject* sender = 0) { Q_UNUSED(item); Q_UNUSED(sender); return false; } //! @todo make it protected, outside world should use KexiProject /*! "Opens" an instance that the part provides, pointed by \a item in a mode \a viewMode. \a viewMode is one of Kexi::ViewMode enum. \a staticObjectArgs can be passed for static Kexi Parts. The new widget will be a child of \a parent. */ KexiWindow* openInstance(QWidget* parent, KexiPart::Item *item, Kexi::ViewMode viewMode = Kexi::DataViewMode, QMap* staticObjectArgs = 0); //! @todo make it protected, outside world should use KexiProject /*! Removes any stored data pointed by \a item (example: table is dropped for table part). From now this data is inaccesible, and \a item disappear. You do not need to remove \a item, or remove object's schema stored in the database, beacuse this will be done automatically by KexiProject after successful call of this method. All object's data blocks are also automatically removed from database (from "kexi__objectdata" table). For this, a database connection associated with kexi project owned by \a win can be used. Database transaction is started by KexiProject before calling this method, and it will be rolled back if you return false here. You shouldn't use by hand transactions here. Default implementation just removes object from kexi__* system structures at the database backend using KDbConnection::removeObject(). */ virtual tristate remove(KexiPart::Item *item); /*! Renames stored data pointed by \a item to \a newName (example: table name is altered in the database). For this, a database connection associated with kexi project owned by \a win can be used. You do not need to change \a item, and change object's schema stored in the database, beacuse this is automatically handled by KexiProject. Database transaction is started by KexiProject before calling this method, and it will be rolled back if you return false here. You shouldn't use by hand transactions here. Default implementation does nothing and returns true. */ virtual tristate rename(KexiPart::Item *item, const QString& newName); /*! Creates and returns a new temporary data for a window \a window. This method is called on openInstance() once per dialog. Reimplement this to return KexiWindowData subclass instance. Default implemention just returns empty KexiWindowData object. */ virtual KexiWindowData* createWindowData(KexiWindow *window) Q_REQUIRED_RESULT; /*! Creates a new view for mode \a viewMode, \a item and \a parent. The view will be used inside \a dialog. */ virtual KexiView *createView(QWidget *parent, KexiWindow *window, KexiPart::Item *item, Kexi::ViewMode viewMode = Kexi::DataViewMode, - QMap *staticObjectArgs = nullptr) Q_REQUIRED_RESULT = 0; + QMap *staticObjectArgs = nullptr) /*Q_REQUIRED_RESULT*/ = 0; //virtual void initTabs(); /*! @return i18n'd instance name usable for displaying in gui as object's name, e.g. "table". The name is valid identifier - contains latin-1 lowercase characters only. */ QString instanceName() const; /*! @return i18n'd tooltip that can also act as descriptive name of the action. Example: "Create new table". */ QString toolTip() const; /*! @return i18n'd "what's this" string. Example: "Creates new table." */ QString whatsThis() const; /*! \return part's GUI Client, so you can create part-wide actions using this client. */ GUIClient *guiClient() const; /*! \return part's GUI Client, so you can create instance-wide actions using this client. */ GUIClient *instanceGuiClient(Kexi::ViewMode mode = Kexi::AllViewModes) const; /*! \return action collection for mode \a viewMode. */ KActionCollection* actionCollectionForMode(Kexi::ViewMode viewMode) const; const Kexi::ObjectStatus& lastOperationStatus() const; /*! \return query schema currently edited in the \a view. * It may be the original/saved query if user has no unsaved changes so far * or a temporary unsaved query if there are unsaved modifications. * The query can be used for example by data exporting routines so user can * export result of a running unsaved query without prior saving it. For implementation in plugins. */ virtual KDbQuerySchema *currentQuery(KexiView* view); /*! @internal Creates GUIClients for this part, attached to the main window. This method is called by KexiMainWindow. */ void createGUIClients(); Q_SIGNALS: void newObjectRequest(KexiPart::Info *info); protected: /*! Creates new Plugin @param parent parent of this plugin @param instanceName i18n'd instance name written using only lowercase alphanumeric characters (a..z, 0..9). Use '_' character instead of spaces. First character should be a..z character. If you cannot use latin characters in your language, use english word. Example: "table". @param toolTip i18n'd tooltip that can also act as descriptive name of the action. Example: "Create new table". @param whatsThis i18n'd "what's this" string. Example: "Creates new table." @param list extra arguments passed to the plugin */ Part(QObject *parent, const QString& instanceName, const QString& toolTip, const QString& whatsThis, const QVariantList& list); //! Used by StaticPart Part(QObject* parent, StaticPartInfo *info); virtual void initPartActions(); virtual void initInstanceActions(); /*! Can be reimplemented if object data is extended behind the default set of properties. This is the case for table and query schema objects, where object of KDbObject subclass is returned. In this case value pointed by @a ownedByWindow is set to false. Default implemenatation owned (value pointed by @a ownedByWindow is set to true). */ virtual KDbObject* loadSchemaObject(KexiWindow *window, const KDbObject& object, Kexi::ViewMode viewMode, bool *ownedByWindow); bool loadDataBlock(KexiWindow *window, QString *dataString, const QString& dataID = QString()); /*! Creates shared action for action collection declared for 'instance actions' of this part. See KexiSharedActionHost::createSharedAction() for details. Pass desired QAction subclass with \a subclassName (e.g. "KToggleAction") to have that subclass allocated instead just QAction (what is the default). */ QAction * createSharedAction(Kexi::ViewMode mode, const QString &text, const QString &pix_name, const QKeySequence &cut, const char *name, const char *subclassName = 0); /*! Convenience version of above method - creates shared toggle action. */ QAction * createSharedToggleAction(Kexi::ViewMode mode, const QString &text, const QString &pix_name, const QKeySequence &cut, const char *name); /*! Creates shared action for action collection declared for 'part actions' of this part. See KexiSharedActionHost::createSharedAction() for details. Pass desired QAction subclass with \a subclassName (e.g. "KToggleAction") to have that subclass allocated instead just QAction (what is the default). */ QAction * createSharedPartAction(const QString &text, const QString &pix_name, const QKeySequence &cut, const char *name, const char *subclassName = 0); /*! Convenience version of above method - creates shared toggle action for 'part actions' of this part. */ QAction * createSharedPartToggleAction(const QString &text, const QString &pix_name, const QKeySequence &cut, const char *name); void setActionAvailable(const char *action_name, bool avail); private: //! Calls loadSchemaObject() (virtual), updates ownership of object data for @a window //! and assigns the created data to @a window. void loadAndSetSchemaObject(KexiWindow *window, const KDbObject& object, Kexi::ViewMode viewMode); Q_DISABLE_COPY(Part) class Private; Private * const d; friend class Manager; friend class ::KexiWindow; friend class GUIClient; }; /*! \return full caption for item \a item and part \a part. If \a part is provided, the captions will be in a form of "name : inctancetype", e.g. "Employees : Table", otherwise it will be in a form of "name", e.g. "Employees". */ KEXICORE_EXPORT QString fullCaptionForItem(KexiPart::Item *item, KexiPart::Part *part); } // namespace KexiPart #endif diff --git a/src/formeditor/widgetfactory.h b/src/formeditor/widgetfactory.h index 57d04b3ca..94c4de680 100644 --- a/src/formeditor/widgetfactory.h +++ b/src/formeditor/widgetfactory.h @@ -1,383 +1,383 @@ /* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004-2009 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KFORMDESIGNERWIDGETFACTORY_H #define KFORMDESIGNERWIDGETFACTORY_H #include #include #include #include #include "kformdesigner_export.h" class QWidget; class QListWidget; class QMenu; class QDomElement; class QDomDocument; class QVariant; class KActionCollection; class KPropertySet; namespace KFormDesigner { class Container; class ObjectTreeItem; class Form; class WidgetLibrary; class WidgetInfo; //! Used by WidgetFactory class KFORMDESIGNER_EXPORT InternalPropertyHandlerInterface { protected: InternalPropertyHandlerInterface(); virtual ~InternalPropertyHandlerInterface(); /*! Assigns \a value for internal property \a property for a class \a classname. Internal properties are not stored within objects, but can be provided to describe class' details. */ virtual void setInternalProperty(const QByteArray& classname, const QByteArray& property, const QVariant& value) = 0; friend class WidgetInfo; }; //! The base class for all widget Factories /*! This is the class you need to inherit to create a new Factory. There are few virtuals you need to implement, and some other functions to implement if you want more features.\n \n Widget Creation\n To be able to create widgets, you need to implement the create() function, an classes(), which should return all the widgets supported by this factory.\n \n GUI Integration\n The following functions allow you to customize even more the look-n-feel of your widgets inside KFormDesigner. You can use createMenuActions() to add custom items in widget's context menu. The previewWidget() is called when the Form gets in Preview mode, and you have a last opportunity to remove all editing-related stuff (see eg \ref Spring class).\n You can also choose which properties to show in the Property Editor. By default, most all properties are shown (see implementation for details), but you can hide some reimplementing isPropertyVisibleInternal() (don't forget to call superclass' method) To add new properties, just define new Q_PROPERTY in widget class definition.\n \n Inline editing\n KFormDesigner allow you to edit the widget's contents inside Form, without using a dialog. You can of course customize the behaviour of your widgets, using startInlineEditing(). There are some editing modes already implemented in WidgetFactroy, but you can create your own if you want: \li Editing using a line edit (createInlineEditor()): a line edit is created on top of widget, where the user inputs text. As the text changes, changeInlineText() is called (where you should set your widget's text and resize widget to fit the text if needed) and resizeEditor() to update editor's position when widget is moved/resized.\n \li Editing by disabling event filter: if you call disableFilter(), the event filter on the object is temporarily disabled, so the widget behaves as usual. This can be used for more complex widgets, such as spinbox, date/time edit, etc. \li Other modes: there are 3 other modes, to edit a string list: editList() (for combo box, listbox), to edit rich text: editRichText() (for labels, etc.)\n \n Widget saving/loading\n You can also control how your widget are saved/loaded. You can choose which properties to save (see autoSaveProperties()), and save/load custom properties, ie properties that are not Q_PROPERTY but you want to save in the UI file. This is used eg to save combo box or list widget contents (see saveSpecialProperty() and readSpecialProperty()). \n \n Special internal properties\n Use void WidgetInfo::setInternalProperty(const QByteArray& property, const QVariant& value) to set values of special internal properties. Currently these properties are used for customizing popup menu items used for orientation selection. Customization for class ClassName should look like: WidgetInfo *wi = ... wi->setInternalProperty("orientationSelectionPopup", true); wi->setInternalProperty("orientationSelectionPopup:horizontalIcon", "myicon"); Available internal properties: * "orientationSelectionPopup" - set it to true if you want a given class to offer orientation selection, so orientation selection popup will be displayed when needed. * "orientationSelectionPopup:horizontalIcon" - sets a name of icon for "Horizontal" item for objects of class 'ClassName'. Set this property only for classes supporting orientations. * "orientationSelectionPopup:verticalIcon" - the same for "Vertical" item. Set this property only for classes supporting orientations. * "orientationSelectionPopup:horizontalText" - sets a i18n'd text for "Horizontal" item for objects of class 'ClassName', e.g. xi18n("Insert Horizontal Line"). Set this property only for classes supporting orientations. * "orientationSelectionPopup:verticalText" - the same for "Vertical" item, e.g. xi18n("Insert Vertical Line"). Set this property only for classes supporting orientations. * "dontStartEditingOnInserting" - if true, WidgetFactory::startInlineEditing() will not be executed upon widget inseting by a user. * "forceShowAdvancedProperty:{propertyname}" - set it to true for "{propertyname}" advanced property if you want to force it to be visible even if WidgetLibrary::setAdvancedPropertiesVisible(false) has been called. For example, setting "forceShowAdvancedProperty:pixmap" to true unhides "pixmap" property for a given class. See KexiStandardFormWidgetsFactory::KexiStandardFormWidgetsFactory() for properties like "Line:orientationSelectionPopup:horizontalIcon". \n\n See the standard factories in formeditor/factories for an example of factories, and how to deal with complex widgets (eg tabwidget). */ class KFORMDESIGNER_EXPORT WidgetFactory : public QObject, public InternalPropertyHandlerInterface { Q_OBJECT public: //! Options used in createWidget() enum CreateWidgetOption { NoCreateWidgetOptions = 0, AnyOrientation = 1, //!< any orientation hint HorizontalOrientation = 2, //!< horizontal orientation hint VerticalOrientation = 4, //!< vertical orientation hint DesignViewMode = 8, //!< create widget in design view mode, otherwise preview mode DefaultOptions = AnyOrientation | DesignViewMode }; Q_DECLARE_FLAGS(CreateWidgetOptions, CreateWidgetOption) explicit WidgetFactory(QObject *parent); virtual ~WidgetFactory(); /*! Adds a new class described by \a w. */ void addClass(WidgetInfo *w); /*! This method allows to force a class \a classname to hidden. It is useful if you do not want a class to be available (e.g. because it is not implemented well yet for our purposes). All widget libraries are affected by this setting. */ void hideClass(const char *classname); /** * \return all classes which are provided by this factory */ QHash classes() const; /** * Creates a widget (and if needed a KFormDesigner::Container) * \return the created widget * \param classname the classname of the widget, which should get created * \param parent the parent for the created widget * \param name the name of the created widget * \param container the toplevel Container (if a container should get created) * \param options options for the created widget: orientation and view mode (see CreateWidgetOptions) */ virtual QWidget* createWidget(const QByteArray &classname, QWidget *parent, const char *name, KFormDesigner::Container *container, - CreateWidgetOptions options = DefaultOptions) Q_REQUIRED_RESULT = 0; + CreateWidgetOptions options = DefaultOptions) /*Q_REQUIRED_RESULT*/ = 0; /*! Creates custom actions. Reimplement this if you need to add some actions coming from the factory. */ virtual void createCustomActions(KActionCollection *col) { Q_UNUSED(col); } /*! This function can be used to add custom items in widget \a w context menu \a menu. */ virtual bool createMenuActions(const QByteArray &classname, QWidget *w, QMenu *menu, KFormDesigner::Container *container) = 0; //! Arguments used by Form::createInlineEditor() and startInlineEditing() /*! @a text is the text to display by default in the line edit. @a widget is the edited widget, @a geometry is the geometry the new line edit should have, and @a alignment is Qt::Alignment of the new line edit. If @a useFrame is false (the default), the line edit has no frame. if @a multiLine is false (the default), the line edit has single line. @a background describes line edit's background. If @a execute is true (the default), createInlineEditor() will be executed. */ class KFORMDESIGNER_EXPORT InlineEditorCreationArguments { public: InlineEditorCreationArguments( const QByteArray& _classname, QWidget *_widget, Container *_container); QByteArray classname; QString text; QWidget *widget; Container *container; QRect geometry; Qt::Alignment alignment; bool useFrame; bool multiLine; bool execute; //! true if the inline editor's bakground should be transparent (false by default) bool transparentBackground; }; /*! Sets up (if necessary) aguments for the inline editor used to edit the contents of the widget directly within the Form, e.g. creates a line edit to change the text of a label. @a args is used to pass the arguments back to the caller. */ virtual bool startInlineEditing(InlineEditorCreationArguments& args) = 0; /*! This function is called just before the Form is previewed. It allows widgets to make changes before switching (ie for a Spring, hiding the cross) */ virtual bool previewWidget(const QByteArray &classname, QWidget *widget, Container *container) = 0; virtual bool clearWidgetContent(const QByteArray &classname, QWidget *w); /*! This function is called when FormIO finds a property, at save time, that it cannot handle (ie not a normal property). This way you can save special properties, for example the contents of a listbox. \sa readSpecialProperty() */ virtual bool saveSpecialProperty(const QByteArray &classname, const QString &name, const QVariant &value, QWidget *w, QDomElement &parentNode, QDomDocument &parent); /*! This function is called when FormIO finds a property or an unknown element in a .ui file. You can this way load a special property, for example the contents of a listbox. \sa saveSpecialProperty() */ virtual bool readSpecialProperty(const QByteArray &classname, QDomElement &node, QWidget *w, ObjectTreeItem *item); /*! This function is used to know whether the \a property for the widget \a w should be shown or not in the PropertyEditor. If \a multiple is true, then multiple widgets of the same class are selected, and you should only show properties shared by widgets (eg font, color). By default, all properties are shown if multiple == true, and none if multiple == false. */ bool isPropertyVisible(const QByteArray &classname, QWidget *w, const QByteArray &property, bool multiple, bool isTopLevel); /*! \return The i18n'ed name of the property whose name is \a name, that will be displayed in PropertyEditor. */ QString propertyDescription(const char* name) const; /*! \return The i18n'ed name of the property's value whose name is \a name. */ QString valueDescription(const char* name) const; /*! This method is called after form's property set was filled with properties of a widget \a w, of class defined by \a info. Default implementation does nothing. Implement this if you need to set options for properties within the set \a set. */ virtual void setPropertyOptions(KPropertySet& set, const WidgetInfo& info, QWidget *w); /*! \return internal property \a property for a class \a classname. Internal properties are not stored within objects, but can be just provided to describe class' details. */ QVariant internalProperty(const QByteArray& classname, const QByteArray& property) const; /*! This function is called when the widget is resized, and the @a editor size needs to be updated. */ virtual void resizeEditor(QWidget *editor, QWidget *widget, const QByteArray &classname); /*! @return selectable item for @a item item. By default it is equal to @a item but e.g. for pages of QTabWidget, item for the widget itself is returned. Used when user clicks on the Widget Tree item or when parent of the current widget should to be selected. Defaults can be overridden by reimplementing this method. */ virtual ObjectTreeItem* selectableItem(ObjectTreeItem* item); /*! Sets the i18n'ed description of a property, which will be shown in PropertyEditor. */ void setPropertyDescription(const char *property, const QString &description); /*! Sets the i18n'ed description of a property value, which will be shown in PropertyEditor. */ void setValueDescription(const char *valueName, const QString &description); void setAdvancedPropertiesVisible(bool set); protected: /*! This function is called when we want to know whether the property should be visible. Implement it in the factory; don't forget to call implementation in the superclass. Default implementation hides "windowTitle", "windowIcon", "sizeIncrement" and "windowIconText" properties. */ virtual bool isPropertyVisibleInternal(const QByteArray &classname, QWidget *w, const QByteArray &property, bool isTopLevel); /*! Sometimes property sets should be reloaded when a given property value changed. Implement it in the factory. Default implementation always returns false. */ virtual bool propertySetShouldBeReloadedAfterPropertyChange(const QByteArray& classname, QWidget *w, const QByteArray& property); /*! This function provides a simple editing mode: it just disables event filtering for the widget, and it install it again when the widget loose focus or Enter is pressed. */ void disableFilter(QWidget *w, Container *container); /*! This function creates a little dialog (a KEditListBox) to modify the contents of a list (of strings). It can be used to modify the contents of a combo box for instance. The modified list is copied into \a list if the user presses "Ok" and true is returned. When user presses "Cancel" false is returned. */ bool editList(QWidget *w, QStringList &list) const; /*! This function creates a little editor to modify rich text. It supports alignment, subscript and superscript and all basic formatting properties. If the user presses "Ok", the edited text is put into @a text and true is returned. If the user presses "Cancel" false is returned. */ bool editRichText(QWidget *w, QString &text) const; #ifdef KEXI_LIST_FORM_WIDGET_SUPPORT /*! This function creates a dialog to modify the contents of a list widget. You can modify both columns and list items. The list widget is automatically updated if the user presses "Ok".*/ void editListWidget(QListWidget *listwidget) const; #endif /*! This function is used to modify a property of a widget (eg after editing it). Please use it instead of w->setProperty() to allow sync inside PropertyEditor. */ void changeProperty(Form *form, QWidget *widget, const char *name, const QVariant &value); /*! \return true if at least one class defined by this factory inherits a class from other factory. Used in WidgetLibrary::loadFactories() to load factories in proper order. */ bool inheritsFactories(); /*! Assigns \a value for internal property \a property for a class \a classname. Internal properties are not stored within objects, but can be provided to describe class' details. */ void setInternalProperty(const QByteArray& classname, const QByteArray& property, const QVariant& value); WidgetInfo* widgetInfoForClassName(const char* classname); const QSet* hiddenClasses() const; WidgetLibrary* library(); bool advancedPropertiesVisible() const; void setLibrary(WidgetLibrary* library); public Q_SLOTS: /*! @internal. This slot is called when the editor has lost focus or the user pressed Enter. It destroys the editor or installs again the event filter on the widget. */ //! Changes inline text for widget @a widget to @a text /*! Default implementation changes "text" property of the widget. You have to reimplement this function for inline editing inside the form @a form if your widget's property you want to change is not named "text". This slot is called when the line edit text changes, and you have to make it really change property of the widget using changeProperty() (text, title, etc.). */ virtual bool changeInlineText(Form *form, QWidget *widget, const QString& text, QString &oldText); private: class Private; Private* const d; friend class WidgetLibrary; }; Q_DECLARE_OPERATORS_FOR_FLAGS(WidgetFactory::CreateWidgetOptions) } #endif