src/hbcore/gui/hbtoolbutton.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/gui/hbtoolbutton.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbCore module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbtoolbutton.h"
+#include "hbtoolbutton_p.h"
+#include "hbtooltip.h"
+#include "hbstyleoptiontoolbutton.h"
+#include "hbtoolbarextension.h"
+#include "hbtoolbarextension_p.h"
+#include "hbaction.h"
+#include "hbaction_p.h"
+#include <hbglobal.h>
+#include "hbcolorscheme.h"
+#include "hbtextitem.h"
+#include "hbiconitem.h"
+
+#include <QGraphicsSceneHelpEvent>
+#include <QGraphicsSceneMouseEvent>
+
+/*!
+    @stable
+    @hbcore
+    \class HbToolButton
+    \brief The HbToolButton class provides a quick-access button for actions.
+
+    A tool button is a special button that provides quick-access to
+    a specific action. Unlike a normal push button HbPushButton, a tool
+    button represents an action. In other words, HbToolButton is
+    synchronized with an instance of HbAction.
+
+    The action may also be associated with other parts of the user interface,
+    as menu items and keyboard shortcuts. Sharing actions in this way helps
+    make the user interface more consistent and is often less work to implement.
+
+    Tool buttons are normally created indirectly when actions are added to a
+    toolbar with HbToolBar::addAction(). It is also possible to
+    construct tool buttons directly in the same way as any other widget, and
+    arrange them alongside other widgets in layouts.
+
+    The style of a tool button is adjustable with setToolButtonStyle().
+    By default a tool button shows only an icon.
+
+    A tool button's background is set as HbIcon. This makes it possible to
+    specify different images for the normal and pressed states.
+
+    Example usage:
+    \code
+    HbAction *action = new HbAction(icon, name, this);
+    HbToolButton *toolButton = new HbToolButton(action, this);
+    layout->addItem(toolButton);
+    \endcode
+
+    \sa HbAction, HbPushButton
+*/
+
+/*!
+    \enum HbToolButton::ToolButtonStyle
+
+    This enum defines available tool button styles.
+
+    The tool button style describes how the button's text and icon should be displayed.
+ */
+
+/*!
+    \var HbToolButton::ToolButtonIcon
+
+    Only display the icon.
+ */
+
+/*!
+    \var HbToolButton::ToolButtonText
+
+    Only display the text.
+ */
+
+/*!
+    \var HbToolButton::ToolButtonTextAndIcon
+
+    Display both text and icon.
+ */
+
+/*!
+    \fn void HbToolButton::triggered(HbAction *action)
+
+    This signal is emitted when the \a action is triggered.
+ */
+
+/*!
+    \reimp
+    \fn int HbToolButton::type() const
+ */
+
+HbToolButtonPrivate::HbToolButtonPrivate() :
+    action(0),
+    textItem(0),
+    iconItem(0),
+    frameItem(0),
+    customBackground(),
+    backgroundVisible(true),
+    buttonStyle(HbToolButton::ToolButtonIcon),
+    toolBarPosition(HbStyleOptionToolButton::TB_None),
+    orientation(Qt::Vertical),
+    mDialogToolBar(false),
+    mButtonSize(QSizeF())
+{    
+}
+
+HbToolButtonPrivate::~HbToolButtonPrivate()
+{
+}
+
+void HbToolButtonPrivate::createPrimitives()
+{
+    Q_Q(HbToolButton);
+    
+    if (backgroundVisible) {
+        if (!frameItem) {
+            frameItem = q->style()->createPrimitive(HbStyle::P_ToolButton_frame, q);
+        }
+    } else if (frameItem) {
+        delete frameItem;
+        frameItem = 0;
+    }
+
+    if (action && !action->text().isEmpty()) {
+        if (!textItem) {
+            textItem = static_cast<HbTextItem *>(q->style()->createPrimitive(HbStyle::P_ToolButton_text, q));            
+            textItem->setTextWrapping(Hb::TextWordWrap);
+        }
+        textItem->setVisible(buttonStyle & HbToolButton::ToolButtonText);
+    } else if (textItem) {
+        delete textItem;
+        textItem = 0;
+    }
+
+    if (action && (buttonStyle & HbToolButton::ToolButtonIcon)) {
+        if (!iconItem) {
+            iconItem = q->style()->createPrimitive(HbStyle::P_ToolButton_icon, q);
+        }
+    } else if (iconItem){
+        delete iconItem;
+        iconItem = 0;
+    }
+}
+
+void HbToolButtonPrivate::setOrientation(Qt::Orientation orientation)
+{
+    if (this->orientation != orientation) {
+        this->orientation = orientation;
+        Q_Q(HbToolButton);        
+        if (q->isVisible() && polished) {
+            q->repolish();
+        }
+    }    
+}
+
+void HbToolButtonPrivate::setToolBarPosition(HbStyleOptionToolButton::ToolBarPosition position)
+{
+    Q_Q(HbToolButton);
+    if (toolBarPosition != position) {
+        toolBarPosition = position;
+        // required for toolbar()->action()[i]->setVisible(visible)
+        // to work for all cases
+        if (q->isVisible() && polished) {
+            q->updatePrimitives();
+        }
+    }    
+}
+
+void HbToolButtonPrivate::setBackgroundVisible(bool visible)
+{
+    Q_Q(HbToolButton);
+    if (backgroundVisible != visible) {
+        backgroundVisible = visible;
+        // required to make extension orientation switch from
+        // landscape to portrait work correctly with automatic more
+        // extension.
+        q->repolish();
+    }
+}
+
+void HbToolButtonPrivate::setLayoutProperty(const char *name, bool value)
+{
+    Q_Q(HbToolButton);
+    q->setProperty(name, value);
+    if (q->isVisible() && polished) {
+        q->repolish();
+    }
+}
+
+QSizeF HbToolButtonPrivate::getMinimumSize()
+{
+    Q_Q(HbToolButton);
+    mRepolishRequested = true;
+    polishPending = false;
+    q->updateGeometry();
+    QSizeF size = q->minimumSize();
+    //Workaround (causing extra polish)
+    mSizeHintPolish = false;
+    //workaround ends
+    return size;
+}
+
+void HbToolButtonPrivate::_q_actionTriggered()
+{
+    Q_Q(HbToolButton);
+    emit q->triggered(action);
+}
+
+void HbToolButtonPrivate::_q_actionChanged()
+{
+    Q_Q(HbToolButton);
+    if (!action->icon().isNull()) {
+        if (orientation == Qt::Horizontal) {
+            buttonStyle = HbToolButton::ToolButtonIcon;
+        } else if (!action->text().isEmpty()) {
+            buttonStyle = HbToolButton::ToolButtonTextAndIcon;
+        } else {
+            buttonStyle = HbToolButton::ToolButtonIcon;
+        }
+    } else {
+        buttonStyle = HbToolButton::ToolButtonText;
+    }
+    // action text/icon may have changed,            
+    if (q->isVisible() && polished) {
+        q->repolish();
+    }
+}
+
+void HbToolButtonPrivate::showToolTip()
+{
+    Q_Q(HbToolButton);
+    HbToolTip::showText(q->toolTip(), q, orientation == Qt::Vertical ? Qt::AlignTop : Qt::AlignLeft);
+}
+
+/*!
+    Constructs a new HbToolButton with \a parent.
+*/
+HbToolButton::HbToolButton(QGraphicsItem *parent) :
+    HbAbstractButton(*new HbToolButtonPrivate, parent)
+{
+    Q_D(HbToolButton);
+    d->q_ptr = this;
+}
+
+/*!
+    Constructs a new HbToolButton with \a action and \a parent.
+
+    Ownership of the \a action is not transferred to the tool button.
+ */
+HbToolButton::HbToolButton(HbAction *action, QGraphicsItem *parent) :
+    HbAbstractButton(*new HbToolButtonPrivate, parent)
+{
+    Q_D(HbToolButton);
+    d->q_ptr = this;
+    setAction(action);
+    setProperty("state", "normal");
+}
+
+/*!
+    Destructs the tool button.
+ */
+HbToolButton::~HbToolButton()
+{
+}
+
+/*!
+    Returns the action of the button.
+
+    \sa setAction()
+ */
+HbAction *HbToolButton::action() const
+{
+    Q_D(const HbToolButton);
+    return d->action;
+}
+
+/*!
+    Sets the \a action of the button.
+
+    Ownership of the \a action is not transferred to the tool button.
+
+    \sa action()
+ */
+void HbToolButton::setAction(HbAction *action)
+{
+    Q_D(HbToolButton);
+    if (d->action == action) {
+        return;
+    }
+
+    if (d->action) {
+        disconnect(d->action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+        disconnect(d->action, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+    }
+
+    HbAction *oldAction = d->action;
+    d->action = action;
+    if (d->action) {
+        connect(action, SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
+        connect(action, SIGNAL(changed()), this, SLOT(_q_actionChanged()));
+    }
+
+    if (isVisible() && d->polished) {
+        // If action was null then there is a chance that the iconitem is not yet created.
+        // If the new action is null then we may need to get rid of the icon completely.
+        if ((!oldAction && action) || (oldAction && !action)) {
+            repolish(); // will call createPrimitives()
+        }
+        updatePrimitives();
+    }
+}
+
+/*!
+    Returns the background image of the button.
+ */
+HbIcon HbToolButton::background() const
+{
+    Q_D(const HbToolButton);
+    return d->customBackground;
+}
+
+/*!
+    Sets the \a background image of the button.
+ */
+void HbToolButton::setBackground(const HbIcon &background)
+{
+    Q_D(HbToolButton);
+    if (d->customBackground != background) {
+        d->customBackground = background;
+        if (isVisible() || d->polished)
+            updatePrimitives();
+    }
+}
+
+/*!
+    @beta
+    Returns the tool button style.
+
+    The default value is \b HbToolButton::ToolButtonIcon.
+
+    \sa setToolButtonStyle()
+ */
+HbToolButton::ToolButtonStyle HbToolButton::toolButtonStyle() const
+{
+    Q_D(const HbToolButton);
+    return d->buttonStyle;
+}
+
+/*!
+    @beta
+    Sets the tool button style.
+
+    \sa toolButtonStyle()
+ */
+void HbToolButton::setToolButtonStyle(HbToolButton::ToolButtonStyle style)
+{    
+    Q_D(HbToolButton);
+    if (d->buttonStyle != style) {
+        d->buttonStyle = style;
+
+        // action text/icon may have changed,
+        // primitives might need to be created/cleaned up
+        if (size() != QSize(0, 0)) {
+            repolish();
+        }
+    }
+}
+
+/*!
+    \reimp
+ */
+QGraphicsItem *HbToolButton::primitive(HbStyle::Primitive primitive) const
+{
+    Q_D(const HbToolButton);
+    switch (primitive) {
+        case HbStyle::P_ToolButton_frame:
+            return d->frameItem;
+        case HbStyle::P_ToolButton_icon:
+            return d->iconItem;
+        case HbStyle::P_ToolButton_text:
+            return d->textItem;
+        default:
+            return 0;
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbToolButton::updatePrimitives()
+{
+    Q_D(HbToolButton);
+
+    HbStyleOptionToolButton option;
+    if (d->action) {
+        setCheckable(d->action->isCheckable());
+        setChecked(d->action->isChecked());
+        setEnabled(d->action->isEnabled());
+        HbAction *hbAction = qobject_cast<HbAction *>(d->action);
+        if (hbAction && (!hbAction->toolTip().isEmpty()) && (hbAction->toolTip() != toolTip())) {
+            setToolTip(hbAction->toolTip());
+        } else if(!hbAction && d->action->toolTip() != toolTip()) {
+            setToolTip(d->action->toolTip());
+        }
+        setVisible(d->action->isVisible());
+    }
+
+    initStyleOption(&option);
+    setProperty("dialogtoolbar", d->mDialogToolBar);
+    if (d->frameItem) {
+        style()->updatePrimitive(d->frameItem, HbStyle::P_ToolButton_frame, &option);
+    }
+    if (d->textItem) {
+        style()->updatePrimitive(d->textItem, HbStyle::P_ToolButton_text, &option);
+    }
+    if (d->iconItem) {
+        style()->updatePrimitive(d->iconItem, HbStyle::P_ToolButton_icon, &option);
+        if (d->action && d->action->icon().flags() & HbIcon::Colorized) {
+            static_cast<HbIconItem *>(d->iconItem)->setFlags(HbIcon::Colorized);
+        }
+    }
+}
+
+/*!
+    Initializes \a option with the values from this HbToolButton. This method is useful for
+    subclasses when they need a HbStyleOptionToolButton, but don't want to fill in all the
+    information themselves.
+ */
+void HbToolButton::initStyleOption(HbStyleOptionToolButton *option) const
+{
+    Q_D(const HbToolButton);
+    HbAbstractButton::initStyleOption(option);
+
+    Q_ASSERT(option);
+    option->customBackground = d->customBackground;
+    option->backgroundVisible = d->backgroundVisible;
+    option->toolBarPosition = d->toolBarPosition;
+    option->orientation = d->orientation;
+    option->isCheckable = d->checkable;
+    option->useSecondaryGraphics = d->mDialogToolBar;
+
+    if (d->action) {
+        option->text = d->action->text();
+        option->icon = d->action->icon();
+    }
+}
+
+/*!
+    \internal
+ */
+HbToolButton::HbToolButton(HbToolButtonPrivate &dd, QGraphicsItem *parent) :
+    HbAbstractButton(dd, parent)
+{
+}
+
+/*!
+    \reimp
+ */
+void HbToolButton::resizeEvent(QGraphicsSceneResizeEvent *event)
+{
+    Q_D(HbToolButton);
+    QGraphicsWidget::resizeEvent(event);
+    if (event->newSize() !=  event->oldSize() && d->polished && isVisible()) {
+        updatePrimitives();
+    }
+    if (action() && action()->toolBarExtension()) {
+        HbToolBarExtensionPrivate::d_ptr(action()->toolBarExtension())->placeToolBarExtension();
+    }
+}
+
+/*!
+    \reimp
+ */
+void HbToolButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    HbAbstractButton::mousePressEvent(event);
+    setProperty("state", "pressed");
+    updatePrimitives();
+}
+
+/*!
+    \reimp
+ */
+void HbToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    HbAbstractButton::mouseReleaseEvent(event);
+    setProperty("state", "normal");
+    updatePrimitives();
+}
+
+/*!
+    \reimp
+ */
+void HbToolButton::nextCheckState()
+{
+    Q_D(HbToolButton);
+    HbAbstractButton::nextCheckState();
+    if (!d->action) {
+        return;
+    }
+    if ( d->action->toolBarExtension() ) {
+        HbToolBarExtensionPrivate::d_ptr(d->action->toolBarExtension())->mExtendedButton = this;
+        d->action->toolBarExtension()->show();
+    }
+
+    d->action->trigger();
+}
+
+/*!
+    \reimp
+ */
+bool HbToolButton::event(QEvent *event)
+{
+    if (event) {
+        switch (event->type()) {
+            case QEvent::GraphicsSceneMouseRelease: {
+                mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
+                return true;
+            }
+            case QEvent::GraphicsSceneHelp: {
+                    Q_D(HbToolButton);                    
+                    // Check whether toolbutton is inside a toolbar.
+                    if (d->toolBarPosition != HbStyleOptionToolButton::TB_None) {
+                        d->showToolTip();
+                        event->accept();
+                        return true;
+                    }
+                }
+                break;
+
+        default: break;
+        }
+    }
+
+    return HbAbstractButton::event(event);
+}
+
+void HbToolButton::polish(HbStyleParameters &params)
+{
+    Q_D(HbToolButton);
+    setProperty("orientation", d->orientation);
+    d->createPrimitives();
+    updatePrimitives();
+    HbAbstractButton::polish(params);
+    // workaround for caching problem
+    setMinimumSize(minimumSize());
+    // workaround ends
+}
+
+#include "moc_hbtoolbutton.cpp"