src/hbcore/inputfw/hbinputfocusobject.cpp
changeset 28 b7da29130b0e
parent 23 e6ad4ef83b23
child 30 80e4d18b72f5
--- a/src/hbcore/inputfw/hbinputfocusobject.cpp	Thu Sep 02 20:44:51 2010 +0300
+++ b/src/hbcore/inputfw/hbinputfocusobject.cpp	Fri Sep 17 08:32:10 2010 +0300
@@ -23,22 +23,19 @@
 **
 ****************************************************************************/
 #include "hbinputfocusobject.h"
+#include "hbinputfocusobject_p.h"
 
 #include <QInputMethodEvent>
-#include <QGraphicsWidget>
+#include <QGraphicsObject>
 #include <QGraphicsScene>
 #include <QGraphicsProxyWidget>
 #include <QLineEdit>
 #include <QTextEdit>
-#include <QPointer>
-#include <QGraphicsView>
 
 #include "hbinputmethod.h"
-#include "hbinputeditorinterface.h"
 #include "hbinputvkbhost.h"
 #include "hbinputstandardfilters.h"
 #include "hbdeviceprofile.h"
-#include "hbinpututils.h"
 #include "hbnamespace_p.h"
 #include "hbmainwindow.h"
 #include "hbevent.h"
@@ -46,73 +43,52 @@
 #include "hbinputmainwindow_p.h"
 
 /*!
-@alpha
+@beta
 @hbcore
 \class HbInputFocusObject
 \brief A helper class for accessing editor widget in abstract way.
 
-This class is input method side API for accessing editor widgets. It was added because
-in some cases Qt's QInputMethodEvent/inputMethodQuery system is not enough and direct
-access via type casting between QWidget and QGraphiscWidget based editors is needed.
-Focus object hides those cases behind a convinience API.
+This class is input method side API for accessing editor widgets. It hides
+the details of performing editor related operations, such as sending input
+method events, querying editor geometry, querying editor attributes and so on.
+It implements a collection of convenience methods for most commonly used
+editor operations.
 
 This class is purely a convenience or helper type of class in nature. Everything
-it does, can be done directly in input method code as well. It just wraps
-most commonly used operations behind one API to avoid duplicate code.
+it does, can be done directly in input method code as well. The benefit from using
+this class is that an input method implementation doesn't need to care whether
+the focused editor is QWidget or QGraphicsWidget based (or proxied QWidget).
 
-Application developers should never need to use this class, it is for input method developers only.
+Application developers typically do not need this class, it is for input method
+developers only.
+
+The active focus object can be accessed through HbInputMethod::focusObject()
+method.
 
 \sa HbEditorInterface
+\sa HbInputMethod
 */
 
 /// @cond
 
-/*
-This function ensures cursor visibility for known editor types.
+/*!
+\internal
+Returns main window in case the editor is QGraphicsObject based and lives
+inside HbGraphicsScene.
 */
