diff --git a/src/core/kexipartguiclient.cpp b/src/core/kexipartguiclient.cpp index 721884a81..8783a5e1f 100644 --- a/src/core/kexipartguiclient.cpp +++ b/src/core/kexipartguiclient.cpp @@ -1,72 +1,72 @@ /* 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. */ #include "kexipart.h" #include "kexipartinfo.h" #include "kexipartitem.h" -//! @todo KEXI3 #include "kexistaticpart.h" +//! @todo KEXI3 include "kexistaticpart.h" #include "KexiWindow.h" #include "KexiWindowData.h" #include "KexiView.h" #include "kexipartguiclient.h" #include "KexiMainWindowIface.h" #include "kexi.h" #include #include #include #include #include namespace KexiPart { class Q_DECL_HIDDEN GUIClient::Private { public: Private() : actionCollection(static_cast(0)) {} KActionCollection actionCollection; }; } //------------------------------------------------------------------------- using namespace KexiPart; GUIClient::GUIClient(Part* part, bool partInstanceClient, const char* nameSuffix) : QObject(part) , d(new Private) { Q_UNUSED(partInstanceClient); setObjectName( part->info()->id() + (nameSuffix ? QString(":%1").arg(nameSuffix) : QString())); } GUIClient::~GUIClient() { delete d; } KActionCollection* GUIClient::actionCollection() const { return &d->actionCollection; } diff --git a/src/formeditor/form.h b/src/formeditor/form.h index 98ff3466c..6589a02cd 100644 --- a/src/formeditor/form.h +++ b/src/formeditor/form.h @@ -1,756 +1,756 @@ /* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004-2017 Jarosław Staniek Copyright (C) 2014 Michał Poteralski 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 KFORMDESIGNERFORM_H #define KFORMDESIGNERFORM_H #include "kformdesigner_export.h" #include "widgetlibrary.h" #include #include #include class QWidget; class KActionCollection; class PixmapCollection; class KProperty; class KPropertySet; class KUndo2Command; namespace KFormDesigner { class Command; class PropertyCommandGroup; #ifdef KFD_SIGSLOTS class ConnectionBuffer; #endif class Container; class ObjectTree; class ObjectTreeItem; typedef QList ObjectTreeList; class FormPrivate; class FormWidget; class ResizeHandleSet; /*! This class represents one form and holds the corresponding ObjectTree and Containers. It takes care of widget selection and pasting widgets. **/ //! A simple class representing a form class KFORMDESIGNER_EXPORT Form : public QObject { Q_OBJECT public: enum WidgetAlignment { AlignToGrid, AlignToLeft, AlignToRight, AlignToTop, AlignToBottom }; //! Form's mode: design or data. enum Mode { DataMode, DesignMode }; //! States like widget inserting. Used only in design mode. enum State { WidgetSelecting, //!< widget selecting WidgetInserting //!< widget inserting #ifdef KFD_SIGSLOTS , Connecting //!< signal/slot connecting #endif }; /*! Features used while creating Form objects. */ enum Feature { NoFeatures = 0, EnableEvents = 1, EnableFileActions = 2 #ifdef KFD_SIGSLOTS , EnableConnections = 4 #endif }; Q_DECLARE_FLAGS(Features, Feature) //! Types of layout enum LayoutType { NoLayout = 0, HBox, VBox, Grid, HFlow, VFlow, /* special types */ HSplitter, VSplitter }; /*! Creates Form object. */ Form(WidgetLibrary* library, Mode mode, KActionCollection &col, ActionGroup& group); /*! Creates Form object as a child of other form. */ explicit Form(Form *parent); ~Form(); //! \return A pointer to the WidgetLibrary supporting this form. WidgetLibrary* library() const; KPropertySet* propertySet(); void setFeatures(Features features); Features features() const; /*! Creates a toplevel widget out of another widget. \a container will become the Form toplevel widget, will be associated to an ObjectTree and so on. \code QWidget *toplevel = new QWidget(this); form->createToplevel(toplevel); \endcode */ void createToplevel(QWidget *container, FormWidget *formWidget = 0, const QByteArray &classname = "QWidget"); /*! \return the toplevel Container or 0 if the form is in data mode or createToplevel() has not been called yet. */ Container* toplevelContainer() const; //! \return the FormWidget that holds this Form FormWidget* formWidget() const; //! \return a pointer to this form's ObjectTree. ObjectTree* objectTree() const; //! \return the form's toplevel widget, or 0 if not in design mode. QWidget* widget() const; /*! \return A pointer to the currently active Container, ie the parent Container for a simple widget, and the widget's Container if it is itself a container. */ Container* activeContainer(); /*! \return A pointer to the parent Container of the currently selected widget. It is the same as activeContainer() for a simple widget, but unlike this function it will also return the parent Container if the widget itself is a Container. */ Container* parentContainer(QWidget *w = 0) const; - /*! \return The \ref Container which is a parent of all widgets in \a wlist. - Used by \ref activeContainer(), and to find where + /*! \return The Container which is a parent of all widgets in \a wlist. + Used by activeContainer(), and to find where to paste widgets when multiple widgets are selected. */ ObjectTreeItem* commonParentContainer(const QWidgetList &wlist); //! \return the list of currently selected widgets in this form QWidgetList* selectedWidgets() const; /*! \return currently selected widget in this form, or 0 if there is no widget selected or more than one widget selected. \see selectedWidgets() */ QWidget* selectedWidget() const; //! \return true if form widget itself is selected. /*! Used to check whether it is possible to execute copy/cut/delete actions. */ bool isFormWidgetSelected() const; /*! Emits the action signals. */ void emitActionSignals(); /*! Emits the action signals for the undo/redo related signals. */ void emitUndoActionSignals(); /*! Emits again all signal related to selection (ie Form::selectionChanged()). Called eg when the user has the focus again. */ void emitSelectionSignals(); /*! Sets the Form interactivity mode. Form is not interactive when pasting widgets, or loading a Form. */ void setInteractiveMode(bool interactive); /*! \return true if the Form is being updated by the user, ie the created widget were drawn on the Form. \return false if the Form is being updated by the program, ie the widget are created by FormIO, and so composed widgets should not be populated automatically (such as QTabWidget). */ bool interactiveMode() const; /*! Sets form's mode to @a mode. In data mode, information related to design mode (object tree and the containers..) is removed. */ void setMode(Mode mode); //! @return The actual mode of the Form. Mode mode() const; //! @return true if the form modification flag is set. bool isModified() const; //! Sets modification flag. Always emits modified() signal. void setModified(bool set); //! \return the default margin for all the layout inside this Form. int defaultMargin() const; //! \return the default spacing for all the layout inside this Form. int defaultSpacing() const; /*! This function is used by ObjectTree to emit childAdded() signal (as it is not a QObject). */ void emitChildAdded(ObjectTreeItem *item); /*! This function is used by ObjectTree to emit childRemoved() signal (as it is not a QObject). */ void emitChildRemoved(ObjectTreeItem *item); /*! \return The filename of the UI file this Form was saved to, or empty string if the Form hasn't be saved yet. */ //! @todo move this field out of this class QString fileName() const; //! Sets the filename of this Form to \a filename. //! @todo move this field out of this class void setFileName(const QString &file); /*! Clears form's undo/redo stack. */ void clearUndoStack(); /*! Sets undo/redo stack in a clean state, used when the document is saved. */ void setUndoStackClean(); #ifdef KFD_SIGSLOTS ConnectionBuffer* connectionBuffer() const; #endif PixmapCollection* pixmapCollection() const; void setPixmapsStoredInline(bool set); bool pixmapsStoredInline() const; //! Options for addCommand() method. enum AddCommandOption { DontExecuteCommand = 0, //!< command is not executed in addCommand() ExecuteCommand = 1 //!< command is executed in addCommand() }; /*! Adds a command @a command in the form's undo/redo stack and returns true. If @a command is merged with the existing command and deleted, false is returned. */ bool addCommand(Command *command, AddCommandOption option = ExecuteCommand); //! Creates a new PropertyCommand object and adds it to the undo/redo stack. /*! Takes care about the case when the same property of the same object is changed one-after-one. In this case only value of the present command on stack is changed. */ void addPropertyCommand(const QByteArray &wname, const QVariant &oldValue, const QVariant &value, const QByteArray &propertyName, AddCommandOption addOption, int idOfPropertyCommand = 0); void addPropertyCommand(const QHash &oldValues, const QVariant &value, const QByteArray &propertyName, AddCommandOption addOption, int idOfPropertyCommand = 0); //! Adds @a commandGroup to the undo/redo stack. /*! Assuming the @a commandGroup contains PropertyCommand objects, the method takes care about the case when the same properties of the same list of objects is changed one-after-one. In this case only values of the command in the present command group on the stack are changed and @a commandGroup is deleted.*/ void addPropertyCommandGroup(PropertyCommandGroup *commandGroup, AddCommandOption addOption, int idOfPropertyCommand = 0); /*! \return tabstops list. It contains all the widgets that can have focus (i.e. no labels, etc.) in the order of the tabs.*/ ObjectTreeList* tabStops(); /*! Called (e.g. by KexiDBForm) when certain widgets can have updated focusPolicy properties these having no TabFocus flags set are removed from tabStops() list. */ void updateTabStopsOrder(); /*! Adds the widget at the end of tabstops list. Called on widget creation. */ void addWidgetToTabStops(ObjectTreeItem *it); /*! \return True if the Form automatically handles tab stops. */ bool autoTabStops() const; /*! If \a autoTab is true (the default), then the Form will automatically handle tab stops, and the "Edit Tab Order" dialog will be disabled. The tab widget will be set from the top-left to the bottom-right corner.\n If \a autoTab is false, it's up to the user to change tab stops.*/ void setAutoTabStops(bool autoTab); /*! Tells the Form to reassign the tab stops because the widget layout has changed (called for example before saving or displaying the tab order dialog). Automatically sorts widget from the top-left to bottom-right corner. Widget can be grouped with containers. In particular, for tab widgets, child widgets should ordered by parent tab's order. */ void autoAssignTabStops(); //! Specifies target of context menu. Used in createContextMenu(). enum ContextMenuTarget { FormContextMenuTarget, //!< Context menu should be displayed on the form //!< with offset specified by menuPos argument. WidgetTreeContextMenuTarget //!< Context menu should be displayed on the widget tree //!< area with offset specified by menuPos argument. }; /*! This function creates and displays the context menu corresponding to the widget \a w. The menu item are disabled if necessary, and the widget specific part is added (menu from the factory and buddy selection). */ void createContextMenu(QWidget *w, Container *container, const QPoint& menuPos, ContextMenuTarget target); //! @return true if snapping to grid is enabled. The defalt value is false. bool isSnapToGridEnabled() const; //! Sets state of snapping to grid to @a enabled. void setSnapToGridEnabled(bool enabled); //! @return size of grid. Positive values make sense here. The defalt value is 0. //! @todo make gridSize configurable at global level int gridSize() const; //! Sets size of grid to @a gridSize. void setGridSize(int gridSize); #ifdef KEXI_DEBUG_GUI //! For debugging purposes QString m_recentlyLoadedUICode; #endif ResizeHandleSet* resizeHandlesForWidget(QWidget* w); /*! A set of value/key pairs provided to be stored as attributes in XML element (saved as a first child of \ element). */ QHash* headerProperties(); //! \return format version number for this form. //! For new forms it is equal to KFormDesigner::version(). QString formatVersion() const; void setFormatVersion(const QString &ver); //! \return original format version number for this form (as loaded from .ui XML string) //! For new forms it is equal to KFormDesigner::version(). QString originalFormatVersion() const; void setOriginalFormatVersion(const QString &ver); #ifdef KFD_SIGSLOTS /*! Related to signal/slots connections. Resets recently selected signal/slot connection (when the user clicks outside of signals/slots menu). We stay in "connection creation" mode, but user can only start a new connection. */ void resetSelectedConnection(); #endif //! @return state ofthe Form, i.e. the current operation like inserting a widget or selecting. State state() const; //! selection flags used in methods like selectWidget() enum WidgetSelectionFlag { AddToPreviousSelection = 0, //!< add to the previous selection, for clarity, //!< do not use with ReplacePreviousSelection ReplacePreviousSelection = 1, //!< replace the actually selected widget(s) MoreWillBeSelected = 0, //!< indicates that more selections will be added //!< do not use with LastSelection //!< so the property editor can be updated (used without ReplacePreviousSelection) LastSelection = 2, //!< indicates that this selection is the last one //!< so the property editor can be updated (used without ReplacePreviousSelection) Raise = 0, //!< raise the widget(s) on selection //!< do not use with DontRaise DontRaise = 4, //!< do not raise the widget(s) on selection DefaultWidgetSelectionFlags = ReplacePreviousSelection | LastSelection | Raise }; Q_DECLARE_FLAGS(WidgetSelectionFlags, WidgetSelectionFlag) /*! \return The name of the class being inserted, corresponding to the menu item or the toolbar button clicked. */ QByteArray selectedClass() const; /*! @return widgets list for names @a names. Form widget, if present is omitted. */ QList widgetsForNames(const QList& names) const; //! @return action from related action collection QAction* action(const QString& name); void createPropertyCommandsInDesignMode(QWidget* widget, const QHash &propValues, Command *parentCommand, bool addToActiveForm = true); //! @return class name of currently edited widget's QByteArray editedWidgetClass() const; //! @return true if we're within redo(). Useful to check if command is being executed //! in response of a redo or it is caused by some other event. bool isRedoing() const; public Q_SLOTS: /*! Called when the user presses a widget item of the toolbox. The form enters into "widget inserting" state. Prepares all form's widgets for creation of a new widget (i.e. temporarily changes their cursor). */ void enterWidgetInsertingState(const QByteArray &classname); //! Called when the user presses 'Pointer' icon. Switches to Default mode. void enterWidgetSelectingState(); /*! Aborts the current widget inserting operation (i.e. unsets the cursor ...). */ void abortWidgetInserting(); #ifdef KFD_SIGSLOTS //! Enters the Connection creation state. void enterConnectingState(); //! Leave the Connection creation mode. void abortCreatingConnection(); #endif /*! Called when the name of a widget was changed in the Property Editor. Renames the ObjectTreeItem associated to this widget. */ void changeName(const QByteArray &oldname, const QByteArray &newname); /*! Sets @a selected to be the selected widget of this Form. The form widget is always selected alone. */ void selectWidget(QWidget *selected, WidgetSelectionFlags flags = DefaultWidgetSelectionFlags); /*! Sets all widgets @a widgets to be the selected for this Form. Form widget, if present is omitted. */ void selectWidgets(const QList& widgets, WidgetSelectionFlags flags); /*! Sets all widgets with @a names to be the selected for this Form. Form widget, if present is omitted. */ void selectWidgets(const QList& names, WidgetSelectionFlags flags); /*! Removes selection for widget \a w. The widget is removed from the Container's list and its resize handle is removed as well. */ void deselectWidget(QWidget *w); /*! Sets the form widget selected. Deselects any previously selected widgets. */ void selectFormWidget(); /*! Clears the current selection. */ void clearSelection(); /*! Sets the point where the subsequently pasted widget should be moved to. */ void setInsertionPoint(const QPoint &p); void undo(); void redo(); /*! Changes undoing state of the list. Used by Undo command to prevent recursion. */ void setUndoing(bool isUndoing); bool isUndoing() const; /*! @return number of commands on the undo stack. */ int commandsCount() const; /*! @return command with index @a index on the undo stack. */ const KUndo2Command* command(int index) const; bool isTopLevelWidget(QWidget *w) const; /*! Deletes the selected widget in active Form and all of its children. */ void deleteWidget(); /*! Copies the slected widget and all its children of the active Form using an XML representation. */ void copyWidget(); /*! Cuts (ie Copies and deletes) the selected widget and all its children of the active Form using an XML representation. */ void cutWidget(); /*! Pastes the XML representation of the copied or cut widget. The widget is pasted when the user clicks the Form to indicate the new position of the widget, or at the position of the contextual menu if there is one. */ void pasteWidget(); /*! Selects all toplevel widgets in trhe current form. */ void selectAll(); /*! Clears the contents of the selected widget(s) (eg for a line edit or a listview). */ void clearWidgetContent(); /*! Displays a dialog where the user can modify the tab order of the active Form, by drag-n-drop or using up/down buttons. */ void editTabOrder(); /*! Adjusts the size of the selected widget, ie resize it to its size hint. */ void adjustWidgetSize(); - /*! Creates a dialog to edit the \ref activeForm() PixmapCollection. */ + /*! Creates a dialog to edit the activeForm() PixmapCollection. */ void editFormPixmapCollection(); - /*! Creates a dialog to edit the Connection of \ref activeForm(). */ + /*! Creates a dialog to edit the Connection of activeForm(). */ void editConnections(); void alignWidgetsToLeft(); void alignWidgetsToRight(); void alignWidgetsToTop(); void alignWidgetsToBottom(); void alignWidgetsToGrid(); void adjustSizeToGrid(); //! Resize all selected widgets to the width of the narrowest widget. void adjustWidthToSmall(); //! Resize all selected widgets to the width of the widest widget. void adjustWidthToBig(); //! Resize all selected widgets to the height of the shortest widget. void adjustHeightToSmall(); //! Resize all selected widgets to the height of the tallest widget. void adjustHeightToBig(); void bringWidgetToFront(); void sendWidgetToBack(); /*! Executes font dialog and changes it for currently selected widget(s). */ void changeFont(); //! Sets slotPropertyChangedEnabled() enabled or disabled. void setSlotPropertyChangedEnabled(bool set); /*! @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. */ void resetInlineEditor(); /*! 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); protected Q_SLOTS: /*! This slot is called when the toplevel widget of this Form is deleted (ie the window closed) so that the Form gets deleted at the same time. */ void formDeleted(); void emitUndoEnabled(); void emitRedoEnabled(); /*! This slot is called when form is restored, ie when the user has undone all actions. The form modified flag is updated, and \ref modified() is called. */ void slotFormRestored(); /*! This function is called every time a property is modifed. It also takes care of saving set and enum properties. */ void slotPropertyChanged(KPropertySet& set, KProperty& property); /*! This slot is called when a property is reset using the "reload" button in PropertyEditor. */ void slotPropertyReset(KPropertySet& set, KProperty& property); /*! Default implementation changes "text" property. You have to reimplement this function for editing inside the Form to work if your widget's property you want to change isn't named "text". This slot is called when the line edit text changes, and you have to make it really change the good property of the widget using changeProperty() (text, or title, etc.). */ void changeInlineTextInternal(const QString& text); void slotInlineTextChanged(); /*! This slot is called when the editor is destroyed.*/ void inlineEditorDeleted(); void widgetDestroyed(); //! Called as delayed slot when invalid name is entered. //! @see checkNameValidity() void checkNameValidityForSelection(); Q_SIGNALS: /*! This signal is emitted by selectWidget() when user selects a new widget, to update both the Property Editor and the Object Tree View. \a w is the newly selected widget. */ void selectionChanged(QWidget *w, KFormDesigner::Form::WidgetSelectionFlags flags); /*! This signal is emitted when a new widget is created, to update ObjectTreeView. \a it is the ObjectTreeItem representing this new widget. */ void childAdded(KFormDesigner::ObjectTreeItem *it); /*! This signal is emitted when a widget is deleted, to update ObjectTreeView. \a it is the ObjectTreeItem representing this deleted widget. */ void childRemoved(KFormDesigner::ObjectTreeItem *it); //! This signal emitted when Form is about to be destroyed void destroying(); /*! This signal is emitted when the property set has been switched. */ void propertySetSwitched(); /*! This signal is emitted when any change is made to the 'modified' flag of the form. */ void modified(bool m); /*! Signal emitted when a normal widget is selected inside of the form (not the form's widget). If \a multiple is true, then more than one widget is selected. Use this to update actions state. */ void widgetSelected(bool multiple); /*! Signal emitted when the form widget is selected inside of the form. Use this to update actions state. */ void formWidgetSelected(); /*! Signal emitted when no form (or a preview form) is selected. Use this to update actions state. */ void noFormSelected(); #ifdef KFD_SIGSLOTS /*! Signal emitted when the Connection creation by drag-and-drop ends. \a connection is the created Connection. You should copy it, because it is deleted just after the signal is emitted. */ void connectionCreated(KFormDesigner::Form *form, KFormDesigner::Connection &connection); /*! Signal emitted when the Connection creation by drag-and-drop is aborted by user. */ void connectionAborted(KFormDesigner::Form *form); #endif /*! Emitted when the name of the widget is modified. @a oldname is the name of the widget before the change, @a newname is the name after renaming. */ void widgetNameChanged(const QByteArray &oldname, const QByteArray &newname); protected: void emitSelectionChanged(QWidget *w, WidgetSelectionFlags flags); void updatePropertiesForSelection(QWidget *w, WidgetSelectionFlags flags); #ifdef KFD_SIGSLOTS //! Sets connection buffer to @a b, which will be owned by the form. //! The previous buffer will be deleted, if there is any. void setConnectionBuffer(ConnectionBuffer *b); #endif void setFormWidget(FormWidget* w); void emitFormWidgetSelected(); void emitWidgetSelected(bool multiple); //! @internal void emitNoFormSelected(); void enableFormActions(); void disableWidgetActions(); enum CheckValidityMode { CheckValidityOnly, CheckValidityShowMessages }; /*! Checks if the name entered by user is valid, ie that it is a valid identifier, and that there is no name conflict. */ bool checkNameValidity(const QString &name, CheckValidityMode mode) const; void addWidget(QWidget *w); /*! Clears the current property set and fills it with properties related to the widget @a w. Also updates the newly created properties with previously set values. */ void createPropertiesForWidget(QWidget *w); /*! Changes \a property old value and changed state, using the value stored in \a tree. Optional \a meta can be specified if you need to handle enum values. */ void updatePropertyValue(ObjectTreeItem *tree, const char *property, const QMetaProperty &meta = QMetaProperty()); /*! Function called by all other alignWidgets*() function. */ void alignWidgets(WidgetAlignment alignment); /*! This function is used to filter the properties to be shown (ie not show "caption" if the widget isn't toplevel). \return true if the property should be shown. False otherwise.*/ bool isPropertyVisible(const QByteArray &property, bool isTopLevel, const QByteArray &classname = QByteArray()) const; // Following methods are used to create special types of properties, different // from Q_PROPERTY /*! Creates the properties related to alignment (ie hAlign, vAlign) for the QWidget \a widget. \a subwidget is the same as \a widget if the widget itself handles the property and it's a child widget if the child handles the property. For example, the second case is true for KexiDBAutoField. \a meta is the QMetaProperty for "alignment" property" of subwidget. */ void createAlignProperty(const QMetaProperty &meta, QWidget *widget, QWidget *subwidget); /*! Saves the properties related to alignment (ie hAlign, vAlign) and modifies the "alignment" property of the widget.*/ void saveAlignProperty(const QString &property); KActionCollection *actionCollection() const; //! @todo rm when the 2 libs are merged KFormDesigner::ActionGroup* widgetActionGroup() const; /*! Called when a property has been changed. @a w is the widget concerned, @a property is the name of the modified property, and @a value is the new value of this property. */ void handleWidgetPropertyChanged(QWidget *w, const QByteArray &name, const QVariant &value); /*! This function creates a QLineEdit to input some text and edit a widget's contents. */ void createInlineEditor(const KFormDesigner::WidgetFactory::InlineEditorCreationArguments& args); QString inlineEditorText() const; void setInlineEditorText(const QString& text); /*! This function destroys the editor when it loses focus or Enter is pressed. */ virtual bool eventFilter(QObject *obj, QEvent *ev); private: void init(Mode mode, KActionCollection &col, KFormDesigner::ActionGroup &group); void selectWidgetInternal(QWidget *w, WidgetSelectionFlags flags); FormPrivate * const d; friend class FormWidget; friend class WidgetLibrary; #ifdef KFD_SIGSLOTS friend class ConnectionDialog; #endif }; Q_DECLARE_OPERATORS_FOR_FLAGS(Form::Features) Q_DECLARE_OPERATORS_FOR_FLAGS(Form::WidgetSelectionFlags) } #endif diff --git a/src/formeditor/formIO.h b/src/formeditor/formIO.h index d3882966b..87e6efdbd 100644 --- a/src/formeditor/formIO.h +++ b/src/formeditor/formIO.h @@ -1,223 +1,225 @@ /* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2005-2007 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 FORMIO_H #define FORMIO_H #include "kformdesigner_export.h" #include #include #include #include class QString; class QDomElement; class QDomNode; class QDomDocument; class QVariant; class QLabel; //! A blank widget displayed when class is not supported class KFORMDESIGNER_EXPORT CustomWidget : public QWidget { Q_OBJECT public: CustomWidget(const QByteArray &className, QWidget *parent); virtual ~CustomWidget(); virtual void paintEvent(QPaintEvent *ev); private: QByteArray m_className; }; namespace KFormDesigner { class Form; class ObjectTreeItem; class Container; //! KFormDesigner API major version number. Increased on every breaking of backward compatibility. //! Use KFormDesigner::version() to get real version number of the library. #define KFORMDESIGNER_VERSION_MAJOR KEXI_STABLE_VERSION_MAJOR //! KFormDesigner API minor version number. Increased on every compatible change. //! Use KFormDesigner::version() to get real version number of the library. #define KFORMDESIGNER_VERSION_MINOR KEXI_STABLE_VERSION_MINOR //! \return KFormDesigner API version number for this library: "major.minor" KFORMDESIGNER_EXPORT QString version(); /** This class act as a namespace for all .ui files related functions, ie saving/loading .ui files. You don't need to create a FormIO object, as all methods are static.\n This class is able to read and write Forms to .ui files, and to save each type of properties, including set and enum properties, and pixmaps(pixmap-related code was taken from Qt Designer). **/ //! A class to save/load forms from .ui files class KFORMDESIGNER_EXPORT FormIO : public QObject { Q_OBJECT public: FormIO(); ~FormIO(); /*! Save the Form in the \a domDoc QDomDocument. Called by saveForm(). \return true if saving succeeded. \sa saveForm() */ static bool saveFormToDom(Form *form, QDomDocument &domDoc); /*! Save the Form \a form to the file \a filename. If \a filename is null or not given, a Save File dialog will be shown to choose dest file. \return true if saving succeeded. \todo Add errors code and error dialog */ static bool saveFormToFile(Form *form, const QString &filename = QString()); /*! Saves the Form to the \a dest string. \a indent can be specified to apply indentation. \return true if saving succeeded. \sa saveForm() */ static bool saveFormToString(Form *form, QString &dest, int indent = 0); /*! Saves the \a form inside the \a dest QByteArray. \return true if saving succeeded. \sa saveFormToDom(), saveForm() */ static bool saveFormToByteArray(Form *form, QByteArray &dest); /*! Loads a form from the \a domDoc QDomDocument. Called by loadForm() and loadFormData(). \return true if loading succeeded. */ static bool loadFormFromDom(Form *form, QWidget *container, const QDomDocument &domDoc); /*! Loads a form from the \a src QByteArray. \sa loadFormFromDom(), loadForm(). \return true if loading succeeded. */ static bool loadFormFromByteArray(Form *form, QWidget *container, QByteArray &src, bool preview = false); static bool loadFormFromString(Form *form, QWidget *container, const QString &src, bool preview = false); /*! Loads the .ui file \a filename in the Form \a form. If \a filename is null or not given, a Open File dialog will be shown to select the file to open. createToplevelWidget() is used to load the Form's toplevel widget. \return true if loading succeeded. \todo Add errors code and error dialog */ static bool loadFormFromFile(Form *form, QWidget *container, const QString &filename = QString()); /*! Saves the widget associated to the ObjectTreeItem \a item into DOM document \a domDoc, with \a parent as parent node. It calls readPropertyValue() for each object property, readAttribute() for each attribute and itself to save child widgets. \return true if saving succeeded. This is used to copy/paste widgets. */ static void saveWidget(ObjectTreeItem *item, QDomElement &parent, QDomDocument &domDoc, bool insideGridLayout = false); /*! Cleans the "UI" QDomElement after saving widget. It deletes the "includes" element not needed when pasting, and make sure all the "widget" elements are at the beginning. Call this after copying a widget, before pasting.*/ static void cleanClipboard(QDomElement &uiElement); /*! Loads the widget associated to the QDomElement \a el into the Container \a container, with \a parent as parent widget. If parent = 0, the Container::widget() is used as parent widget. This is used to copy/paste widgets. */ static void loadWidget(Container *container, const QDomElement &el, QWidget *parent, QHash *buddies); /*! Save an element in the \a domDoc as child of \a parentNode. The element will be saved like this : \code <$(tagName) name = "$(property)">< value_as_XML ><$(tagName)/> \endcode */ static void savePropertyElement(QDomElement &parentNode, QDomDocument &domDoc, const QString &tagName, const QString &property, const QVariant &value); /*! Read an object property in the DOM doc. + \param form the Form of the property \param node the QDomNode of the property \param obj the widget whose property is being read \param name the name of the property being read */ static QVariant readPropertyValue(Form *form, QDomNode node, QObject *obj, const QString &name); /*! Write an object property in the DOM doc. \param item the widget item whose property is being saved - \param parentNode the DOM document to write to + \param parentNode the DOM element to write to + \param parent the parent QDomDocument \param name the name of the property being saved \param value the value of this property - Properties of subwidget are saved with subwidget="true" arribute added + Properties of subwidget are saved with subwidget="true" attribute added to 'property' XML element. */ static void savePropertyValue(ObjectTreeItem *item, QDomElement &parentNode, QDomDocument &parent, const char *name, const QVariant &value); protected: /*! Saves the QVariant \a value as text to be included in an xml file, with \a parentNode.*/ static void writeVariant(QDomDocument &parent, QDomElement &parentNode, const QVariant& value); /*! Creates a toplevel widget from the QDomElement \a element in the Form \a form, with \a parent as parent widget. It calls readPropertyValue() and loadWidget() to load child widgets. */ static void createToplevelWidget(Form *form, QWidget *container, QDomElement &element); /*! \return the name of the pixmap saved, to use to access it This function save the QPixmap \a pixmap into the DOM document \a domDoc. The pixmap is converted to XPM and compressed for compatibility with Qt Designer. Encoding code is taken from Designer. */ static QString saveImage(QDomDocument &domDoc, const QPixmap &pixmap); /*! \return the loaded pixmap This function loads the pixmap named \a name in the DOM document \a domDoc. Decoding code is taken from QT Designer. */ //! @todo handle result of loading static QPixmap loadImage(QDomDocument domDoc, const QString& name); /*! Reads the child nodes of a "widget" element. */ static void readChildNodes(ObjectTreeItem *tree, Container *container, const QDomElement &el, QWidget *w, QHash *buddies); /*! Adds an include file name to be saved in the "includehints" part of .ui file, which is needed by uic. */ static void addIncludeFileName(const QString &include, QDomDocument &domDoc); private: //! This hash stores buddies associations until the Form is completely loaded. static QHash *m_buddies; }; } #endif diff --git a/src/formeditor/widgetfactory.h b/src/formeditor/widgetfactory.h index 94c4de680..592cbbe1e 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 + stuff (see eg 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; /*! 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 diff --git a/src/kexiutils/KexiAnimatedLayout.h b/src/kexiutils/KexiAnimatedLayout.h index ad6f7d4ae..ab71fbb42 100644 --- a/src/kexiutils/KexiAnimatedLayout.h +++ b/src/kexiutils/KexiAnimatedLayout.h @@ -1,63 +1,63 @@ /* This file is part of the KDE project Copyright (C) 2011 Jarosław Staniek This program 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 program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXIANIMATEDLAYOUT_H #define KEXIANIMATEDLAYOUT_H #include #include "kexiutils_export.h" //! A tool for animated switching between widgets in a given stacked layout. /*! Animation is performed if the graphic effects level is set at least at "simple" level, i.e. when (KexiUtils::graphicEffectsLevel() & KexiUtils::SimpleAnimationEffects) is true. */ class KEXIUTILS_EXPORT KexiAnimatedLayout : public QStackedLayout { Q_OBJECT public: explicit KexiAnimatedLayout(QWidget* parent = 0); ~KexiAnimatedLayout(); public Q_SLOTS: //! Sets the current widget to be the specified widget. /*! Animation is performed while switching the widgets (assuming animations are enabled (see the explanation - for @ref KexiAnimatedStackedLayout). + for KexiAnimatedStackedLayout). The new current widget must already be contained in this stacked layout. Because of the animation, changing current widget is asynchronous, i.e. after this methods returns, current widget is not changed. Connect to signal QStackedLayout::currentChanged(int index) to be notified about actual change of the current widget when animation finishes. @note this method is not virtual, so when calling it, make sure the pointer is KexiAnimatedStackedLayout, not parent class QStackedLayout. @see setCurrentIndex() currentWidget() */ void setCurrentWidget(QWidget* widget); //! Sets the current widget to be the specified index. /*! Animation is performed as for setCurrentWidget(). */ void setCurrentIndex(int index); private: class Private; Private* const d; }; #endif diff --git a/src/plugins/importexport/csv/kexicsvexport.h b/src/plugins/importexport/csv/kexicsvexport.h index a5e999ca3..c5b40eb30 100644 --- a/src/plugins/importexport/csv/kexicsvexport.h +++ b/src/plugins/importexport/csv/kexicsvexport.h @@ -1,64 +1,66 @@ /* This file is part of the KDE project Copyright (C) 2005,2006 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 KEXI_CSVEXPORT_H #define KEXI_CSVEXPORT_H #include class QTextStream; class KDbConnection; class KDbTableOrQuerySchema; namespace KexiCSVExport { //! Exporting mode: a file or clipboard enum Mode { Clipboard, File }; //! Options used in KexiCSVExportWizard constructor. class Options { public: Options(); //! Assigns \a args. \return false on failure. bool assign(QMap *args); Mode mode; int itemId; //!< Table or query ID QString fileName; QString delimiter; QString forceDelimiter; //!< Used for "clipboard" mode QString textQuote; bool addColumnNames; bool useTempQuery; }; /*! Exports data. \return false on failure. + @param conn connection + @param tableOrQuery table OR query schema @param options options for the export - @param recordCount record count of the input data or -1 if the record cound has not yet been computed + @param recordCount record count of the input data or -1 if the record count has not yet been computed @param predefinedTextStream text stream that should be used instead of writing to a file */ bool exportData(KDbConnection* conn, KDbTableOrQuerySchema *tableOrQuery, const Options& options, int recordCount = -1, QTextStream *predefinedTextStream = 0); } #endif diff --git a/src/plugins/reports/kexireportview.cpp b/src/plugins/reports/kexireportview.cpp index 47cb834c1..b57057b5d 100644 --- a/src/plugins/reports/kexireportview.cpp +++ b/src/plugins/reports/kexireportview.cpp @@ -1,480 +1,480 @@ /* * Kexi Report Plugin * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * Copyright (C) 2014-2018 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kexireportview.h" #include #include "KexiDBReportDataSource.h" #ifndef KEXI_MOBILE #include #endif #include #include #include #include -//! @todo KEXI3 #include "../scripting/kexiscripting/kexiscriptadaptor.h" +//! @todo KEXI3 include "../scripting/kexiscripting/kexiscriptadaptor.h" #include #include #include #include #include "krscriptfunctions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include KexiReportView::KexiReportView(QWidget *parent) : KexiView(parent), m_preRenderer(0), m_functions(0) //! @todo KEXI3, m_kexi(0) { setObjectName("KexiReportDesigner_DataView"); m_reportView = new KReportView(this); setViewWidget(m_reportView); KexiStyle::setupFrame(m_reportView->scrollArea()); #ifndef KEXI_MOBILE m_pageSelector = new KexiRecordNavigator(*m_reportView->scrollArea(), m_reportView); m_pageSelector->setInsertingButtonVisible(false); m_pageSelector->setInsertingEnabled(false); m_pageSelector->setLabelText(xi18nc("Page selector label", "Page:")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonFirst, xi18n("Go to first page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonFirst, xi18n("Goes to first page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonPrevious, xi18n("Go to previous page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonPrevious, xi18n("Goes to previous page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonNext, xi18n("Go to next page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonNext, xi18n("Goes to next page")); m_pageSelector->setButtonToolTipText(KexiRecordNavigator::ButtonLast, xi18n("Go to last page")); m_pageSelector->setButtonWhatsThisText(KexiRecordNavigator::ButtonLast, xi18n("Goes to last page")); m_pageSelector->setNumberFieldToolTips(xi18n("Current page number"), xi18n("Number of pages")); m_pageSelector->setRecordHandler(this); #endif // -- setup local actions QList viewActions; QAction* a; #ifndef KEXI_MOBILE viewActions << (a = new QAction(koIcon("document-print"), xi18n("Print"), this)); a->setObjectName("print_report"); a->setToolTip(xi18n("Print report")); a->setWhatsThis(xi18n("Prints the current report.")); connect(a, SIGNAL(triggered()), this, SLOT(slotPrintReport())); KActionMenu *exportMenu = new KActionMenu(koIcon("document-export"), xi18nc("@title:menu","E&xport As"), this); exportMenu->setObjectName("report_export_as"); exportMenu->setDelayed(false); #endif #ifdef KEXI_SHOW_UNFINISHED #ifdef KEXI_MOBILE viewActions << (a = new QAction(xi18n("Export:"), this)); a->setEnabled(false); //!TODO this is a bit of a dirty way to add what looks like a label to the toolbar! // " ", not "", is said to be needed in maemo, the icon didn't display properly without it viewActions << (a = new QAction(koIcon("application-vnd.oasis.opendocument.text"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-vnd.oasis.opendocument.text"), xi18nc("open dialog to export as text document", "Text Document..."), this)); #endif a->setObjectName("export_as_text_document"); a->setToolTip(xi18n("Export the report as a text document (in OpenDocument Text format)")); a->setWhatsThis(xi18n("Exports the report as a text document (in OpenDocument Text format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsTextDocument())); #endif #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("application-pdf"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-pdf"), xi18nc("Portable Document Format...", "PDF..."), this)); #endif a->setObjectName("export_as_pdf"); a->setToolTip(xi18n("Export as PDF")); a->setWhatsThis(xi18n("Exports the current report as PDF.")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsPdf())); #ifdef KEXI_SHOW_UNFINISHED #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), xi18nc("open dialog to export as spreadsheet", "Spreadsheet..."), this)); #endif a->setObjectName("export_as_spreadsheet"); a->setToolTip(xi18n("Export the report as a spreadsheet (in OpenDocument Spreadsheet format)")); a->setWhatsThis(xi18n("Exports the report as a spreadsheet (in OpenDocument Spreadsheet format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsSpreadsheet())); #endif #ifdef KEXI_MOBILE viewActions << (a = new QAction(koIcon("text-html"), QLatin1String(" "), this)); #else exportMenu->addAction(a = new QAction(koIcon("text-html"), xi18nc("open dialog to export as web page", "Web Page..."), this)); #endif a->setObjectName("export_as_web_page"); a->setToolTip(xi18n("Export the report as a web page (in HTML format)")); a->setWhatsThis(xi18n("Exports the report as a web page (in HTML format).")); a->setEnabled(true); connect(a, SIGNAL(triggered()), this, SLOT(slotExportAsWebPage())); setViewActions(viewActions); #ifndef KEXI_MOBILE // setup main menu actions QList mainMenuActions; mainMenuActions << exportMenu; setMainMenuActions(mainMenuActions); #endif } KexiReportView::~KexiReportView() { delete m_preRenderer; } void KexiReportView::slotPrintReport() { QScopedPointer renderer(m_factory.createInstance("print")); if (!renderer) { return; } QPrinter printer(QPrinter::HighResolution); QPrintDialog dialog(&printer, this); if (dialog.exec() == QDialog::Accepted) { KReportRendererContext cxt; QPainter painter; cxt.setPrinter(&printer); cxt.setPainter(&painter); if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, xi18n("Printing the report failed."), xi18n("Print Failed")); } } } void KexiReportView::slotExportAsPdf() { QScopedPointer renderer(m_factory.createInstance("print")); if (renderer) { KReportRendererContext cxt; cxt.setUrl(getExportUrl(QLatin1String("application/pdf"), xi18n("Export Report as PDF"), "kfiledialog:///LastVisitedPDFExportPath/", "pdf")); if (!cxt.url().isValid()) { return; } QPrinter printer; QPainter painter; printer.setOutputFileName(cxt.url().path()); printer.setOutputFormat(QPrinter::PdfFormat); printer.setColorMode(QPrinter::Color); painter.begin(&printer); cxt.setPrinter(&printer); cxt.setPainter(&painter); if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, xi18n("Exporting the report as PDF to %1 failed.", cxt.url().toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.url()); } } } QUrl KexiReportView::getExportUrl(const QString &mimetype, const QString &caption, const QString &lastExportPath, const QString &extension) { QString defaultSavePath; QString recentDirClass; //TODO use utils defaultSavePath = KFileWidget::getStartUrl(QUrl(lastExportPath), recentDirClass).toLocalFile() + '/' + window()->partItem()->captionOrName() + '.' + extension; // loop until an url has been chosen or the file selection has been cancelled const QMimeDatabase db; const QString filterString = db.mimeTypeForName(mimetype).filterString(); return QFileDialog::getSaveFileUrl(this, caption, QUrl(defaultSavePath), filterString); } void KexiReportView::openExportedDocument(const QUrl &destination) { const int answer = KMessageBox::questionYesNo( this, xi18n("Do you want to open exported document?"), QString(), KStandardGuiItem::open(), KStandardGuiItem::close()); if (answer == KMessageBox::Yes) { (void)new KRun(destination, this->topLevelWidget()); } } #ifdef KEXI_SHOW_UNFINISHED void KexiReportView::slotExportAsSpreadsheet() { QScopedPointer renderer(m_factory.createInstance("ods")); if (renderer) { KReportRendererContext cxt; cxt.setUrl(getExportUrl(QLatin1String("application/vnd.oasis.opendocument.spreadsheet"), xi18n("Export Report as Spreadsheet"), "kfiledialog:///LastVisitedODSExportPath/", "ods")); if (!cxt.url().isValid()) { return; } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, xi18n("Failed to export the report as spreadsheet to %1.", cxt.url().toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.url()); } } } void KexiReportView::slotExportAsTextDocument() { QScopedPointer renderer(m_factory.createInstance("odt")); //! @todo Show error or don't show the commands to the user if the plugin isn't available. //! The same for other createInstance() calls. if (renderer) { KReportRendererContext cxt; cxt.setUrl(getExportUrl(QLatin1String("application/vnd.oasis.opendocument.text"), xi18n("Export Report as Text Document"), "kfiledialog:///LastVisitedODTExportPath/", "odt")); if (!cxt.url().isValid()) { return; } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, xi18n("Exporting the report as text document to %1 failed.", cxt.url().toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.url()); } } } #endif void KexiReportView::slotExportAsWebPage() { const QString dialogTitle = xi18n("Export Report as Web Page"); KReportRendererContext cxt; cxt.setUrl(getExportUrl(QLatin1String("text/html"), dialogTitle, "kfiledialog:///LastVisitedHTMLExportPath/", "html")); if (!cxt.url().isValid()) { return; } const int answer = KMessageBox::questionYesNo( this, xi18nc("@info", "Would you like to use Cascading Style Sheets (CSS) in the exported " "web page or use HTML tables?" "CSS give output closer to the original."), dialogTitle, KGuiItem(xi18nc("@action:button", "Use CSS")), KGuiItem(xi18nc("@action:button", "Use Table"))); QScopedPointer renderer( m_factory.createInstance(answer == KMessageBox::Yes ? "htmlcss" : "htmltable")); if (!renderer) { return; } if (!renderer->render(cxt, m_preRenderer->document())) { KMessageBox::error(this, xi18n("Exporting the report as web page to %1 failed.", cxt.url().toDisplayString()), xi18n("Export Failed")); } else { openExportedDocument(cxt.url()); } } tristate KexiReportView::beforeSwitchTo(Kexi::ViewMode mode, bool *dontStore) { Q_UNUSED(mode); Q_UNUSED(dontStore); return true; } tristate KexiReportView::afterSwitchFrom(Kexi::ViewMode mode) { Q_UNUSED(mode); if (tempData()->reportSchemaChangedInPreviousView) { tempData()->reportSchemaChangedInPreviousView = false; delete m_preRenderer; //qDebug() << tempData()->reportDefinition.tagName(); m_preRenderer = new KReportPreRenderer(tempData()->reportDefinition); if (m_preRenderer->isValid()) { KexiDBReportDataSource *reportData = nullptr; if (!tempData()->connectionDefinition.isNull()) { reportData = createDataSource(tempData()->connectionDefinition); } m_preRenderer->setDataSource(reportData); m_preRenderer->setScriptSource(qobject_cast(part())); m_preRenderer->setName(window()->partItem()->name()); //Add a kexi object to provide kexidb and extra functionality //! @todo KEXI3 if we want this if(!m_kexi) { // m_kexi = new KexiScriptAdaptor(); // } // m_preRenderer->registerScriptObject(m_kexi, "Kexi"); //If using a kexidb source, add a functions scripting object if (reportData && tempData()->connectionDefinition.attribute("type") == "internal") { m_functions = new KRScriptFunctions(reportData); m_preRenderer->registerScriptObject(m_functions, "field"); connect(m_preRenderer, SIGNAL(groupChanged(QMap)), m_functions, SLOT(setGroupData(QMap))); } connect(m_preRenderer, SIGNAL(finishedAllASyncItems()), this, SLOT(finishedAllASyncItems())); if (!m_preRenderer->generateDocument()) { qWarning() << "Could not generate report document"; return false; } m_reportView->setDocument(m_preRenderer->document()); #ifndef KEXI_MOBILE m_pageSelector->setRecordCount(m_reportView->pageCount()); m_pageSelector->setCurrentRecordNumber(1); #endif } else { KMessageBox::error(this, xi18n("Report schema appears to be invalid or corrupt"), xi18n("Opening failed")); } } return true; } KexiDBReportDataSource* KexiReportView::createDataSource(const QDomElement &e) { if (e.attribute("type") == "internal" && !e.attribute("source").isEmpty()) { return new KexiDBReportDataSource(e.attribute("source"), e.attribute("class"), tempData()); } return nullptr; } KexiReportPartTempData* KexiReportView::tempData() const { return static_cast(window()->data()); } void KexiReportView::addNewRecordRequested() { } void KexiReportView::moveToFirstRecordRequested() { m_reportView->moveToFirstPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToLastRecordRequested() { m_reportView->moveToLastPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToNextRecordRequested() { m_reportView->moveToNextPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToPreviousRecordRequested() { m_reportView->moveToPreviousPage(); #ifndef KEXI_MOBILE m_pageSelector->setCurrentRecordNumber(m_reportView->currentPage()); #endif } void KexiReportView::moveToRecordRequested(int r) { #ifdef KEXI_MOBILE m_reportView->moveToPage(r + 1); #else // set in the navigator widget first, this will fix up the value it it's too small or large m_pageSelector->setCurrentRecordNumber(r + 1); m_reportView->moveToPage(m_pageSelector->currentRecordNumber()); #endif } int KexiReportView::currentRecord() const { return m_reportView->currentPage(); } int KexiReportView::recordCount() const { return m_reportView->pageCount(); } void KexiReportView::finishedAllASyncItems() { m_reportView->refreshCurrentPage(); } diff --git a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h index 9530d428a..dfd4c1c9f 100644 --- a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h +++ b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.h @@ -1,125 +1,126 @@ /* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2004-2012 Jarosław Staniek Copyright (C) 2005 Cedric Pasteur Copyright (C) 2005 Sebastian Sauer This program 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 program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXISCRIPTDESIGNVIEW_H #define KEXISCRIPTDESIGNVIEW_H #include #include #include #include // Forward declarations. class KexiScriptEditor; class KexiScriptDesignViewPrivate; /** * The KexiScriptDesignView class provides the KexiView to * manage script modules in the design-view. The design-view * is used to be able to view and edit the scripting code via * a \a KexiScriptEditor instance. */ class KexiScriptDesignView : public KexiView { Q_OBJECT public: /** * Constructor. */ KexiScriptDesignView(QWidget *parent); /** * Destructor. */ virtual ~KexiScriptDesignView(); /** * \return the program string this \a KexiScriptDesignView * is responsible for. */ // QString scriptAction() const; /** * \return a property set for this view. */ virtual KPropertySet* propertySet(); /** * Try to call \a storeData with new data we like to store. On * success the matching \a KDbObject is returned. * * \param object The source \a KDbObject instance. + * \param options options for the export * \param cancel Cancel on failure and don't try to clean * possible temporary created data up. * \return The matching \a KDbObject instance or NULL * if storing failed. */ virtual KDbObject* storeNewData(const KDbObject& object, KexiView::StoreNewDataOptions options, bool *cancel); /** * Try to store the modified data in the already opened and * currently used \a KDbObject instance. */ virtual tristate storeData(bool dontAsk = false); private Q_SLOTS: /** * Deferred initialization. */ void initialize(const QString &program); void slotImport(); void slotExport(); /** * Handle changes in the property editor. */ void slotPropertyChanged(KPropertySet& set, KProperty& property); /** * Update the \a KProperty::Dict propertymap of the * interpreter-dependent options. */ void updateProperties(); /** * Execute the scripting code. */ void execute(); private: KexiScriptDesignViewPrivate* d; /** * Load the data from XML source and fill the internally * used \a Kross::Action instance. */ bool loadData(); }; #endif diff --git a/src/plugins/tables/kexitabledesignerview_p.h b/src/plugins/tables/kexitabledesignerview_p.h index 1261a5f3e..cc24161d7 100644 --- a/src/plugins/tables/kexitabledesignerview_p.h +++ b/src/plugins/tables/kexitabledesignerview_p.h @@ -1,159 +1,159 @@ /* This file is part of the KDE project Copyright (C) 2004-2012 Jarosław Staniek This program 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 program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXITABLEDESIGNERVIEW_P_H #define KEXITABLEDESIGNERVIEW_P_H #include "kexitabledesignerview.h" #include #include class KexiDataAwarePropertySet; namespace KexiTableDesignerCommands { class Command; } //! @internal indices for table columns #define COLUMN_ID_ICON 0 #define COLUMN_ID_CAPTION 1 #define COLUMN_ID_TYPE 2 #define COLUMN_ID_DESC 3 //! @internal class KexiTableDesignerViewPrivate { public: explicit KexiTableDesignerViewPrivate(KexiTableDesignerView* aDesignerView); ~KexiTableDesignerViewPrivate(); int generateUniqueId(); /*! @internal Sets property \a propertyName in property set \a set to \a newValue. If \a commandGroup is not 0, a new ChangeFieldPropertyCommand object is added there as well. While setting the new value, addHistoryCommand_in_slotPropertyChanged_enabled is set to false, so addHistoryCommand() wont be executed in slotPropertyChanged() as an answer to setting the property. If \a forceAddCommand is false (the default) and \a newValue does not differ from curent property value (set[propertyName].value()), ChangeFieldPropertyCommand command is not added to the \a commandGroup. Otherwise, command is always added. \a rememberOldValue argument is passed to Property::setValue() If \a slist and \a nlist if not NULL and not empty, these are passed to Property::setListData(). If \a slist and \a nlist if not NULL but empty, Property::setListData(0) is called. addHistoryCommand_in_slotPropertyChanged_enabled is then set back to the original state. */ void setPropertyValueIfNeeded(const KPropertySet& set, const QByteArray& propertyName, const QVariant& newValue, KexiTableDesignerCommands::Command* commandGroup, bool forceAddCommand = false, bool rememberOldValue = true, KPropertyListData *listData = nullptr); /*! Like above but allows to specify \a oldValue. */ void setPropertyValueIfNeeded( const KPropertySet& set, const QByteArray& propertyName, const QVariant& newValue, const QVariant& oldValue, KexiTableDesignerCommands::Command* commandGroup, bool forceAddCommand = false, bool rememberOldValue = true, KPropertyListData *listData = nullptr); /*! @internal Used in updatePropertiesVisibility(). Does nothing if visibility should not be changed, i.e. when prop->isVisible()==visible, otherwise sets changed to true and sets visibility of property \a prop to \a visible. */ void setVisibilityIfNeeded(const KPropertySet& set, KProperty* prop, bool visible, bool *changed, KexiTableDesignerCommands::Command *commandGroup); bool updatePropertiesVisibility(KDbField::Type fieldType, KPropertySet &set, KexiTableDesignerCommands::Command *commandGroup = 0); /*! \return message used to ask user for accepting saving the design. \a emptyTable is set to true if the table designed contains no rows. If \a skipWarning is true, no warning about data loss is appended (useful when only non-physical altering actions will be performed). */ KLocalizedString messageForSavingChanges(bool *emptyTable, bool skipWarning = false); /*! Updates icon in the first column, depending on property set \a set. For example, when "rowSource" and "rowSourceType" propertiesa are not empty, "combobox" icon appears. */ void updateIconForRecord(KDbRecordData *data, KPropertySet *set); KexiTableDesignerView* designerView; KexiTableScrollArea *view; //!< helper KDbTableViewData *data; KexiDataAwarePropertySet *sets; int row; //!< used to know if a new row is selected in slotCellSelected() KToggleAction *action_toggle_pkey; QAction *contextMenuTitle; int uniqueIdCounter; //! internal int maxTypeNameTextWidth; //! Set to true in beforeSwitchTo() to avoid asking again in storeData() bool dontAskOnStoreData; bool slotTogglePrimaryKeyCalled; bool primaryKeyExists; //! Used in slotPropertyChanged() to avoid infinite recursion bool slotPropertyChanged_primaryKey_enabled; //! Used in slotPropertyChanged() to avoid infinite recursion bool slotPropertyChanged_subType_enabled; //! used in slotPropertyChanged() to disable addHistoryCommand() bool addHistoryCommand_in_slotPropertyChanged_enabled; //! used in slotRecordUpdated() to disable addHistoryCommand() bool addHistoryCommand_in_slotRecordUpdated_enabled; //! used in slotAboutToDeleteRecord() to disable addHistoryCommand() bool addHistoryCommand_in_slotAboutToDeleteRecord_enabled; //! used in slotRecordInserted() to disable addHistoryCommand() bool addHistoryCommand_in_slotRecordInserted_enabled; //! used to disable slotBeforeCellChanged() bool slotBeforeCellChanged_enabled; //! @todo temp; remove this: //! Temporary flag, used for testing the Alter Table machinery. Affects storeData() //! Used in slotExecuteRealAlterTable() to switch on real alter table for a while. bool tempStoreDataUsingRealAlterTable; - /*! Set to a recent result of calling \ref tristate KexiTableDesignerView::storeData(bool dontAsk). - Then, it is used in \ref void KexiTableDesignerView::executeRealAlterTable() + /*! Set to a recent result of calling KexiTableDesignerView::storeData(bool dontAsk). + Then, it is used in KexiTableDesignerView::executeRealAlterTable() to know what return value should be. */ tristate recentResultOfStoreData; KActionCollection* historyActionCollection; KUndo2Stack* history; //! A set used in KexiTableDesignerView::buildField() to quickly identify //! properties internal to the designer QSet internalPropertyNames; }; #endif diff --git a/src/widget/dataviewcommon/kexidataawareobjectiface.h b/src/widget/dataviewcommon/kexidataawareobjectiface.h index cdb356c99..dff9f11a0 100644 --- a/src/widget/dataviewcommon/kexidataawareobjectiface.h +++ b/src/widget/dataviewcommon/kexidataawareobjectiface.h @@ -1,1040 +1,1040 @@ /* This file is part of the KDE project Copyright (C) 2005-2015 Jarosław Staniek Based on KexiTableView code. Copyright (C) 2002 Till Busch Copyright (C) 2003 Lucijan Busch Copyright (C) 2003 Daniel Molkentin Copyright (C) 2003 Joseph Wenninger This program 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 program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KEXIDATAAWAREOBJECTIFACE_H #define KEXIDATAAWAREOBJECTIFACE_H #include "kexidataviewcommon_export.h" #include #include #include #include #include #include #include #include class QHeaderView; class QScrollBar; class QMenu; class KDbRecordData; class KDbTableViewData; class KexiRecordNavigatorIface; //! default column width in pixels #define KEXI_DEFAULT_DATA_COLUMN_WIDTH 120 //! \brief The KexiDataAwareObjectInterface is an interface for record-based data object. /** This interface is implemented by KexiTableScrollArea and KexiFormView and used by KexiDataAwareView. If yu're implementing this interface, add KEXI_DATAAWAREOBJECTINTERFACE convenience macro just after Q_OBJECT. You should add following code to your destructor so data is deleted: \code if (m_owner) delete m_data; m_data = 0; \endcode This is not performed in KexiDataAwareObjectInterface because you may need to access m_data in your desctructor. */ class KEXIDATAVIEWCOMMON_EXPORT KexiDataAwareObjectInterface { public: KexiDataAwareObjectInterface(); virtual ~KexiDataAwareObjectInterface(); /*! Sets data for this object. if \a owner is true, the object will own \a data and therefore will be destroyed when needed, else: \a data is (possibly) shared and not owned by the widget. If widget already has _different_ data object assigned (and owns this data), old data is destroyed before new assignment. */ void setData(KDbTableViewData *data, bool owner = true); /*! \return data structure displayed for this object */ inline KDbTableViewData *data() const { return m_data; } /*! \return currently selected column number or -1. */ inline int currentColumn() const { return m_curColumn; } /*! \return number of the currently selected record number or -1. */ inline int currentRecord() const { return m_curRecord; } /*! \return last record visible on the screen (counting from 0). The returned value is guaranteed to be smaller or equal to currentRecord() or -1 if there are no records. */ virtual int lastVisibleRecord() const = 0; /*! \return currently selected record data or null. */ KDbRecordData *selectedRecord() const { return m_currentRecord; } /*! \return number of records in this view. */ int recordCount() const; /*! \return number of visible columns in this view. By default returns dataColumns(), what is proper table view. In case of form view, there can be a number of duplicated columns defined (data-aware widgets, see KexiFormScrollView::columnCount()), so columnCount() can return greater number than dataColumns(). */ virtual int columnCount() const; /*! Helper function. \return number of columns of data. */ int dataColumns() const; /*! \return true if data represented by this object is not editable (it can be editable with other ways although, outside of this object). */ virtual bool isReadOnly() const; /*! Sets readOnly flag for this object. Unless the flag is set, the widget inherits readOnly flag from it's data structure assigned with setData(). The default value if false. This method is useful when you need to switch on the flag indepentently from the data structure. Note: it is not allowed to force readOnly off when internal data is readOnly - in that case the method does nothing. You can check internal data flag calling data()->isReadOnly(). If \a set is true, insertingEnabled flag will be cleared automatically. \sa isInsertingEnabled() */ void setReadOnly(bool set); /*! \return true if sorting is enabled. */ inline bool isSortingEnabled() const { return m_isSortingEnabled; } /*! Sets sorting order on column @a column to @a order. This method do not work if sorting is disabled using setSortingEnabled(false). @a column may be -1, what means "no sorting". */ virtual void setSorting(int column, KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending); /*! Enables or disables sorting for this object This method is different that setSorting() because it prevents both user and programmer from sorting by clicking a column's header or calling setSorting(). By default sorting is enabled. */ virtual void setSortingEnabled(bool set); /*! \return sorted column number or -1 if no column is sorted within data or there is no data assigned at all. This does not mean that any sorting has been performed within GUI of this object, because the data could be changed in the meantime outside of this GUI object. */ int dataSortColumn() const; /*! \return sort order for data. This information does not mean that any sorting has been performed within GUI of this object, because the data could be changed in the meantime outside of this GUI object. dataSortColumn() should be checked first to see if sorting is enabled (and if there's data). */ KDbOrderByColumn::SortOrder dataSortOrder() const; /*! Sorts all records by column selected with setSorting(). If there is currently record edited, it is accepted. If acception failed, sort() will return false. \return true on success. */ virtual bool sort(); /*! Sorts currently selected column in ascending order. This slot is used typically for "data_sort_az" action. */ void sortAscending(); /*! Sorts currently selected column in descending order. This slot is used typically for "data_sort_za" action. */ void sortDescending(); /*! \return true if data inserting is enabled (the default). */ virtual bool isInsertingEnabled() const; /*! Sets insertingEnabled flag. If true, empty record is available at the end of this widget for new entering new data. Unless the flag is set, the widget inherits insertingEnabled flag from it's data structure assigned with setData(). The default value if false. Note: it is not allowed to force insertingEnabled on when internal data has insertingEnabled set off - in that case the method does nothing. You can check internal data flag calling data()->insertingEnabled(). Setting this flag to true will have no effect if read-only flag is true. \sa setReadOnly() */ void setInsertingEnabled(bool set); /*! \return true if record deleting is enabled. Equal to deletionPolicy() != NoDelete && !isReadOnly()). */ bool isDeleteEnabled() const; /*! \return true if inserting empty records is enabled (false by default). Mostly usable for not db-aware objects (e.g. used in Kexi Alter Table). Note, that if inserting is disabled, or the data set is read-only, this flag will be ignored. */ bool isEmptyRecordInsertingEnabled() const { return m_emptyRecordInsertingEnabled; } /*! Sets the emptyRecordInsertingEnabled flag. Note, that if inserting is disabled, this flag is ignored. */ void setEmptyRecordInsertingEnabled(bool set); /*! Enables or disables filtering. Filtering is enabled by default. */ virtual void setFilteringEnabled(bool set); /*! \return true if filtering is enabled. */ inline bool isFilteringEnabled() const { return m_isFilteringEnabled; } /*! Added for convenience: if @a set is true, this object will behave more like a spreadsheet (it's used for things like table designer view): - hides navigator - disables sorting, inserting and filtering - enables accepting record after cell accepting; see setAcceptsRecordEditAfterCellAccepting() - enables inserting empty record; see setEmptyRecordInsertingEnabled() */ virtual void setSpreadSheetMode(bool set); /*! \return true id "spreadSheetMode" is enabled. It's false by default. */ bool spreadSheetMode() const { return m_spreadSheetMode; } /*! \return number of currently edited record or -1. */ inline int recordEditing() const { return m_recordEditing; } enum DeletionPolicy { NoDelete = 0, AskDelete = 1, ImmediateDelete = 2, SignalDelete = 3 }; /*! \return deletion policy for this object. The default (after allocating) is AskDelete. */ DeletionPolicy deletionPolicy() const { return m_deletionPolicy; } virtual void setDeletionPolicy(DeletionPolicy policy); /*! Deletes currently selected record; does nothing if no record is currently selected. If record is in edit mode, editing is cancelled before deleting. */ virtual void deleteCurrentRecord(); /*! Inserts one empty record above \a pos. If \a pos is -1 (the default), new record is inserted above the current record (or above 1st record if there is no current). A new record becomes current if \a pos is -1 or if \a pos is equal currentRecord(). This method does nothing if: -inserting flag is disabled (see isInsertingEnabled()) -read-only flag is set (see isReadOnly()) \return inserted record's data */ virtual KDbRecordData *insertEmptyRecord(int pos = -1); /*! For reimplementation: called by deleteItem(). If returns false, deleting is aborted. Default implementation just returns true. */ virtual bool beforeDeleteItem(KDbRecordData *data); /*! Deletes \a record. Used by deleteCurrentRecord(). Calls beforeDeleteItem() before deleting, to double-check if deleting is allowed. \return true on success. */ bool deleteItem(KDbRecordData *data); /*! Inserts \a data at position \a pos. -1 means current record. Used by insertEmptyRecord(). */ void insertItem(KDbRecordData *data, int pos = -1); /*! Clears entire table data, its visible representation and deletes data at database backend (if this is db-aware object). Does not clear columns information. Does not destroy KDbTableViewData object (if present) but only clears its contents. Displays confirmation dialog if \a ask is true (the default is false). Repaints widget if \a repaint is true (the default). For empty tables, true is returned immediately. If isDeleteEnabled() is false, false is returned. For spreadsheet mode all current records are just replaced by empty records. \return true on success, false on failure, and cancelled if user cancelled deletion (only possible if \a ask is true). */ tristate deleteAllRecords(bool ask = false, bool repaint = true); /*! \return maximum number of records that can be displayed per one "page" for current view's size. */ virtual int recordsPerPage() const = 0; virtual void selectRecord(int record); virtual void selectNextRecord(); virtual void selectPreviousRecord(); virtual void selectNextPage(); //!< page down action virtual void selectPreviousPage(); //!< page up action virtual void selectFirstRecord(); virtual void selectLastRecord(); virtual void addNewRecordRequested(); /*! Clears the current selection. Current record and column will be now unspecified: currentRecord(), currentColumn() will return -1, and selectedRecord() will return null. */ virtual void clearSelection(); //! Flags for setCursorPosition() enum CursorPositionFlag { NoCursorPositionFlags = 0, //!< Default flag ForceSetCursorPosition = 1, //!< Update cursor position even if record and col doesn't //!< differ from actual position. DontEnsureCursorVisibleIfPositionUnchanged = 2 //!< Don't call ensureCellVisible() //!< when position is unchanged and //!< ForceSetCursorPosition is off. }; Q_DECLARE_FLAGS(CursorPositionFlags, CursorPositionFlag) /*! Moves cursor to \a record and \a col. If \a col is -1, current column number is used. If forceSet is true, cursor position is updated even if \a record and \a col doesn't differ from actual position. */ virtual void setCursorPosition(int record, int col = -1, CursorPositionFlags flags = NoCursorPositionFlags); /*! Ensures that cell at \a record and \a col is visible. If \a col is -1, current column number is used. \a record and \a col, if not -1, must be between 0 and recordCount()-1 (or columnCount()-1 accordingly). */ virtual void ensureCellVisible(int record, int col) = 0; /*! Ensures that column \a col is visible. If \a col is -1, current column number is used. \a col, if not -1, must be between 0 and columnCount()-1. */ virtual void ensureColumnVisible(int col) = 0; /*! Specifies, if this object automatically accepts record editing (using acceptRecordEdit()) on accepting any cell's edit (i.e. after acceptEditor()). \sa acceptsRecordEditAfterCellAccepting() */ virtual void setAcceptsRecordEditAfterCellAccepting(bool set); /*! \return true, if this object automatically accepts record editing (using acceptRecordEdit()) on accepting any cell's edit (i.e. after acceptEditor()). By default this flag is set to false. Not that if the query for this table has given constraints defined, like NOT NULL / NOT EMPTY for more than one field - editing a record would be impossible for the flag set to true, because of constraints violation. However, setting this flag to true can be useful especially for not-db-aware data set (it's used e.g. in Kexi Alter Table's field editor). */ bool acceptsRecordEditAfterCellAccepting() const { return m_acceptsRecordEditAfterCellAccepting; } /*! \return true, if this table accepts dropping data on the records. */ bool dropsAtRecordEnabled() const { return m_dropsAtRecordEnabled; } /*! Specifies, if this table accepts dropping data on the records. If enabled: - dragging over record is indicated by drawing a line at bottom side of this record - dragOverRecord() signal will be emitted on dragging, -droppedAtRecord() will be emitted on dropping By default this flag is set to false. */ virtual void setDropsAtRecordEnabled(bool set); /*! \return currently used data (field/cell) editor or 0 if there is no data editing. */ inline KexiDataItemInterface *editor() const { return m_editor; } /*! Cancels record editing. All changes made to the editing record during this current session will be undone. \return true on success or false on failure (e.g. when editor does not exist) */ virtual bool cancelRecordEditing(); /*! Accepts record editing. All changes made to the editing record during this current session will be accepted (saved). \return true if accepting was successful, false otherwise (e.g. when current record contains data that does not meet given constraints). */ virtual bool acceptRecordEditing(); virtual void removeEditor(); /*! Cancels changes made to the currently active editor. Reverts the editor's value to old one. \return true on success or false on failure (e.g. when editor does not exist) */ virtual bool cancelEditor(); //! Accepst changes made to the currently active editor. //! \return true on success or false on failure (e.g. when editor does not exist or there is data validation error) virtual bool acceptEditor(); //! Flags for use in createEditor() enum CreateEditorFlag { ReplaceOldValue = 1, //!< Remove old value replacing it with a new one EnsureCellVisible = 2, //!< Ensure the cell behind the editor is visible DefaultCreateEditorFlags = EnsureCellVisible //!< Default flags. }; Q_DECLARE_FLAGS(CreateEditorFlags, CreateEditorFlag) //! Creates editors and shows it, what usually means the beginning of a cell editing virtual void createEditor(int record, int col, const QString& addText = QString(), CreateEditorFlags flags = DefaultCreateEditorFlags) = 0; /*! Used when Return key is pressed on cell, the cell has been double clicked or "+" navigator's button is clicked. Also used when we want to continue editing a cell after "invalid value" message was displayed (in this case, \a setText is usually not empty, what means that text will be set in the cell replacing previous value). */ virtual void startEditCurrentCell(const QString& setText = QString(), CreateEditorFlags flags = DefaultCreateEditorFlags); /*! Deletes currently selected cell's contents, if allowed. In most cases delete is not accepted immediately but "record editing" mode is just started. */ virtual void deleteAndStartEditCurrentCell(); inline KDbRecordData *recordAt(int pos) const; /*! \return column information for column number \a col. Default implementation just returns column # col, but for Kexi Forms column data corresponding to widget number is used here (see KexiFormScrollView::fieldNumberForColumn()). */ virtual KDbTableViewColumn* column(int col); /*! \return field number within data model connected to a data-aware widget at column \a col. Can return -1 if there's no such column. */ virtual int fieldNumberForColumn(int col) { return col; } bool hasDefaultValueAt(const KDbTableViewColumn& tvcol); const QVariant* bufferedValueAt(int record, int col, bool useDefaultValueIfPossible = true); //! \return a type of column \a col - one of KDbField::Type int columnType(int col); //! \return default value for column \a col QVariant columnDefaultValue(int col) const; /*! \return true if column \a col is editable. Default implementation takes information about 'readOnly' flag from data member. Within forms, this is reimplemented for checking 'readOnly' flag from a widget ('readOnly' flag from data member is still checked though). */ virtual bool columnEditable(int col); /*! Redraws the current cell. To be implemented. */ virtual void updateCurrentCell() = 0; //! @return height of the horizontal header, 0 by default. virtual int horizontalHeaderHeight() const; //! signals virtual void itemChanged(KDbRecordData* data, int record, int column) = 0; virtual void itemChanged(KDbRecordData* data, int record, int column, const QVariant &oldValue) = 0; virtual void itemDeleteRequest(KDbRecordData* data, int record, int column) = 0; virtual void currentItemDeleteRequest() = 0; //! Emitted for spreadsheet mode when an item was deleted and a new item has been appended virtual void newItemAppendedForAfterDeletingInSpreadSheetMode() = 0; /*! Data has been refreshed on-screen - emitted from initDataContents(). */ virtual void dataRefreshed() = 0; virtual void dataSet(KDbTableViewData *data) = 0; /*! \return a pointer to context menu. This can be used to plug some actions there. */ QMenu* contextMenu() const { return m_contextMenu; } /*! \return true if the context menu is enabled (visible) for the view. True by default. */ bool contextMenuEnabled() const { return m_contextMenuEnabled; } /*! Enables or disables the context menu for the view. */ void setContextMenuEnabled(bool set) { m_contextMenuEnabled = set; } /*! Sets a title with icon for the context menu. Set empty icon and text to remove the title item. This method should be called before customizing the menu because it will be recreated by the method. */ void setContextMenuTitle(const QIcon &icon, const QString &text); /*! \return title text of the context menu. */ QString contextMenuTitleText() const { return m_contextMenuTitleText; } /*! \return title icon of the context menu. */ QIcon contextMenuTitleIcon() const { return m_contextMenuTitleIcon; } /*! \return true if vertical scrollbar's tooltips are enabled (true by default). */ bool scrollbarToolTipsEnabled() const; /*! Enables or disables vertical scrollbar's tooltip. */ void setScrollbarToolTipsEnabled(bool set); /*! Typically handles pressing Enter or F2 key: if current cell has boolean type, toggles it's value, otherwise starts editing (startEditCurrentCell()). */ void startEditOrToggleValue(); /*! \return true if the new record is edited; implies: recordEditing==true. */ inline bool newRecordEditing() const { return m_newRecordEditing; } /*! Reaction on toggling a boolean value of a cell: we're starting to edit the cell and inverting it's state. */ virtual void boolToggled(); virtual void connectCellSelectedSignal(const QObject* receiver, const char* intIntMember) = 0; virtual void connectRecordEditingStartedSignal(const QObject* receiver, const char* intMember) = 0; virtual void connectRecordEditingTerminatedSignal(const QObject* receiver, const char* voidMember) = 0; virtual void connectUpdateSaveCancelActionsSignal(const QObject* receiver, const char* voidMember) = 0; virtual void connectReloadActionsSignal(const QObject* receiver, const char* voidMember) = 0; virtual void connectDataSetSignal(const QObject* receiver, const char* kexiTableViewDataMember) = 0; virtual void connectToReloadDataSlot(const QObject* sender, const char* voidSignal) = 0; virtual void slotDataDestroying(); //! Copy current selection to a clipboard (e.g. cell) virtual void copySelection() = 0; //! Cut current selection to a clipboard (e.g. cell) virtual void cutSelection() = 0; //! Paste current clipboard contents (e.g. to a cell) virtual void paste() = 0; /*! Finds \a valueToFind within the data items \a options are used to control the process. Selection is moved to found value. If \a next is true, "find next" is performed, else "find previous" is performed. Searching behaviour also depends on status of the previous search: for every search, position of the cells containing the found value is stored internally by the data-aware interface (not in options). Moreover, position (start, end) of the found value is also stored. Thus, the subsequent search will reuse this information to be able to start searching exactly after the previously found value (or before for "find previous" option). The flags can be zeroed, what will lead to seaching from the first character of the current item (cell). \return true if value has been found, false if value has not been found, and cancelled if there is nothing to find or there is no data to search in. */ virtual tristate find(const QVariant& valueToFind, const KexiSearchAndReplaceViewInterface::Options& options, bool next); /*! Finds \a valueToFind within the data items and replaces with \a replacement \a options are used to control the process. \return true if value has been found and replaced, false if value has not been found and replaced, and cancelled if there is nothing to find or there is no data to search in or the data is read only. If \a replaceAll is true, all found values are replaced. */ virtual tristate findNextAndReplace(const QVariant& valueToFind, const QVariant& replacement, const KexiSearchAndReplaceViewInterface::Options& options, bool replaceAll); /*! \return vertical scrollbar */ virtual QScrollBar* verticalScrollBar() const = 0; /*! Used in KexiTableView::keyPressEvent() (and in continuous forms). \return true when the key press event \e was consumed. You should also check e->isAccepted(), if it's true, nothing should be done; if it is false, you should call setCursorPosition() for the altered \a curentColumn and \c currentRecord variables. If \a moveToFirstField is not 0, *moveToFirstField will be set to true when the cursor should be moved to the first field (in tab order) and to false otherwise. If \a moveToLastField is not 0, *moveToLastField will be set to true when the cursor should be moved to the last field (in tab order) and to false otherwise. Note for forms: if moveToFirstField and moveToLastField are not 0, \a currentColumn is altered after calling this method, so setCursorPosition() will set to the index of an appropriate column (field). This is needed because field widgets can be inserted and ordered in custom tab order, so the very first field in the data source can be other than the very first field in the form. Used by KexiTableView::keyPressEvent() and KexiTableView::keyPressEvent(). */ virtual bool handleKeyPress(QKeyEvent *e, int *currentRecord, int *currentColumn, bool fullRecordSelection, bool *moveToFirstField = 0, bool *moveToLastField = 0); protected: /*! Reimplementation for KexiDataAwareObjectInterface. Initializes data contents (resizes it, sets cursor at the first record). Sets record count for record navigator. Sets cursor positin (using setCursorPosition()) to first record or sets (-1, -1) position if no records are available. Called on setData(). Also called once on show event after refreshRequested() signal was received from TableViewData object. */ virtual void initDataContents(); /*! Clears columns information and thus all internal table data and its visible representation. Repaints widget if \a repaint is true. */ virtual void clearColumns(bool repaint = true); /*! Called by clearColumns() to clear internals of the object. */ virtual void clearColumnsInternal(bool repaint) = 0; /*! @internal for implementation \return sorting order (within GUI). currentLocalSortColumn() should be also checked, and if it returns -1, no particular sorting is set up. Even this does not mean that any sorting has been performed within GUI of this object, because the data could be changed in the meantime outside of this GUI object. @see dataSortOrder() currentLocalSortColumn() */ virtual KDbOrderByColumn::SortOrder currentLocalSortOrder() const = 0; /*! @internal for implementation \return sorted column number for this widget or -1 if no column is sorted witin GUI. This does not mean that the same sorting is performed within data member which is used by this widget, because the data could be changed in the meantime outside of this GUI widget. @see dataSortColumn() currentLocalSortOrder() */ virtual int currentLocalSortColumn() const = 0; /*! @internal for implementation Shows sorting indicator order in the GUI for column @a column. This should not perform any sorting in data assigned to this object. @a column may be -1, what means "no sorting". */ virtual void setLocalSortOrder(int column, KDbOrderByColumn::SortOrder order) = 0; /*! @internal Sets order for \a column: -1: descending, 1: ascending, 0: invert order */ virtual void sortColumnInternal(int col, int order = 0); /*! @internal for implementation Updates GUI after sorting. After sorting you need to ensure current record and column is visible to avoid user confusion. For exaple, in KexiTableView implementation, current cell is centered (if possible) and updateContents() is called. */ virtual void updateGUIAfterSorting(int previousRecord) = 0; /*! Emitted in initActions() to force reload actions You should remove existing actions and add them again. Define and emit reloadActions() signal here. */ virtual void reloadActions() = 0; /*! Reloads data for this object. */ virtual void reloadData(); /*! for implementation as a signal */ virtual void itemSelected(KDbRecordData *) = 0; /*! for implementation as a signal */ virtual void cellSelected(int record, int col) = 0; /*! for implementation as a signal */ virtual void sortedColumnChanged(int col) = 0; /*! for implementation as a signal */ virtual void recordEditingTerminated(int record) = 0; /*! for implementation as a signal */ virtual void updateSaveCancelActions() = 0; /*! Prototype for signal recordEditingStarted(int), implemented by KexiFormScrollView. */ virtual void recordEditingStarted(int record) = 0; /*! Clear temporary members like the pointer to current editor. If you reimplement this method, don't forget to call this one. */ virtual void clearVariables(); /*! @internal Creates editor structure without filling it with data. Used in createEditor() and few places to be able to display cell contents dependending on its type. If \a ignoreMissingEditor is false (the default), and editor cannot be instantiated, current record editing (if present) is cancelled. */ virtual KexiDataItemInterface *editor(int col, bool ignoreMissingEditor = false) = 0; /*! Updates editor's position, size and shows its focus (not the editor!) for \a record and \a column, using editor(). Does nothing if editor not found. */ virtual void editorShowFocus(int record, int column) = 0; /*! Redraws specified cell. */ virtual void updateCell(int record, int column) = 0; /*! Redraws all cells of specified record \a record. */ virtual void updateRecord(int record) = 0; /*! Updates contents of the widget. Just call update() here on your widget. */ virtual void updateWidgetContents() = 0; /*! Updates widget's contents size e.g. using QScrollView::resizeContents(). */ virtual void updateWidgetContentsSize() = 0; /*! @internal Updates record appearance after canceling record edit. Used by cancelRecordEdit(). By default just calls updateRecord(m_curRecord). Reimplemented by KexiFormScrollView. */ virtual void updateAfterCancelRecordEditing(); /*! @internal Updates record appearance after accepting record edit. Used by acceptRecordEditing(). By default just calls updateRecord(m_curRecord). Reimplemented by KexiFormScrollView. */ virtual void updateAfterAcceptRecordEditing(); //! Handles TableViewData::recordRepaintRequested() signal virtual void slotRecordRepaintRequested(KDbRecordData* data) { Q_UNUSED(data); } //! Handles TableViewData::aboutToDeleteRecord() signal. Prepares info for slotRecordDeleted(). virtual void slotAboutToDeleteRecord(KDbRecordData* data, KDbResultInfo* result, bool repaint); //! Handles TableViewData::recordDeleted() signal to repaint when needed. virtual void slotRecordDeleted(); //! Handles TableViewData::recordInserted() signal to repaint when needed. virtual void slotRecordInserted(KDbRecordData *data, bool repaint); virtual void beginInsertItem(KDbRecordData *data, int pos); virtual void endInsertItem(KDbRecordData *data, int pos); virtual void beginRemoveItem(KDbRecordData *data, int pos); virtual void endRemoveItem(int pos); //! Like above, not db-aware version virtual void slotRecordInserted(KDbRecordData *data, int record, bool repaint); virtual void slotRecordsDeleted(const QList &) {} //! for sanity checks (return true if m_data is present; else: outputs warning) inline bool hasData() const; /*! Used by setCursorPosition() if cursor's position changed. */ virtual void selectCellInternal(int previousRecord, int previousColumn); /*! Used in KexiDataAwareObjectInterface::slotRecordDeleted() to repaint tow \a record and all visible below. Implemented if there is more than one record displayed, i.e. currently for KexiTableView. */ virtual void updateAllVisibleRecordsBelow(int record) { Q_UNUSED(record); } /*! @return geometry of the viewport, i.e. the scrollable area, minus any scrollbars, etc. */ virtual QRect viewportGeometry() const = 0; //! Call this from the subclass. */ virtual void focusOutEvent(QFocusEvent* e); /*! Handles verticalScrollBar()'s valueChanged(int) signal. Called when vscrollbar's value has been changed. Call this method from the subclass. */ virtual void verticalScrollBarValueChanged(int v); /*! Changes 'record editing' >=0 there's currently edited record, else -1. * Can be reimplemented with calling superclass setRecordEditing() * Sends recordEditingStarted(int) signal. * @see recordEditing() recordEditingStarted(). */ void setRecordEditing(int record); /*! Shows error message box suitable for \a resultInfo. This can be "sorry" or "detailedSorry" message box or "queryYesNo" if resultInfo->allowToDiscardChanges is true. \return code of button clicked: KMessageBox::Ok in case of "sorry" or "detailedSorry" messages and KMessageBox::Yes or KMessageBox::No in case of "queryYesNo" message. */ int showErrorMessageForResult(const KDbResultInfo& resultInfo); /*! Shows context message @a message for editor @a item. */ void showEditorContextMessage( KexiDataItemInterface *item, const QString &message, KMessageWidget::MessageType type, KMessageWidget::CalloutPointerDirection direction); /*! Shows context message about exceeded length for editor @a item. If @a exceeded is true, a new message is created, else the message will be removed. */ void showLengthExceededMessage(KexiDataItemInterface *item, bool exceeded); /*! Updates message about exceeded length for editor @a item. Useful only where message created with showLengthExceededMessage() is displayed. */ void showUpdateForLengthExceededMessage(KexiDataItemInterface *item); /*! Prepares array of indices of visible values to search within. This is per-interface global cache. Needed for faster lookup because there could be lookup values. Called whenever columns definition changes, i.e. in setData() and clearColumns(). @see find() */ void updateIndicesForVisibleValues(); //! @return horizontal header, 0 by default. virtual QHeaderView* horizontalHeader() const; //! @return vertical header, 0 by default. virtual QHeaderView* verticalHeader() const; //! Update section of vertical header virtual void updateVerticalHeaderSection(int section) = 0; //! data structure displayed for this object KDbTableViewData *m_data; //! current record (cursor) int m_curRecord; //! current column (cursor) int m_curColumn; //! current record's data KDbRecordData *m_currentRecord; //! data iterator KDbTableViewDataIterator m_itemIterator; //! record's data for inserting KDbRecordData *m_insertRecord; //! true if m_data member is owned by this object bool m_owner; /*! true if a new record is edited; implies: m_recorfEditing == true. */ bool m_newRecordEditing; /*! 'sorting by column' availability flag for widget */ bool m_isSortingEnabled; /*! true if filtering is enabled for the view. */ bool m_isFilteringEnabled; /*! Public version of 'acceptsRecordEditingAfterCellAcceptin' flag (available for a user). It's OR'es together with above flag. */ bool m_acceptsRecordEditAfterCellAccepting; /*! Used in acceptEditor() to avoid infinite recursion, eg. when we're calling acceptRecordEditing() during cell accepting phase. */ bool m_inside_acceptEditor; // no bit field allowed /*! Used in acceptRecordEditing() to avoid infinite recursion, eg. when we're calling acceptRecordEdit() during cell accepting phase. */ bool m_inside_acceptRecordEdit; // no bit field allowed /*! @internal if true, this object automatically accepts record editing (using acceptRecordEditing()) on accepting any cell's edit (i.e. after acceptEditor()). */ bool m_internal_acceptsRecordEditingAfterCellAccepting; /*! true, if inserting empty records are enabled (false by default) */ bool m_emptyRecordInsertingEnabled; /*! Contains 1 if the object is readOnly, 0 if not; otherwise (-1 means "do not know") the 'readOnly' flag from object's internal data structure (KDbTableViewData *KexiTableView::m_data) is reused. */ int m_readOnly; //! @todo really keep this here and not in KexiTableView? /*! true if currently double click action was is performed - (so accept/cancel editor shoudn't be executed) */ + (so accept/cancel editor shouldn't be executed) */ bool m_contentsMousePressEvent_dblClick; /*! like for readOnly: 1 if inserting is enabled */ int m_insertingEnabled; /*! true, if initDataContents() should be called on show event. */ bool m_initDataContentsOnShow; /*! Set to true in setCursorPosition() to indicate that cursor position was set before show() and it shouldn't be changed on show(). Only used if initDataContentsOnShow is true. */ bool m_cursorPositionSetExplicityBeforeShow; /*! true if spreadSheetMode is enabled. False by default. @see KexiTableView::setSpreadSheetMode() */ bool m_spreadSheetMode; /*! true, if this table accepts dropping data on the records (false by default). */ bool m_dropsAtRecordEnabled; - /*! true, if this entire (visible) record should be updated when boving to other record. + /*! true, if this entire (visible) record should be updated when moving to other record. False by default. For table view with 'record highlighting' flag enabled, it is true. */ bool m_updateEntireRecordWhenMovingToOtherRecord; DeletionPolicy m_deletionPolicy; KexiDataItemInterface *m_editor; /*! Navigation panel, used if navigationPanelEnabled is true. */ KexiRecordNavigatorIface *m_navPanel; //!< main navigation widget bool m_navPanelEnabled; /*! Record number that over which user drags a mouse pointer. Used to indicate dropping possibility for that record. Equal -1 if no indication is needed. */ int m_dragIndicatorLine; /*! Context menu widget. */ QMenu *m_contextMenu; /*! Text of context menu title. */ QString m_contextMenuTitleText; /*! Icon of context menu title. */ QIcon m_contextMenuTitleIcon; /*! True if context menu is enabled. */ bool m_contextMenuEnabled; //! Used by updateAfterCancelRecordEditing() bool m_alsoUpdateNextRecord; /*! Record number (>=0 or -1 == no record) that will be deleted in deleteRecord(). It is set in slotAboutToDeleteRecord(KDbRecordData*,KDbResultInfo*,bool)) slot received from KDbTableViewData member. This value will be used in slotRecordDeleted() after recordDeleted() signal is received from KDbTableViewData member and then cleared (set to -1). */ int m_recordWillBeDeleted; /*! Displays passive error popup label used when invalid data has been entered. */ QPointer m_errorMessagePopup; /*! Used to enable/disable execution of verticalScrollBarValueChanged() when users navigate through records using keyboard, so scrollbar tooltips are not visible. */ bool m_verticalScrollBarValueChanged_enabled; /*! True, if vscrollbar tooltips are enabled (true by default). */ bool m_scrollbarToolTipsEnabled; //! Used to mark recently found value class PositionOfValue { public: PositionOfValue() : firstCharacter(0), lastCharacter(0), exists(false) {} int firstCharacter; int lastCharacter; bool exists; }; /*! Used to mark recently found value. Updated on successful execution of find(). If the current cursor's position changes, or data in the current cell changes, positionOfRecentlyFoundValue.exists is set to false. */ PositionOfValue m_positionOfRecentlyFoundValue; /*! Used to compare whether we're looking for new value. */ QVariant m_recentlySearchedValue; /*! Used to compare whether the search direction has changed. */ KexiSearchAndReplaceViewInterface::Options::SearchDirection m_recentSearchDirection; //! Setup by updateIndicesForVisibleValues() and used by find() QVector m_indicesForVisibleValues; private: /*! >= 0 if a record is edited */ int m_recordEditing; bool m_lengthExceededMessageVisible; //! true if acceptRecordEditing() should be called in setCursorPosition() (true by default) bool m_acceptRecordEditing_in_setCursorPosition_enabled; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KexiDataAwareObjectInterface::CreateEditorFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(KexiDataAwareObjectInterface::CursorPositionFlags) inline bool KexiDataAwareObjectInterface::hasData() const { if (!m_data) qDebug() << "No data assigned!"; return m_data != 0; } inline KDbRecordData *KexiDataAwareObjectInterface::recordAt(int pos) const { KDbRecordData *data = m_data->at(pos); if (!data) qDebug() << "pos:" << pos << "- NO ITEM!!"; else { /* qDebug() << "record:" << record; int i=1; for (KexiTableItem::Iterator it = item->begin();it!=item->end();++it,i++) qDebug() << i<<":" << (*it).toString();*/ } return data; } //! Convenience macro used for KexiDataAwareObjectInterface implementations. #define KEXI_DATAAWAREOBJECTINTERFACE \ public: \ void connectCellSelectedSignal(const QObject* receiver, const char* intIntMember) { \ connect(this, SIGNAL(cellSelected(int,int)), receiver, intIntMember); \ } \ void connectRecordEditingStartedSignal(const QObject* receiver, const char* intMember) { \ connect(this, SIGNAL(recordEditingStarted(int)), receiver, intMember); \ } \ void connectRecordEditingTerminatedSignal(const QObject* receiver, const char* voidMember) { \ connect(this, SIGNAL(recordEditingTerminated(int)), receiver, voidMember); \ } \ void connectUpdateSaveCancelActionsSignal(const QObject* receiver, \ const char* voidMember) { \ connect(this, SIGNAL(updateSaveCancelActions()), receiver, voidMember); \ } \ void connectReloadActionsSignal(const QObject* receiver, const char* voidMember) { \ connect(this, SIGNAL(reloadActions()), receiver, voidMember); \ } \ void connectDataSetSignal(const QObject* receiver, \ const char* kexiTableViewDataMember) { \ connect(this, SIGNAL(dataSet(KDbTableViewData*)), receiver, kexiTableViewDataMember); \ } \ void connectToReloadDataSlot(const QObject* sender, const char* voidSignal) { \ connect(sender, voidSignal, this, SLOT(reloadData())); \ } #endif diff --git a/src/widget/kexiqueryparameters.h b/src/widget/kexiqueryparameters.h index 661bad802..3940eb49d 100644 --- a/src/widget/kexiqueryparameters.h +++ b/src/widget/kexiqueryparameters.h @@ -1,46 +1,46 @@ /* This file is part of the KDE project Copyright (C) 2006-2015 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 KEXIQUERYPARAMETERS_H #define KEXIQUERYPARAMETERS_H #include "kexiextwidgets_export.h" #include //! @short Utilities providing GUI for getting query parameters class KEXIEXTWIDGETS_EXPORT KexiQueryParameters { public: /*! Asks for query parameters using a QInputDialog, one dialog per query parameter - (see @ref KDbQuerySchema::parameters()). The type of each dialog depends + (see KDbQuerySchema::parameters()). The type of each dialog depends on the type of query parameter. \return list of values obtained from the user \a ok is set to true on success and to false on failure. */ //! @todo do not use QInputDialog - switch to more powerful custom dialog //! @todo offer option to display one dialog (form) with all the parameters //! @todo support more types (using validators) //! @todo support defaults //! @todo support validation rules, e.g. min/max value, unsigned //! @todo support Enum type (list of strings, need support for keys and user-visible strings) static QList getParameters(QWidget *parent, KDbConnection *conn, KDbQuerySchema *querySchema, bool *ok); }; #endif // KEXIDBCONNECTIONWIDGET_H diff --git a/src/widget/properties/KexiCustomPropertyFactory_p.h b/src/widget/properties/KexiCustomPropertyFactory_p.h index 878a8222d..14097bc9e 100644 --- a/src/widget/properties/KexiCustomPropertyFactory_p.h +++ b/src/widget/properties/KexiCustomPropertyFactory_p.h @@ -1,88 +1,88 @@ /* This file is part of the KDE project Copyright (C) 2005-2008 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 KEXICUSTOMPROPERTYFACTORY_P_H #define KEXICUSTOMPROPERTYFACTORY_P_H //! @todo #include #include #include #if 0 // todo //! Kexi-specific image editor for property editor's item class KexiImagePropertyEdit : public KPropertyPixmapEditor { Q_OBJECT public: explicit KexiImagePropertyEdit(KProperty *property, QWidget *parent = 0); virtual ~KexiImagePropertyEdit(); virtual QVariant value() const; virtual void setValue(const QVariant &value, bool emitChange = true); virtual void drawViewer(QPainter *p, cg, const QRect &r, const QVariant &value); public Q_SLOTS: virtual void selectPixmap(); protected: KexiBLOBBuffer::Id_t m_id; }; #endif /*! Identifier editor based on ordinary string editor but always keeps a valid identifier - or empty value. It's line edit has IdentifierValidator::IdentifierValidator set, so user - is unable to enter invalid characters. Any chages to a null value or empty string, + or empty value. It's line edit has IdentifierValidator set, so user + is unable to enter invalid characters. Any changes to a null value or empty string, have no effect. @todo move this to the KPropertyWidgets library (when KexiUtils moves to KProperty) */ class KexiIdentifierPropertyEditor : public KPropertyStringEditor { Q_OBJECT Q_PROPERTY(QString value READ value WRITE setValue USER true) public: explicit KexiIdentifierPropertyEditor(QWidget *parent = 0); virtual ~KexiIdentifierPropertyEditor(); public Q_SLOTS: /*! Reimplemented: sets \a value but it is converted to identifier using KDb::stringToIdentifier(). If \a value is empty string, this method has no effect. */ virtual void setValue(const QString &value); }; class KexiImagePropertyEditor: public KPropertyPixmapEditor { Q_OBJECT public: explicit KexiImagePropertyEditor(KProperty *property, QWidget *parent = nullptr); virtual ~KexiImagePropertyEditor(); public Q_SLOTS: void selectPixmap() override; }; #endif