homescreenapp/stateplugins/hsapplibrarystateplugin/src/hssearchview.cpp
branchRCL_3
changeset 82 5f0182e07bfb
equal deleted inserted replaced
79:f00a6757af32 82:5f0182e07bfb
       
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description: hssearchview.cpp
       
    15  *
       
    16  */
       
    17 
       
    18 #include <QApplication>
       
    19 #include <QSortFilterProxyModel>
       
    20 #include <HbGroupBox>
       
    21 #include <HbLineEdit>
       
    22 #include <HbListView>
       
    23 #include <HbAbstractViewItem>
       
    24 #include <HbView>
       
    25 #include <HbSearchPanel>
       
    26 
       
    27 #include <caitemmodel.h>
       
    28 
       
    29 #include "hslistviewitem.h"
       
    30 #include "hsmainwindow.h"
       
    31 #include "hssearchview.h"
       
    32 
       
    33 /*!
       
    34  * \fn void activated(const QModelIndex &index)
       
    35  * This signal is emitted when item is tapped.
       
    36  * \param index of an item that was tapped.
       
    37  */
       
    38 
       
    39  /*!
       
    40  * \fn void longPressed(HbAbstractViewItem *item, const QPointF &coords)
       
    41  * This singal is emitted when view is long pressed.
       
    42  * \param item View item that was long pressed.
       
    43  * \param coords View coordinates of the long press.
       
    44  */
       
    45  
       
    46  /*!
       
    47   * \fn void searchComplete(const QModelIndex &firstMatching)
       
    48   * This signal is emitted when search action has been finished 
       
    49   * and search view is about to quit.
       
    50   * \param firstMatching of first item in search filtered view.
       
    51   */
       
    52     
       
    53     
       
    54 /*!
       
    55   Set up proxy model for search.
       
    56   \param builder Retrieves UI widgets.
       
    57   \param stateContext Identifies the state where search starts from.
       
    58   \param mainWindow Enables switching between originating and search view.
       
    59  */
       
    60 HsSearchView::HsSearchView(HsMenuViewBuilder &builder,
       
    61         HsStateContext stateContext, HsMainWindow &mainWindow) :
       
    62     mProxyModel(new QSortFilterProxyModel(this)), mSearchView(NULL),
       
    63     mSearchListView(NULL), mSearchPanel(NULL), mStateContext(stateContext),
       
    64     mBuilder(builder), mMainWindow(mainWindow), mListView(NULL),
       
    65     mVkbHost(NULL), mSearchViewBuilder(), mEmptyResultText(true)
       
    66 {
       
    67     mProxyModel->setFilterRole(CaItemModel::TextRole);
       
    68     mProxyModel->setFilterKeyColumn(0);
       
    69     mProxyModel->setSortRole(CaItemModel::TextRole);
       
    70     mProxyModel->setDynamicSortFilter(true);
       
    71 }
       
    72 
       
    73 /*!
       
    74   Empty.
       
    75  */
       
    76 HsSearchView::~HsSearchView()
       
    77 {
       
    78 }
       
    79 
       
    80 /*!
       
    81     Makes the UI to show or hide view search panel.
       
    82     When search panel is shown the view toolbar and status pane
       
    83     are hidden until search panel is hidden.
       
    84     \param visible When true search panel will be shown,
       
    85      otherwise it will be hidden.
       
    86  */
       
    87 void HsSearchView::setSearchPanelVisible(bool visible)
       
    88 {
       
    89     HSMENUTEST_FUNC_ENTRY("HsMenuView::setSearchPanelVisible");
       
    90 
       
    91     if (visible && !isActive()) {
       
    92         searchBegins();
       
    93         connectSearchItemViewsSignals();
       
    94         connectSearchPanelSignals();
       
    95     } else if (isActive()) {
       
    96         disconnectSearchPanelSignals();
       
    97         disconnectSearchItemViewsSignals();
       
    98         searchFinished();
       
    99     }
       
   100     HSMENUTEST_FUNC_EXIT("HsMenuView::setSearchPanelVisible");
       
   101 }
       
   102 
       
   103 /*!
       
   104     \param view List view to operate on.
       
   105     \return Index of F=first visible item of \a view if any
       
   106     or default QModelIndex otherwise.
       
   107  */
       
   108 QModelIndex HsSearchView::firstVisibleItemIndex(const HbListView *view) const
       
   109 {
       
   110     const QList<HbAbstractViewItem *> array = view->visibleItems();
       
   111     if (array.count()) {
       
   112         return array[0]->modelIndex();
       
   113     }
       
   114     return QModelIndex();
       
   115 }
       
   116 
       
   117 /*!
       
   118  Displays search panel with view representing search results.
       
   119  */
       
   120 void HsSearchView::searchBegins()
       
   121 {
       
   122     HSMENUTEST_FUNC_ENTRY("HsSearchView::searchBegins");
       
   123 
       
   124     setOriginatingContext();
       
   125 
       
   126     mListView = mBuilder.currentListView();
       
   127     mSearchViewInitialIndex = firstVisibleItemIndex(mListView);
       
   128 
       
   129     mProxyModel->invalidate();
       
   130     mProxyModel->setSourceModel(mListView->model());
       
   131     mProxyModel->setFilterRegExp(
       
   132             QRegExp(QString(".*"), Qt::CaseInsensitive, QRegExp::RegExp));
       
   133 
       
   134     mSearchView = mSearchViewBuilder.searchView();
       
   135     mSearchListView = mSearchViewBuilder.searchListView();
       
   136     mSearchPanel = mSearchViewBuilder.searchPanel();
       
   137     initSearchPanel(*mSearchPanel);
       
   138     mVkbHost.reset(new HbShrinkingVkbHost(mSearchView));
       
   139 
       
   140     if (mBuilder.currentViewLabel()) {
       
   141         mSearchViewBuilder.searchViewLabel()->setHeading(
       
   142                 mBuilder.currentViewLabel()->heading());
       
   143         mSearchViewBuilder.setSearchLabledContext();
       
   144     }
       
   145 
       
   146     mSearchView->hideItems(Hb::AllItems);
       
   147     mSearchListView->setModel(mProxyModel, new HsListViewItem());
       
   148 
       
   149     mMainWindow.setCurrentView(mSearchView);
       
   150 
       
   151     openVkb();
       
   152 
       
   153     mSearchListView->scrollTo(
       
   154         mProxyModel->mapFromSource(mSearchViewInitialIndex),
       
   155         HbAbstractItemView::PositionAtTop);
       
   156 
       
   157     setNoResultsVisibility();
       
   158     HSMENUTEST_FUNC_EXIT("HsSearchView::searchBegins");
       
   159 }
       
   160 
       
   161 /*!
       
   162  Handles button visibility.
       
   163  \param visibility indicates whether show or not to show 'empty' label.
       
   164  */
       
   165 void HsSearchView::setNoResultsVisibility()
       
   166 {
       
   167     if (mProxyModel->rowCount() && mEmptyResultText) {
       
   168         mSearchViewBuilder.loadViewListSection();
       
   169         mEmptyResultText = false;
       
   170     } else if (!mProxyModel->rowCount() && !mEmptyResultText) {
       
   171         mSearchViewBuilder.loadViewEmptySection();
       
   172         mEmptyResultText = true;
       
   173     }
       
   174 }
       
   175 
       
   176 /*
       
   177  Connects \a activated and \a longPressed signals coming from search list
       
   178  view to emit corresponding signal of this object with translated model index.
       
   179 */
       
   180 void HsSearchView::connectSearchItemViewsSignals()
       
   181 {
       
   182     connect(mSearchListView, SIGNAL(pressed(QModelIndex)),
       
   183                 this, SLOT(hideVkb()), Qt::UniqueConnection);
       
   184     connect(mSearchListView, SIGNAL(activated(QModelIndex)),
       
   185             this, SLOT(activatedProxySlot(QModelIndex)), Qt::UniqueConnection);
       
   186     connect(mSearchListView, SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
       
   187             this, SLOT(longPressedProxySlot(HbAbstractViewItem *, QPointF)), 
       
   188 			    Qt::UniqueConnection);
       
   189 
       
   190 }
       
   191 
       
   192 /*!
       
   193  Disconnects \a activated and \a longPressed signals coming from list
       
   194  view from to emit corresponding signal
       
   195  of this object with translated model index.
       
   196 */
       
   197 void HsSearchView::disconnectSearchItemViewsSignals()
       
   198 {
       
   199     disconnect(mSearchListView, SIGNAL(pressed(QModelIndex)),
       
   200             this, SLOT(hideVkb()));
       
   201     disconnect(mSearchListView, SIGNAL(activated(QModelIndex)),
       
   202             this, SLOT(activatedProxySlot(QModelIndex)));
       
   203     disconnect(mSearchListView,
       
   204             SIGNAL(longPressed(HbAbstractViewItem *, QPointF)),
       
   205             this, SLOT(longPressedProxySlot(HbAbstractViewItem *, QPointF)));
       
   206 }
       
   207 
       
   208 
       
   209 /*!
       
   210  Makes search panel invisible.
       
   211  Equivalent to \a setSearchPanelVisible(false).
       
   212  */
       
   213 void HsSearchView::hideSearchPanel()
       
   214 {
       
   215     HSMENUTEST_FUNC_ENTRY("HsMenuView::hideSearchPanel");
       
   216     setSearchPanelVisible(false);
       
   217     HSMENUTEST_FUNC_EXIT("HsMenuView::hideSearchPanel");
       
   218 }
       
   219 
       
   220 /*!
       
   221  Connects signals \a exitClicked and \a criteriaChanged emitted
       
   222  by search panel with handling slots of the object or its members.
       
   223 */
       
   224 void HsSearchView::connectSearchPanelSignals()
       
   225 {
       
   226     connect(mProxyModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
       
   227             this, SLOT(setNoResultsVisibility()), Qt::UniqueConnection);
       
   228     connect(mProxyModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
       
   229             this, SLOT(setNoResultsVisibility()));
       
   230     connect(mProxyModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
       
   231             this, SLOT(setNoResultsVisibility()));
       
   232     connect(mSearchPanel, SIGNAL(exitClicked()),
       
   233             this, SLOT(hideSearchPanel()));
       
   234     connect(mSearchPanel, SIGNAL(criteriaChanged(QString)),
       
   235             this, SLOT(findItem(QString)), Qt::UniqueConnection);
       
   236 }
       
   237 
       
   238 /*!
       
   239  Disconnects signals \a exitClicked and \a criteriaChanged emitted
       
   240  by search panel from handling slots of the object or its members
       
   241  Scrolls view to state before connections.
       
   242 */
       
   243 void HsSearchView::disconnectSearchPanelSignals()
       
   244 {
       
   245     mProxyModel->disconnect(this);
       
   246     mSearchPanel->disconnect(this);
       
   247 }
       
   248 
       
   249 /*!
       
   250   Scrolls originating view to first item matching search criteria.
       
   251  */
       
   252 void HsSearchView::searchFinished()
       
   253 {
       
   254     HSMENUTEST_FUNC_ENTRY("HsSearchView::searchFinished");
       
   255 
       
   256     mIndexToScrollAfterSearchDone = firstVisibleItemIndex(mSearchListView);
       
   257 
       
   258     // emiting searchComplete must be done
       
   259     // after this->isActive() returns false
       
   260     mSearchListView = NULL;
       
   261     mSearchPanel = NULL;
       
   262     
       
   263     emit searchComplete(mProxyModel->mapToSource(
       
   264             mIndexToScrollAfterSearchDone));
       
   265 
       
   266     HbVkbHost::detachHost(mSearchView);
       
   267     mVkbHost.reset(NULL);
       
   268 
       
   269     mProxyModel->setSourceModel(NULL);
       
   270     HSMENUTEST_FUNC_EXIT("HsSearchView::searchFinished");
       
   271 }
       
   272 
       
   273 /*!
       
   274  Looks up for item and if found scrolls to it.
       
   275  \param criteriaStr The item name to find.
       
   276  */
       
   277 void HsSearchView::findItem(QString criteriaStr)
       
   278 {
       
   279     qDebug() << "HsSearchView::findItem: " + criteriaStr;
       
   280     HSMENUTEST_FUNC_ENTRY("HsSearchView::findItem");
       
   281 
       
   282     mProxyModel->setFilterRegExp(
       
   283             QRegExp("(^|\\b)" + criteriaStr, Qt::CaseInsensitive));
       
   284 
       
   285     mSearchListView->scrollTo(
       
   286             mProxyModel->index(0, 0), HbAbstractItemView::PositionAtTop);
       
   287 
       
   288     HSMENUTEST_FUNC_EXIT("HsSearchView::findItem");
       
   289 }
       
   290 
       
   291 /*!
       
   292  Slot used to translate activated signal from proxy model to normal model.
       
   293  \param index Represents an item activated in search list view.
       
   294  */
       
   295 void HsSearchView::activatedProxySlot(const QModelIndex &index)
       
   296 {
       
   297     emit activated(mProxyModel->mapToSource(index));
       
   298 }
       
   299 
       
   300 /*!
       
   301  Slot used to forward 'long pressed' signal with item description transladed
       
   302  from search view context to context of the view search was requested from.
       
   303   \param item Long pressed item.
       
   304   \param coords Coordinates of the long press action.
       
   305  */
       
   306 void HsSearchView::longPressedProxySlot(
       
   307         HbAbstractViewItem *item, const QPointF &coords)
       
   308 {
       
   309     /*
       
   310     this is a kind of hack, introduced for reasons:
       
   311     item object should be reusable later, but orbit (or qt) prevents setting
       
   312     its index model to previous state
       
   313     */
       
   314     mSearchViewLongPressedIndex = mProxyModel->mapToSource(
       
   315             item->modelIndex());
       
   316     QScopedPointer<HbAbstractViewItem> itemNew(item->createItem());
       
   317     itemNew->setModelIndex(mSearchViewLongPressedIndex);
       
   318     emit longPressed(itemNew.data(), coords);
       
   319 }
       
   320 
       
   321 /*!
       
   322   Sets up search panel.
       
   323 
       
   324  \param searchPanel Search panel to initialize.
       
   325  */
       
   326 void HsSearchView::initSearchPanel(HbSearchPanel &searchPanel)
       
   327 {
       
   328     HbLineEdit *const lineEdit(searchPanelLineEdit(searchPanel));
       
   329 
       
   330     lineEdit->setText("");
       
   331     lineEdit->setFocus();
       
   332     lineEdit->setInputMethodHints(
       
   333             Qt::ImhNoPredictiveText | Qt::ImhNoAutoUppercase);
       
   334 }
       
   335 
       
   336 /*!
       
   337  \param searchPanel Search panel to operate on.
       
   338  \return Line edit of the searchPanel on success, NULL otherwise.
       
   339  */
       
   340 HbLineEdit *HsSearchView::searchPanelLineEdit(
       
   341         HbSearchPanel &searchPanel) const
       
   342 {
       
   343     HSMENUTEST_FUNC_ENTRY("HsSearchView::searchPanelLineEdit");
       
   344 
       
   345     HbLineEdit *result(0);
       
   346     foreach(QGraphicsItem *obj, searchPanel.childItems()) {
       
   347         QGraphicsWidget *const widget = static_cast<QGraphicsWidget *>(obj);
       
   348         if (widget != NULL) {
       
   349             HbLineEdit *const lineEdit = qobject_cast<HbLineEdit *>(widget);
       
   350             if (lineEdit != NULL) {
       
   351                 result = lineEdit;
       
   352                 break;
       
   353             }
       
   354         }
       
   355     }
       
   356     HSMENUTEST_FUNC_EXIT("HsSearchView::searchPanelLineEdit");
       
   357 
       
   358     return result;
       
   359 }
       
   360 
       
   361 /*!
       
   362   Sets the builder context to the one determined by \a mStateContext and
       
   363   \a HsItemViewContext.
       
   364  */
       
   365 void HsSearchView::setOriginatingContext()
       
   366 {
       
   367     mBuilder.setStateContext(mStateContext);
       
   368     mBuilder.setOperationalContext(HsItemViewContext);
       
   369 }
       
   370 
       
   371 /*!
       
   372   \retval true when search view is actually responsible for view management, 
       
   373   \a false otherwise.
       
   374  */
       
   375 bool HsSearchView::isActive() const
       
   376 {
       
   377     return mSearchListView != NULL;
       
   378 }
       
   379 
       
   380 /*!
       
   381   Slot to close virtual keyboard.
       
   382  */
       
   383 void HsSearchView::hideVkb()
       
   384 {
       
   385     sendEvent(QEvent::CloseSoftwareInputPanel);
       
   386 }
       
   387 
       
   388 /*!
       
   389  Makes Vkb open provided there is an editor visible in the graphics scene.
       
   390  */
       
   391 void HsSearchView::openVkb()
       
   392 {
       
   393     sendEvent(QEvent::RequestSoftwareInputPanel);
       
   394 }
       
   395 
       
   396 /*!
       
   397   Sends QEvent.
       
   398   \param eventType Identifies event to be sent.
       
   399  */
       
   400 void HsSearchView::sendEvent(const QEvent::Type eventType)
       
   401 {
       
   402     QInputContext *const ic = qApp->inputContext();
       
   403     if (ic != NULL) {
       
   404         QScopedPointer<QEvent> event(
       
   405             new QEvent(eventType));
       
   406 
       
   407         ic->filterEvent(event.data());
       
   408     }
       
   409 
       
   410 }
       
   411