From 9e838079f5f8d62aebb542f2415cd77ef9d71df2 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 7 Apr 2009 12:22:01 +0200 Subject: Added an event to request and close software input panel. This is meant to be used by widgets to signal that they want input. The event will then be passed on to QInputContext::filterEvent, which can create an appropriate virtual keyboard on devices with touch interface only. RevBy: denis --- src/corelib/kernel/qcoreevent.cpp | 2 ++ src/corelib/kernel/qcoreevent.h | 3 +++ src/gui/inputmethod/qinputcontext.cpp | 14 +++++++++++++- src/gui/kernel/qapplication.cpp | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 11a2d3c..e0be174 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -108,6 +108,7 @@ QT_BEGIN_NAMESPACE \value ApplicationLayoutDirectionChange The default application layout direction has changed. \value ApplicationPaletteChange The default application palette has changed. \value ApplicationWindowIconChange The application's icon has changed. + \value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP). \value ChildAdded An object gets a child (QChildEvent). \value ChildInserted An object gets a child (QChildEvent). Qt3Support only, use ChildAdded instead. \value ChildPolished A widget child gets polished (QChildEvent). @@ -186,6 +187,7 @@ QT_BEGIN_NAMESPACE \value Polish The widget is polished. \value PolishRequest The widget should be polished. \value QueryWhatsThis The widget should accept the event if it has "What's This?" help. + \value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP). \value Resize Widget's size changed (QResizeEvent). \value Shortcut Key press in child for shortcut key handling (QShortcutEvent). \value ShortcutOverride Key press in child, for overriding shortcut key handling (QKeyEvent). diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index fa472e6..d229ac9 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -266,6 +266,9 @@ public: CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear + RequestSoftwareInputPanel = 192, + CloseSoftwareInputPanel = 193, + // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp index 3d6d303..dba377a 100644 --- a/src/gui/inputmethod/qinputcontext.cpp +++ b/src/gui/inputmethod/qinputcontext.cpp @@ -209,7 +209,19 @@ void QInputContext::setFocusWidget(QWidget *widget) way. Although the input events have accept() and ignore() methods, leave it untouched. - \a event is currently restricted to QKeyEvent and QMouseEvent. + \a event is currently restricted to events of these types: + + \list + \i CloseSoftwareInputPanel + \i KeyPress + \i KeyRelease + \i MouseButtonDblClick + \i MouseButtonPress + \i MouseButtonRelease + \i MouseMove + \i RequestSoftwareInputPanel + \endlist + But some input method related events such as QWheelEvent or QTabletEvent may be added in future. diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index d65a352..6f0a4e6 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4040,6 +4040,20 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; #endif + case QEvent::RequestSoftwareInputPanel: + case QEvent::CloseSoftwareInputPanel: +#ifndef QT_NO_IM + if (receiver->isWidgetType()) { + QWidget *w = static_cast(receiver); + QInputContext *ic = w->inputContext(); + if (ic && ic->filterEvent(e)) { + break; + } + } +#endif + res = d->notify_helper(receiver, e); + break; + default: res = d->notify_helper(receiver, e); break; -- cgit v0.12 From 8d08c42c6a5478e8890d59f58483f4eff3d286ca Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 7 Apr 2009 16:26:37 +0200 Subject: Added QApplication::autoSipOnMouseFocus. RevBy: denis --- src/gui/kernel/qapplication.cpp | 33 +++++++++++++++++++++++++++++++++ src/gui/kernel/qapplication.h | 5 +++++ src/gui/kernel/qapplication_p.h | 1 + 3 files changed, 39 insertions(+) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 6f0a4e6..28e152a 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -449,6 +449,7 @@ bool QApplicationPrivate::animate_tooltip = false; bool QApplicationPrivate::fade_tooltip = false; bool QApplicationPrivate::animate_toolbox = false; bool QApplicationPrivate::widgetCount = false; +bool QApplicationPrivate::auto_sip_on_mouse_focus = false; QString* QApplicationPrivate::styleOverride = 0; #if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) bool QApplicationPrivate::inSizeMove = false; @@ -1080,6 +1081,7 @@ QApplication::~QApplication() QApplicationPrivate::animate_tooltip = false; QApplicationPrivate::fade_tooltip = false; QApplicationPrivate::widgetCount = false; + QApplicationPrivate::auto_sip_on_mouse_focus = false; // trigger unregistering of QVariant's GUI types extern int qUnregisterGuiVariant(); @@ -3447,6 +3449,37 @@ Qt::LayoutDirection QApplication::layoutDirection() return layout_direction; } +/*! + \property autoSipOnMouseFocus + + This property holds whether widgets should request a software input + panel when it is focused with the mouse. This is typically used to + launch a virtual keyboard on devices which have very few or no keys. + + If the property is set to true, the widget asks for an input panel + on the mouse click which causes the widget to be focused. If the + property is set to false, the user must click a second time before + the widget asks for an input panel. + + \note If the widget is focused by other means than a mouse click, + the next click is will trigger an input panel request, + regardless of the value of this property. + + The default is platform dependent. + + \sa QEvent::RequestSoftwareInputPanel, QInputContext +*/ + +void QApplication::setAutoSipOnMouseFocus(bool enable) +{ + QApplicationPrivate::auto_sip_on_mouse_focus = enable; +} + +bool QApplication::autoSipOnMouseFocus() +{ + return QApplicationPrivate::auto_sip_on_mouse_focus; +} + /*! \obsolete diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 807d347..64b33bf 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -96,6 +96,8 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication Q_PROPERTY(int cursorFlashTime READ cursorFlashTime WRITE setCursorFlashTime) Q_PROPERTY(int doubleClickInterval READ doubleClickInterval WRITE setDoubleClickInterval) Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval) + Q_PROPERTY(bool autoSipOnMouseFocus READ autoSipOnMouseFocus + WRITE setAutoSipOnMouseFocus) #ifndef QT_NO_WHEELEVENT Q_PROPERTY(int wheelScrollLines READ wheelScrollLines WRITE setWheelScrollLines) #endif @@ -198,6 +200,9 @@ public: static void setKeyboardInputInterval(int); static int keyboardInputInterval(); + static void setAutoSipOnMouseFocus(bool); + static bool autoSipOnMouseFocus(); + #ifndef QT_NO_WHEELEVENT static void setWheelScrollLines(int); static int wheelScrollLines(); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 553efbe..bfc5652 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -354,6 +354,7 @@ public: static bool fade_tooltip; static bool animate_toolbox; static bool widgetCount; // Coupled with -widgetcount switch + static bool auto_sip_on_mouse_focus; #ifdef Q_WS_MAC static bool native_modal_dialog_active; #endif -- cgit v0.12 From 0bc0c1c9b09cda459dbfdc16cb4089297160ce85 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 7 Apr 2009 16:28:57 +0200 Subject: Implemented RequestSoftwareInputPanel events in QLineEdit. AutoTest: Included RevBy: denis --- src/gui/widgets/qlineedit.cpp | 9 +++++ src/gui/widgets/qlineedit_p.h | 4 ++- tests/auto/qinputcontext/tst_qinputcontext.cpp | 49 +++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 8b553f9..d03cd3e 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1768,6 +1768,13 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) } } #endif + + if (e->button() == Qt::LeftButton && (!d->clickCausedFocus + || QApplication::autoSipOnMouseFocus())) { + QEvent event(QEvent::RequestSoftwareInputPanel); + QApplication::sendEvent(this, &event); + } + d->clickCausedFocus = 0; } /*! \reimp @@ -2350,6 +2357,8 @@ void QLineEdit::focusInEvent(QFocusEvent *e) d->moveCursor(d->nextMaskBlank(0)); else if (!d->hasSelectedText()) selectAll(); + } else if (e->reason() == Qt::MouseFocusReason) { + d->clickCausedFocus = 1; } #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason)) diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 532528b..3db903f 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -76,7 +76,8 @@ public: : cursor(0), preeditCursor(0), cursorTimer(0), frame(1), cursorVisible(0), hideCursor(false), separator(0), readOnly(0), dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0), - selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0), + selDirty(0), validInput(1), clickCausedFocus(0), + alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0), maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0), modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false), emitingEditingFinished(false), passwordEchoEditing(false) @@ -110,6 +111,7 @@ public: uint textDirty : 1; uint selDirty : 1; uint validInput : 1; + uint clickCausedFocus : 1; uint alignment; int ascent; int maxLength; diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 08bf614..5fdd931 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -45,6 +45,7 @@ #include #include #include +#include class tst_QInputContext : public QObject { @@ -62,6 +63,7 @@ public slots: private slots: void maximumTextLength(); void filterMouseEvents(); + void requestSoftwareInputPanel(); }; void tst_QInputContext::maximumTextLength() @@ -82,7 +84,7 @@ void tst_QInputContext::maximumTextLength() class QFilterInputContext : public QInputContext { public: - QFilterInputContext() : successful(false) {} + QFilterInputContext() : lastType(QEvent::None) {} ~QFilterInputContext() {} QString identifierName() { return QString(); } @@ -94,26 +96,65 @@ public: bool filterEvent( const QEvent *event ) { - successful = event->type() == QEvent::MouseButtonRelease; + lastType = event->type(); + return false; } public: - bool successful; + QEvent::Type lastType; }; void tst_QInputContext::filterMouseEvents() { QLineEdit le; le.show(); + QApplication::setActiveWindow(&le); QFilterInputContext *ic = new QFilterInputContext; le.setInputContext(ic); QTest::mouseClick(&le, Qt::LeftButton); - QVERIFY(ic->successful); + QCOMPARE(ic->lastType, QEvent::MouseButtonRelease); le.setInputContext(0); } +void tst_QInputContext::requestSoftwareInputPanel() +{ + QWidget w; + QLayout *layout = new QVBoxLayout; + QLineEdit *le1, *le2; + le1 = new QLineEdit; + le2 = new QLineEdit; + layout->addWidget(le1); + layout->addWidget(le2); + w.setLayout(layout); + + QFilterInputContext *ic1, *ic2; + ic1 = new QFilterInputContext; + ic2 = new QFilterInputContext; + le1->setInputContext(ic1); + le2->setInputContext(ic2); + + w.show(); + QApplication::setActiveWindow(&w); + + // Testing single click panel activation. + QApplication::setTwoClicksToRequestSIP(false); + QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(ic2->lastType, QEvent::RequestSoftwareInputPanel); + + // Testing double click panel activation. + QApplication::setTwoClicksToRequestSIP(true); + QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QVERIFY(ic1->lastType != QEvent::RequestSoftwareInputPanel); + QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(ic1->lastType, QEvent::RequestSoftwareInputPanel); + + // Testing right mouse button + QTest::mouseClick(le1, Qt::RightButton, Qt::NoModifier, QPoint(5, 5)); + QVERIFY(ic1->lastType != QEvent::RequestSoftwareInputPanel); +} + QTEST_MAIN(tst_QInputContext) #include "tst_qinputcontext.moc" -- cgit v0.12 From 23972064c554163e4bdb6de0fe6eaa0d41a6ad6a Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 8 Apr 2009 13:29:07 +0200 Subject: Made the S60 FEP use the new RequestSoftwareInputPanel events. RevBy: Trustme --- src/gui/inputmethod/qcoefepinputcontext_p.h | 1 - src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 49 +++++++++---------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 7f0a482..e4357c2 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -102,7 +102,6 @@ private: bool m_inDestruction; int m_cursorVisibility; int m_inlinePosition; - QPoint m_mousePressPos; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; }; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index b9ea4c7..5bf4259 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -208,39 +208,26 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) return false; } - if (event->type() == QEvent::MouseButtonPress) { - const QMouseEvent *mEvent = static_cast(event); - m_mousePressPos = mEvent->globalPos(); - } else if (event->type() == QEvent::MouseButtonRelease) { + if (event->type() == QEvent::RequestSoftwareInputPanel) { // Notify S60 that we want the virtual keyboard to show up. - const QMouseEvent *mEvent = static_cast(event); - - if (mEvent->modifiers() == Qt::NoModifier - && mEvent->button() == Qt::LeftButton - && focusWidget() // Not set if prior MouseButtonPress was not on this widget - && focusWidget()->rect().contains(focusWidget()->mapFromGlobal(mEvent->globalPos())) - && (m_mousePressPos - mEvent->globalPos()).manhattanLength() < QApplication::startDragDistance()) { - - QSymbianControl *sControl; - sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl); - // The FEP UI temporarily steals focus when it shows up the first time, causing - // all sorts of weird effects on the focused widgets. Since it will immediately give - // back focus to us, we temporarily disable focus handling until the job's done. - if (sControl) { - sControl->setIgnoreFocusChanged(true); - } - - m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest); - - if (sControl) { - sControl->setIgnoreFocusChanged(false); - } - - // Although it is tempting to let the click through by returning false, we have to return - // true because the event might have caused focus switches, which may in turn delete - // widgets. - return true; + QSymbianControl *sControl; + Q_ASSERT(focusWidget()); + sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl); + Q_ASSERT(sControl); + + // The FEP UI temporarily steals focus when it shows up the first time, causing + // all sorts of weird effects on the focused widgets. Since it will immediately give + // back focus to us, we temporarily disable focus handling until the job's done. + if (sControl) { + sControl->setIgnoreFocusChanged(true); + } + + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest); + + if (sControl) { + sControl->setIgnoreFocusChanged(false); } + return true; } return false; -- cgit v0.12 From 82840fcce074658bd39ad6425fd50022b9250dcf Mon Sep 17 00:00:00 2001 From: axis Date: Fri, 17 Apr 2009 13:58:37 +0200 Subject: Close the input panel when focusing a non-inputmethods aware widget. AutoTest: Included RevBy: denis --- src/gui/kernel/qapplication.cpp | 10 ++++++++ tests/auto/qinputcontext/tst_qinputcontext.cpp | 35 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 28e152a..c8fedfc 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -2098,6 +2098,16 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) prev->setEditFocus(false); } #endif +#ifndef QT_NO_IM + if (focus) { + QInputContext *prevIc; + prevIc = prev->inputContext(); + if (prevIc && prevIc != focus->inputContext()) { + QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel); + QApplication::sendEvent(prev, &closeSIPEvent); + } + } +#endif QFocusEvent out(QEvent::FocusOut, reason); QPointer that = prev; QApplication::sendEvent(prev, &out); diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 5fdd931..444b400 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -46,6 +46,7 @@ #include #include #include +#include class tst_QInputContext : public QObject { @@ -64,6 +65,7 @@ private slots: void maximumTextLength(); void filterMouseEvents(); void requestSoftwareInputPanel(); + void closeSoftwareInputPanel(); }; void tst_QInputContext::maximumTextLength() @@ -156,5 +158,38 @@ void tst_QInputContext::requestSoftwareInputPanel() QVERIFY(ic1->lastType != QEvent::RequestSoftwareInputPanel); } +void tst_QInputContext::closeSoftwareInputPanel() +{ + QWidget w; + QLayout *layout = new QVBoxLayout; + QLineEdit *le1, *le2; + QRadioButton *rb; + le1 = new QLineEdit; + le2 = new QLineEdit; + rb = new QRadioButton; + layout->addWidget(le1); + layout->addWidget(le2); + layout->addWidget(rb); + w.setLayout(layout); + + QFilterInputContext *ic1, *ic2; + ic1 = new QFilterInputContext; + ic2 = new QFilterInputContext; + le1->setInputContext(ic1); + le2->setInputContext(ic2); + + w.show(); + QApplication::setActiveWindow(&w); + + // Testing that panel doesn't close between two input methods aware widgets. + QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QVERIFY(ic2->lastType != QEvent::CloseSoftwareInputPanel); + + // Testing that panel closes when focusing non-aware widget. + QTest::mouseClick(rb, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); + QCOMPARE(ic2->lastType, QEvent::CloseSoftwareInputPanel); +} + QTEST_MAIN(tst_QInputContext) #include "tst_qinputcontext.moc" -- cgit v0.12 From ce4faedea2b652c1d7fc5430bbd906972a3c93bf Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 20 Apr 2009 16:06:27 +0200 Subject: Added inputMethodHints API. RevBy: denis --- doc/src/qnamespace.qdoc | 24 ++++++++++++++++++++++++ src/corelib/global/qnamespace.h | 16 ++++++++++++++++ src/gui/kernel/qwidget.cpp | 32 +++++++++++++++++++++++++++++++- src/gui/kernel/qwidget.h | 5 +++++ src/gui/kernel/qwidget_p.h | 2 ++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 674169e..5ffae83 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -2392,6 +2392,30 @@ */ /*! + \enum Qt::InputMethodHint + + \value ImhNone No hints. + \value ImhHiddenText Characters should be hidden, as is typically used when entering passwords. + This is automatically set when setting QLineEdit::echoMode to \c Password. + \value ImhNumbersOnly Only number input is allowed. + \value ImhUppercaseOnly Only upper case letter input is allowed. + \value ImhLowercaseOnly Only lower case letter input is allowed. + \value ImhNoAutoUppercase The input method should not try to automatically switch to upper case + when a sentence ends. + \value ImhPreferNumbers Numbers are preferred (but not required). + \value ImhPreferUppercase Upper case letters are preferred (but not required). + \value ImhPreferLowercase Lower case letters are preferred (but not required). + \value ImhNoPredictiveText Do not use predictive text (i.e. dictionary lookup) while typing. + \value ImhDialableCharactersOnly Only characters suitable for phone dialling are allowed. + + \note If several flags ending with \c Only are ORed together, the resulting character set will + consist of the union of the specified sets. For instance specifying \c ImhNumbersOnly and + \c ImhUppercaseOnly would yield a set consisting of numbers and uppercase letters. + + \sa QWidget::inputMethodHints +*/ + +/*! \enum Qt::InputMethodQuery \value ImMicroFocus The rectangle covering the area of the input cursor in widget coordinates. diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 7d8b321..1475b2e 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1398,6 +1398,21 @@ public: ImMaximumTextLength }; + enum InputMethodHint { + ImhNone = 0x0, + ImhHiddenText = 0x1, + ImhNumbersOnly = 0x2, + ImhUppercaseOnly = 0x4, + ImhLowercaseOnly = 0x8, + ImhNoAutoUppercase = 0x10, + ImhPreferNumbers = 0x20, + ImhPreferUppercase = 0x40, + ImhPreferLowercase = 0x80, + ImhNoPredictiveText = 0x100, + ImhDialableCharactersOnly = 0x200 + }; + Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint) + enum ToolButtonStyle { ToolButtonIconOnly, ToolButtonTextOnly, @@ -1559,6 +1574,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DropActions) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ItemFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints) typedef bool (*qInternalCallback)(void **); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7eaebbb..64aeab5 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -199,6 +199,7 @@ QWidgetPrivate::QWidgetPrivate(int version) : ,needWindowChange(0) ,isGLWidget(0) #endif + ,imHints(Qt::ImhNone) ,polished(0) , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred) @@ -8457,7 +8458,7 @@ void QWidget::inputMethodEvent(QInputMethodEvent *event) \a query specifies which property is queried. - \sa inputMethodEvent(), QInputMethodEvent, QInputContext + \sa inputMethodEvent(), QInputMethodEvent, QInputContext, inputMethodHints */ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const { @@ -8471,6 +8472,35 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const } } +/*! + \property QWidget::inputMethodHints + \brief What input method specific hints the widget has. + + This is only relevant for input widgets. It is used by + the input method to retrieve hints as to how the input method + should operate. For example, if the Qt::ImhNumbersOnly flag is + set, the input method may change its visual components to reflect + that only numbers can be entered. + + The effect may vary between input method implementations. + + \since 4.6 + + \sa inputMethodQuery(), QInputContext +*/ +Qt::InputMethodHints QWidget::inputMethodHints() const +{ + Q_D(const QWidget); + return d->imHints; +} + +void QWidget::setInputMethodHints(Qt::InputMethodHints hints) +{ + Q_D(QWidget); + d->imHints = hints; +} + + #ifndef QT_NO_DRAGANDDROP /*! diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 8ecf758..b92794f 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -212,6 +212,7 @@ class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice #endif Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale) Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow) + Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) public: enum RenderFlag { @@ -673,6 +674,10 @@ protected: virtual void inputMethodEvent(QInputMethodEvent *); public: virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const; + + Qt::InputMethodHints inputMethodHints() const; + void setInputMethodHints(Qt::InputMethodHints hints); + protected: void resetInputContext(); protected Q_SLOTS: diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index ec64b6e..2c68338 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -604,6 +604,8 @@ public: uint isGLWidget : 1; #endif + Qt::InputMethodHints imHints; + #if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_S60) #ifdef Q_WS_MAC void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); -- cgit v0.12 From 203b2b2c611e29ee18ee4f546b8695359710fd1b Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 20 Apr 2009 16:07:02 +0200 Subject: Made QLineEdit set input method hints when changing echo mode. RevBy: denis --- src/gui/widgets/qlineedit.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index d03cd3e..fa337af 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -97,8 +97,7 @@ extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp static inline bool shouldEnableInputMethod(QLineEdit *lineedit) { - const QLineEdit::EchoMode mode = lineedit->echoMode(); - return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit); + return !lineedit->isReadOnly(); } /*! @@ -544,7 +543,13 @@ void QLineEdit::setEchoMode(EchoMode mode) Q_D(QLineEdit); if (mode == (EchoMode)d->echoMode) return; - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); + Qt::InputMethodHints imHints = inputMethodHints(); + if (mode == Password) { + imHints |= Qt::ImhHiddenText; + } else { + imHints &= ~Qt::ImhHiddenText; + } + setInputMethodHints(imHints); d->echoMode = mode; d->passwordEchoEditing = false; d->updateTextLayout(); -- cgit v0.12 From 8e5b6aca31d8558ded261920ec50fc32367e4bb0 Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 4 May 2009 13:21:10 +0200 Subject: Make sure to update input context after switching input method hints. RevBy: denis --- src/gui/kernel/qwidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 64aeab5..ea59589 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8498,6 +8498,10 @@ void QWidget::setInputMethodHints(Qt::InputMethodHints hints) { Q_D(QWidget); d->imHints = hints; + if (testAttribute(Qt::WA_InputMethodEnabled)) { + Q_ASSERT(inputContext()); + inputContext()->update(); + } } -- cgit v0.12 From 41f5a37bed62619a67259f2dfe37e3c57e2bf9f7 Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 4 May 2009 13:25:50 +0200 Subject: Updated to slightly better docs. RevBy: denis --- src/gui/kernel/qwidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index ea59589..cfe02d6 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8482,7 +8482,10 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const set, the input method may change its visual components to reflect that only numbers can be entered. - The effect may vary between input method implementations. + \note The flags are only hints, so the particular input method + implementation is free to ignore them. If you want to be + sure that for instance only uppercase letters are entered, + you should also set a QValidator on the widget. \since 4.6 -- cgit v0.12 From ab7578d954c6b5ff496316246cab3644d6f688f1 Mon Sep 17 00:00:00 2001 From: axis Date: Mon, 4 May 2009 09:22:47 +0200 Subject: Implemented support for input method hints in S60 FEP. --- src/gui/inputmethod/qcoefepinputcontext_p.h | 3 + src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 114 ++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index e4357c2..57f0375 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -63,6 +63,7 @@ public: private: void commitCurrentString(); + void applyHints(Qt::InputMethodHints hints); // From MCoeFepAwareTextEditor public: @@ -98,6 +99,8 @@ private: QSymbianControl *m_parent; CAknEdwinState *m_fepState; QString m_preeditString; + Qt::InputMethodHints m_lastImHints; + TUint m_textCapabilities; bool m_isEditing; bool m_inDestruction; int m_cursorVisibility; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 5bf4259..643dc39 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -31,6 +31,8 @@ QT_BEGIN_NAMESPACE QCoeFepInputContext::QCoeFepInputContext(QObject *parent) : QInputContext(parent), m_fepState(new (ELeave) CAknEdwinState), + m_lastImHints(Qt::ImhNone), + m_textCapabilities(TCoeInputCapabilities::EAllText), m_isEditing(false), m_inDestruction(false), m_cursorVisibility(1), @@ -41,12 +43,10 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState->SetObjectProvider(this); m_fepState->SetFlags(EAknEditorFlagDefault); m_fepState->SetDefaultInputMode( EAknEditorTextInputMode ); - m_fepState->SetCurrentInputMode( EAknEditorTextInputMode ); m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetLocalLanguage(ELangEnglish); m_fepState->SetDefaultLanguage(ELangEnglish); m_fepState->SetDefaultCase( EAknEditorLowerCase ); - m_fepState->SetCurrentCase( EAknEditorLowerCase ); m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase ); m_fepState->SetSpecialCharacterTableResourceId( 0 ); m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap ); @@ -74,7 +74,17 @@ void QCoeFepInputContext::reset() void QCoeFepInputContext::update() { - // For pre-5.0 SDKs, we don't do any work. + QWidget *w = focusWidget(); + if (w) { + Qt::InputMethodHints hints = w->inputMethodHints(); + if (hints != m_lastImHints) { + m_lastImHints = hints; + applyHints(hints); + CCoeEnv::Static()->InputCapabilitiesChanged(); + } + } + + // For pre-5.0 SDKs, we don't do text updates on S60 side. if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { return; } @@ -203,7 +213,22 @@ QString QCoeFepInputContext::language() bool QCoeFepInputContext::filterEvent(const QEvent *event) { - // For pre-5.0 SDKs, we don't do any work. + Q_ASSERT(focusWidget()); + + if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + const QKeyEvent *keyEvent = static_cast(event); + Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); + if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) { + // Special case in Symbian. On editors with secret text, F20 is for some reason + // considered to be a backspace. + QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), + keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); + QApplication::sendEvent(focusWidget(), &modifiedEvent); + return true; + } + } + + // For pre-5.0 SDKs, we don't launch the keyboard. if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { return false; } @@ -211,7 +236,6 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) if (event->type() == QEvent::RequestSoftwareInputPanel) { // Notify S60 that we want the virtual keyboard to show up. QSymbianControl *sControl; - Q_ASSERT(focusWidget()); sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl); Q_ASSERT(sControl); @@ -294,7 +318,7 @@ TCoeInputCapabilities QCoeFepInputContext::inputCapabilities() return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0); } - return TCoeInputCapabilities(TCoeInputCapabilities::EAllText, this, 0); + return TCoeInputCapabilities(m_textCapabilities, this, 0); } static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat) @@ -310,6 +334,84 @@ static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat return qFormat; } +void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) +{ + using namespace Qt; + + // Some sanity checking. Just make sure that the preferred set is within + // the permitted set. + InputMethodHints prefs = ImhNumbersOnly | ImhUppercaseOnly | ImhLowercaseOnly; + prefs &= hints; + if (prefs != ImhNumbersOnly && prefs != ImhUppercaseOnly && prefs != ImhLowercaseOnly) { + hints &= ~prefs; + } + + bool noOnlys = !(hints & ImhNumbersOnly || hints & ImhUppercaseOnly + || hints & ImhLowercaseOnly); + TInt flags; + + if (hints & ImhPreferNumbers && noOnlys || hints & ImhNumbersOnly) { + m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode); + } else { + m_fepState->SetDefaultInputMode(EAknEditorTextInputMode); + } + flags = 0; + if (hints & ImhNumbersOnly) { + flags |= EAknEditorNumericInputMode; + } + if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) { + flags |= EAknEditorTextInputMode; + } + if (flags == 0) { + flags = EAknEditorAllInputModes; + } + m_fepState->SetPermittedInputModes(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate); + + if (hints & ImhPreferLowercase && noOnlys || hints & ImhLowercaseOnly) { + m_fepState->SetDefaultCase(EAknEditorLowerCase); + } else if (hints & ImhPreferUppercase && noOnlys || hints & ImhUppercaseOnly) { + m_fepState->SetDefaultCase(EAknEditorUpperCase); + } else if (hints & ImhNoAutoUppercase) { + m_fepState->SetDefaultCase(EAknEditorLowerCase); + } else { + m_fepState->SetDefaultCase(EAknEditorTextCase); + } + flags = 0; + if (hints & ImhUppercaseOnly) { + flags |= EAknEditorUpperCase; + } + if (hints & ImhLowercaseOnly) { + flags |= EAknEditorLowerCase; + } + if (flags == 0) { + flags = EAknEditorAllCaseModes; + if (hints & ImhNoAutoUppercase) { + flags &= ~EAknEditorTextCase; + } + } + m_fepState->SetPermittedCases(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate); + + flags = 0; + if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly) + || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) { + flags |= EAknEditorFlagFixedCase; + } + // Using T9 and hidden text together may actually crash the FEP, so check for hidden text too. + if (hints & ImhNoPredictiveText || hints & ImhHiddenText) { + flags |= EAknEditorFlagNoT9; + } + m_fepState->SetFlags(flags); + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateFlagsUpdate); + + if (hints & ImhHiddenText) { + m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText; + } else { + m_textCapabilities = TCoeInputCapabilities::EAllText; + } +} + void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/, MFepInlineTextFormatRetriever& aInlineTextFormatRetriever, -- cgit v0.12 From 8731f4ca737d032ffdf12fa9f2dfb2fa550931dd Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 5 May 2009 09:05:04 +0200 Subject: Small optimization to input context update. Only update the input context if it has already been created. RevBy: denis --- src/gui/kernel/qwidget.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index cfe02d6..d8d7be7 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8501,9 +8501,11 @@ void QWidget::setInputMethodHints(Qt::InputMethodHints hints) { Q_D(QWidget); d->imHints = hints; - if (testAttribute(Qt::WA_InputMethodEnabled)) { - Q_ASSERT(inputContext()); - inputContext()->update(); + // Optimisation to update input context only it has already been created. + if (d->ic || qApp->d_func()->inputContext) { + QInputContext *ic = inputContext(); + if (ic) + ic->update(); } } -- cgit v0.12 From 54a61942de75faf2d7f8d1a58ec15f36505e1d38 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 5 May 2009 15:55:44 +0200 Subject: Split ImhNumbersOnly into DigitsOnly and FormattedNumbersOnly. This was discussed with denis, and we found out that PIN codes on phones are a use case where it would be an advantage to have digits only. S60 already supports this mode of operation in their VK. --- doc/src/qnamespace.qdoc | 7 +++++-- src/corelib/global/qnamespace.h | 19 ++++++++++--------- src/gui/kernel/qwidget.cpp | 4 ++-- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 5ffae83..346c425 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -2397,12 +2397,15 @@ \value ImhNone No hints. \value ImhHiddenText Characters should be hidden, as is typically used when entering passwords. This is automatically set when setting QLineEdit::echoMode to \c Password. - \value ImhNumbersOnly Only number input is allowed. + \value ImhDigitsOnly Only digit input is allowed. + \value ImhFormattedNumbersOnly Only number input (including integers and real numbers) is allowed. \value ImhUppercaseOnly Only upper case letter input is allowed. \value ImhLowercaseOnly Only lower case letter input is allowed. \value ImhNoAutoUppercase The input method should not try to automatically switch to upper case when a sentence ends. - \value ImhPreferNumbers Numbers are preferred (but not required). + \value ImhPreferNumbers Numbers are preferred (but not required). This can include only digits, + or all numbers, depending on which one of the \c ImhDigitsOnly and + \c ImhFormattedNumbersOnly flags is given. \value ImhPreferUppercase Upper case letters are preferred (but not required). \value ImhPreferLowercase Lower case letters are preferred (but not required). \value ImhNoPredictiveText Do not use predictive text (i.e. dictionary lookup) while typing. diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 1475b2e..e0ca27c 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1401,15 +1401,16 @@ public: enum InputMethodHint { ImhNone = 0x0, ImhHiddenText = 0x1, - ImhNumbersOnly = 0x2, - ImhUppercaseOnly = 0x4, - ImhLowercaseOnly = 0x8, - ImhNoAutoUppercase = 0x10, - ImhPreferNumbers = 0x20, - ImhPreferUppercase = 0x40, - ImhPreferLowercase = 0x80, - ImhNoPredictiveText = 0x100, - ImhDialableCharactersOnly = 0x200 + ImhDigitsOnly = 0x2, + ImhFormattedNumbersOnly = 0x4, + ImhUppercaseOnly = 0x8, + ImhLowercaseOnly = 0x10, + ImhNoAutoUppercase = 0x20, + ImhPreferNumbers = 0x40, + ImhPreferUppercase = 0x80, + ImhPreferLowercase = 0x100, + ImhNoPredictiveText = 0x200, + ImhDialableCharactersOnly = 0x400 }; Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index d8d7be7..639d964 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8478,8 +8478,8 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const This is only relevant for input widgets. It is used by the input method to retrieve hints as to how the input method - should operate. For example, if the Qt::ImhNumbersOnly flag is - set, the input method may change its visual components to reflect + should operate. For example, if the Qt::ImhFormattedNumbersOnly flag + is set, the input method may change its visual components to reflect that only numbers can be entered. \note The flags are only hints, so the particular input method -- cgit v0.12 From 7e6dd153858710282ddcb526e413226c3b7db833 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 5 May 2009 15:57:59 +0200 Subject: Clarified the docs a bit. --- src/gui/kernel/qwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 639d964..19fdfbf 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8484,7 +8484,7 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const \note The flags are only hints, so the particular input method implementation is free to ignore them. If you want to be - sure that for instance only uppercase letters are entered, + sure that a certain type of characters are entered, you should also set a QValidator on the widget. \since 4.6 -- cgit v0.12 From ae3a933997580381c052fdba74e38df37cf78722 Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 6 May 2009 15:00:50 +0200 Subject: Improved the docs a bit. --- doc/src/qnamespace.qdoc | 7 +++++-- src/gui/kernel/qwidget.cpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 346c425..84b3a01 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -2402,9 +2402,10 @@ \value ImhUppercaseOnly Only upper case letter input is allowed. \value ImhLowercaseOnly Only lower case letter input is allowed. \value ImhNoAutoUppercase The input method should not try to automatically switch to upper case - when a sentence ends. + at the beginning of a sentence. \value ImhPreferNumbers Numbers are preferred (but not required). This can include only digits, - or all numbers, depending on which one of the \c ImhDigitsOnly and + phone numbers, or all numbers, depending on which one of the + \c ImhDigitsOnly, \c ImhDialableCharactersOnly and \c ImhFormattedNumbersOnly flags is given. \value ImhPreferUppercase Upper case letters are preferred (but not required). \value ImhPreferLowercase Lower case letters are preferred (but not required). @@ -2415,6 +2416,8 @@ consist of the union of the specified sets. For instance specifying \c ImhNumbersOnly and \c ImhUppercaseOnly would yield a set consisting of numbers and uppercase letters. + \note If several flags of the \c Prefer type are ORed together, the result is undefined. + \sa QWidget::inputMethodHints */ diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 19fdfbf..b28a95e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8487,6 +8487,8 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const sure that a certain type of characters are entered, you should also set a QValidator on the widget. + The default value is Qt::ImhNone. + \since 4.6 \sa inputMethodQuery(), QInputContext -- cgit v0.12 From c4ee1ec3f05e14d17708d6e1102ba7dd994d422a Mon Sep 17 00:00:00 2001 From: axis Date: Wed, 6 May 2009 15:01:54 +0200 Subject: Improved the handling of input method hints in S60. Made it more robust, as well as added support for the new ImhDigitsOnly and ImhFormattedNumbers flags. --- src/gui/inputmethod/qcoefepinputcontext_p.h | 1 + src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 91 +++++++++++++++++++------ 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 57f0375..9ce9724 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -63,6 +63,7 @@ public: private: void commitCurrentString(); + void updateHints(); void applyHints(Qt::InputMethodHints hints); // From MCoeFepAwareTextEditor diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 643dc39..bf50383 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -74,15 +74,7 @@ void QCoeFepInputContext::reset() void QCoeFepInputContext::update() { - QWidget *w = focusWidget(); - if (w) { - Qt::InputMethodHints hints = w->inputMethodHints(); - if (hints != m_lastImHints) { - m_lastImHints = hints; - applyHints(hints); - CCoeEnv::Static()->InputCapabilitiesChanged(); - } - } + updateHints(); // For pre-5.0 SDKs, we don't do text updates on S60 side. if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) { @@ -102,6 +94,8 @@ void QCoeFepInputContext::setFocusWidget(QWidget *w) CCoeEnv::Static()->Fep()->CancelTransaction(); QInputContext::setFocusWidget(w); + + updateHints(); } void QCoeFepInputContext::widgetDestroyed(QWidget *w) @@ -334,29 +328,67 @@ static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat return qFormat; } +void QCoeFepInputContext::updateHints() +{ + QWidget *w = focusWidget(); + if (w) { + Qt::InputMethodHints hints = w->inputMethodHints(); + if (hints != m_lastImHints) { + m_lastImHints = hints; + applyHints(hints); + } + } +} + void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) { using namespace Qt; - // Some sanity checking. Just make sure that the preferred set is within - // the permitted set. - InputMethodHints prefs = ImhNumbersOnly | ImhUppercaseOnly | ImhLowercaseOnly; + bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly; + bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly + || hints & ImhLowercaseOnly); + TInt flags; + Qt::InputMethodHints oldHints = hints; + + // Some sanity checking. Make sure that only one preference is set. + InputMethodHints prefs = ImhPreferNumbers | ImhPreferUppercase | ImhPreferLowercase; prefs &= hints; - if (prefs != ImhNumbersOnly && prefs != ImhUppercaseOnly && prefs != ImhLowercaseOnly) { + if (prefs != ImhPreferNumbers && prefs != ImhPreferUppercase && prefs != ImhPreferLowercase) { hints &= ~prefs; } + if (!noOnlys) { + // Make sure that the preference is within the permitted set. + if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly)) { + hints &= ~ImhPreferNumbers; + } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) { + hints &= ~ImhPreferUppercase; + } else if (hints & ImhPreferLowercase && !(hints & ImhLowercaseOnly)) { + hints &= ~ImhPreferLowercase; + } + // If there is no preference, set it to something within the permitted set. + if (!(hints & ImhPreferNumbers || hints & ImhPreferUppercase || hints & ImhPreferLowercase)) { + if (hints & ImhLowercaseOnly) { + hints |= ImhPreferLowercase; + } else if (hints & ImhUppercaseOnly) { + hints |= ImhPreferUppercase; + } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly + || hints & ImhDialableCharactersOnly) { + hints |= ImhPreferNumbers; + } + } + } - bool noOnlys = !(hints & ImhNumbersOnly || hints & ImhUppercaseOnly - || hints & ImhLowercaseOnly); - TInt flags; - - if (hints & ImhPreferNumbers && noOnlys || hints & ImhNumbersOnly) { + if (hints & ImhPreferNumbers) { m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode); + m_fepState->SetCurrentInputMode(EAknEditorNumericInputMode); } else { m_fepState->SetDefaultInputMode(EAknEditorTextInputMode); + m_fepState->SetCurrentInputMode(EAknEditorTextInputMode); } flags = 0; - if (hints & ImhNumbersOnly) { + if (numbersOnly) { flags |= EAknEditorNumericInputMode; } if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) { @@ -368,14 +400,18 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetPermittedInputModes(flags); m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate); - if (hints & ImhPreferLowercase && noOnlys || hints & ImhLowercaseOnly) { + if (hints & ImhPreferLowercase) { m_fepState->SetDefaultCase(EAknEditorLowerCase); - } else if (hints & ImhPreferUppercase && noOnlys || hints & ImhUppercaseOnly) { + m_fepState->SetCurrentCase(EAknEditorLowerCase); + } else if (hints & ImhPreferUppercase) { m_fepState->SetDefaultCase(EAknEditorUpperCase); + m_fepState->SetCurrentCase(EAknEditorUpperCase); } else if (hints & ImhNoAutoUppercase) { m_fepState->SetDefaultCase(EAknEditorLowerCase); + m_fepState->SetCurrentCase(EAknEditorLowerCase); } else { m_fepState->SetDefaultCase(EAknEditorTextCase); + m_fepState->SetCurrentCase(EAknEditorTextCase); } flags = 0; if (hints & ImhUppercaseOnly) { @@ -405,11 +441,24 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) m_fepState->SetFlags(flags); m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateFlagsUpdate); + if (hints & ImhFormattedNumbersOnly) { + flags = EAknEditorCalculatorNumberModeKeymap; + } else if (hints & ImhDigitsOnly) { + flags = EAknEditorPlainNumberModeKeymap; + } else { + // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for + // that flag. + flags = EAknEditorStandardNumberModeKeymap; + } + m_fepState->SetNumericKeymap(static_cast(flags)); + if (hints & ImhHiddenText) { m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText; } else { m_textCapabilities = TCoeInputCapabilities::EAllText; } + + CCoeEnv::Static()->InputCapabilitiesChanged(); } void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, -- cgit v0.12