src/hbcore/inputfw/hbinputregioncollector.cpp
changeset 5 627c4a0fd0e7
child 6 c3690ec91ef8
equal deleted inserted replaced
3:11d3954df52a 5:627c4a0fd0e7
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include <QRegion>
       
    27 #include <QTransform>
       
    28 #include <QPointer>
       
    29 
       
    30 #include "hbinputregioncollector_p.h"
       
    31 #include "hbwidget.h"
       
    32 #include "hbmainwindow.h"
       
    33 #include "hbpopup.h"
       
    34 #include "hbdeviceprofile.h"
       
    35 
       
    36 /*!
       
    37 \proto
       
    38 \class HbInputRegionCollector
       
    39 \brief Installs a filter on a HbWidget and observes for a change in position, size and visibility
       
    40 of the attached widget. As soon as it detects a change in size, position or visibility it calculates
       
    41 total of the region of all the widgets attached and emits updateRegion signal.
       
    42 
       
    43 It is enabled and disabled by input framework, it is enabled when ever input framework detects
       
    44 that the application is not having any HbMainWindow.
       
    45 
       
    46 */
       
    47 
       
    48 /// @cond
       
    49 
       
    50 class HbWidgetFilterList
       
    51 {
       
    52 public:
       
    53     HbWidgetFilterList(HbWidget *w)
       
    54         :mWidget (w), mIsVisible (false)
       
    55     {
       
    56     }
       
    57     bool operator ==(const HbWidgetFilterList &other) const {return mWidget == other.mWidget;}
       
    58     QPointer <HbWidget> mWidget;
       
    59     // visibility is needed as the time when we get show event inside eventFilter
       
    60     // widget is not visible.
       
    61     bool mIsVisible;
       
    62 };
       
    63 
       
    64 class HbInputRegionCollectorPrivate
       
    65 {
       
    66 public:
       
    67     HbInputRegionCollectorPrivate()
       
    68         :mEnabled(false), mModalDialogs(0){}
       
    69     QList < HbWidgetFilterList > mInputWidgets;
       
    70     bool mEnabled;
       
    71     int mModalDialogs;
       
    72 };
       
    73 
       
    74 
       
    75 /*!
       
    76 Creates a static instance of HbInputRegionCollector.
       
    77 */
       
    78 HbInputRegionCollector *HbInputRegionCollector::instance()
       
    79 {
       
    80     static HbInputRegionCollector regionCollector;
       
    81     return &regionCollector;
       
    82 }
       
    83 
       
    84 /*!
       
    85 Constructor.
       
    86 */
       
    87 HbInputRegionCollector::HbInputRegionCollector()
       
    88     :d_ptr(new HbInputRegionCollectorPrivate())
       
    89 {
       
    90 }
       
    91 
       
    92 /*!
       
    93 Destructor.
       
    94 */
       
    95 HbInputRegionCollector::~HbInputRegionCollector()
       
    96 {
       
    97     delete d_ptr;
       
    98 }
       
    99 
       
   100 /*!
       
   101 Installs a even filter on the passed widget.
       
   102 */
       
   103 void HbInputRegionCollector::attach (HbWidget *widget)
       
   104 {
       
   105     if (widget && !d_ptr->mInputWidgets.contains(widget)) {
       
   106         if (d_ptr->mEnabled) {
       
   107             widget->installEventFilter(this);
       
   108         }
       
   109         d_ptr->mInputWidgets.append(HbWidgetFilterList(widget));
       
   110     }
       
   111 }
       
   112 
       
   113 /*!
       
   114 Detaches widget from region collection and updates current region if region collection is enabled.
       
   115 */
       
   116 void HbInputRegionCollector::detach (HbWidget *widget)
       
   117 {
       
   118     if (widget && d_ptr->mInputWidgets.contains(widget)) {
       
   119         widget->removeEventFilter(this);
       
   120         d_ptr->mInputWidgets.removeOne(widget);
       
   121         if (d_ptr->mEnabled) {
       
   122             update();
       
   123         }
       
   124     }
       
   125 }
       
   126 
       
   127 /*!
       
   128 Observes size, position and move events of all attached widgets and calls update().
       
   129 */
       
   130 bool HbInputRegionCollector::eventFilter (QObject *obj, QEvent *event)
       
   131 {
       
   132     HbWidget *widget = qobject_cast<HbWidget *>(obj);
       
   133     if (widget) {
       
   134         switch (event->type()) {
       
   135         case QEvent::GraphicsSceneResize:
       
   136         case QEvent::GraphicsSceneMove:
       
   137             update();
       
   138             break;
       
   139         case QEvent::Show:
       
   140             {
       
   141                 // We can not query for HbWidget visiblility at this point
       
   142                 // so have to set it inside the strcuture variable.
       
   143                 int pos = d_ptr->mInputWidgets.indexOf(widget);
       
   144                 if (pos != -1) {
       
   145                     // Temporary TODO ++
       
   146                     // TODO write a HbInputWidgetStore class which will hold all the 
       
   147                     // active widgets and will emit signals for example sceneBlocked() 
       
   148                     // sceneUnBlocked(). And then connect to region collector.
       
   149                     HbPopup *popup = qobject_cast<HbPopup *>(obj);
       
   150                     // since there is a bug in Qt that QGraphicsItem geenrates two show events
       
   151                     // once when you do a show() and once when you added it to the scene(), 
       
   152                     // so need a check on visibility.
       
   153                     if (popup && popup->isModal() && !d_ptr->mInputWidgets[pos].mIsVisible) {
       
   154                         d_ptr->mModalDialogs++;
       
   155                     }
       
   156                     // Temporary TODO --                
       
   157                     d_ptr->mInputWidgets[pos].mIsVisible = true;
       
   158                     update();
       
   159                 }
       
   160                 break;
       
   161             }
       
   162         case QEvent::Hide:
       
   163             {
       
   164                 int pos = d_ptr->mInputWidgets.indexOf(widget);
       
   165                 if (pos != -1) {
       
   166                     // Temporary TODO ++
       
   167                     HbPopup *popup = qobject_cast<HbPopup *>(obj);
       
   168                     if (popup && popup->isModal()) {
       
   169                         d_ptr->mModalDialogs--;
       
   170                     }
       
   171                     // Temporary TODO --
       
   172                     d_ptr->mInputWidgets[pos].mIsVisible = false;
       
   173                     update();
       
   174                 }
       
   175                 break;
       
   176             }
       
   177         default:
       
   178             break;
       
   179         };
       
   180     }
       
   181     return false;
       
   182 }
       
   183 
       
   184 /*!
       
   185 Calculates all the attached HbWidget's rectangle and prepares a region out of it and then
       
   186 emits updateRegion.
       
   187 */
       
   188 void HbInputRegionCollector::update()
       
   189 {
       
   190     QRegion region;
       
   191 
       
   192     // since there is a modal dialog launched we need to mask the entire window.
       
   193     if (d_ptr->mModalDialogs) {
       
   194         region += QRect(QPoint(0, 0), HbDeviceProfile::current().logicalSize());
       
   195         emit updateRegion(region);
       
   196         return;
       
   197     }
       
   198 
       
   199     QList<HbWidgetFilterList> list = d_ptr->mInputWidgets;
       
   200     for (int i = 0; i < list.size(); ++i) {
       
   201         if (list.at(i).mIsVisible) {
       
   202             HbWidget *widget = list.at(i).mWidget;
       
   203             if (widget) {
       
   204                 HbMainWindow *window = widget->mainWindow();
       
   205                 if (window) {
       
   206                     QRectF rect = widget->rect();
       
   207                     rect.translate(widget->pos());
       
   208                     // we need to check transformation of the QGraphicsView.
       
   209                     // for example when there is a orientation switch transformation
       
   210                     // is 270 degree. We should map it to get transformed rectangle.
       
   211                     QTransform t = window->viewportTransform();
       
   212                     QRectF tRect = t.mapRect(rect);
       
   213                     region += tRect.toRect();
       
   214                     QRectF intersection = QRectF(window->geometry()).intersected(tRect);
       
   215                     region += intersection.toRect();
       
   216                 }
       
   217             }
       
   218         }
       
   219      }
       
   220     emit updateRegion(region);
       
   221 }
       
   222 
       
   223 /*!
       
   224 Enables region collection, this function is called by input framework.
       
   225 */
       
   226 void HbInputRegionCollector::setEnabled(bool enabled)
       
   227 {
       
   228     d_ptr->mEnabled = enabled;
       
   229     QList<HbWidgetFilterList>& list = d_ptr->mInputWidgets;
       
   230     for (int i = 0; i < list.size(); ++i) {
       
   231         HbWidget *widget = list.at(i).mWidget;
       
   232         if (widget) {
       
   233             if (enabled) {
       
   234                 widget->installEventFilter(this);
       
   235             } else {
       
   236                 widget->removeEventFilter(this);
       
   237             }
       
   238         }
       
   239     }
       
   240 }
       
   241 
       
   242 //EOF