diff options
Diffstat (limited to 'doc/src/examples/drilldown.qdoc')
-rw-r--r-- | doc/src/examples/drilldown.qdoc | 536 |
1 files changed, 0 insertions, 536 deletions
diff --git a/doc/src/examples/drilldown.qdoc b/doc/src/examples/drilldown.qdoc deleted file mode 100644 index f8086c193e..0000000000 --- a/doc/src/examples/drilldown.qdoc +++ /dev/null @@ -1,536 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example sql/drilldown - \title Drill Down Example - - The Drill Down example shows how to read data from a database as - well as submit changes, using the QSqlRelationalTableModel and - QDataWidgetMapper classes. - - \image drilldown-example.png Screenshot of the Drill Down Example - - When running the example application, a user can retrieve - information about each of Nokia's Qt offices by clicking the - corresponding image. The application pops up an information window - displaying the data, and allows the users to alter the location - description as well as the image. The main view will be updated - when the users submit their changes. - - The example consists of three classes: - - \list - \li \c ImageItem is a custom graphics item class used to - display the office images. - - \li \c View is the main application widget allowing the user to - browse through the various locations. - - \li \c InformationWindow displays the requested information, - allowing the users to alter it and submit their changes to the - database. - \endlist - - We will first take a look at the \c InformationWindow class to see - how you can read and modify data from a database. Then we will - review the main application widget, i.e., the \c View class, and - the associated \c ImageItem class. - - \section1 InformationWindow Class Definition - - The \c InformationWindow class is a custom widget inheriting - QWidget: - - \snippet examples/sql/drilldown/informationwindow.h 0 - - When we create an information window, we pass the associated - location ID, a parent, and a pointer to the database, to the - constructor. We will use the database pointer to populate our - window with data, while passing the parent parameter on to the - base class. The ID is stored for future reference. - - Once a window is created, we will use the public \c id() function - to locate it whenever information for the given location is - requested. We will also use the ID to update the main application - widget when the users submit their changes to the database, i.e., - we will emit a signal carrying the ID and file name as parameters - whenever the users changes the associated image. - - \snippet examples/sql/drilldown/informationwindow.h 1 - - Since we allow the users to alter some of the location data, we - must provide functionality for reverting and submitting their - changes. The \c enableButtons() slot is provided for convenience - to enable and disable the various buttons when required. - - \snippet examples/sql/drilldown/informationwindow.h 2 - - The \c createButtons() function is also a convenience function, - provided to simplify the constructor. As mentioned above we store - the location ID for future reference. We also store the name of - the currently displayed image file to be able to determine when to - emit the \c imageChanged() signal. - - The information window uses the QLabel class to display the office - location and the country. The associated image file is displayed - using a QComboBox instance while the description is displayed using - QTextEdit. In addition, the window has three buttons to control - the data flow and whether the window is shown or not. - - Finally, we declare a \e mapper. The QDataWidgetMapper class - provides mapping between a section of a data model to widgets. We - will use the mapper to extract data from the given database, - updating the database whenever the user modifies the data. - - \section1 InformationWindow Class Implementation - - The constructor takes three arguments: a location ID, a database - pointer and a parent widget. The database pointer is actually a - pointer to a QSqlRelationalTableModel object providing an editable - data model (with foreign key support) for our database table. - - \snippet examples/sql/drilldown/informationwindow.cpp 0 - \snippet examples/sql/drilldown/informationwindow.cpp 1 - - First we create the various widgets required to display the data - contained in the database. Most of the widgets are created in a - straight forward manner. But note the combobox displaying the - name of the image file: - - \snippet examples/sql/drilldown/informationwindow.cpp 2 - - In this example, the information about the offices are stored in a - database table called "offices". When creating the model, - we will use a foreign key to establish a relation between this - table and a second data base table, "images", containing the names - of the available image files. We will get back to how this is done - when reviewing the \c View class. The rationale for creating such - a relation though, is that we want to ensure that the user only - can choose between predefined image files. - - The model corresponding to the "images" database table, is - available through the QSqlRelationalTableModel's \l - {QSqlRelationalTableModel::}{relationModel()} function, requiring - the foreign key (in this case the "imagefile" column number) as - argument. We use QComboBox's \l {QComboBox::}{setModel()} function - to make the combobox use the "images" model. And, since this model - has two columns ("locationid" and "file"), we also specify which - column we want to be visible using the QComboBox::setModelColumn() - function. - - \snippet examples/sql/drilldown/informationwindow.cpp 3 - - Then we create the mapper. The QDataWidgetMapper class allows us - to create data-aware widgets by mapping them to sections of an - item model. - - The \l {QDataWidgetMapper::}{addMapping()} function adds a mapping - between the given widget and the specified section of the - model. If the mapper's orientation is horizontal (the default) the - section is a column in the model, otherwise it is a row. We call - the \l {QDataWidgetMapper::}{setCurrentIndex()} function to - initialize the widgets with the data associated with the given - location ID. Every time the current index changes, all the widgets - are updated with the contents from the model. - - We also set the mapper's submit policy to - QDataWidgetMapper::ManualSubmit. This means that no data is - submitted to the database until the user expliclity requests a - submit (the alternative is QDataWidgetMapper::AutoSubmit, - automatically submitting changes when the corresponding widget - looses focus). Finally, we specify the item delegate the mapper - view should use for its items. The QSqlRelationalDelegate class - represents a delegate that unlike the default delegate, enables - combobox functionality for fields that are foreign keys into other - tables (like "imagefile" in our "trolltechoffices" table). - - \snippet examples/sql/drilldown/informationwindow.cpp 4 - - Finally, we connect the "something's changed" signals in the - editors to our custom \c enableButtons() slot, enabling the users - to either submit or revert their changes. We add all the widgets - into a layout, store the location ID and the name of the displayed - image file for future reference, and set the window title and - initial size. - - Note that we also set the Qt::Window window flag to indicate that - our widget is in fact a window, with a window system frame and a - title bar. - - \snippet examples/sql/drilldown/informationwindow.cpp 5 - - When a window is created, it is not deleted until the main - application exits (i.e., if the user closes the information - window, it is only hidden). For this reason we do not want to - create more than one \c InformationWindow object for each - location, and we provide the public \c id() function to be able to - determine whether a window already exists for a given location - when the user requests information about it. - - \snippet examples/sql/drilldown/informationwindow.cpp 6 - - The \c revert() slot is triggered whenever the user hits the \uicontrol - Revert button. - - Since we set the QDataWidgetMapper::ManualSubmit submit policy, - none of the user's changes are written back to the model unless - the user expliclity choose to submit all of them. Nevertheless, we - can use the QDataWidgetMapper's \l {QDataWidgetMapper::}{revert()} - slot to reset the editor widgets, repopulating all widgets with - the current data of the model. - - \snippet examples/sql/drilldown/informationwindow.cpp 7 - - Likewise, the \c submit() slot is triggered whenever the users - decide to submit their changes by pressing the \uicontrol Submit button. - - We use QDataWidgetMapper's \l {QDataWidgetMapper::}{submit()} slot - to submit all changes from the mapped widgets to the model, - i.e. to the database. For every mapped section, the item delegate - will then read the current value from the widget and set it in the - model. Finally, the \e model's \l {QAbstractItemModel::}{submit()} - function is invoked to let the model know that it should submit - whatever it has cached to the permanent storage. - - Note that before any data is submitted, we check if the user has - chosen another image file using the previously stored \c - displayedImage variable as reference. If the current and stored - file names differ, we store the new file name and emit the \c - imageChanged() signal. - - \snippet examples/sql/drilldown/informationwindow.cpp 8 - - The \c createButtons() function is provided for convenience, i.e., - to simplify the constructor. - - We make the \uicontrol Close button the default button, i.e., the button - that is pressed when the user presses \uicontrol Enter, and connect its - \l {QPushButton::}{clicked()} signal to the widget's \l - {QWidget::}{close()} slot. As mentioned above closing the window - only hides the widget; it is not deleted. We also connect the \uicontrol - Submit and \uicontrol Revert buttons to the corresponding \c submit() - and \c revert() slots. - - \snippet examples/sql/drilldown/informationwindow.cpp 9 - - The QDialogButtonBox class is a widget that presents buttons in a - layout that is appropriate to the current widget style. Dialogs - like our information window, typically present buttons in a layout - that conforms to the interface guidelines for that - platform. Invariably, different platforms have different layouts - for their dialogs. QDialogButtonBox allows us to add buttons, - automatically using the appropriate layout for the user's desktop - environment. - - Most buttons for a dialog follow certain roles. We give the \uicontrol - Submit and \uicontrol Revert buttons the \l - {QDialogButtonBox::ButtonRole}{reset} role, i.e., indicating that - pressing the button resets the fields to the default values (in - our case the information contained in the database). The \l - {QDialogButtonBox::ButtonRole}{reject} role indicates that - clicking the button causes the dialog to be rejected. On the other - hand, since we only hide the information window, any changes that - the user has made wil be preserved until the user expliclity - revert or submit them. - - \snippet examples/sql/drilldown/informationwindow.cpp 10 - - The \c enableButtons() slot is called to enable the buttons - whenever the user changes the presented data. Likewise, when the - data the user choose to submit the changes, the buttons are - disabled to indicate that the current data is stored in the - database. - - This completes the \c InformationWindow class. Let's take a look - at how we have used it in our example application. - - \section1 View Class Definition - - The \c View class represents the main application window and - inherits QGraphicsView: - - \snippet examples/sql/drilldown/view.h 0 - \codeline - \snippet examples/sql/drilldown/view.h 1 - - The QGraphicsView class is part of the \l {Graphics View - Framework} which we will use to display the images of Nokia's - Qt offices. To be able to respond to user interaction; - i.e., showing the - appropriate information window whenever the user clicks one of the - office images, we reimplement QGraphicsView's \l - {QGraphicsView::}{mouseReleaseEvent()} function. - - Note that the constructor expects the names of two database - tables: One containing the detailed information about the offices, - and another containing the names of the available image files. We - also provide a private \c updateImage() slot to catch \c - {InformationWindow}'s \c imageChanged() signal that is emitted - whenever the user changes a location's image. - - \snippet examples/sql/drilldown/view.h 2 - - The \c addItems() function is a convenience function provided to - simplify the constructor. It is called only once, creating the - various items and adding them to the view. - - The \c findWindow() function, on the other hand, is frequently - used. It is called from the \c showInformation() function to - detemine whether a window is already created for the given - location (whenever we create an \c InformationWindow object, we - store a reference to it in the \c informationWindows list). The - latter function is in turn called from our custom \c - mouseReleaseEvent() implementation. - - \snippet examples/sql/drilldown/view.h 3 - - Finally we declare a QSqlRelationalTableModel pointer. As - previously mentioned, the QSqlRelationalTableModel class provides - an editable data model with foreign key support. There are a - couple of things you should keep in mind when using the - QSqlRelationalTableModel class: The table must have a primary key - declared and this key cannot contain a relation to another table, - i.e., it cannot be a foreign key. Note also that if a relational - table contains keys that refer to non-existent rows in the - referenced table, the rows containing the invalid keys will not be - exposed through the model. It is the user's or the database's - responsibility to maintain referential integrity. - - \section1 View Class Implementation - - Although the constructor requests the names of both the table - containing office details as well as the table containing the - names of the available image files, we only have to create a - QSqlRelationalTableModel object for the office table: - - \snippet examples/sql/drilldown/view.cpp 0 - - The reason is that once we have a model with the office details, - we can create a relation to the available image files using - QSqlRelationalTableModel's \l - {QSqlRelationalTableModel::}{setRelation()} function. This - function creates a foreign key for the given model column. The key - is specified by the provided QSqlRelation object constructed by - the name of the table the key refers to, the field the key is - mapping to and the field that should be presented to the user. - - Note that setting the table only specifies which table the model - operates on, i.e., we must explicitly call the model's \l - {QSqlRelationalTableModel::}{select()} function to populate our - model. - - \snippet examples/sql/drilldown/view.cpp 1 - - Then we create the contents of our view, i.e., the scene and its - items. The location labels are regular QGraphicsTextItem objects, - and the "Qt" logo is represented by a QGraphicsPixmapItem - object. The images, on the other hand, are instances of the \c - ImageItem class (derived from QGraphicsPixmapItem). We will get - back to this shortly when reviewing the \c addItems() function. - - Finally, we set the main application widget's size constraints and - window title. - - \snippet examples/sql/drilldown/view.cpp 3 - - The \c addItems() function is called only once, i.e., when - creating the main application window. For each row in the database - table, we first extract the corresponding record using the model's - \l {QSqlRelationalTableModel::}{record()} function. The QSqlRecord - class encapsulates both the functionality and characteristics of a - database record, and supports adding and removing fields as well - as setting and retrieving field values. The QSqlRecord::value() - function returns the value of the field with the given name or - index as a QVariant object. - - For each record, we create a label item as well as an image item, - calculate their position and add them to the scene. The image - items are represented by instances of the \c ImageItem class. The - reason we must create a custom item class is that we want to catch - the item's hover events, animating the item when the mouse cursor - is hovering over the image (by default, no items accept hover - events). Please see the \l{Graphics View Framework} documentation - and the \l{Graphics View Examples} for more details. - - \snippet examples/sql/drilldown/view.cpp 5 - - We reimplement QGraphicsView's \l - {QGraphicsView::}{mouseReleaseEvent()} event handler to respond to - user interaction. If the user clicks any of the image items, this - function calls the private \c showInformation() function to pop up - the associated information window. - - The \l {Graphics View Framework} provides the qgraphicsitem_cast() - function to determine whether the given QGraphicsItem instance is - of a given type. Note that if the event is not related to any of - our image items, we pass it on to the base class implementation. - - \snippet examples/sql/drilldown/view.cpp 6 - - The \c showInformation() function is given an \c ImageItem object - as argument, and starts off by extracting the item's location - ID. Then it determines if there already is created an information - window for this location. If it is, and the window is visible, it - ensures that the window is raised to the top of the widget stack - and activated. If the window exists but is hidden, calling its \l - {QWidget::}{show()} slot gives the same result. - - If no window for the given location exists, we create one by - passing the location ID, a pointer to the model, and our view as a - parent, to the \c InformationWindow constructor. Note that we - connect the information window's \c imageChanged() signal to \e - this widget's \c updateImage() slot, before we give it a suitable - position and add it to the list of existing windows. - - \snippet examples/sql/drilldown/view.cpp 7 - - The \c updateImage() slot takes a location ID and the name of an - image files as arguments. It filters out the image items, and - updates the one that correspond to the given location ID, with the - provided image file. - - \snippet examples/sql/drilldown/view.cpp 8 - - The \c findWindow() function simply searches through the list of - existing windows, returning a pointer to the window that matches - the given location ID, or 0 if the window doesn't exists. - - Finally, let's take a quick look at our custom \c ImageItem class: - - \section1 ImageItem Class Definition - - The \c ImageItem class is provided to facilitate animation of the - image items. It inherits QGraphicsPixmapItem and reimplements its - hover event handlers: - - \snippet examples/sql/drilldown/imageitem.h 0 - - In addition, we implement a public \c id() function to be able to - identify the associated location and a public \c adjust() function - that can be called to ensure that the image item is given the - preferred size regardless of the original image file. - - The animation is implemented using the QTimeLine class together - with the event handlers and the private \c setFrame() slot: The - image item will expand when the mouse cursor hovers over it, - returning back to its original size when the cursor leaves its - borders. - - Finally, we store the location ID that this particular record is - associated with as well as a z-value. In the \l {Graphics View - Framework}, an item's z-value determines its position in the item - stack. An item of high z-value will be drawn on top of an item - with a lower z-value if they share the same parent item. We also - provide an \c updateItemPosition() function to refresh the view - when required. - - \section1 ImageItem Class Implementation - - The \c ImageItem class is really only a QGraphicsPixmapItem with - some additional features, i.e., we can pass most of the - constructor's arguments (the pixmap, parent and scene) on to the - base class constructor: - - \snippet examples/sql/drilldown/imageitem.cpp 0 - - Then we store the ID for future reference, and ensure that our - item will accept hover events. Hover events are delivered when - there is no current mouse grabber item. They are sent when the - mouse cursor enters an item, when it moves around inside the item, - and when the cursor leaves an item. As we mentioned earlier, none - of the \l {Graphics View Framework}'s items accept hover - event's by default. - - The QTimeLine class provides a timeline for controlling - animations. Its \l {QTimeLine::}{duration} property holds the - total duration of the timeline in milliseconds. By default, the - time line runs once from the beginning and towards the end. The - QTimeLine::setFrameRange() function sets the timeline's frame - counter; when the timeline is running, the \l - {QTimeLine::}{frameChanged()} signal is emitted each time the - frame changes. We set the duration and frame range for our - animation, and connect the time line's \l - {QTimeLine::}{frameChanged()} and \l {QTimeLine::}{finished()} - signals to our private \c setFrame() and \c updateItemPosition() - slots. - - Finally, we call \c adjust() to ensure that the item is given the - preferred size. - - \snippet examples/sql/drilldown/imageitem.cpp 1 - \codeline - \snippet examples/sql/drilldown/imageitem.cpp 2 - - Whenever the mouse cursor enters or leave the image item, the - corresponding event handlers are triggered: We first set the time - line's direction, making the item expand or shrink, - respectively. Then we alter the item's z-value if it is not already - set to the expected value. - - In the case of hover \e enter events, we immediately update the - item's position since we want the item to appear on top of all - other items as soon as it starts expanding. In the case of hover - \e leave events, on the other hand, we postpone the actual update - to achieve the same result. But remember that when we constructed - our item, we connected the time line's \l - {QTimeLine::}{finished()} signal to the \c updateItemPosition() - slot. In this way the item is given the correct position in the - item stack once the animation is completed. Finally, if the time - line is not already running, we start it. - - \snippet examples/sql/drilldown/imageitem.cpp 3 - - When the time line is running, it triggers the \c setFrame() slot - whenever the current frame changes due to the connection we - created in the item constructor. It is this slot that controls the - animation, expanding or shrinking the image item step by step. - - We first call the \c adjust() function to ensure that we start off - with the item's original size. Then we scale the item with a - factor depending on the animation's progress (using the \c frame - parameter). Note that by default, the transformation will be - relative to the item's top-left corner. Since we want the item to - be transformed relative to its center, we must translate the - coordinate system before we scale the item. - - In the end, only the following convenience functions remain: - - \snippet examples/sql/drilldown/imageitem.cpp 4 - \codeline - \snippet examples/sql/drilldown/imageitem.cpp 5 - \codeline - \snippet examples/sql/drilldown/imageitem.cpp 6 - - The \c adjust() function defines and applies a transformation - matrix, ensuring that our image item appears with the preferred - size regardless of the size of the source image. The \c id() - function is trivial, and is simply provided to be able to identify - the item. In the \c updateItemPosition() slot we call the - QGraphicsItem::setZValue() function, setting the elevation (i.e., - the position) of the item. -*/ |