summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/drilldown.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/examples/drilldown.qdoc')
-rw-r--r--doc/src/examples/drilldown.qdoc536
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.
-*/