homescreenapp/stateplugins/hsapplibrarystateplugin/src/hscollectionstate.cpp
branchRCL_3
changeset 82 5f0182e07bfb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/homescreenapp/stateplugins/hsapplibrarystateplugin/src/hscollectionstate.cpp	Tue Aug 31 15:06:34 2010 +0300
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description: Menu collection state.
+ *
+ */
+
+#include <QStateMachine>
+#include <HbAction>
+#include <HbView>
+#include <HbGroupBox>
+#include <HbListView>
+#include <HbPushButton>
+#include <HbAbstractViewItem>
+#include <HbMenu>
+
+#include <cadefs.h>
+#include <caentry.h>
+#include <caitemmodel.h>
+
+#include "hsapp_defs.h"
+#include "hsmenuevent.h"
+#include "hsmenueventfactory.h"
+#include "hsmenuservice.h"
+#include "hsmenumodewrapper.h"
+#include "hsmenuitemmodel.h"
+#include "hscollectionstate.h"
+#include "hsaddappstocollectionstate.h"
+#include "hsapplibstateutils.h"
+
+/*!
+ \class HsCollectionState
+ \ingroup group_hsmenustateplugin
+ \brief Collection State.
+ Displays a concrete collection.
+ \lib ?library
+ \see StateMachine
+ */
+
+/*!
+ \var HsCollectionState::mSortAttribute
+ Sort order.
+ */
+
+/*!
+ \var HsCollectionState::mCollectionId
+ The id of the current collection.
+ */
+
+/*!
+ \var HsCollectionState::mCollectionType
+ The type of the current collection.
+ */
+
+
+/*!
+  \fn void HsCollectionState::sortOrderChanged(SHsSortAttribute sortOrder);
+  This signal is emitted when sort order is changed to \a sortOrder.
+  \param sortAttribute sort attribute
+ */
+
+/*!
+  \fn void HsCollectionState::constructMenu(bool isDynamic);
+  Set up Menu.
+  \param isDynamic Decides which options should be added to menu.
+ */
+
+/*!
+ Constructor.
+ \param menuViewBuilder Menu view builder.
+ \param menuMode menu mode object (add mode on/add mode off).
+ \param mainWindow main window wrapper.
+ \param parent Owner.
+*/
+HsCollectionState::HsCollectionState(HsMenuViewBuilder &menuViewBuilder,
+                                     HsMenuModeWrapper &menuMode,
+                                     HsMainWindow &mainWindow,
+                                     QState *parent) :
+    HsBaseViewState(mainWindow, menuMode, parent),
+    mSortAttribute(Hs::LatestOnTopHsSortAttribute),
+    mCollectionId(-1)
+{
+    initialize(menuViewBuilder, HsCollectionContext);
+    construct();
+}
+
+/*!
+ Constructs contained objects.
+ */
+void HsCollectionState::construct()
+{
+    HSMENUTEST_FUNC_ENTRY("HsCollectionState::construct");
+
+    const QString parentName =
+        parent() != 0 ? parent()->objectName() : QString("");
+    setObjectName(parentName + "/collectionstate");
+
+    HSMENUTEST_FUNC_EXIT("HsCollectionState::construct");
+}
+
+/*!
+ Destructor.
+ */
+HsCollectionState::~HsCollectionState()
+{
+    mMenuView->inactivate();
+    mMenuView->view()->setNavigationAction(NULL);
+}
+
+
+/*!
+ Sets entry event.
+ \param event entry event.
+ */
+void HsCollectionState::onEntry(QEvent *event)
+{
+    qDebug("HsCollectionState::onEntry()");
+    HSMENUTEST_FUNC_ENTRY("HsCollectionState::onEntry");
+    QState::onEntry(event);
+
+    if (event->type() == HsMenuEvent::eventType()) {
+        HsMenuEvent *menuEvent = static_cast<HsMenuEvent *>(event);
+        QVariantMap data = menuEvent->data();
+        mCollectionId = data.value(Hs::itemIdKey).toInt();
+        mCollectionType = data.value(Hs::entryTypeNameKey).toString();
+    }
+
+    HSMENUTEST_FUNC_EXIT("HsCollectionState::onEntry");
+}
+
+/*!
+ Slot invoked when a state is entered.
+ */
+void HsCollectionState::stateEntered()
+{
+    HSMENUTEST_FUNC_ENTRY("HsCollectionState::stateEntered");
+    if (!mModel) {
+        mModel =
+            HsMenuService::getCollectionModel(
+                mCollectionId, mSortAttribute, mCollectionType);
+    }
+
+    handleEmptyChange(mModel->rowCount() == 0);
+
+    makeConnect();
+    
+    mMenuView->viewLabel()->setHeading(
+        mModel->root().data(CaItemModel::CollectionTitleRole).toString());
+
+    HsBaseViewState::stateEntered();
+    HSMENUTEST_FUNC_EXIT("HsCollectionState::stateEntered");
+}
+
+/*!
+ Creates and installs menu options for the view
+ */
+void HsCollectionState::setMenuOptions()
+{
+    HSMENUTEST_FUNC_ENTRY("HsAllCollectionsState::setMenuOptions");
+
+    EntryFlags flags =
+        mModel->root().data(CaItemModel::FlagsRole).value<EntryFlags> ();
+
+    mViewOptions->clearActions();
+
+    mViewOptions->addAction(hbTrId("txt_applib_opt_task_switcher"),
+                            static_cast<HsBaseViewState*>(this),
+                            SLOT(openTaskSwitcher()));
+
+    if (flags & RemovableEntryFlag) {
+        mViewOptions->addAction(hbTrId("txt_applib_opt_add_content"), this,
+                            SLOT(addAppsAction()));
+    }
+
+    mViewOptions->addAction(hbTrId("txt_applib_opt_add_to_home_screen"),
+                        this, SLOT(addCollectionShortcutToHomeScreenAction()));
+
+    if (flags & RemovableEntryFlag) {
+        if (mModel->rowCount() > 0) {
+            mViewOptions->addAction(
+                hbTrId("txt_applib_opt_arrange"),
+                this,
+                SLOT(createArrangeCollection()));
+        }
+        mViewOptions->addAction(
+            hbTrId("txt_common_opt_rename_item"),
+            this,
+            SLOT(renameAction()));
+        mViewOptions->addAction(
+            hbTrId("txt_common_opt_delete"),
+            this,
+            SLOT(deleteAction()));
+    }
+    if (mCollectionType == Hs::collectionDownloadedTypeName && 
+            mModel->rowCount() > 0) {
+        HbMenu *sortMenu = mViewOptions->addMenu(
+                               hbTrId("txt_applib_opt_sort_by"));
+        //Grouped options are exclusive by default.
+        QActionGroup *sortGroup = new QActionGroup(this);
+        sortGroup->addAction(
+            sortMenu->addAction(
+                hbTrId("txt_applib_opt_sub_latest_on_top"),
+                this,
+                SLOT(latestOnTopMenuAction())));
+        sortGroup->addAction(
+            sortMenu->addAction(
+                hbTrId("txt_applib_opt_sub_oldest_on_top"),
+                this,
+                SLOT(oldestOnTopMenuAction())));
+        foreach(QAction *action, sortMenu->actions()) {
+            action->setCheckable(true);
+        }
+        static const int defaultSortingPosition = 0;
+        sortGroup->actions().at(defaultSortingPosition)->setChecked(true);
+    }
+    mMenuView->view()->setMenu(mViewOptions);
+    HSMENUTEST_FUNC_EXIT("HsAllCollectionsState::setMenuOptions");
+}
+
+/*!
+ Slot invoked when a state is exited.
+ */
+void HsCollectionState::stateExited()
+{
+    HSMENUTEST_FUNC_ENTRY("HsCollectionState::stateExited");
+    mMenuView->disableSearch(false);
+    makeDisconnect();
+
+    delete mModel;
+    mModel = NULL;
+    this->mSortAttribute = Hs::NoHsSortAttribute;
+
+    HsBaseViewState::stateExited();
+
+    HSMENUTEST_FUNC_EXIT("HsCollectionState::stateExited");
+    qDebug("CollectionState::stateExited()");
+}
+
+/*!
+ Perform all signal connections.
+ */
+void HsCollectionState::makeConnect()
+{
+    connect(mBackKeyAction, SIGNAL(triggered()),
+            static_cast<HsBaseViewState*>(this), SLOT(openAppLibrary()));
+    connect(mMenuView.data(),
+            SIGNAL(activated(QModelIndex)),
+            static_cast<HsBaseViewState*>(this),
+            SLOT(launchItem(QModelIndex)));
+    connect(mMenuView.data(),
+            SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
+            static_cast<HsBaseViewState*>(this),
+            SLOT(showContextMenu(HbAbstractViewItem *, QPointF)));
+    connect(mModel, SIGNAL(modelReset()), SLOT(updateLabel()));
+    connect(mModel, SIGNAL(empty(bool)),this,
+            SLOT(handleEmptyChange(bool)));
+    connect(mModel, SIGNAL(empty(bool)),this,
+            SLOT(lockSearchButton(bool)));
+}
+
+/*!
+ Perform all signal disconnections.
+ */
+void HsCollectionState::makeDisconnect()
+{
+    disconnect(mBackKeyAction, SIGNAL(triggered()),
+               static_cast<HsBaseViewState*>(this), SLOT(openAppLibrary()));
+
+    disconnect(mMenuView.data(),
+               SIGNAL(activated(QModelIndex)),
+               static_cast<HsBaseViewState*>(this),
+               SLOT(launchItem(QModelIndex)));
+    disconnect(mMenuView.data(),
+               SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
+               static_cast<HsBaseViewState*>(this),
+               SLOT(showContextMenu(HbAbstractViewItem *, QPointF)));
+    disconnect(mModel, SIGNAL(empty(bool)),this,
+               SLOT(handleEmptyChange(bool)));
+
+    disconnect(mModel, SIGNAL(empty(bool)),this,
+               SLOT(lockSearchButton(bool)));
+
+    disconnect(mModel, SIGNAL(modelReset()),
+                   this, SLOT(updateLabel()));
+}
+
+/*!
+ Handles context menu actions
+ \param action action taken in context menu
+ */
+void HsCollectionState::contextMenuAction(HbAction *action)
+{
+    HsBaseViewState::contextMenuAction(action);
+    Hs::HsContextAction command =
+            static_cast<Hs::HsContextAction>(action->data().toInt());
+    if (command == Hs::RemoveFromCollectionContextAction ) {
+        const int itemId = mContextModelIndex.data(CaItemModel::IdRole).toInt();
+        machine()->postEvent(
+            HsMenuEventFactory::createRemoveAppFromCollectionEvent(
+                itemId, mCollectionId));
+    }
+}
+
+/*!
+ Handler to be called when model becomes not empty or model becomes empty.
+  \param empty \a true when model becomes empty \a false otherwise.
+ */
+void HsCollectionState::handleEmptyChange(bool empty)
+{
+
+    EntryFlags flags =
+        mModel->root().data(CaItemModel::FlagsRole).value<
+        EntryFlags> ();
+
+    if (empty){
+        if (flags & RemovableEntryFlag){
+            mMenuView->reset(HsButtonContext);
+            connect(mMenuView->contentButton(),
+                    SIGNAL(clicked()), this, SLOT(addAppsAction()),
+                    Qt::UniqueConnection);
+        } else {
+            mMenuView->reset(HsEmptyLabelContext);
+        }
+
+    } else {
+        mMenuView->reset(HsItemViewContext);
+        mMenuView->setModel(mModel);
+        mMenuView->listView()->scrollTo(
+            mModel->index(0), HbAbstractItemView::PositionAtTop);
+    }
+	
+    mMenuView->disableSearch(empty);
+    
+    mMenuView->activate();
+
+    setMenuOptions();
+}
+
+
+/*!
+ Handles lock search button
+  \param lock if true lock search button.
+ */
+void HsCollectionState::lockSearchButton(bool lock)
+{
+    mMenuView->disableSearch(lock);
+}
+
+
+/*!
+ Menu add applications action slot
+   \param addApps if true create event for add enties to collection.
+   Parametr use by toggled from HbPushButton
+ */
+void HsCollectionState::addAppsAction()
+{
+    // Add applications
+    machine()->postEvent(
+        HsMenuEventFactory::createAddAppsFromCollectionViewEvent(
+            mCollectionId));
+}
+
+/*!
+ Menu add shortcut action slot
+ */
+void HsCollectionState::addCollectionShortcutToHomeScreenAction()
+{
+    addToHomeScreen(mCollectionId);
+}
+
+/*!
+ Menu rename action slot
+ */
+void HsCollectionState::renameAction()
+{
+    machine()->postEvent(HsMenuEventFactory::createRenameCollectionEvent(
+                             mCollectionId));
+}
+
+/*!
+ Menu delete action slot
+ */
+void HsCollectionState::deleteAction()
+{
+    machine()->postEvent(HsMenuEventFactory::createDeleteCollectionEvent(
+                             mCollectionId));
+}
+
+/*!
+ Updates label
+ */
+void HsCollectionState::updateLabel()
+{
+    HSMENUTEST_FUNC_ENTRY("HsCollectionState::updateLabel");
+    if (mModel) {
+        mMenuView->viewLabel()->setHeading(
+            mModel->root().data(Qt::DisplayRole).toString());
+    }
+    HSMENUTEST_FUNC_EXIT("HsCollectionState::updateLabel");
+}
+
+/*!
+ Method setting context menu options.
+ */
+void HsCollectionState::setContextMenuOptions(HbAbstractViewItem *item, EntryFlags flags)
+{
+    HbAction *openAction = mContextMenu->addAction(hbTrId(
+        "txt_common_menu_open"));
+    openAction->setData(Hs::OpenAppContextAction);
+    HbAction *addToHomeScreenAction = mContextMenu->addAction(hbTrId(
+        "txt_applib_menu_add_to_home_screen"));
+    addToHomeScreenAction->setData(Hs::AddToHomeScreenContextAction);
+    HbAction *addToCollection = mContextMenu->addAction(hbTrId(
+        "txt_applib_menu_add_to_collection"));
+    addToCollection->setData(Hs::AddToCollectionFromCollectionViewContextAction);
+    HbAction *removeAction(NULL);
+    HbAction *uninstallAction(NULL);
+    HbAction *appSettingsAction(NULL);
+    HbAction *appDetailsAction(NULL);
+    // we do not add remove option in locked collection
+    // check conditions and hide irrelevant menu items
+    EntryFlags rootFlags =
+        mModel->root().data(CaItemModel::FlagsRole).value<
+        EntryFlags> ();
+
+    if (rootFlags & RemovableEntryFlag) {
+        removeAction = mContextMenu->addAction(
+                           hbTrId("txt_applib_menu_remove_from_collection"));
+        removeAction->setData(Hs::RemoveFromCollectionContextAction);
+    }
+
+    if ((flags & RemovableEntryFlag)) {
+        uninstallAction = mContextMenu->addAction(hbTrId("txt_common_menu_delete"));
+        uninstallAction->setData(Hs::UninstallContextAction);
+    }
+    QSharedPointer<const CaEntry> entry = mModel->entry(item->modelIndex());
+
+    if (!(entry->attribute(Hs::appSettingsPlugin).isEmpty())) {
+        appSettingsAction = mContextMenu->addAction(hbTrId(
+                                                "txt_common_menu_settings"));
+        appSettingsAction->setData(Hs::AppSettingContextAction);
+    }
+
+    if (!(entry->attribute(Hs::componentIdAttributeName).isEmpty()) &&
+            (flags & RemovableEntryFlag) ) {
+        appDetailsAction = mContextMenu->addAction(hbTrId(
+                                                "txt_common_menu_details"));
+        appDetailsAction->setData(Hs::AppDetailsContextAction);
+    }
+    
+    addToHomeScreenAction->setVisible(
+        !HsAppLibStateUtils::isCWRTWidgetOnHomeScreen(entry.data()));
+}
+
+/*!
+  A Slot called when an action for sorting (latest
+  on top) is invoked for Downloaded collection.
+ */
+void HsCollectionState::latestOnTopMenuAction()
+{
+    mSortAttribute = Hs::LatestOnTopHsSortAttribute;
+    mModel->setSort(mSortAttribute);
+    emit sortOrderChanged(mSortAttribute);
+}
+
+/*!
+  A Slot called when an action for sorting (oldest
+  on top) is invoked for Downloaded collection.
+ */
+void HsCollectionState::oldestOnTopMenuAction()
+{
+    mSortAttribute = Hs::OldestOnTopHsSortAttribute;
+    mModel->setSort(mSortAttribute);
+    emit sortOrderChanged(mSortAttribute);
+}
+
+/*!
+  A Slot called when an arrange operation
+  is invoked for a static collection.
+ */
+void HsCollectionState::createArrangeCollection()
+{
+    // Arrange collection via the Arrange view
+    int topItemId(0);
+
+    if (mMenuView->listView() != NULL) {
+        const QList<HbAbstractViewItem *> array =
+            mMenuView->listView()->visibleItems();
+
+        if (array.count() >= 1) {
+            QModelIndex idx = array[0]->modelIndex();
+            topItemId = idx.data(CaItemModel::IdRole).toInt();
+        }
+    }
+
+    machine()->postEvent(
+        HsMenuEventFactory::createArrangeCollectionEvent(
+            topItemId,
+            mCollectionId));
+}