homescreenapp/stateplugins/hsapplibrarystateplugin/src/hssearchview.cpp
branchRCL_3
changeset 82 5f0182e07bfb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/homescreenapp/stateplugins/hsapplibrarystateplugin/src/hssearchview.cpp	Tue Aug 31 15:06:34 2010 +0300
@@ -0,0 +1,411 @@
+/*
+ * 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: hssearchview.cpp
+ *
+ */
+
+#include <QApplication>
+#include <QSortFilterProxyModel>
+#include <HbGroupBox>
+#include <HbLineEdit>
+#include <HbListView>
+#include <HbAbstractViewItem>
+#include <HbView>
+#include <HbSearchPanel>
+
+#include <caitemmodel.h>
+
+#include "hslistviewitem.h"
+#include "hsmainwindow.h"
+#include "hssearchview.h"
+
+/*!
+ * \fn void activated(const QModelIndex &index)
+ * This signal is emitted when item is tapped.
+ * \param index of an item that was tapped.
+ */
+
+ /*!
+ * \fn void longPressed(HbAbstractViewItem *item, const QPointF &coords)
+ * This singal is emitted when view is long pressed.
+ * \param item View item that was long pressed.
+ * \param coords View coordinates of the long press.
+ */
+ 
+ /*!
+  * \fn void searchComplete(const QModelIndex &firstMatching)
+  * This signal is emitted when search action has been finished 
+  * and search view is about to quit.
+  * \param firstMatching of first item in search filtered view.
+  */
+    
+    
+/*!
+  Set up proxy model for search.
+  \param builder Retrieves UI widgets.
+  \param stateContext Identifies the state where search starts from.
+  \param mainWindow Enables switching between originating and search view.
+ */
+HsSearchView::HsSearchView(HsMenuViewBuilder &builder,
+        HsStateContext stateContext, HsMainWindow &mainWindow) :
+    mProxyModel(new QSortFilterProxyModel(this)), mSearchView(NULL),
+    mSearchListView(NULL), mSearchPanel(NULL), mStateContext(stateContext),
+    mBuilder(builder), mMainWindow(mainWindow), mListView(NULL),
+    mVkbHost(NULL), mSearchViewBuilder(), mEmptyResultText(true)
+{
+    mProxyModel->setFilterRole(CaItemModel::TextRole);
+    mProxyModel->setFilterKeyColumn(0);
+    mProxyModel->setSortRole(CaItemModel::TextRole);
+    mProxyModel->setDynamicSortFilter(true);
+}
+
+/*!
+  Empty.
+ */
+HsSearchView::~HsSearchView()
+{
+}
+
+/*!
+    Makes the UI to show or hide view search panel.
+    When search panel is shown the view toolbar and status pane
+    are hidden until search panel is hidden.
+    \param visible When true search panel will be shown,
+     otherwise it will be hidden.
+ */
+void HsSearchView::setSearchPanelVisible(bool visible)
+{
+    HSMENUTEST_FUNC_ENTRY("HsMenuView::setSearchPanelVisible");
+
+    if (visible && !isActive()) {
+        searchBegins();
+        connectSearchItemViewsSignals();
+        connectSearchPanelSignals();
+    } else if (isActive()) {
+        disconnectSearchPanelSignals();
+        disconnectSearchItemViewsSignals();
+        searchFinished();
+    }
+    HSMENUTEST_FUNC_EXIT("HsMenuView::setSearchPanelVisible");
+}
+
+/*!
+    \param view List view to operate on.
+    \return Index of F=first visible item of \a view if any
+    or default QModelIndex otherwise.
+ */
+QModelIndex HsSearchView::firstVisibleItemIndex(const HbListView *view) const
+{
+    const QList<HbAbstractViewItem *> array = view->visibleItems();
+    if (array.count()) {
+        return array[0]->modelIndex();
+    }
+    return QModelIndex();
+}
+
+/*!
+ Displays search panel with view representing search results.
+ */
+void HsSearchView::searchBegins()
+{
+    HSMENUTEST_FUNC_ENTRY("HsSearchView::searchBegins");
+
+    setOriginatingContext();
+
+    mListView = mBuilder.currentListView();
+    mSearchViewInitialIndex = firstVisibleItemIndex(mListView);
+
+    mProxyModel->invalidate();
+    mProxyModel->setSourceModel(mListView->model());
+    mProxyModel->setFilterRegExp(
+            QRegExp(QString(".*"), Qt::CaseInsensitive, QRegExp::RegExp));
+
+    mSearchView = mSearchViewBuilder.searchView();
+    mSearchListView = mSearchViewBuilder.searchListView();
+    mSearchPanel = mSearchViewBuilder.searchPanel();
+    initSearchPanel(*mSearchPanel);
+    mVkbHost.reset(new HbShrinkingVkbHost(mSearchView));
+
+    if (mBuilder.currentViewLabel()) {
+        mSearchViewBuilder.searchViewLabel()->setHeading(
+                mBuilder.currentViewLabel()->heading());
+        mSearchViewBuilder.setSearchLabledContext();
+    }
+
+    mSearchView->hideItems(Hb::AllItems);
+    mSearchListView->setModel(mProxyModel, new HsListViewItem());
+
+    mMainWindow.setCurrentView(mSearchView);
+
+    openVkb();
+
+    mSearchListView->scrollTo(
+        mProxyModel->mapFromSource(mSearchViewInitialIndex),
+        HbAbstractItemView::PositionAtTop);
+
+    setNoResultsVisibility();
+    HSMENUTEST_FUNC_EXIT("HsSearchView::searchBegins");
+}
+
+/*!
+ Handles button visibility.
+ \param visibility indicates whether show or not to show 'empty' label.
+ */
+void HsSearchView::setNoResultsVisibility()
+{
+    if (mProxyModel->rowCount() && mEmptyResultText) {
+        mSearchViewBuilder.loadViewListSection();
+        mEmptyResultText = false;
+    } else if (!mProxyModel->rowCount() && !mEmptyResultText) {
+        mSearchViewBuilder.loadViewEmptySection();
+        mEmptyResultText = true;
+    }
+}
+
+/*
+ Connects \a activated and \a longPressed signals coming from search list
+ view to emit corresponding signal of this object with translated model index.
+*/
+void HsSearchView::connectSearchItemViewsSignals()
+{
+    connect(mSearchListView, SIGNAL(pressed(QModelIndex)),
+                this, SLOT(hideVkb()), Qt::UniqueConnection);
+    connect(mSearchListView, SIGNAL(activated(QModelIndex)),
+            this, SLOT(activatedProxySlot(QModelIndex)), Qt::UniqueConnection);
+    connect(mSearchListView, SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
+            this, SLOT(longPressedProxySlot(HbAbstractViewItem *, QPointF)), 
+			    Qt::UniqueConnection);
+
+}
+
+/*!
+ Disconnects \a activated and \a longPressed signals coming from list
+ view from to emit corresponding signal
+ of this object with translated model index.
+*/
+void HsSearchView::disconnectSearchItemViewsSignals()
+{
+    disconnect(mSearchListView, SIGNAL(pressed(QModelIndex)),
+            this, SLOT(hideVkb()));
+    disconnect(mSearchListView, SIGNAL(activated(QModelIndex)),
+            this, SLOT(activatedProxySlot(QModelIndex)));
+    disconnect(mSearchListView,
+            SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
+            this, SLOT(longPressedProxySlot(HbAbstractViewItem *, QPointF)));
+}
+
+
+/*!
+ Makes search panel invisible.
+ Equivalent to \a setSearchPanelVisible(false).
+ */
+void HsSearchView::hideSearchPanel()
+{
+    HSMENUTEST_FUNC_ENTRY("HsMenuView::hideSearchPanel");
+    setSearchPanelVisible(false);
+    HSMENUTEST_FUNC_EXIT("HsMenuView::hideSearchPanel");
+}
+
+/*!
+ Connects signals \a exitClicked and \a criteriaChanged emitted
+ by search panel with handling slots of the object or its members.
+*/
+void HsSearchView::connectSearchPanelSignals()
+{
+    connect(mProxyModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
+            this, SLOT(setNoResultsVisibility()), Qt::UniqueConnection);
+    connect(mProxyModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
+            this, SLOT(setNoResultsVisibility()));
+    connect(mProxyModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+            this, SLOT(setNoResultsVisibility()));
+    connect(mSearchPanel, SIGNAL(exitClicked()),
+            this, SLOT(hideSearchPanel()));
+    connect(mSearchPanel, SIGNAL(criteriaChanged(QString)),
+            this, SLOT(findItem(QString)), Qt::UniqueConnection);
+}
+
+/*!
+ Disconnects signals \a exitClicked and \a criteriaChanged emitted
+ by search panel from handling slots of the object or its members
+ Scrolls view to state before connections.
+*/
+void HsSearchView::disconnectSearchPanelSignals()
+{
+    mProxyModel->disconnect(this);
+    mSearchPanel->disconnect(this);
+}
+
+/*!
+  Scrolls originating view to first item matching search criteria.
+ */
+void HsSearchView::searchFinished()
+{
+    HSMENUTEST_FUNC_ENTRY("HsSearchView::searchFinished");
+
+    mIndexToScrollAfterSearchDone = firstVisibleItemIndex(mSearchListView);
+
+    // emiting searchComplete must be done
+    // after this->isActive() returns false
+    mSearchListView = NULL;
+    mSearchPanel = NULL;
+    
+    emit searchComplete(mProxyModel->mapToSource(
+            mIndexToScrollAfterSearchDone));
+
+    HbVkbHost::detachHost(mSearchView);
+    mVkbHost.reset(NULL);
+
+    mProxyModel->setSourceModel(NULL);
+    HSMENUTEST_FUNC_EXIT("HsSearchView::searchFinished");
+}
+
+/*!
+ Looks up for item and if found scrolls to it.
+ \param criteriaStr The item name to find.
+ */
+void HsSearchView::findItem(QString criteriaStr)
+{
+    qDebug() << "HsSearchView::findItem: " + criteriaStr;
+    HSMENUTEST_FUNC_ENTRY("HsSearchView::findItem");
+
+    mProxyModel->setFilterRegExp(
+            QRegExp("(^|\\b)" + criteriaStr, Qt::CaseInsensitive));
+
+    mSearchListView->scrollTo(
+            mProxyModel->index(0, 0), HbAbstractItemView::PositionAtTop);
+
+    HSMENUTEST_FUNC_EXIT("HsSearchView::findItem");
+}
+
+/*!
+ Slot used to translate activated signal from proxy model to normal model.
+ \param index Represents an item activated in search list view.
+ */
+void HsSearchView::activatedProxySlot(const QModelIndex &index)
+{
+    emit activated(mProxyModel->mapToSource(index));
+}
+
+/*!
+ Slot used to forward 'long pressed' signal with item description transladed
+ from search view context to context of the view search was requested from.
+  \param item Long pressed item.
+  \param coords Coordinates of the long press action.
+ */
+void HsSearchView::longPressedProxySlot(
+        HbAbstractViewItem *item, const QPointF &coords)
+{
+    /*
+    this is a kind of hack, introduced for reasons:
+    item object should be reusable later, but orbit (or qt) prevents setting
+    its index model to previous state
+    */
+    mSearchViewLongPressedIndex = mProxyModel->mapToSource(
+            item->modelIndex());
+    QScopedPointer<HbAbstractViewItem> itemNew(item->createItem());
+    itemNew->setModelIndex(mSearchViewLongPressedIndex);
+    emit longPressed(itemNew.data(), coords);
+}
+
+/*!
+  Sets up search panel.
+
+ \param searchPanel Search panel to initialize.
+ */
+void HsSearchView::initSearchPanel(HbSearchPanel &searchPanel)
+{
+    HbLineEdit *const lineEdit(searchPanelLineEdit(searchPanel));
+
+    lineEdit->setText("");
+    lineEdit->setFocus();
+    lineEdit->setInputMethodHints(
+            Qt::ImhNoPredictiveText | Qt::ImhNoAutoUppercase);
+}
+
+/*!
+ \param searchPanel Search panel to operate on.
+ \return Line edit of the searchPanel on success, NULL otherwise.
+ */
+HbLineEdit *HsSearchView::searchPanelLineEdit(
+        HbSearchPanel &searchPanel) const
+{
+    HSMENUTEST_FUNC_ENTRY("HsSearchView::searchPanelLineEdit");
+
+    HbLineEdit *result(0);
+    foreach(QGraphicsItem *obj, searchPanel.childItems()) {
+        QGraphicsWidget *const widget = static_cast<QGraphicsWidget *>(obj);
+        if (widget != NULL) {
+            HbLineEdit *const lineEdit = qobject_cast<HbLineEdit *>(widget);
+            if (lineEdit != NULL) {
+                result = lineEdit;
+                break;
+            }
+        }
+    }
+    HSMENUTEST_FUNC_EXIT("HsSearchView::searchPanelLineEdit");
+
+    return result;
+}
+
+/*!
+  Sets the builder context to the one determined by \a mStateContext and
+  \a HsItemViewContext.
+ */
+void HsSearchView::setOriginatingContext()
+{
+    mBuilder.setStateContext(mStateContext);
+    mBuilder.setOperationalContext(HsItemViewContext);
+}
+
+/*!
+  \retval true when search view is actually responsible for view management, 
+  \a false otherwise.
+ */
+bool HsSearchView::isActive() const
+{
+    return mSearchListView != NULL;
+}
+
+/*!
+  Slot to close virtual keyboard.
+ */
+void HsSearchView::hideVkb()
+{
+    sendEvent(QEvent::CloseSoftwareInputPanel);
+}
+
+/*!
+ Makes Vkb open provided there is an editor visible in the graphics scene.
+ */
+void HsSearchView::openVkb()
+{
+    sendEvent(QEvent::RequestSoftwareInputPanel);
+}
+
+/*!
+  Sends QEvent.
+  \param eventType Identifies event to be sent.
+ */
+void HsSearchView::sendEvent(const QEvent::Type eventType)
+{
+    QInputContext *const ic = qApp->inputContext();
+    if (ic != NULL) {
+        QScopedPointer<QEvent> event(
+            new QEvent(eventType));
+
+        ic->filterEvent(event.data());
+    }
+
+}
+