src/hbcore/gui/hbstackedwidget.cpp
changeset 0 16d8024aca5e
child 2 06ff229162e9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/gui/hbstackedwidget.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** 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 "hbstackedwidget.h"
+#include "hbstackedlayout.h"
+#include "hbwidget_p.h"
+
+/*!
+    \class HbStackedWidget
+    \brief HbStackedWidget manages geometries of stacked layout contents.
+    
+    HbStackedLayout is a simple container that allows client add several widgets
+    and then select one widget to be shown. This widget will manage visibility 
+    and focus in addition to size and position. 
+
+    Example code:
+    \snippet{stackedwidgetsample.cpp,1}
+    
+    \sa HbStackedLayout
+    \alpha
+ */
+
+
+class HbStackedWidgetPrivate : public HbWidgetPrivate
+{
+    Q_DECLARE_PUBLIC(HbStackedWidget)
+
+public:
+    HbStackedWidgetPrivate() : mCurrentIndex(-1), mLayout(0) {}
+
+    void setCurrentIndex(int index, QGraphicsWidget *prev, bool hideOld = true, bool showNew = true);
+    
+    int mCurrentIndex;
+    HbStackedLayout *mLayout;
+};
+
+/*!
+    \brief Sets current widget from specified index.
+    \param index position of desired widget.
+    \param prev previous widget.
+ */
+void HbStackedWidgetPrivate::setCurrentIndex(int index, QGraphicsWidget *prev, bool hideOld, bool showNew)
+{
+    Q_Q(HbStackedWidget);
+    if (index < 0 || index >= mLayout->count()) {
+        qWarning("HbStackedWidget::setCurrentIndex: index %i is out of range", index);
+        return;
+    }
+
+    QGraphicsWidget *next = q->widgetAt(index);
+    if (next == prev)
+        return;
+
+    QGraphicsWidget* focused = 0;
+    if (prev) {
+        focused = prev->focusWidget();
+        // Set previous widget invisible. Focus will be reset after this statement.
+        if (hideOld) {
+            prev->setVisible(false);
+        }
+    }
+    mCurrentIndex = index;
+    if (showNew) {
+        next->setVisible(true);
+    }
+
+    // set the focus if prev was focusable
+    if (focused) {
+        next->setFocus();
+    }
+    emit q->currentChanged(index);
+}
+
+/*!
+    Constructor.
+    \param parent parent graphics item
+ */
+HbStackedWidget::HbStackedWidget(QGraphicsItem *parent)
+    : HbWidget(*new HbStackedWidgetPrivate, parent)
+{
+    Q_D(HbStackedWidget);
+    d->q_ptr = this;
+
+    HbStackedLayout *layout = new HbStackedLayout;
+    setLayout( layout );
+    d->mLayout = layout;
+}
+
+/*!
+    Destructor
+ */
+HbStackedWidget::~HbStackedWidget()
+{
+}
+
+/*!
+    \brief Returns amount of widgets.
+    \return amount of widgets.
+ */
+int HbStackedWidget::count() const
+{
+    Q_D(const HbStackedWidget);
+    return d->mLayout->count();
+}
+
+/*!
+    \brief Adds a widget.
+
+    This is a convenience function which will internally call the \c insertWidget method.
+
+    \param widget widget to be added.
+    \return index of the added widget in the stack.
+ */
+int HbStackedWidget::addWidget(QGraphicsWidget *widget)
+{
+    return insertWidget(-1, widget);
+}
+
+/*!
+    \brief Inserts a widget.
+
+    Inserts the given \a widget to given position \a index.
+    Takes ownership of the widget.
+
+    If \a index is out of range, the widget is appended (in which case it is the actual
+    index of the widget that is returned).
+
+    If the stack was empty before this function is called, the given widget becomes
+    the current widget and it will be set visible. Otherwise the widget will be set
+    invisible.
+
+    Inserting a new widget at an index less than or equal to the current index will increment
+    the current index, but keep the current widget.
+
+    \param index index to which to add.
+    \param widget widget to be inserted.
+    \return index of the added widget in the stack.
+ */
+int HbStackedWidget::insertWidget(int index, QGraphicsWidget *widget)
+{
+    Q_D(HbStackedWidget);
+    int addedIndex = d->mLayout->insertItem(index, widget); // this will usually reparent 'widget'
+    if ( addedIndex != -1 ) {
+        // Need to store current index, since it might change
+        // during "widgetAdded" signal (someone might call back
+        // e.g. "setCurrentIndex".
+        int currentIndex = d->mCurrentIndex;
+        emit widgetAdded(addedIndex);
+        if ( currentIndex == d->mCurrentIndex ) {
+            // Current index not touched from outside.
+            if (d->mCurrentIndex < 0) {
+                setCurrentIndex(addedIndex);
+            } else  {
+                widget->setVisible(false);
+                if (addedIndex <= d->mCurrentIndex) {
+                    d->mCurrentIndex++;
+                    emit currentChanged(d->mCurrentIndex);
+                }
+            }
+        }
+    }
+    return addedIndex;
+}
+
+/*!
+    \brief Removes a widget.
+
+    Removes the given \a widget from the stack. The widget is not deleted.
+    The widget is set invisible.
+
+    Removing the current widget will set the next widget (or previous
+    if the current widget was the last one) to be the current widget.
+
+    Removing a widget from an index less than the current index will
+    decrement the current index, but keep the current widget.
+
+    \param widget widget to be removed.
+ */
+void HbStackedWidget::removeWidget(QGraphicsWidget *widget)
+{
+    Q_D(HbStackedWidget);
+    int index = indexOf(widget);
+    if ( index == -1 ) {
+        return;
+    }
+    d->mLayout->removeAt(index);
+
+    if ( index == d->mCurrentIndex ) {
+        d->mCurrentIndex = -1;
+        int c = count();
+        if ( c > 0 ) {
+            int newIndex = (index == c) ? index-1 : index;
+            d->setCurrentIndex(newIndex, widget);
+        } else {
+            // The last widget was removed.
+            widget->setVisible(false);
+            emit currentChanged( -1 );
+        }
+    } else if ( index <= d->mCurrentIndex ) {
+        d->mCurrentIndex--;
+        emit currentChanged(d->mCurrentIndex);
+    }
+    widget->setParentItem(0);
+    emit widgetRemoved(index);
+    emit widgetRemoved(widget);
+}
+
+/*!
+    \brief Removes a widget from specified position.
+
+    This is a convenience function which will internally call the \c removeWidget method.
+
+    The removed widget is not deleted but returned to caller.
+
+    \param index position of the widget to be removed.
+    \return the removed widget.
+ */
+QGraphicsWidget *HbStackedWidget::removeAt(int index)
+{
+    QGraphicsWidget *widget = widgetAt(index);
+    if ( widget ) {
+        removeWidget(widget);
+    }
+    return widget;
+}
+
+
+/*!
+    \brief Returns position of specified widget.
+    \param widget widget to look for.
+ */
+int HbStackedWidget::indexOf(QGraphicsWidget *widget) const
+{
+    Q_D(const HbStackedWidget);
+    return d->mLayout->indexOf(widget);
+}
+
+/*!
+    \brief Returns index of current widget.
+    \return current index, or -1 if undefined.
+ */
+int HbStackedWidget::currentIndex() const
+{
+    Q_D(const HbStackedWidget);
+    return d->mCurrentIndex;
+}
+
+/*!
+    \brief Returns widget at specified position.
+    \param index position of widget.
+ */
+QGraphicsWidget *HbStackedWidget::widgetAt(int index) const
+{
+    Q_D(const HbStackedWidget);
+    return static_cast<QGraphicsWidget*>(d->mLayout->itemAt(index));
+}
+
+/*!
+    \brief Returns current widget.
+    \return current widget, or 0 if undefined.
+ */
+QGraphicsWidget *HbStackedWidget::currentWidget() const
+{
+    Q_D(const HbStackedWidget);
+    return widgetAt(d->mCurrentIndex);
+}
+
+/*! \fn void HbStackedWidget::widgetAdded(int index)
+    \brief This signal is emitted when a widget is added to this widget.
+    \param index position of the added widget.
+ */
+
+/*! \fn void HbStackedWidget::widgetRemoved(int index)
+    \brief This signal is emitted when a widget is removed from this widget.
+    \param index position of the removed widget.
+ */
+
+/*! \fn void HbStackedWidget::widgetRemoved(QGraphicsWidget *widget)
+    \brief This signal is emitted when a widget is removed from this widget.
+    \param widget the removed widget.
+ */
+
+/*! \fn void HbStackedWidget::currentChanged(int index)
+    \brief This signal is emitted when the current widget is changed.
+
+    The signal is emitted whenever either the current index or the current
+    widget changes. In some cases (e.g. when removing a widget before the
+    current widget) the current index changes but current widget doesn't and
+    in some other cases (e.g. when removing the current widget) the current
+    widget changes but the current index doesn't.
+
+    \param index position of the new current widget.
+ */
+
+ /*!
+    \brief Sets current widget from specified index.
+
+    This method will set the widget at given \a index visible and 
+    the previous widget invisible.
+
+    \param index position of desired widget.
+ */
+void HbStackedWidget::setCurrentIndex(int index)
+{
+    Q_D(HbStackedWidget);
+    d->setCurrentIndex(index, currentWidget());
+}
+
+/*!
+    \brief Sets current widget.
+
+    This is a convenience function, same as finding the widget's index
+    and calling setCurrentIndex().
+
+    \param widget desired widget.
+ */
+void HbStackedWidget::setCurrentWidget(QGraphicsWidget *widget)
+{
+    Q_D(HbStackedWidget);
+    int index = d->mLayout->indexOf(widget);
+    if (index == -1) {
+        qWarning("HbStackedWidget::setCurrentWidget: Widget %p not contained in stack", widget);
+        return;
+    }
+    d->setCurrentIndex(index, currentWidget());
+}
+
+/*!
+    \brief Sets current widget.
+
+    This is a convenience function which will internally call the \c setCurrentIndex method.
+
+    \param widget Desired widget.
+    \param hideOld Indicates of the old widget (from which we are switching away) should be made invisible or not.
+    \param showNew Indicates if the new widget (\a widget) should be made visible or not.
+ */
+void HbStackedWidget::setCurrentWidget(QGraphicsWidget *widget, bool hideOld, bool showNew)
+{
+    Q_D(HbStackedWidget);
+    int index = d->mLayout->indexOf(widget);
+    if (index == -1) {
+        qWarning("HbStackedWidget::setCurrentWidget: Widget %p not contained in stack", widget);
+        return;
+    }
+    d->setCurrentIndex(index, currentWidget(), hideOld, showNew);
+}