|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbCore module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbtoolbutton.h" |
|
27 #include "hbtoolbutton_p.h" |
|
28 #include "hbtooltip.h" |
|
29 #include "hbstyleoptiontoolbutton.h" |
|
30 #include "hbtoolbarextension.h" |
|
31 #include "hbtoolbarextension_p.h" |
|
32 #include "hbaction.h" |
|
33 #include "hbaction_p.h" |
|
34 #include <hbglobal.h> |
|
35 #include "hbcolorscheme.h" |
|
36 #include "hbtextitem.h" |
|
37 #include "hbiconitem.h" |
|
38 |
|
39 #include <QGraphicsSceneHelpEvent> |
|
40 #include <QGraphicsSceneMouseEvent> |
|
41 |
|
42 /*! |
|
43 @stable |
|
44 @hbcore |
|
45 \class HbToolButton |
|
46 \brief The HbToolButton class provides a quick-access button for actions. |
|
47 |
|
48 A tool button is a special button that provides quick-access to |
|
49 a specific action. Unlike a normal push button HbPushButton, a tool |
|
50 button represents an action. In other words, HbToolButton is |
|
51 synchronized with an instance of HbAction. |
|
52 |
|
53 The action may also be associated with other parts of the user interface, |
|
54 as menu items and keyboard shortcuts. Sharing actions in this way helps |
|
55 make the user interface more consistent and is often less work to implement. |
|
56 |
|
57 Tool buttons are normally created indirectly when actions are added to a |
|
58 toolbar with HbToolBar::addAction(). It is also possible to |
|
59 construct tool buttons directly in the same way as any other widget, and |
|
60 arrange them alongside other widgets in layouts. |
|
61 |
|
62 The style of a tool button is adjustable with setToolButtonStyle(). |
|
63 By default a tool button shows only an icon. |
|
64 |
|
65 A tool button's background is set as HbIcon. This makes it possible to |
|
66 specify different images for the normal and pressed states. |
|
67 |
|
68 Example usage: |
|
69 \code |
|
70 HbAction *action = new HbAction(icon, name, this); |
|
71 HbToolButton *toolButton = new HbToolButton(action, this); |
|
72 layout->addItem(toolButton); |
|
73 \endcode |
|
74 |
|
75 \sa HbAction, HbPushButton |
|
76 */ |
|
77 |
|
78 /*! |
|
79 \enum HbToolButton::ToolButtonStyle |
|
80 |
|
81 This enum defines available tool button styles. |
|
82 |
|
83 The tool button style describes how the button's text and icon should be displayed. |
|
84 */ |
|
85 |
|
86 /*! |
|
87 \var HbToolButton::ToolButtonIcon |
|
88 |
|
89 Only display the icon. |
|
90 */ |
|
91 |
|
92 /*! |
|
93 \var HbToolButton::ToolButtonText |
|
94 |
|
95 Only display the text. |
|
96 */ |
|
97 |
|
98 /*! |
|
99 \var HbToolButton::ToolButtonTextAndIcon |
|
100 |
|
101 Display both text and icon. |
|
102 */ |
|
103 |
|
104 /*! |
|
105 \fn void HbToolButton::triggered(HbAction *action) |
|
106 |
|
107 This signal is emitted when the \a action is triggered. |
|
108 */ |
|
109 |
|
110 /*! |
|
111 \reimp |
|
112 \fn int HbToolButton::type() const |
|
113 */ |
|
114 |
|
115 HbToolButtonPrivate::HbToolButtonPrivate() : |
|
116 action(0), |
|
117 textItem(0), |
|
118 iconItem(0), |
|
119 frameItem(0), |
|
120 customBackground(), |
|
121 backgroundVisible(true), |
|
122 buttonStyle(HbToolButton::ToolButtonIcon), |
|
123 toolBarPosition(HbStyleOptionToolButton::TB_None), |
|
124 orientation(Qt::Vertical), |
|
125 mDialogToolBar(false), |
|
126 mButtonSize(QSizeF()) |
|
127 { |
|
128 } |
|
129 |
|
130 HbToolButtonPrivate::~HbToolButtonPrivate() |
|
131 { |
|
132 } |
|
133 |
|
134 void HbToolButtonPrivate::createPrimitives() |
|
135 { |
|
136 Q_Q(HbToolButton); |
|
137 |
|
138 if (backgroundVisible) { |
|
139 if (!frameItem) { |
|
140 frameItem = q->style()->createPrimitive(HbStyle::P_ToolButton_frame, q); |
|
141 } |
|
142 } else if (frameItem) { |
|
143 delete frameItem; |
|
144 frameItem = 0; |
|
145 } |
|
146 |
|
147 if (action && !action->text().isEmpty()) { |
|
148 if (!textItem) { |
|
149 textItem = static_cast<HbTextItem *>(q->style()->createPrimitive(HbStyle::P_ToolButton_text, q)); |
|
150 textItem->setTextWrapping(Hb::TextWordWrap); |
|
151 } |
|
152 textItem->setVisible(buttonStyle & HbToolButton::ToolButtonText); |
|
153 } else if (textItem) { |
|
154 delete textItem; |
|
155 textItem = 0; |
|
156 } |
|
157 |
|
158 if (action && (buttonStyle & HbToolButton::ToolButtonIcon)) { |
|
159 if (!iconItem) { |
|
160 iconItem = q->style()->createPrimitive(HbStyle::P_ToolButton_icon, q); |
|
161 } |
|
162 } else if (iconItem){ |
|
163 delete iconItem; |
|
164 iconItem = 0; |
|
165 } |
|
166 } |
|
167 |
|
168 void HbToolButtonPrivate::setOrientation(Qt::Orientation orientation) |
|
169 { |
|
170 if (this->orientation != orientation) { |
|
171 this->orientation = orientation; |
|
172 Q_Q(HbToolButton); |
|
173 if (q->isVisible() && polished) { |
|
174 q->repolish(); |
|
175 } |
|
176 } |
|
177 } |
|
178 |
|
179 void HbToolButtonPrivate::setToolBarPosition(HbStyleOptionToolButton::ToolBarPosition position) |
|
180 { |
|
181 Q_Q(HbToolButton); |
|
182 if (toolBarPosition != position) { |
|
183 toolBarPosition = position; |
|
184 // required for toolbar()->action()[i]->setVisible(visible) |
|
185 // to work for all cases |
|
186 if (q->isVisible() && polished) { |
|
187 q->updatePrimitives(); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 void HbToolButtonPrivate::setBackgroundVisible(bool visible) |
|
193 { |
|
194 Q_Q(HbToolButton); |
|
195 if (backgroundVisible != visible) { |
|
196 backgroundVisible = visible; |
|
197 // required to make extension orientation switch from |
|
198 // landscape to portrait work correctly with automatic more |
|
199 // extension. |
|
200 q->repolish(); |
|
201 } |
|
202 } |
|
203 |
|
204 void HbToolButtonPrivate::setLayoutProperty(const char *name, bool value) |
|
205 { |
|
206 Q_Q(HbToolButton); |
|
207 q->setProperty(name, value); |
|
208 if (q->isVisible() && polished) { |
|
209 q->repolish(); |
|
210 } |
|
211 } |
|
212 |
|
213 QSizeF HbToolButtonPrivate::getMinimumSize() |
|
214 { |
|
215 Q_Q(HbToolButton); |
|
216 mRepolishRequested = true; |
|
217 polishPending = false; |
|
218 q->updateGeometry(); |
|
219 QSizeF size = q->minimumSize(); |
|
220 //Workaround (causing extra polish) |
|
221 mSizeHintPolish = false; |
|
222 //workaround ends |
|
223 return size; |
|
224 } |
|
225 |
|
226 void HbToolButtonPrivate::_q_actionTriggered() |
|
227 { |
|
228 Q_Q(HbToolButton); |
|
229 emit q->triggered(action); |
|
230 } |
|
231 |
|
232 void HbToolButtonPrivate::_q_actionChanged() |
|
233 { |
|
234 Q_Q(HbToolButton); |
|
235 if (!action->icon().isNull()) { |
|
236 if (orientation == Qt::Horizontal) { |
|
237 buttonStyle = HbToolButton::ToolButtonIcon; |
|
238 } else if (!action->text().isEmpty()) { |
|
239 buttonStyle = HbToolButton::ToolButtonTextAndIcon; |
|
240 } else { |
|
241 buttonStyle = HbToolButton::ToolButtonIcon; |
|
242 } |
|
243 } else { |
|
244 buttonStyle = HbToolButton::ToolButtonText; |
|
245 } |
|
246 // action text/icon may have changed, |
|
247 if (q->isVisible() && polished) { |
|
248 q->repolish(); |
|
249 } |
|
250 } |
|
251 |
|
252 void HbToolButtonPrivate::showToolTip() |
|
253 { |
|
254 Q_Q(HbToolButton); |
|
255 HbToolTip::showText(q->toolTip(), q, orientation == Qt::Vertical ? Qt::AlignTop : Qt::AlignLeft); |
|
256 } |
|
257 |
|
258 /*! |
|
259 Constructs a new HbToolButton with \a parent. |
|
260 */ |
|
261 HbToolButton::HbToolButton(QGraphicsItem *parent) : |
|
262 HbAbstractButton(*new HbToolButtonPrivate, parent) |
|
263 { |
|
264 Q_D(HbToolButton); |
|
265 d->q_ptr = this; |
|
266 } |
|
267 |
|
268 /*! |
|
269 Constructs a new HbToolButton with \a action and \a parent. |
|
270 |
|
271 Ownership of the \a action is not transferred to the tool button. |
|
272 */ |
|
273 HbToolButton::HbToolButton(HbAction *action, QGraphicsItem *parent) : |
|
274 HbAbstractButton(*new HbToolButtonPrivate, parent) |
|
275 { |
|
276 Q_D(HbToolButton); |
|
277 d->q_ptr = this; |
|
278 setAction(action); |
|
279 setProperty("state", "normal"); |
|
280 } |
|
281 |
|
282 /*! |
|
283 Destructs the tool button. |
|
284 */ |
|
285 HbToolButton::~HbToolButton() |
|
286 { |
|
287 } |
|
288 |
|
289 /*! |
|
290 Returns the action of the button. |
|
291 |
|
292 \sa setAction() |
|
293 */ |
|
294 HbAction *HbToolButton::action() const |
|
295 { |
|
296 Q_D(const HbToolButton); |
|
297 return d->action; |
|
298 } |
|
299 |
|
300 /*! |
|
301 Sets the \a action of the button. |
|
302 |
|
303 Ownership of the \a action is not transferred to the tool button. |
|
304 |
|
305 \sa action() |
|
306 */ |
|
307 void HbToolButton::setAction(HbAction *action) |
|
308 { |
|
309 Q_D(HbToolButton); |
|
310 if (d->action == action) { |
|
311 return; |
|
312 } |
|
313 |
|
314 if (d->action) { |
|
315 disconnect(d->action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); |
|
316 disconnect(d->action, SIGNAL(changed()), this, SLOT(_q_actionChanged())); |
|
317 } |
|
318 |
|
319 HbAction *oldAction = d->action; |
|
320 d->action = action; |
|
321 if (d->action) { |
|
322 connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); |
|
323 connect(action, SIGNAL(changed()), this, SLOT(_q_actionChanged())); |
|
324 } |
|
325 |
|
326 if (isVisible() && d->polished) { |
|
327 // If action was null then there is a chance that the iconitem is not yet created. |
|
328 // If the new action is null then we may need to get rid of the icon completely. |
|
329 if ((!oldAction && action) || (oldAction && !action)) { |
|
330 repolish(); // will call createPrimitives() |
|
331 } |
|
332 updatePrimitives(); |
|
333 } |
|
334 } |
|
335 |
|
336 /*! |
|
337 Returns the background image of the button. |
|
338 */ |
|
339 HbIcon HbToolButton::background() const |
|
340 { |
|
341 Q_D(const HbToolButton); |
|
342 return d->customBackground; |
|
343 } |
|
344 |
|
345 /*! |
|
346 Sets the \a background image of the button. |
|
347 */ |
|
348 void HbToolButton::setBackground(const HbIcon &background) |
|
349 { |
|
350 Q_D(HbToolButton); |
|
351 if (d->customBackground != background) { |
|
352 d->customBackground = background; |
|
353 if (isVisible() || d->polished) |
|
354 updatePrimitives(); |
|
355 } |
|
356 } |
|
357 |
|
358 /*! |
|
359 @beta |
|
360 Returns the tool button style. |
|
361 |
|
362 The default value is \b HbToolButton::ToolButtonIcon. |
|
363 |
|
364 \sa setToolButtonStyle() |
|
365 */ |
|
366 HbToolButton::ToolButtonStyle HbToolButton::toolButtonStyle() const |
|
367 { |
|
368 Q_D(const HbToolButton); |
|
369 return d->buttonStyle; |
|
370 } |
|
371 |
|
372 /*! |
|
373 @beta |
|
374 Sets the tool button style. |
|
375 |
|
376 \sa toolButtonStyle() |
|
377 */ |
|
378 void HbToolButton::setToolButtonStyle(HbToolButton::ToolButtonStyle style) |
|
379 { |
|
380 Q_D(HbToolButton); |
|
381 if (d->buttonStyle != style) { |
|
382 d->buttonStyle = style; |
|
383 |
|
384 // action text/icon may have changed, |
|
385 // primitives might need to be created/cleaned up |
|
386 if (size() != QSize(0, 0)) { |
|
387 repolish(); |
|
388 } |
|
389 } |
|
390 } |
|
391 |
|
392 /*! |
|
393 \reimp |
|
394 */ |
|
395 QGraphicsItem *HbToolButton::primitive(HbStyle::Primitive primitive) const |
|
396 { |
|
397 Q_D(const HbToolButton); |
|
398 switch (primitive) { |
|
399 case HbStyle::P_ToolButton_frame: |
|
400 return d->frameItem; |
|
401 case HbStyle::P_ToolButton_icon: |
|
402 return d->iconItem; |
|
403 case HbStyle::P_ToolButton_text: |
|
404 return d->textItem; |
|
405 default: |
|
406 return 0; |
|
407 } |
|
408 } |
|
409 |
|
410 /*! |
|
411 \reimp |
|
412 */ |
|
413 void HbToolButton::updatePrimitives() |
|
414 { |
|
415 Q_D(HbToolButton); |
|
416 |
|
417 HbStyleOptionToolButton option; |
|
418 if (d->action) { |
|
419 setCheckable(d->action->isCheckable()); |
|
420 setChecked(d->action->isChecked()); |
|
421 setEnabled(d->action->isEnabled()); |
|
422 HbAction *hbAction = qobject_cast<HbAction *>(d->action); |
|
423 if (hbAction && (!hbAction->toolTip().isEmpty()) && (hbAction->toolTip() != toolTip())) { |
|
424 setToolTip(hbAction->toolTip()); |
|
425 } else if(!hbAction && d->action->toolTip() != toolTip()) { |
|
426 setToolTip(d->action->toolTip()); |
|
427 } |
|
428 setVisible(d->action->isVisible()); |
|
429 } |
|
430 |
|
431 initStyleOption(&option); |
|
432 setProperty("dialogtoolbar", d->mDialogToolBar); |
|
433 if (d->frameItem) { |
|
434 style()->updatePrimitive(d->frameItem, HbStyle::P_ToolButton_frame, &option); |
|
435 } |
|
436 if (d->textItem) { |
|
437 style()->updatePrimitive(d->textItem, HbStyle::P_ToolButton_text, &option); |
|
438 } |
|
439 if (d->iconItem) { |
|
440 style()->updatePrimitive(d->iconItem, HbStyle::P_ToolButton_icon, &option); |
|
441 if (d->action && d->action->icon().flags() & HbIcon::Colorized) { |
|
442 static_cast<HbIconItem *>(d->iconItem)->setFlags(HbIcon::Colorized); |
|
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 /*! |
|
448 Initializes \a option with the values from this HbToolButton. This method is useful for |
|
449 subclasses when they need a HbStyleOptionToolButton, but don't want to fill in all the |
|
450 information themselves. |
|
451 */ |
|
452 void HbToolButton::initStyleOption(HbStyleOptionToolButton *option) const |
|
453 { |
|
454 Q_D(const HbToolButton); |
|
455 HbAbstractButton::initStyleOption(option); |
|
456 |
|
457 Q_ASSERT(option); |
|
458 option->customBackground = d->customBackground; |
|
459 option->backgroundVisible = d->backgroundVisible; |
|
460 option->toolBarPosition = d->toolBarPosition; |
|
461 option->orientation = d->orientation; |
|
462 option->isCheckable = d->checkable; |
|
463 option->useSecondaryGraphics = d->mDialogToolBar; |
|
464 |
|
465 if (d->action) { |
|
466 option->text = d->action->text(); |
|
467 option->icon = d->action->icon(); |
|
468 } |
|
469 } |
|
470 |
|
471 /*! |
|
472 \internal |
|
473 */ |
|
474 HbToolButton::HbToolButton(HbToolButtonPrivate &dd, QGraphicsItem *parent) : |
|
475 HbAbstractButton(dd, parent) |
|
476 { |
|
477 } |
|
478 |
|
479 /*! |
|
480 \reimp |
|
481 */ |
|
482 void HbToolButton::resizeEvent(QGraphicsSceneResizeEvent *event) |
|
483 { |
|
484 Q_D(HbToolButton); |
|
485 QGraphicsWidget::resizeEvent(event); |
|
486 if (event->newSize() != event->oldSize() && d->polished && isVisible()) { |
|
487 updatePrimitives(); |
|
488 } |
|
489 if (action() && action()->toolBarExtension()) { |
|
490 HbToolBarExtensionPrivate::d_ptr(action()->toolBarExtension())->placeToolBarExtension(); |
|
491 } |
|
492 } |
|
493 |
|
494 /*! |
|
495 \reimp |
|
496 */ |
|
497 void HbToolButton::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
498 { |
|
499 HbAbstractButton::mousePressEvent(event); |
|
500 setProperty("state", "pressed"); |
|
501 updatePrimitives(); |
|
502 } |
|
503 |
|
504 /*! |
|
505 \reimp |
|
506 */ |
|
507 void HbToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) |
|
508 { |
|
509 HbAbstractButton::mouseReleaseEvent(event); |
|
510 setProperty("state", "normal"); |
|
511 updatePrimitives(); |
|
512 } |
|
513 |
|
514 /*! |
|
515 \reimp |
|
516 */ |
|
517 void HbToolButton::nextCheckState() |
|
518 { |
|
519 Q_D(HbToolButton); |
|
520 HbAbstractButton::nextCheckState(); |
|
521 if (!d->action) { |
|
522 return; |
|
523 } |
|
524 if ( d->action->toolBarExtension() ) { |
|
525 HbToolBarExtensionPrivate::d_ptr(d->action->toolBarExtension())->mExtendedButton = this; |
|
526 d->action->toolBarExtension()->show(); |
|
527 } |
|
528 |
|
529 d->action->trigger(); |
|
530 } |
|
531 |
|
532 /*! |
|
533 \reimp |
|
534 */ |
|
535 bool HbToolButton::event(QEvent *event) |
|
536 { |
|
537 if (event) { |
|
538 switch (event->type()) { |
|
539 case QEvent::GraphicsSceneMouseRelease: { |
|
540 mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event)); |
|
541 return true; |
|
542 } |
|
543 case QEvent::GraphicsSceneHelp: { |
|
544 Q_D(HbToolButton); |
|
545 // Check whether toolbutton is inside a toolbar. |
|
546 if (d->toolBarPosition != HbStyleOptionToolButton::TB_None) { |
|
547 d->showToolTip(); |
|
548 event->accept(); |
|
549 return true; |
|
550 } |
|
551 } |
|
552 break; |
|
553 |
|
554 default: break; |
|
555 } |
|
556 } |
|
557 |
|
558 return HbAbstractButton::event(event); |
|
559 } |
|
560 |
|
561 void HbToolButton::polish(HbStyleParameters ¶ms) |
|
562 { |
|
563 Q_D(HbToolButton); |
|
564 setProperty("orientation", d->orientation); |
|
565 d->createPrimitives(); |
|
566 updatePrimitives(); |
|
567 HbAbstractButton::polish(params); |
|
568 // workaround for caching problem |
|
569 setMinimumSize(minimumSize()); |
|
570 // workaround ends |
|
571 } |
|
572 |
|
573 #include "moc_hbtoolbutton.cpp" |