-void ensureCursorVisible(QObject *widget)
-{
-    if (widget) {
-        QTextEdit *textEdit = qobject_cast<QTextEdit *>(widget);
-        if (textEdit) {
-            textEdit->ensureCursorVisible();
-        }
-    }
-}
-
-class HbInputFocusObjectPrivate
-{
-    Q_DECLARE_PUBLIC(HbInputFocusObject)
-
-public:
-    HbInputFocusObjectPrivate(QObject *focusedObject)
-        : mFocusedObject(focusedObject),
-          mEditorInterface(focusedObject)
-    {}
-
-    HbMainWindow *mainWindow() const;    
-
-public:
-    HbInputFocusObject *q_ptr;
-    QPointer<QObject> mFocusedObject;
-    HbEditorInterface mEditorInterface;
-    QString mPreEditString;
-};
-
 HbMainWindow *HbInputFocusObjectPrivate::mainWindow() const
 {
-    QWidget *qWidgetObject = qobject_cast<QWidget *>(mFocusedObject);
     QGraphicsObject *graphicsObject = 0;
 
     // check for graphics view related widgets.
-    if (qWidgetObject) {
-        if (qWidgetObject->graphicsProxyWidget()) {
-            graphicsObject = qWidgetObject->graphicsProxyWidget();
+    if (mWidget) {
+        if (mWidget->graphicsProxyWidget()) {
+            graphicsObject = mWidget->graphicsProxyWidget();
         } else {
             return HbInputMainWindow::instance();
         }
     } else {
-        graphicsObject = qobject_cast<QGraphicsObject *>(mFocusedObject);
+        graphicsObject = mGraphicsObject;
     }
 
     if (graphicsObject) {
@@ -132,6 +108,20 @@
     return 0;
 }
 
+/*!
+\internal
+Ensures cursor visibility for known editor types.
+*/
+void HbInputFocusObjectPrivate::ensureCursorVisible(QObject *widget)
+{
+    if (widget) {
+        QTextEdit *textEdit = qobject_cast<QTextEdit *>(widget);
+        if (textEdit) {
+            textEdit->ensureCursorVisible();
+        }
+    }
+}
+
 /// @endcond
 
 HbInputFocusObject::HbInputFocusObject(QObject *focusedObject)
@@ -141,6 +131,17 @@
     d->q_ptr = this;
 
     if (focusedObject) {
+        if (focusedObject->isWidgetType()) {
+            d->mWidget = qobject_cast<QWidget*>(focusedObject);
+        } else {
+            QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget*>(focusedObject);
+            if (proxy) {
+                d->mWidget = proxy->widget();
+            } else {
+                d->mGraphicsObject = qobject_cast<QGraphicsObject*>(focusedObject);
+            }
+        }
+
         HbEvent *event = new HbEvent(HbEvent::InputMethodFocusIn);
         QCoreApplication::sendEvent(focusedObject, event);
         delete event;
@@ -155,11 +156,10 @@
 
 HbInputFocusObject::~HbInputFocusObject()
 {
-    Q_D(HbInputFocusObject);
-
-    if (d->mFocusedObject) {
+    QObject *obj = object();
+    if (obj) {
         HbEvent *event = new HbEvent(HbEvent::InputMethodFocusOut);
-        QCoreApplication::postEvent(d->mFocusedObject, event);
+        QCoreApplication::postEvent(obj, event);
     }
 
     delete d_ptr;
@@ -204,7 +204,8 @@
         }
     }
 
-    if (d->mFocusedObject) {
+    QObject *obj = object();
+    if (obj) {
         if (event.type() == QEvent::InputMethod) {
             QInputContext *ic = qApp->inputContext();
             QInputMethodEvent *imEvent = static_cast<QInputMethodEvent *>(&event);
@@ -214,7 +215,7 @@
             // Currently in Qt, QTextEdit doesn't ensure cursor visibility
             // in case we are sending text in the form of QInputMethodEvent. So we need
             // to call QTextEdit:ensureCursorVisible() here till we get a fix from Qt.
-            ensureCursorVisible(d->mFocusedObject);
+            d->ensureCursorVisible(obj);
         } else {
             QInputContext *ic = qApp->inputContext();
             if (ic && ic->focusWidget()) {
@@ -240,31 +241,29 @@
         }
     }
 
-    if (d->mFocusedObject) {
-        QApplication::postEvent(d->mFocusedObject, &event);
+    QObject *obj = object();
+    if (obj) {
+        QApplication::postEvent(obj, &event);
     }
 }
 
 /*!
-Passes input method query to focused editor.
+Passes input method query to focused editor widget.
 */
 QVariant HbInputFocusObject::inputMethodQuery(Qt::InputMethodQuery query) const
 {
     Q_D(const HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
-    if (graphicsObject && graphicsObject->scene()) {
-        return graphicsObject->scene()->inputMethodQuery(query);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
+    if (graphicsObject) {
+        if (graphicsObject->scene()) {
+            return graphicsObject->scene()->inputMethodQuery(query);
+        }
+
+        return QVariant();
     }
 
-    // check if QWidget is embedded as a proxy in scene. If yes try to get details
-    // from the scene.
-    QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
-    QGraphicsProxyWidget *pw = HbInputUtils::graphicsProxyWidget(widget);
-    if (pw && pw->scene()) {
-        return pw->scene()->inputMethodQuery(query);
-    }
-
+    QWidget *widget = d->mWidget;
     if (widget) {
         // QWidget returns microfocus in local coordinate.
         // we need to map it to global coordinate.
@@ -343,11 +342,13 @@
 {
     Q_D(HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (!graphicsObject) {
-        QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+        QWidget *widget = d->mWidget;
         if (widget) {
-            if (!(graphicsObject = HbInputUtils::graphicsProxyWidget(widget))) {
+            if (widget->graphicsProxyWidget()) {
+                graphicsObject = widget->graphicsProxyWidget();
+            } else {
                 widget->clearFocus();
                 return;
             }
@@ -399,33 +400,20 @@
 {
     Q_D(const HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (!graphicsObject) {
-        QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+        QWidget *widget = d->mWidget;
         if (widget) {
-            // check if widget is inside a proxy.
-            QGraphicsProxyWidget *pw = HbInputUtils::graphicsProxyWidget(widget);
+            // Check if widget is inside a proxy.
+            QGraphicsProxyWidget *pw = widget->graphicsProxyWidget();
             if (pw) {
-                // check if we are pointing to the toplevel
-                // proxy widget, if not then we must check for
-                // the widgets window and see if it is a proxy.
-                if (pw->widget() == widget) {
-                    graphicsObject = pw;
-                } else if (pw->widget() == widget->window()) {
-                    // focused object is not a proxy but it is
-                    // inside a proxy, query to proxy about
-                    // the focused objects rect.
-                    QRectF rect = pw->subWidgetRect(widget);
-                    rect.translate(pw->scenePos());
-                    return rect;
-                }
+                graphicsObject = pw;
             } else {
                 return QRectF(widget->mapToGlobal(QPoint(0, 0)), widget->size());
             }
         }
     }
 
-    // we need to find the editor which is inside
     if (graphicsObject) {
         return QRectF(graphicsObject->scenePos(), graphicsObject->boundingRect().size());
     }
@@ -442,7 +430,7 @@
     Q_D(const HbInputFocusObject);
 
     QRectF rect = inputMethodQuery(Qt::ImMicroFocus).toRectF();
-    QGraphicsObject *editorWidget = qobject_cast<QGraphicsObject*>(d->mFocusedObject);
+    QGraphicsObject *editorWidget = d->mGraphicsObject;
     if (editorWidget) {
         rect = editorWidget->mapRectToScene(rect);
     }
@@ -468,11 +456,11 @@
 {
     Q_D(const HbInputFocusObject);
 
-    QGraphicsObject *editorWidget = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *editorWidget = d->mGraphicsObject;
     if (!editorWidget) {
-        QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+        QWidget *widget = d->mWidget;
         if (widget) {
-            editorWidget = HbInputUtils::graphicsProxyWidget(widget);
+            editorWidget = widget->graphicsProxyWidget();
         }
     }
 
@@ -497,12 +485,12 @@
 {
     Q_D(const HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (graphicsObject) {
         return graphicsObject->inputMethodHints();
     }
 
-    QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+    QWidget *widget = d->mWidget;
     if (widget) {
         return widget->inputMethodHints();
     }
@@ -517,13 +505,13 @@
 {
     Q_D(HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (graphicsObject) {
         graphicsObject->setInputMethodHints(hints);
         return;
     }
 
-    QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+    QWidget *widget = d->mWidget;
     if (widget) {
         widget->setInputMethodHints(hints);
     }
@@ -590,30 +578,18 @@
 {
     Q_D(const HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (graphicsObject) {
         return graphicsObject->scenePos();
     }
 
-    QWidget *w = qobject_cast<QWidget *>(d->mFocusedObject);
-    // check if widget is inside a proxy.
-    QGraphicsProxyWidget *pw = HbInputUtils::graphicsProxyWidget(w);
-    if (pw) {
-        // check if we are pointing to the toplevel
-        // proxy widget, if not then we must check for
-        // the widgets window and see if it is a proxy.
-        if (pw->widget() == w) {
-            return pw->scenePos();
-        } else if (pw->widget() == w->window()) {
-            QRectF rect = pw->subWidgetRect(w);
-            rect.translate(pw->scenePos());
-            return rect.topLeft();
+    QWidget *widget = d->mWidget;
+    if (widget) {
+        QGraphicsProxyWidget *proxy = widget->graphicsProxyWidget();
+        if (proxy) {
+            return proxy->scenePos();
         }
-    }
-
-    if (w) {
-        // not a proxy.. Meaning widget is inside a QWidget window.
-        return w->mapToGlobal(QPoint(0, 0));
+        return widget->mapToGlobal(QPoint(0, 0));
     }
 
     return QPointF(0.0, 0.0);
@@ -625,7 +601,7 @@
 bool HbInputFocusObject::stringAllowedInEditor(const QString &string) const
 {
     // Two pass filtering. This can be a case constrained editor with a filter.
-    Qt::InputMethodHints hints;
+    Qt::InputMethodHints hints = inputMethodHints();
     if (hints & Qt::ImhLowercaseOnly) {
         QString outStr;
         HbInputLowerCaseFilter::instance()->filterString(string, outStr);
@@ -655,10 +631,9 @@
 */
 void HbInputFocusObject::commitSmiley(QString smiley)
 {
-    Q_D(HbInputFocusObject);
-
-    if (d->mFocusedObject) {
-        d->mFocusedObject->setProperty("SmileyIcon", smiley);
+    QObject *obj = object();
+    if (obj) {
+        obj->setProperty("SmileyIcon", smiley);
     }
 }
 
@@ -668,7 +643,12 @@
 QObject *HbInputFocusObject::object() const
 {
     Q_D(const HbInputFocusObject);
-    return d->mFocusedObject;
+
+    if (d->mGraphicsObject) {
+        return d->mGraphicsObject.data();
+    }
+
+    return d->mWidget.data();
 }
 
 /*!
@@ -739,21 +719,26 @@
 {
     Q_D(HbInputFocusObject);
 
-    QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(d->mFocusedObject);
+    bool sendRequest = false;
+    QGraphicsObject *graphicsObject = d->mGraphicsObject;
     if (graphicsObject && graphicsObject->scene()) {
         graphicsObject->scene()->setFocusItem(graphicsObject);
+        sendRequest = true;
     } else {
-        QWidget *widget = qobject_cast<QWidget *>(d->mFocusedObject);
+        QWidget *widget = d->mWidget;
         if (widget) {
             widget->setFocus();
+            sendRequest = true;
         }
     }
 
-    QInputContext* ic = qApp->inputContext();
-    if (ic) {
-        QEvent *openEvent = new QEvent(QEvent::RequestSoftwareInputPanel);
-        ic->filterEvent(openEvent);
-        delete openEvent;
+    if (sendRequest) {
+        QInputContext* ic = qApp->inputContext();
+        if (ic) {
+            QEvent *openEvent = new QEvent(QEvent::RequestSoftwareInputPanel);
+            ic->filterEvent(openEvent);
+            delete openEvent;
+        }
     }
 }