37 #include <hbdataformmodel.h> |
37 #include <hbdataformmodel.h> |
38 #include <hbcombobox.h> |
38 #include <hbcombobox.h> |
39 |
39 |
40 #include <QGraphicsSceneMouseEvent> |
40 #include <QGraphicsSceneMouseEvent> |
41 #include <QCoreApplication> |
41 #include <QCoreApplication> |
42 |
42 #include <QGraphicsScene> |
|
43 #include <QGestureRecognizer> |
|
44 |
|
45 #include <hbgesturerecognizers_p.h> |
|
46 #include <hbgestures_p.h> |
|
47 |
|
48 class HbTapDelayGesture:public HbTapGesture |
|
49 { |
|
50 public: |
|
51 using HbTapGesture::d_ptr; |
|
52 |
|
53 Q_DECLARE_PRIVATE_D(d_ptr, HbTapGesture) |
|
54 }; |
|
55 class HbTapDelayGestureRecognizer : public HbTapGestureRecognizer |
|
56 { |
|
57 public: |
|
58 explicit HbTapDelayGestureRecognizer(){} |
|
59 virtual ~HbTapDelayGestureRecognizer() |
|
60 { |
|
61 int i = 0; |
|
62 i++; |
|
63 }; |
|
64 |
|
65 QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event) |
|
66 { |
|
67 HbTapDelayGesture* gesture = static_cast<HbTapDelayGesture *>(state); |
|
68 QMouseEvent* me = toMouseEvent(event); |
|
69 Qt::GestureState gestureState = state->state(); |
|
70 switch(event->type()) |
|
71 { |
|
72 case QEvent::MouseButtonDblClick: |
|
73 case QEvent::MouseButtonPress: |
|
74 if ( state->state() == Qt::NoGesture && me->button() == Qt::LeftButton){ |
|
75 |
|
76 gesture->setPosition(me->globalPos()); |
|
77 gesture->setHotSpot(me->globalPos()); |
|
78 gesture->setStartPos(me->globalPos()); |
|
79 gesture->setScenePosition(HbGestureUtils::mapToScene(watched, me->globalPos())); |
|
80 gesture->setSceneStartPos(HbGestureUtils::mapToScene(watched, me->globalPos())); |
|
81 mTapRadius = (int)(HbDefaultTapRadius * HbDeviceProfile::current().ppmValue()); |
|
82 |
|
83 HbTapGesturePrivate* d_ptr = gesture->d_func(); |
|
84 d_ptr->mTapStyleHint = HbTapGesture::Tap; |
|
85 if ( d_ptr->mTimerId ) { |
|
86 gesture->killTimer(d_ptr->mTimerId); |
|
87 } |
|
88 d_ptr->mTimerId = gesture->startTimer(50); |
|
89 return QGestureRecognizer::MayBeGesture; |
|
90 |
|
91 } |
|
92 else { |
|
93 return QGestureRecognizer::Ignore; |
|
94 } |
|
95 |
|
96 |
|
97 case QEvent::MouseMove: |
|
98 if(gestureState != Qt::NoGesture && gestureState != Qt::GestureCanceled) { |
|
99 return handleMouseMove(gestureState, gesture, watched, toMouseEvent(event)); |
|
100 } |
|
101 else{ |
|
102 if (gesture->d_func()->mTimerId) { |
|
103 gesture->setPosition(me->globalPos()); |
|
104 gesture->setScenePosition(HbGestureUtils::mapToScene(watched, me->globalPos())); |
|
105 gesture->setHotSpot(me->globalPos()); |
|
106 |
|
107 int tapRadiusSquare(mTapRadius * mTapRadius); |
|
108 if(gesture->property(HbPrivate::TapRadius.latin1()).isValid()) { |
|
109 qWarning("WARNING using widget specific properties in HbTapGestureRecognizer"); |
|
110 int tapRadius = gesture->property(HbPrivate::TapRadius.latin1()).toInt(); |
|
111 tapRadiusSquare = tapRadius * tapRadius; |
|
112 } |
|
113 QPointF delta = me->globalPos() - gesture->startPos(); |
|
114 |
|
115 // cancel long press with radius |
|
116 if((delta.x() * delta.x() + delta.y() * delta.y()) > tapRadiusSquare) { |
|
117 gesture->killTimer(gesture->d_func()->mTimerId); |
|
118 gesture->d_func()->mTimerId = 0; |
|
119 } |
|
120 |
|
121 } |
|
122 return QGestureRecognizer::Ignore; |
|
123 } |
|
124 |
|
125 case QEvent::MouseButtonRelease: |
|
126 if(gestureState != Qt::NoGesture) { |
|
127 return handleMouseRelease(gestureState, gesture, watched, toMouseEvent(event)); |
|
128 } |
|
129 else{ |
|
130 |
|
131 if (gesture->d_func()->mTimerId) { |
|
132 gesture->killTimer(gesture->d_func()->mTimerId); |
|
133 gesture->d_func()->mTimerId = 0; |
|
134 return QGestureRecognizer::FinishGesture; |
|
135 } else { |
|
136 return QGestureRecognizer::Ignore; |
|
137 } |
|
138 } |
|
139 |
|
140 case QEvent::Timer: |
|
141 { |
|
142 QGestureRecognizer::Result result; |
|
143 gesture->killTimer(gesture->d_func()->mTimerId); |
|
144 gesture->d_func()->mTimerId = 0; |
|
145 if(gestureState == Qt::NoGesture) { |
|
146 result = QGestureRecognizer::TriggerGesture; |
|
147 gesture->d_func()->mTimerId = gesture->startTimer(HbTapAndHoldTimeout); |
|
148 |
|
149 } |
|
150 else { |
|
151 result = handleTimerEvent(gesture->state(),gesture,watched); |
|
152 } |
|
153 |
|
154 return result; |
|
155 } |
|
156 case QEvent::TouchBegin: |
|
157 case QEvent::TouchUpdate: |
|
158 return HbTapGestureRecognizer::recognize(state, watched, event); |
|
159 |
|
160 default: break; |
|
161 } |
|
162 |
|
163 return QGestureRecognizer::Ignore; |
|
164 |
|
165 } |
|
166 }; |
|
167 |
|
168 class DelayGestureInstaller |
|
169 { |
|
170 public: |
|
171 DelayGestureInstaller():count(0){} |
|
172 void install() |
|
173 { |
|
174 if(count <=0){ |
|
175 QGestureRecognizer::unregisterRecognizer(Qt::TapGesture); |
|
176 QGestureRecognizer::registerRecognizer(new HbTapDelayGestureRecognizer); |
|
177 |
|
178 } |
|
179 count++; |
|
180 } |
|
181 void unInstall() |
|
182 { |
|
183 count--; |
|
184 if(count <1){ |
|
185 QGestureRecognizer::unregisterRecognizer(Qt::TapGesture); |
|
186 QGestureRecognizer::registerRecognizer(new HbTapGestureRecognizer); |
|
187 } |
|
188 } |
|
189 int count; |
|
190 }; |
|
191 static DelayGestureInstaller delayGestureInstaller; |
43 /*! |
192 /*! |
44 @beta |
193 @beta |
45 @hbwidgets |
194 @hbwidgets |
46 \class HbDataForm |
195 \class HbDataForm |
47 \brief HbDataForm represents hierarchical dataitems in form of form pages, groups, group pages |
196 |
48 and data items. |
197 \brief The HbDataForm class is for showing and entering data in |
49 HbDataForm implements a hierarchical representation of view items for each model items from |
198 hierarchically organized pages and groups of a form. |
50 HbDataFormModel. |
199 |
51 |
200 A data form contains data items for showing and entering data in an |
52 HbDataForm implements the interfaces defined by the HbAbstractItemView class to allow |
201 application. Each data item shown in a data form can contain an input widget |
53 it to display data provided by models which are derived from QAbstractItemModel class. |
202 and an optional text label. Text fields, sliders and check boxes are typical |
54 |
203 widgets used to show and collect data in an application. If a complex data |
55 It is simple to construct a dataform displaying data from a model. The user has to create |
204 form contains many data items a user may be required to scroll the data form |
56 HbDataFormModel and create the hierarchy of HbDataFormModelItems.The hierarchy is |
205 content. To reduce the need to scroll, the data items can be organised into |
57 similar to the following. |
206 elements whose hierarchy is the following: |
58 |
207 - %Data form |
59 - HbDataForm |
208 - Form pages |
60 - HbDataFormPage1 |
209 - Groups |
61 - HbDataGroup1 |
210 - Group pages |
62 - HbDataGroupPage1 |
211 |
63 - HbDataItem |
212 The data form uses a model-view architecture. HbDataFormModel represents the |
64 - HbDataItem |
213 data model for the form. You add HbDataFormModelItem objects (i.e. form |
65 - HbDataItem |
214 pages, groups, group pages and data items) to a data form model by creating |
66 - HbDataItem |
215 a HbDataFormModel object and adding HbDataFormModelItem objects to it. You |
67 - HbDataFormPage2 |
216 can then create a data form widget to show the data by creating an |
68 - HbDataGroup2 |
217 HbDataForm object and setting its data form model. The model-view |
69 - HbDataGroupPage2 |
218 architecture ensures that the content of the data form view is updated as |
70 - HbDataItem |
219 the data form model changes. |
71 - HbDataItem |
220 |
72 - HbDataItem |
221 The important thing to note is that you do not create data form widgets |
73 - HbDataItem |
222 directly in your data form. The HbDataForm object creates the appropriate UI |
74 - HbDataGroup3 |
223 widget type for each data item in your data form model. You must specify the |
75 - HbDataItem |
224 type of widget that is shown in the data form when you create your data form |
76 - HbDataItem |
225 model. |
77 - HbDataItem |
226 |
78 - HbDataItem |
227 HbDataForm implements the interface defined by the HbAbstractItemView class |
79 - HbDataItem |
228 to display the data provided by the data form model. This model is derived |
80 |
229 from the QAbstractItemModel class. To construct a data form for displaying |
81 HbDataItem can be the child of HbDataForm, HbDataFormPage, HbDataGroup and |
230 the data from a data form model, create HbDataFormModel and the hierarchy of |
82 HbDataGroupPage. An instance of HbDataForm has to be created and model should be set |
231 HbDataFormModelItem objects. The following rules apply in the hierarchy: |
83 to the form using setModel( ) API. |
232 - A form page can be a child of the data form only. |
84 The properties of each data item node can be set using HbDataFormModelItem convenient |
233 - A group can be a child of the data form or a form page. |
85 API's like setContentWidgetData( ). These model data are parsed and set while the visualization |
234 - A group page can be a child of a group only. |
86 instance of each item is created. |
235 - A data item can be the child of data form, form page, group, and group page. |
87 |
236 |
88 The model/view architecture ensures that the view contents are updated as and when the data in |
237 The hierarchy can be for example the following: |
89 model changes. |
238 |
90 |
239 - %Data form |
91 Only model items that can have children can be in expanded (childrens are visible) or |
240 - Form page 1 |
92 collapsed (childrens are hidden) state. Model items of type HbDataFormModelItem::FormPageItem, |
241 - Group 1 |
93 HbDataFormModelItem::GroupItem and HbDataFormModelItem::GroupPageItem can be expanded |
242 - Group page 1 |
94 or collapsed. Which in turn means that these types of model item can only have children. |
243 - %Data item 1 |
95 Each item in model is represented by either an instance of HbDataFormViewItem or classes which |
244 - %Data item 2 |
96 are derived from HbDataFormViewItem. HbDataFormViewItem can be subclassed for |
245 - %Data item 3 |
|
246 - %Data item 4 |
|
247 - Form page 2 |
|
248 - %Data item 5 |
|
249 - Group 2 |
|
250 - %Data item 6 |
|
251 - Group page 2 |
|
252 - %Data item 7 |
|
253 - %Data item 8 |
|
254 - Group 3 |
|
255 - %Data item 9 |
|
256 |
|
257 To build the structure create first the HbDataForm object and set the model |
|
258 to the form with the setModel() method. Set properties of each data item |
|
259 with methods of HbDataFormModelItem class. The data is parsed when the |
|
260 visualization instance of each item is created and set on each item. |
|
261 |
|
262 Items which have children (i.e. form pages, groups, and group pages) can be |
|
263 in expanded (i.e. children are visible) or collapsed (i.e. children are |
|
264 hidden) state. Each item in data form model is represented by an |
|
265 HbDataFormViewItem object. HbDataForm uses HbDataFormViewItem prototype to |
|
266 instantiate the data form items. HbDataFormViewItem can be subclassed for |
97 customization purposes. |
267 customization purposes. |
98 |
268 |
99 The Model hierarchy can be created using the convenient API's provided in model class like |
269 The signals emitted by HbDataForm are the following: |
100 appendDataFormPage(), appendDataFormGroup(), appendDataFormGroupPage() and |
270 \li itemShown(const QModelIndex &index) signal is emitted when the |
101 appendDataFormItem(). All these API's return HbDataFormModelItem instance corresponding |
271 HbDataFormViewItem corresponding to \a index is shown. You can connect to |
102 to each HbDataFormModelItem::DataItemType type on which user can set item |
272 this signal and fetch the instance of HbDataFormViewItem from HbDataForm |
103 specific(content widget) data. Otherwise each HbDataFormModelItem can be created individually |
273 with HbAbstractItemView::itemByIndex(). |
104 by passing the corresponding type of item (GroupItem, GroupPageItem, FormPageItem) and create |
274 \li dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) |
105 the tree of HbDataFormModelItem using setParent API or by passing the parent |
275 signal is emitted when the HbDataFormModel is updated \a topLeft and \a |
106 HbDataFormModelItem in constructor. Later the top level HbDataFormModelItem can be added in |
276 bottomRight will be same since every node has only one column. You can |
107 model. |
277 connect to this signal and fetch the instance of |
108 |
278 - HbDataFormViewItem from HbDataForm with HbAbstractItemView::itemByIndex() or |
109 After setting model in HbDataForm using setModel(), the visualization gets created. |
279 - HbDataFormModelItem with HbDataFormModel::itemFromIndex(). HbDataForm |
110 Only the items inside the expanded form page, group or group page are created. When an item's |
280 takes care of updating the corresponding the visualization of item when you |
111 visualization is created, HbDataForm emits itemShown(constQModelIndex&) signal. The application |
281 update the model with HbDataFormModelItem::setContentWidgetData(). |
112 can connect to this signal and when corresponding slot is called then application can get |
282 |
113 HbDataFormViewItem instance and even content widget instance. Use HbAbstractItemView::itemByIndex() |
283 You can also provide the connection information to the corresponding content |
114 to get HbDataFormViewItem instance. Use HbDataFormViewItem::dataItemContentWidget() to get |
284 widget of each HbDataFormModelItem with the \link HbDataForm::addConnection(HbDataFormModelItem * item, const char* signal, QObject *receiver, const char* slot) HbDataForm::addConnection()\endlink |
115 content widget instance. |
285 method. The connection is established when the item visualization is |
116 |
286 created. You can use \link HbDataForm::removeConnection(HbDataFormModelItem *item, const char* signal, QObject *receiver, const char* slot) HbDataForm::removeConnection()\endlink and HbDataForm::removeAllConnection() |
117 The signals emitted by HbDataForm |
287 methods in the same way. You can establish and remove the connection also at |
118 \li itemShown(const QModelIndex &index) Emitted when the HbDataFormViewItem corresponding to |
288 runtime. |
119 \a index is shown. User can connect to this signal and can fetch the instance of |
289 |
120 HbDataFormViewItem from HbDataForm using the API dataFormViewItem(const QModelIndex &index). |
290 \sa HbDataFormViewItem, HbDataFormModel, and HbDataFormModelItem |
121 This signal is only emitted for model items of type greater than HbDataFormModelItem::GroupPageItem |
291 |
122 |
292 \section _usecases_hbdataform Using the HbDataForm class |
123 The user can also provide connection information to correspoding content widget of each |
293 |
124 HbDataFormModelItem using API |
294 \subsection _uc_hbdataform_001 Creating a data form. |
125 addConnection(HbDataFormModelItem* item, const char* signal, QObject* receiver, const char* slot) |
295 |
126 provided in HbDataForm. The connection will be established when the item visualization is created. |
296 The following example shows how to create a data form. The code |
127 Using addConnection() API user can also connect to hbdialog's signals(for ex: aboutToClose) in case |
297 - creates the data form and data form model |
128 of popup items like radio button list item and multi selection list item. Below code snippet demonstrates |
298 - adds the data form model items (i.e. groups, group pages, and data items) |
129 the same: |
299 - sets the model to the view |
130 |
300 |
131 \code |
301 |
132 HbDataFormModelItem *days = model->appendDataFormItem(HbDataFormModelItem::MultiselectionItem, |
302 \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,31} |
133 QString("Days"), themeGeneral); |
303 |
134 QStringList multiItems; |
304 The code creates the following structure: |
135 multiItems<<"Sunday"<<"Monday"<<"Tuesday"<<"Wednesday"<<"Thursday"<<"Friday"; |
305 - Group 1 - group |
136 days->setContentWidgetData(QString("items"), multiItems); |
306 - %Data Item 1 (check box) - data item |
137 QList<QVariant> selected; |
307 - Check box added to group - text property of the data item |
138 selected<<2<<3; |
308 - %Data Item 2 (text item) - data item |
139 days->setContentWidgetData(QString("selectedItems"), selected); |
309 - Text Item added to group - text property of the data item |
140 days->setContentWidgetData(QString("items"), multiItems); |
310 - %Data Item 3 (combo box) - data item |
141 form->addConnection(days, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); |
311 - Profile - group |
142 form->addConnection(days, SIGNAL(aboutToHide()()), this, SLOT(aboutToHide()())); |
312 - Silent - group page |
143 form->addConnection(days, SIGNAL(aboutToClose()), this, SLOT(aboutToClose())); |
313 - Slider - data item |
144 form->addConnection(days, SIGNAL(finished(HbAction*)), this, SLOT(finished(HbAction*))); |
314 - General - group page |
145 |
315 - Meeting - group page |
146 \endcode |
316 |
147 |
317 The generated data form is the following: |
148 Similar way |
318 |
149 removeConnection(HbDataFormModelItem *item, const char* signal, QObject *receiver, const char* slot) |
319 \image html hbsettingform.png |
150 and removeAllConnection() API can be used. Connection can be established or removed even at runtime. |
320 |
151 An example of how to make connection and setting the content widget property: |
321 The picture below shows the generated data form in the landscape mode. |
152 |
322 |
|
323 \image html hbsettingform_landscape.png |
|
324 |
|
325 \subsection _uc_hbdataform_002 Connecting the "sliderReleased" signal to the "volumeChanged" slot. |
|
326 |
|
327 In the following example the content widget is a slider whose |
|
328 "sliderReleased" \a signal is connected to the "volumeChanged" slot which |
|
329 handles the changed volume. |
|
330 |
153 \code |
331 \code |
154 HbDataForm *form = new HbDataForm(); |
332 HbDataForm *form = new HbDataForm(); |
155 model = new HbDataFormModel(); |
333 model = new HbDataFormModel(); |
156 |
334 |
157 HbDataFormModelItem *sliderItem = |
335 HbDataFormModelItem *sliderItem = |
164 form->addConnection(sliderItem, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); |
342 form->addConnection(sliderItem, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); |
165 |
343 |
166 form->setModel(model); |
344 form->setModel(model); |
167 setWidget(form); |
345 setWidget(form); |
168 \endcode |
346 \endcode |
169 |
347 |
170 An example of how to create HbDataForm: |
348 \subsection _uc_hbdataform_003 Creating the model hierarchy. |
171 \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,31} |
349 |
172 |
350 You can create the model hierarchy with the \link |
173 The output generated by the above code looks like: |
351 HbDataFormModel::appendDataFormPage() appendDataFormPage()\endlink, \link |
174 |
352 HbDataFormModel::appendDataFormGroup() appendDataFormGroup()\endlink, \link |
175 \image html hbsettingform.png |
353 HbDataFormModel::appendDataFormGroupPage() |
176 |
354 appendDataFormGroupPage()\endlink, and \link |
177 This is how HbDataForm will look like in landscape mode: |
355 HbDataFormModel::appendDataFormItem() appendDataFormItem()\endlink methods |
178 |
356 of the HbDataFormModel class. All of these methods will return |
179 \image html hbsettingform_landscape.png |
357 HbDataFormModelItem object corresponding to each type in which the user can |
180 |
358 set item specific data. |
181 \sa HbDataFormViewItem, HbDataFormModel, HbDataFormModelItem |
359 |
182 |
360 After running the setModel method the visualization is created . The items |
183 Creating Custom Item: |
361 of expanded groups and group pages are created. The data form emits the |
184 |
362 itemShown(const QModelIndex &index) signal when an the visualization of |
185 Application developer can create custom DataItem by deriving from HbDataFormViewItem and setting this as |
363 item is created. The application can get HbDataFormViewItem and content |
186 prototype using setItemProtoType() API. Application has to override virtual API's createCustomWidget(), |
364 widget from HbDataForm using QModelIndex. |
187 restore()and save(). createCustomWidget() API should return the corresponding custom HbWidget which |
365 */ |
188 can also be a compound widget. Signal connection for child widgets inside the compound widget should |
366 |
189 be taken care by the application. restore() API will be called by the framework when the model data |
367 /*! |
190 is changed. So restore() should take care of updating the visual items with correspoding data from model. |
368 \fn void HbDataForm::itemShown(const QModelIndex &index) |
191 save() API should update the model. App developer should connect respective widgets SIGNALs to SLOT save() |
369 |
192 and update the data to model . |
370 This signal is emitted when HbDataFormViewItem corresponding to \a index is |
193 |
371 shown. |
194 */ |
372 |
195 |
373 */ |
196 /*! |
374 |
197 \fn void HbAbstractItemView::itemShown(const QModelIndex &index) |
375 /*! |
198 |
376 Constructs a data form with the given \a parent. |
199 This signal is emitted when HbDataFormViewItem corresponding to \a index is shown. |
|
200 |
|
201 */ |
|
202 |
|
203 /*! |
|
204 Constructs DataForm with given \a parent. |
|
205 \param parent parent . |
|
206 */ |
377 */ |
207 HbDataForm::HbDataForm(QGraphicsItem *parent) |
378 HbDataForm::HbDataForm(QGraphicsItem *parent) |
208 : HbAbstractItemView(*new HbDataFormPrivate(), new HbDataItemContainer(), |
379 : HbAbstractItemView(*new HbDataFormPrivate(), new HbDataItemContainer(), |
209 new HbTreeModelIterator(0, QModelIndex(), false), parent) |
380 new HbTreeModelIterator(0, QModelIndex(), false), parent) |
210 { |
381 { |
211 Q_D( HbDataForm ); |
382 Q_D( HbDataForm ); |
212 d->q_ptr = this; |
383 d->q_ptr = this; |
213 d->init(); |
384 d->init(); |
214 setVerticalScrollBarPolicy(ScrollBarAlwaysOff); |
385 //setVerticalScrollBarPolicy(ScrollBarAlwaysOff); |
215 } |
386 } |
216 |
387 |
217 /*! |
388 /*! |
218 Constructs a data form with a private class object \a dd, |
389 Constructs a data form with the given private class object \a dd, |
219 \a container and \a parent. |
390 \a container and \a parent. |
220 */ |
391 */ |
221 HbDataForm::HbDataForm(HbDataFormPrivate &dd, HbAbstractItemContainer *container, |
392 HbDataForm::HbDataForm(HbDataFormPrivate &dd, HbAbstractItemContainer *container, |
222 QGraphicsItem * parent) |
393 QGraphicsItem * parent) |
223 : HbAbstractItemView(dd, container, new HbTreeModelIterator(0, QModelIndex(), false), parent) |
394 : HbAbstractItemView(dd, container, new HbTreeModelIterator(0, QModelIndex(), false), parent) |