diff -r 7516d6d86cf5 -r ed14f46c0e55 src/hbcore/inputfw/hbinputfocusobject.cpp --- a/src/hbcore/inputfw/hbinputfocusobject.cpp Mon Oct 04 17:49:30 2010 +0300 +++ b/src/hbcore/inputfw/hbinputfocusobject.cpp Mon Oct 18 18:23:13 2010 +0300 @@ -23,49 +23,98 @@ ** ****************************************************************************/ #include "hbinputfocusobject.h" +#include "hbinputfocusobject_p.h" #include -#include +#include #include #include #include #include -#include -#include #include "hbinputmethod.h" -#include "hbinputeditorinterface.h" #include "hbinputvkbhost.h" #include "hbinputstandardfilters.h" -#include "hbinpututils.h" +#include "hbdeviceprofile.h" #include "hbnamespace_p.h" +#include "hbmainwindow.h" #include "hbevent.h" +#include "hbwidget.h" +#include "hbinputmainwindow_p.h" +#include "hbpopup.h" +#include "hbpopup_p.h" + /*! -@alpha +@stable @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) +HbMainWindow *HbInputFocusObjectPrivate::mainWindow() const +{ + QGraphicsObject *graphicsObject = 0; + + // check for graphics view related widgets. + if (mWidget) { + if (mWidget->graphicsProxyWidget()) { + graphicsObject = mWidget->graphicsProxyWidget(); + } else { + return HbInputMainWindow::instance(); + } + } else { + graphicsObject = mGraphicsObject; + } + + if (graphicsObject) { + if (graphicsObject->scene()) { + QList views = graphicsObject->scene()->views(); + foreach (QGraphicsView *view, views) { + HbMainWindow *mainWindow = qobject_cast(view); + if (mainWindow) { + return mainWindow; + } + } + // not a HbMainWindow. + return HbInputMainWindow::instance(); + } + } + + return 0; +} + +/*! +\internal +Ensures cursor visibility for known editor types. +*/ +void HbInputFocusObjectPrivate::ensureCursorVisible(QObject *widget) { if (widget) { QTextEdit *textEdit = qobject_cast(widget); @@ -75,43 +124,44 @@ } } - -class HbInputFocusObjectPrivate -{ -public: - HbInputFocusObjectPrivate(QObject *focusedObject) - : mFocusedObject(focusedObject), - mEditorInterface(focusedObject) - {} - -public: - QPointer mFocusedObject; - HbEditorInterface mEditorInterface; - QString mPreEditString; -}; - - /// @endcond HbInputFocusObject::HbInputFocusObject(QObject *focusedObject) : d_ptr(new HbInputFocusObjectPrivate(focusedObject)) { + Q_D(HbInputFocusObject); + d->q_ptr = this; + if (focusedObject) { + if (focusedObject->isWidgetType()) { + d->mWidget = qobject_cast(focusedObject); + } else { + QGraphicsProxyWidget *proxy = qobject_cast(focusedObject); + if (proxy) { + d->mWidget = proxy->widget(); + } else { + d->mGraphicsObject = qobject_cast(focusedObject); + } + } + HbEvent *event = new HbEvent(HbEvent::InputMethodFocusIn); QCoreApplication::sendEvent(focusedObject, event); delete event; + + HbMainWindow *mainWindow = d->mainWindow(); + if (mainWindow) { + connect(mainWindow, SIGNAL(aboutToChangeOrientation()), this, SIGNAL(aboutToChangeOrientation())); + connect(mainWindow, SIGNAL(orientationChanged(Qt::Orientation)), this, SIGNAL(orientationChanged())); + } } } - HbInputFocusObject::~HbInputFocusObject() { - Q_D(HbInputFocusObject); - - if (d->mFocusedObject) { + QObject *obj = object(); + if (obj) { HbEvent *event = new HbEvent(HbEvent::InputMethodFocusOut); - QCoreApplication::sendEvent(d->mFocusedObject, event); - delete event; + QCoreApplication::postEvent(obj, event); } delete d_ptr; @@ -156,7 +206,8 @@ } } - if (d->mFocusedObject) { + QObject *obj = object(); + if (obj) { if (event.type() == QEvent::InputMethod) { QInputContext *ic = qApp->inputContext(); QInputMethodEvent *imEvent = static_cast(&event); @@ -166,7 +217,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()) { @@ -176,7 +227,6 @@ } } - /*! Posts given event to focused editor in an asynchronous manner. */ @@ -193,31 +243,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(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(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. @@ -296,11 +344,13 @@ { Q_D(HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (!graphicsObject) { - QWidget *widget = qobject_cast(d->mFocusedObject); + QWidget *widget = d->mWidget; if (widget) { - if (!(graphicsObject = HbInputUtils::graphicsProxyWidget(widget))) { + if (widget->graphicsProxyWidget()) { + graphicsObject = widget->graphicsProxyWidget(); + } else { widget->clearFocus(); return; } @@ -352,35 +402,22 @@ { Q_D(const HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (!graphicsObject) { - QWidget *widget = qobject_cast(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()); + return graphicsObject->sceneBoundingRect(); } return QRectF(); @@ -395,7 +432,7 @@ Q_D(const HbInputFocusObject); QRectF rect = inputMethodQuery(Qt::ImMicroFocus).toRectF(); - QGraphicsObject *editorWidget = qobject_cast(d->mFocusedObject); + QGraphicsObject *editorWidget = d->mGraphicsObject; if (editorWidget) { rect = editorWidget->mapRectToScene(rect); } @@ -421,11 +458,11 @@ { Q_D(const HbInputFocusObject); - QGraphicsObject *editorWidget = qobject_cast(d->mFocusedObject); + QGraphicsObject *editorWidget = d->mGraphicsObject; if (!editorWidget) { - QWidget *widget = qobject_cast(d->mFocusedObject); + QWidget *widget = d->mWidget; if (widget) { - editorWidget = HbInputUtils::graphicsProxyWidget(widget); + editorWidget = widget->graphicsProxyWidget(); } } @@ -444,18 +481,47 @@ } /*! +Returns a priority value for the editor if the editor is inside a popup and +in other cases zero is returned. +*/ +quint8 HbInputFocusObject::editorPriority() const +{ + Q_D(const HbInputFocusObject); + + QGraphicsObject *editorWidget = d->mGraphicsObject; + if (!editorWidget) { + QWidget *widget = d->mWidget; + if (widget) { + editorWidget = widget->graphicsProxyWidget(); + } + } + + if (editorWidget) { + // Check if the editor is inside a popup and if so return the popup priority + for (QGraphicsObject *object = editorWidget; object; object = object->parentObject()) { + HbPopup *popup = qobject_cast(object); + if (popup) { + return HbPopupPrivate::d_ptr(popup)->priority(); + } + } + } + + return 0; +} + +/*! Returns input method hints. See QWidget and QGraphicsItem documentation for more information. */ Qt::InputMethodHints HbInputFocusObject::inputMethodHints() const { Q_D(const HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (graphicsObject) { return graphicsObject->inputMethodHints(); } - QWidget *widget = qobject_cast(d->mFocusedObject); + QWidget *widget = d->mWidget; if (widget) { return widget->inputMethodHints(); } @@ -470,13 +536,13 @@ { Q_D(HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (graphicsObject) { graphicsObject->setInputMethodHints(hints); return; } - QWidget *widget = qobject_cast(d->mFocusedObject); + QWidget *widget = d->mWidget; if (widget) { widget->setInputMethodHints(hints); } @@ -543,30 +609,18 @@ { Q_D(const HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (graphicsObject) { return graphicsObject->scenePos(); } - QWidget *w = qobject_cast(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); @@ -578,7 +632,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); @@ -608,10 +662,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); } } @@ -621,7 +674,12 @@ QObject *HbInputFocusObject::object() const { Q_D(const HbInputFocusObject); - return d->mFocusedObject; + + if (d->mGraphicsObject) { + return d->mGraphicsObject.data(); + } + + return d->mWidget.data(); } /*! @@ -683,25 +741,69 @@ } /*! -Sets focus to the editor point by this focus objetc. This method is needed because sometimes +Sets focus to the editor pointed by this focus object. Sometimes input method does something that temporarily removes focus from the original editor, for example displays a dialog which itself contains an editor in it. This method can -be used to return the focus to the original editor. +be used to return the input focus to the original editor. */ void HbInputFocusObject::setFocus() { Q_D(HbInputFocusObject); - QGraphicsObject *graphicsObject = qobject_cast(d->mFocusedObject); + bool sendRequest = false; + QGraphicsObject *graphicsObject = d->mGraphicsObject; if (graphicsObject && graphicsObject->scene()) { graphicsObject->scene()->setFocusItem(graphicsObject); + sendRequest = true; } else { - QWidget *widget = qobject_cast(d->mFocusedObject); + QWidget *widget = d->mWidget; if (widget) { widget->setFocus(); + sendRequest = true; + } + } + + if (sendRequest) { + QInputContext* ic = qApp->inputContext(); + if (ic) { + QEvent *openEvent = new QEvent(QEvent::RequestSoftwareInputPanel); + ic->filterEvent(openEvent); + delete openEvent; } } } +/*! +Returns the screen orientation in editor widget's context. For widgets +living in HbMainWindow, it is main window's orientation. For everything +else, it is device profile's screen orientation. +*/ +Qt::Orientation HbInputFocusObject::orientation() const +{ + Q_D(const HbInputFocusObject); + + HbMainWindow *mainWindow = d->mainWindow(); + if (mainWindow) { + return mainWindow->orientation(); + } + + return HbDeviceProfile::current().orientation(); +} + +/*! +Returns true if focused object is visible. +*/ +bool HbInputFocusObject::isVisible() const +{ + Q_D(const HbInputFocusObject); + + if (d->mGraphicsObject) { + return d->mGraphicsObject.data()->isVisible(); + } + + return d->mWidget.data()->isVisible(); +} + +#include "moc_hbinputfocusobject.cpp" + // End of file -