[meego-commits] 5584: Changes to Trunk:Testing/meegotouch-inputmethodkeyboard
Kaitlin Rupert
kaitlin.rupert at intel.com
Mon Jul 12 18:31:52 UTC 2010
Hi,
I have made the following changes to meegotouch-inputmethodkeyboard in project Trunk:Testing. Please review and accept ASAP.
Thank You,
Kaitlin Rupert
[This message was auto-generated]
---
Request #5584:
submit: devel:nokia:trunk/meegotouch-inputmethodkeyboard(r3) -> Trunk:Testing/meegotouch-inputmethodkeyboard
Message:
Update to release tag 0.4.8-2. This update is dependent on the libmeegotouch u
pdate.
State: new 2010-07-12T06:26:52 krupert
Comment: None
changes files:
--------------
--- meegotouch-inputmethodkeyboard.changes
+++ meegotouch-inputmethodkeyboard.changes
@@ -0,0 +1,3 @@
+* Thu Jul 08 2010 Kaitlin Rupert <kaitlin.rupert at intel.com> - 0.4.8
+- Update to release tag 0.4.8-2
+
old:
----
meegotouch-inputmethodkeyboard-0.4.2.1.tar.bz2
new:
----
meegotouch-inputmethodkeyboard-0.4.8.tar.bz2
spec files:
-----------
--- meegotouch-inputmethodkeyboard.spec
+++ meegotouch-inputmethodkeyboard.spec
@@ -1,13 +1,13 @@
#
# Do not Edit! Generated by:
-# spectacle version 0.17
+# spectacle version 0.18
#
# >> macros
# << macros
Name: meegotouch-inputmethodkeyboard
Summary: MeeGo Virtual Keyboard
-Version: 0.4.2.1
+Version: 0.4.8
Release: 1
Group: System/GUI/Other
License: LGPL v2.1
@@ -24,10 +24,9 @@
BuildRequires: pkgconfig(QtNetwork)
BuildRequires: pkgconfig(QtGui)
BuildRequires: pkgconfig(meegotouch)
-BuildRequires: meegotouch-inputmethodframework-devel
-BuildRequires: meegotouch-inputmethodengine-devel
-BuildRequires: meegotouch-feedback-devel
-BuildRequires: meegotouch-feedbackreactionmaps-devel
+BuildRequires: pkgconfig(MeegoImFramework)
+BuildRequires: pkgconfig(MeegoImEngine)
+BuildRequires: pkgconfig(meegotouch-feedbackreactionmaps)
Provides: duikeyboard >= 0.4.0
Provides: meegokeyboard > 0.4.2
Obsoletes: duikeyboard < 0.4.0
@@ -105,15 +104,17 @@
%{_libdir}/meego-im-plugins/*.so
%{_libdir}/qt4/plugins/tasfixtures/libfixture_virtualkeyboard.so
%{_datadir}/gconf/schemas/meego-keyboard.schemas
-%{_datadir}/meegotouch/virtual-keyboard/*
+%{_datadir}/meegotouch/virtual-keyboard
+%{_datadir}/l10n/meegotouch/virtual-keyboard.qm
+%{_datadir}/themes/base/meegotouch/libmeego-keyboard/style/libmeego-keyboard.css
+%{_datadir}/themes/base/meegotouch/svg/meegotouch-keyboard.svg
# << files
%files devel
%defattr(-,root,root,-)
# >> files devel
-%{_includedir}/meego-keyboard/*
-%{_libdir}/meego-keyboard-tests/*
-%{_datadir}/meego-keyboard-tests/*
+%{_includedir}/meego-keyboard
+%{_libdir}/meego-keyboard-tests
+%{_datadir}/meego-keyboard-tests
# << files devel
-
other changes:
--------------
++++++ meegotouch-inputmethodkeyboard-0.4.2.1.tar.bz2 -> meegotouch-inputmethodkeyboard-0.4.8.tar.bz2
--- debian/api
+++ debian/api
+interface: libmeego-keyboard
+type: library
+scope: Platform
+state: unstable
+libs-pkg: meego-keyboard
+dev-pkg: meego-keyboard-dev
--- debian/changelog
+++ debian/changelog
@@ -1,3 +1,66 @@
+meego-keyboard (0.4.8-2) unstable; urgency=low
+
+ * Hide the opened settings dialog when its parent item is hidden
+
+ -- Ning Chi <ext-chi.ning at nokia.com> Sat, 03 Jul 2010 15:39:20 +0300
+
+meego-keyboard (0.4.8-1) unstable; urgency=low
+
+ * Reduced the number of selected default languages
+ * Popup to appear immediately when button is pressed
+ * Fixed copy/paste button styling
+ * Layouts to use endonyms for language names
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Fri, 02 Jul 2010 12:34:40 +0300
+
+meego-keyboard (0.4.7-1) unstable; urgency=low
+
+ * Fixed vkb crashing when en_gb is not selected to be used
+ * Better implementation for relocation workaround
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Thu, 01 Jul 2010 10:15:00 +0300
+
+meego-keyboard (0.4.6-1) unstable; urgency=low
+
+ * Replaced layoutmenu with framework settings
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Tue, 29 Jun 2010 11:47:12 +0300
+
+meego-keyboard (0.4.5-1) unstable; urgency=low
+
+ * Symbol view is toggled by clicking sym button
+ * Fixes: NB#173809, New: custom autorepeat setup
+ * Fixes: NB#168702, commit preedit in vkb->hwkbd transition
+ * Fixes delete on hardware keyboard
+ * Changes: correct language code in xml file and layoutmanager
+ * Changes: support icon_id for custom toolbar
+ * Implemented SWP#TINME-790, SWP#TINME-941, SWP#TINME-835, SWP#TINME-967, SWP#TINME-908
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Wed, 23 Jun 2010 11:13:18 +0300
+
+meego-keyboard (0.4.4-1) unstable; urgency=low
+
+ * Uses toolbar API from im framework
+ * Uses MeegoImEngine instead of Dui prefixed
+ * Implemented direct mode gesture
+ * Implemented direct mode for hardware keyboard
+ * Fixes: NB#170644, hwkbd: send release events for all press events
+ * Fixes: NB#161309, Keyboard sends Key-Events during "swipe-gesture"
+ * Dead keys to stay pressed when selected
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Wed, 16 Jun 2010 17:37:39 +0300
+
+meego-keyboard (0.4.3-1) unstable; urgency=low
+
+ * Implemented multitouch support (not yet enabled as default)
+ * Better swipe gesture recognition
+ * Error correction disabled as default
+ * Fixed error correction candidate width
+ * Separate package for fixtures required by Matti
+ * Misc fixes
+
+ -- Pekka Vuorela <pekka.ta.vuorela at nokia.com> Thu, 10 Jun 2010 13:54:59 +0300
+
meego-keyboard (0.4.2-1) unstable; urgency=low
* Fixed autocapitalization for plain qt apps
--- debian/control
+++ debian/control
@@ -2,7 +2,7 @@
Section: libs
Priority: extra
Maintainer: Mohammad Anwari <Mohammad.Anwari at nokia.com>
-Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6) | libqt4-maemo5-dev (>= 4.6), doxygen, libduiimenginewords-dev (>= 0.1.8), libmeegoimframework-dev (>= 0.19.2~1), libmeegotouch-dev (>= 0.20), libmeegoreactionmap-dev (>= 0.14.0-1)
+Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.6) | libqt4-maemo5-dev (>= 4.6), doxygen, libmeegoimenginewords-dev (>= 0.1.13), libmeegoimframework-dev (>= 0.19.6), libmeegotouch-dev (>= 0.20), libmeegoreactionmap-dev (>= 0.14.0-1)
Standards-Version: 3.7.2
Package: meego-keyboard
@@ -27,9 +27,15 @@
Package: meego-keyboard-tests
Architecture: any
-Depends: testrunner, libduiimengine-dummydriver, meego-keyboard (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
+Depends: testrunner, libmeegoimengine-dummydriver, meego-keyboard (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
XB-Maemo-CI-Packages: meego-keyboard
XB-Maemo-CI-Stage: fast, staging
Description: MeegoTouch Input Method Keyboard unit test suite
MeegoTouch Keyboard unit test suite.
+Package: meego-keyboard-fixtures
+Architecture: any
+Depends: meego-keyboard (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}
+XB-Maemo-CI-Packages: meego-keyboard
+XB-Maemo-CI-Stage: fast, staging
+Description: MeegoTouch Input Method Keyboard Fixtures used by matti
--- debian/meego-keyboard-fixtures.install
+++ debian/meego-keyboard-fixtures.install
+usr/lib/qt4/plugins/tasfixtures/
--- debian/meego-keyboard-tests.install
+++ debian/meego-keyboard-tests.install
@@ -1,3 +1,2 @@
usr/share/meego-keyboard-tests/
usr/lib/meego-keyboard-tests/
-usr/lib/qt4/plugins/tasfixtures/
--- debian/meego-keyboard.install
+++ debian/meego-keyboard.install
@@ -1,3 +1,5 @@
usr/lib/meego-im-plugins/
usr/share/meegotouch/virtual-keyboard
+usr/share/themes/base
usr/share/gconf
+usr/share/l10n/meegotouch/virtual-keyboard.qm
--- doc/doc.pri
+++ doc/doc.pri
@@ -1,13 +1,14 @@
DOXYGEN_BIN=doxygen
-QMAKE_EXTRA_UNIX_TARGETS += doc
+QMAKE_EXTRA_TARGETS += doc
doc.target = doc
+
isEmpty(DOXYGEN_BIN) {
doc.commands = @echo "Unable to detect doxygen in PATH"
} else {
doc.commands = mkdir -p $${OUT_PWD}/doc/html/ ;
- doc.commands+= ( cat $${IN_PWD}/mdoxy.cfg.in | \
- perl -pe \"s:\@M_SRC_DIR\@:$${IN_PWD}:\" > $${OUT_PWD}/doc/mdoxy.cfg );
+ doc.commands += ( cat $${IN_PWD}/mdoxy.cfg.in | \
+ perl -pe \"s:\\@M_SRC_DIR\\@:$${IN_PWD}:\" > $${OUT_PWD}/doc/mdoxy.cfg );
doc.commands+= ( cd doc ; $${DOXYGEN_BIN} mdoxy.cfg );
doc.commands+= ( cd doc ; $${IN_PWD}/xmlize.pl );
--- fixture_virtualkeyboard/fixture_virtualkeyboard.cpp
+++ fixture_virtualkeyboard/fixture_virtualkeyboard.cpp
@@ -35,7 +35,9 @@
FixtureVirtualKeyboard::~FixtureVirtualKeyboard()
{
}
-
+/*!
+ * \brief execute is called when implementing a fixture from ruby matti
+ */
bool FixtureVirtualKeyboard::execute(void *objectInstance,
const QString &actionName,
const QHash<QString, QString> ¶meters,
@@ -49,7 +51,7 @@
}
QGraphicsItem *gItem = (QGraphicsItem*)objectInstance;
- const SingleWidgetButtonArea* const widget = static_cast<SingleWidgetButtonArea*>((QGraphicsWidget*)gItem);
+ const SingleWidgetButtonArea *const widget = qgraphicsitem_cast<SingleWidgetButtonArea *>(gItem);
if (!widget) {
stdOut = "This fixture can be called for Keybuttonarea only!";
@@ -63,6 +65,13 @@
}
}
+ else if (actionName == "isAccurateMode") {
+
+ stdOut = widget->isAccurateMode() ? "true": "false";
+
+ return true;
+ }
+
const IKeyButton *button = 0;
const QString key = QString(parameters.value("key"));
--- m-keyboard.pro
+++ m-keyboard.pro
@@ -4,6 +4,7 @@
SUBDIRS = m-keyboard \
unit_test \
fixture_virtualkeyboard \
+ translations \
include (doc/doc.pri)
--- m-keyboard/common/common.pri
+++ m-keyboard/common/common.pri
@@ -11,14 +11,12 @@
$$COMMON_DIR/layoutdata.h \
$$COMMON_DIR/layoutsmanager.h \
$$COMMON_DIR/limitedtimer.h \
- $$COMMON_DIR/toolbardata.h \
- $$COMMON_DIR/toolbarwidget.h \
- $$COMMON_DIR/toolbarmanager.h \
$$COMMON_DIR/vkbdatakey.h \
$$COMMON_DIR/mxkb.h \
$$COMMON_DIR/mhardwarekeyboard.h \
$$COMMON_DIR/hwkbcharloops.h \
$$COMMON_DIR/hwkbcharloopsmanager.h \
+ $$COMMON_DIR/keyeventhandler.h \
SOURCES += \
$$COMMON_DIR/keyboarddata.cpp\
@@ -26,14 +24,12 @@
$$COMMON_DIR/layoutdata.cpp\
$$COMMON_DIR/layoutsmanager.cpp\
$$COMMON_DIR/limitedtimer.cpp\
- $$COMMON_DIR/toolbardata.cpp\
- $$COMMON_DIR/toolbarwidget.cpp \
- $$COMMON_DIR/toolbarmanager.cpp\
$$COMMON_DIR/vkbdatakey.cpp\
$$COMMON_DIR/mxkb.cpp \
$$COMMON_DIR/mhardwarekeyboard.cpp \
$$COMMON_DIR/hwkbcharloops.cpp \
$$COMMON_DIR/hwkbcharloopsmanager.cpp \
+ $$COMMON_DIR/keyeventhandler.cpp \
INCLUDEPATH += $$COMMON_DIR
DEPENDPATH += $$COMMON_DIR
--- m-keyboard/common/hwkbcharloopsmanager.cpp
+++ m-keyboard/common/hwkbcharloopsmanager.cpp
@@ -203,8 +203,8 @@
const QString name = element.attribute(HWKBTagName);
if (charLoops.contains(language)) {
//if already contains, overwrite.
- params.currentCharLoop->loops.clear();
params.currentCharLoop = charLoops[language];
+ params.currentCharLoop->loops.clear();
} else {
params.currentCharLoop = new HwKbCharacterLoops(language, name);
charLoops.insert(language, params.currentCharLoop);
--- m-keyboard/common/keyboarddata.cpp
+++ m-keyboard/common/keyboarddata.cpp
@@ -472,13 +472,3 @@
result = KeyBinding::ActionInsert;
return result;
}
-
-bool KeyboardData::isLanguageLongFormat(const QString &language)
-{
- return (language.length() > 2 && language.at(2) == '_');
-}
-
-QString KeyboardData::convertLanguageToShortFormat(const QString &language)
-{
- return language.left(2).toLower();
-}
--- m-keyboard/common/keyboarddata.h
+++ m-keyboard/common/keyboarddata.h
@@ -75,15 +75,6 @@
const LayoutData *layout(LayoutData::LayoutType type, M::Orientation orientation,
bool portraitFallback = true) const;
- /*! \brief Determines whether given language is of "en_GB" style as opposed to "en".
- */
- static bool isLanguageLongFormat(const QString &language);
-
- /*!
- * \brief Converts "en_GB" style language string to shorter "en" style.
- */
- static QString convertLanguageToShortFormat(const QString &language);
-
private:
/*!
* \brief Implements keyboard loading
--- m-keyboard/common/keyeventhandler.cpp
+++ m-keyboard/common/keyeventhandler.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+
+#include "keyeventhandler.h"
+#include "keyevent.h"
+#include "ikeybutton.h"
+#include "keybuttonarea.h"
+
+#include <QDebug>
+
+KeyEventHandler::KeyEventHandler(QObject *parent)
+ : QObject(parent),
+ shiftHeldDown(false),
+ ignoreShiftClick(false)
+{
+}
+
+void KeyEventHandler::addEventSource(KeyButtonArea *eventSource)
+{
+ bool ok = false;
+
+ ok = connect(eventSource, SIGNAL(keyPressed(const IKeyButton *, const QString &, bool)),
+ this, SLOT(handleKeyPress(const IKeyButton *, const QString &, bool)));
+ Q_ASSERT(ok);
+
+ ok = connect(eventSource, SIGNAL(keyReleased(const IKeyButton *, const QString &, bool)),
+ this, SLOT(handleKeyRelease(const IKeyButton *, const QString &, bool)));
+ Q_ASSERT(ok);
+
+ ok = connect(eventSource, SIGNAL(keyClicked(const IKeyButton *, const QString &, bool)),
+ this, SLOT(handleKeyClick(const IKeyButton *, const QString &, bool)));
+ Q_ASSERT(ok);
+}
+
+void KeyEventHandler::handleKeyPress(const IKeyButton *key, const QString &accent, bool upperCase)
+{
+ const KeyEvent event = keyToKeyEvent(*key, QEvent::KeyPress, accent, upperCase);
+ emit keyPressed(event);
+
+ if (event.qtKey() == Qt::Key_Shift) {
+ shiftHeldDown = true;
+ emit shiftPressed(true);
+ } else if (shiftHeldDown) {
+ ignoreShiftClick = true;
+ }
+}
+
+void KeyEventHandler::handleKeyRelease(const IKeyButton *key, const QString &accent, bool upperCase)
+{
+ const KeyEvent event = keyToKeyEvent(*key, QEvent::KeyRelease, accent, upperCase);
+
+ emit keyReleased(event);
+
+ if (event.qtKey() == Qt::Key_Shift && shiftHeldDown) {
+ shiftHeldDown = false;
+ emit shiftPressed(false);
+ }
+}
+
+void KeyEventHandler::handleKeyClick(const IKeyButton *key, const QString &accent, bool upperCase)
+{
+ const KeyEvent event = keyToKeyEvent(*key, QEvent::KeyRelease, accent, upperCase);
+
+ if (event.qtKey() == Qt::Key_Shift && ignoreShiftClick) {
+ ignoreShiftClick = false; // ignore this event
+ } else {
+ emit keyClicked(event);
+ }
+}
+
+KeyEvent KeyEventHandler::keyToKeyEvent(const IKeyButton &key, QKeyEvent::Type eventType,
+ const QString &accent, bool upperCase) const
+{
+ KeyEvent event;
+
+ if (accent.isEmpty()) {
+ event = key.key().toKeyEvent(eventType, upperCase);
+ } else {
+ event = key.key().toKeyEvent(eventType, accent.at(0), upperCase);
+ }
+
+ return event;
+}
+
--- m-keyboard/common/keyeventhandler.h
+++ m-keyboard/common/keyeventhandler.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+
+#ifndef KEYEVENTHANDLER_H
+#define KEYEVENTHANDLER_H
+
+#include <QObject>
+#include <QKeyEvent>
+
+class KeyButtonArea;
+class KeyEvent;
+class IKeyButton;
+class QString;
+
+/*!
+ * \class KeyEventHandler
+ * \brief Logic class to convert signals generated by buttons from
+ * raw information into KeyEvent. Also filters clicks from shift button.
+ */
+class KeyEventHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ //! Constructs new instance of KeyEventHandler with given \a parent
+ explicit KeyEventHandler(QObject *parent = 0);
+
+ //! Connects this object to signals from given \a source
+ void addEventSource(KeyButtonArea *eventSource);
+
+signals:
+ /*!
+ * \brief Emitted when key is pressed
+ *
+ * Note that this happens also when user keeps finger down/mouse
+ * button pressed and moves over another key (event is about the new key)
+ * \param event key event
+ */
+ void keyPressed(const KeyEvent &event);
+
+ /*!
+ * \brief Emitted when key is released
+ *
+ * Note that this happens also when user keeps finger down/mouse
+ * button pressed and moves over another key (event is about the old key)
+ * \param event key event
+ */
+ void keyReleased(const KeyEvent &event);
+
+ /*!
+ * \brief Emitted when user releases mouse button/lifts finger
+ *
+ * Except when done on a dead key
+ * \param event key event
+ */
+ void keyClicked(const KeyEvent &event);
+
+ /*!
+ * \brief Emitted when shift key is pressed or released
+ * \param state Contains true is key is pressed
+ */
+ void shiftPressed(bool state);
+
+private slots:
+ /*!
+ * \brief Generates KeyEvent for given \a key and emits keyPressed
+ */
+ void handleKeyPress(const IKeyButton *key, const QString &accent, bool upperCase);
+
+ /*!
+ * \brief Generates KeyEvent for given \a key and emits keyReleased
+ */
+ void handleKeyRelease(const IKeyButton *key, const QString &accent, bool upperCase);
+
+ /*!
+ * \brief Generates KeyEvent for given \a key and emits keyClicked
+ */
+ void handleKeyClick(const IKeyButton *key, const QString &accent, bool upperCase);
+
+private:
+ //! Turn key button into a KeyEvent, considering current accent and modifier state
+ KeyEvent keyToKeyEvent(const IKeyButton &key, QKeyEvent::Type eventType,
+ const QString &accent, bool upperCase) const;
+
+private:
+ //! Keeps track of shift up/down status.
+ bool shiftHeldDown;
+
+ //! When this is set true the next shift click is ignored.
+ bool ignoreShiftClick;
+
+#ifdef UNIT_TEST
+ friend class Ut_KeyEventHandler;
+#endif
+};
+
+#endif
+
--- m-keyboard/common/layoutdata.cpp
+++ m-keyboard/common/layoutdata.cpp
@@ -30,6 +30,8 @@
}
LayoutData::LayoutData()
+ : layoutOrientation(M::Landscape),
+ layoutType(General)
{
}
@@ -66,7 +68,10 @@
LayoutSection::LayoutSection()
: m_maxColumns(0),
maxRows(0),
- sectionName("")
+ movable(false),
+ m_verticalAlignment(Qt::AlignVCenter),
+ m_horizontalAlignment(Qt::AlignHCenter),
+ sectionType(Sloppy)
{
}
--- m-keyboard/common/layoutsmanager.cpp
+++ m-keyboard/common/layoutsmanager.cpp
@@ -29,7 +29,7 @@
const QString SystemDisplayLanguage("/meegotouch/i18n/language");
const QString DefaultNumberFormat("latin");
const QString LayoutFileExtension(".xml");
- const QString FallbackLanguage("en");
+ const QString FallbackLanguage("en_gb");
const QString NumberKeyboardFileArabic("number_ar.xml");
const QString NumberKeyboardFileLatin("number.xml");
const QString PhoneNumberKeyboardFileArabic("phonenumber_ar.xml");
@@ -163,11 +163,7 @@
bool loaded = keyboard->loadNokiaKeyboard(language + LayoutFileExtension);
if (!loaded) {
- // In case of "en_GB" we'll try to load en.xml.
- if (KeyboardData::isLanguageLongFormat(language)) {
- loaded = keyboard->loadNokiaKeyboard(
- KeyboardData::convertLanguageToShortFormat(language) + LayoutFileExtension);
- }
+ loaded = keyboard->loadNokiaKeyboard(QString(language.toLower() + LayoutFileExtension));
}
if (!loaded) {
@@ -177,9 +173,9 @@
}
// Make sure entry for language exists. Create if it doesn't.
- kbIterator = keyboards.find(language);
+ kbIterator = keyboards.find(language.toLower());
if (kbIterator == keyboards.end()) {
- kbIterator = keyboards.insert(language, 0);
+ kbIterator = keyboards.insert(language.toLower(), 0);
}
if (*kbIterator) {
@@ -243,7 +239,7 @@
foreach(QString language, newLanguages) {
// Existing languages are not reloaded.
- if (!keyboards.contains(language)) {
+ if (!keyboards.contains(language.toLower())) {
// Add new language
if (!loadLanguage(language)) {
qWarning() << __PRETTY_FUNCTION__
@@ -281,8 +277,6 @@
bool val = false;
QString shortFormatLanguage = language;
- if (KeyboardData::isLanguageLongFormat(language))
- shortFormatLanguage = KeyboardData::convertLanguageToShortFormat(language);
if (shortFormatLanguage == "ru" // Russian
|| shortFormatLanguage == "pl" // Polish
|| shortFormatLanguage == "bg" // Bulgaria
--- m-keyboard/common/mhardwarekeyboard.cpp
+++ m-keyboard/common/mhardwarekeyboard.cpp
@@ -28,6 +28,8 @@
#undef KeyPress
#undef KeyRelease
#include <X11/XKBlib.h>
+#define XK_MISCELLANY
+#include <X11/keysymdef.h>
#define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
@@ -39,6 +41,9 @@
const unsigned int SymModifierMask = Mod4Mask;
const unsigned int FnModifierMask = Mod5Mask;
const unsigned int longPressTime = 600; // in milliseconds
+
+ const unsigned short RepeatDelay(660); // in milliseconds
+ const unsigned short RepeatInterval(25); // in milliseconds
};
MHardwareKeyboard::MHardwareKeyboard(MInputContextConnection& icConnection, QObject *parent)
@@ -96,51 +101,113 @@
return currentKeyboardType;
}
-void MHardwareKeyboard::focusChanged(bool focusIn)
+
+void MHardwareKeyboard::toggleCustomAutoRepeat(const bool enable)
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << focusIn;
- if (focusIn) {
- // TODO: this is a temporary hack until we have proper autorepeat setup
- XAutoRepeatOff(QX11Info::display());
-
- shiftShiftCapsLock = false;
- shiftsPressed = 0;
- pressedKeys.clear();
- autoCaps = false;
+ XkbDescPtr description(XkbAllocKeyboard());
+ if (!description) {
+ qWarning() << "Unable to allocate Xkb keyboard description for autorepeat setup.";
+ return;
+ }
+
+ const unsigned int neededControls(XkbRepeatKeysMask | XkbPerKeyRepeatMask);
+ if (Success != XkbGetControls(QX11Info::display(), neededControls, description)) {
+ qWarning() << "Failure to query Xkb server controls for autorepeat setup.";
+ XkbFreeKeyboard(description, 0, True);
+ return;
+ }
+
+ if (!description->ctrls) {
+ qWarning() << "Unable to query Xkb server controls for autorepeat setup.";
+ XkbFreeKeyboard(description, 0, True);
+ return;
+ }
+
+ if (False == XkbChangeEnabledControls(QX11Info::display(), XkbUseCoreKbd,
+ XkbRepeatKeysMask, XkbRepeatKeysMask)) {
+ qWarning() << "Unable to enable controls for autorepeat.";
+ XkbFreeKeyboard(description, 0, True);
+ return;
+ }
+
+ description->ctrls->repeat_delay = RepeatDelay;
+ description->ctrls->repeat_interval = RepeatInterval;
+
+ std::fill(description->ctrls->per_key_repeat,
+ description->ctrls->per_key_repeat + XkbPerKeyBitArraySize, enable ? 0 : 0xff);
- // We reset state without using latch/lockModifiers in order to force notification
- // (to make sure whoever is listening is in sync with us).
- currentLatchedMods = 0;
- mXkb.latchModifiers(ShiftMask | FnModifierMask, 0);
- emit modifierStateChanged(Qt::ShiftModifier, ModifierClearState);
- switch (currentKeyboardType) {
- case M::NumberContentType:
- case M::PhoneNumberContentType:
- // With number and phone number content type Fn must be permanently locked
- currentLockedMods = FnModifierMask;
- mXkb.lockModifiers(FnModifierMask, FnModifierMask);
- emit modifierStateChanged(FnLevelModifier, ModifierLockedState);
- stateTransitionsDisabled = true;
- break;
- default:
- stateTransitionsDisabled = false;
- // clear locked modifiers for other keyboard types.
- currentLockedMods = 0;
- mXkb.lockModifiers(LockMask | FnModifierMask, 0);
- emit modifierStateChanged(FnLevelModifier, ModifierClearState);
- break;
+ if (enable) {
+ static const KeySym repeatableKeys[] = { XK_BackSpace, XK_Left, XK_Up, XK_Right, XK_Down };
+
+ for (unsigned int i = 0; i < ELEMENTS(repeatableKeys); ++i) {
+ const KeyCode repeatableKeyCode(XKeysymToKeycode(QX11Info::display(), repeatableKeys[i]));
+ if (repeatableKeyCode) {
+ description->ctrls->per_key_repeat[repeatableKeyCode >> 3] |= 1 << (repeatableKeyCode & 7);
+ } else {
+ qWarning() << "Unable to make keysym" << repeatableKeys[i] << "repeatable: no keycode found.";
+ }
}
+ }
- inputContextConnection.setRedirectKeys(true);
- } else {
- inputContextConnection.setRedirectKeys(false);
- // Unlock and unlatch everything. If for example non-Qt X application gets focus
- // after this focus out, there is no way to unlock Lock modifier using the
- // physical keyboard. So better clear the state a well as we can.
- lockModifiers(LockMask | FnModifierMask, 0);
- latchModifiers(ShiftMask | FnModifierMask, 0);
- XAutoRepeatOn(QX11Info::display());
+ if (False == XkbSetControls(QX11Info::display(), neededControls, description)) {
+ qWarning() << "Unable to set Xkb server controls for autorepeat setup.";
}
+
+ XkbFreeKeyboard(description, 0, True);
+
+ inputContextConnection.setDetectableAutoRepeat(enable);
+}
+
+void MHardwareKeyboard::enable()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ toggleCustomAutoRepeat(true);
+
+ shiftShiftCapsLock = false;
+ shiftsPressed = 0;
+ pressedKeys.clear();
+ autoCaps = false;
+
+ // We reset state without using latch/lockModifiers in order to force notification
+ // (to make sure whoever is listening is in sync with us).
+ currentLatchedMods = 0;
+ mXkb.latchModifiers(ShiftMask | FnModifierMask, 0);
+ emit modifierStateChanged(Qt::ShiftModifier, ModifierClearState);
+ switch (currentKeyboardType) {
+ case M::NumberContentType:
+ case M::PhoneNumberContentType:
+ // With number and phone number content type Fn must be permanently locked
+ currentLockedMods = FnModifierMask;
+ mXkb.lockModifiers(FnModifierMask, FnModifierMask);
+ emit modifierStateChanged(FnLevelModifier, ModifierLockedState);
+ stateTransitionsDisabled = true;
+ break;
+ default:
+ stateTransitionsDisabled = false;
+ // clear locked modifiers for other keyboard types.
+ currentLockedMods = 0;
+ mXkb.lockModifiers(LockMask | FnModifierMask, 0);
+ emit modifierStateChanged(FnLevelModifier, ModifierClearState);
+ break;
+ }
+
+ inputContextConnection.setRedirectKeys(true);
+}
+
+
+void MHardwareKeyboard::disable()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ inputContextConnection.setRedirectKeys(false);
+ // Unlock and unlatch everything. If for example non-Qt X application gets focus
+ // after this focus out, there is no way to unlock Lock modifier using the
+ // physical keyboard. So better clear the state a well as we can.
+ lockModifiers(LockMask | FnModifierMask, 0);
+ latchModifiers(ShiftMask | FnModifierMask, 0);
+
+ toggleCustomAutoRepeat(false);
}
@@ -280,6 +347,18 @@
keyCode == Qt::Key_Delete ? "\b" : text, autoRepeat, count));
eaten = true;
}
+ // Delete is generated by pressing Shift+Backspace. This results to an event with
+ // shift modifier and Delete key code, which can be interpreted as the cut shortcut
+ // even though user intended just delete action. Shift+Del shouldn't be cut shortcut
+ // on our platform but Qt is not going to change that, so we work around the problem
+ // by removing the shift modifier.
+ else if (shiftsPressed && (keyCode == Qt::Key_Delete)) {
+ inputContextConnection.sendKeyEvent(
+ QKeyEvent(QEvent::KeyPress, keyCode,
+ modifiers & ~Qt::KeyboardModifiers(Qt::ShiftModifier),
+ text, autoRepeat, count));
+ eaten = true;
+ }
// Relatch modifiers, X unlatches them on press but we want to unlatch on release
// (and not even always on release, e.g. with Sym+aaab we unlatch only after the
@@ -296,11 +375,23 @@
quint32 nativeScanCode, quint32 nativeModifiers)
{
bool eaten = false;
+ const bool keyWasPressed(pressedKeys.contains(nativeScanCode));
- if (nativeModifiers & SymModifierMask) {
+ // Relock modifiers; X seems to unlock Fn automatically on Fn release, which is not
+ // desired at least with [phone] number content type.
+ if (currentLockedMods) {
+ mXkb.lockModifiers(currentLockedMods, currentLockedMods);
+ }
+
+ if (keyWasPressed && (nativeModifiers & SymModifierMask)) {
eaten = handleReleaseWithSymModifier(keyCode, text);
}
+ const Qt::KeyboardModifiers filteredModifiers(
+ ((currentLatchedMods & ShiftMask) && !shiftsPressed)
+ ? (modifiers & ~Qt::KeyboardModifiers(Qt::ShiftModifier))
+ : modifiers);
+
if (keyCode == Qt::Key_Shift) {
if (!shiftShiftCapsLock) {
handleCyclableModifierRelease(Qt::Key_Shift, LockMask, ShiftMask, FnModifierMask,
@@ -313,18 +404,13 @@
handleCyclableModifierRelease(FnLevelKey, FnModifierMask, FnModifierMask, LockMask,
ShiftMask);
} else if (!eaten && !passKeyOnPress(keyCode, text, nativeScanCode)) {
- const bool keyWasPressed(pressedKeys.contains(nativeScanCode));
if (keyWasPressed) {
inputContextConnection.sendKeyEvent(
- QKeyEvent(QEvent::KeyPress, keyCode,
- ((currentLatchedMods & ShiftMask) && !shiftsPressed)
- ? (modifiers & ~Qt::KeyboardModifiers(Qt::ShiftModifier))
- : modifiers,
- text, false, 1));
- // TODO: should we send release too? MTextEdit seems to be happy with
- // just press but what about others?
- eaten = true;
+ QKeyEvent(QEvent::KeyPress, keyCode, filteredModifiers, text, false, 1));
+ inputContextConnection.sendKeyEvent(
+ QKeyEvent(QEvent::KeyRelease, keyCode, filteredModifiers, text, false, 1));
}
+ eaten = true;
if (!autoCaps) {
latchModifiers(FnModifierMask | ShiftMask, 0);
@@ -332,10 +418,17 @@
}
// This case works around the problem of host calling setAutoCapitalization()
// after backspace press event but before backspace release. That turns the
- // release event into a Delete release! We eat backspace releases for consistency
- // as well. If the answer the the above "should we send release too?" question is
- // "yes", presumably we need other kind of trickery here.
- else if ((keyCode == Qt::Key_Backspace) || (keyCode == Qt::Key_Delete)) {
+ // release event into a Delete release!
+ else if (!shiftsPressed && (keyCode == Qt::Key_Delete)) {
+ inputContextConnection.sendKeyEvent(
+ QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, filteredModifiers, "\b", false, 1));
+ eaten = true;
+ }
+ // See the same case in filterKeyPress
+ else if (shiftsPressed && (keyCode == Qt::Key_Delete)) {
+ inputContextConnection.sendKeyEvent(
+ QKeyEvent(QEvent::KeyRelease, keyCode,
+ modifiers & ~Qt::KeyboardModifiers(Qt::ShiftModifier), text, false, 1));
eaten = true;
}
@@ -408,6 +501,9 @@
inputContextConnection.sendKeyEvent(
QKeyEvent(QEvent::KeyPress, static_cast<Qt::Key>(QKeySequence(text)[0]), Qt::NoModifier,
text, false, 1));
+ inputContextConnection.sendKeyEvent(
+ QKeyEvent(QEvent::KeyRelease, static_cast<Qt::Key>(QKeySequence(text)[0]), Qt::NoModifier,
+ text, false, 1));
latchModifiers(FnModifierMask | ShiftMask, 0);
pressedKeys.remove(longPressKey);
}
@@ -418,7 +514,7 @@
{
if ((lastKeyCode == SymKey) && (keyCode == SymKey)) {
emit symbolKeyClicked();
- return true; // TODO: or false?
+ return false;
}
if ((characterLoopIndex != -1) && ((lastSymText != text) || (keyCode == SymKey))) {
--- m-keyboard/common/mhardwarekeyboard.h
+++ m-keyboard/common/mhardwarekeyboard.h
@@ -67,16 +67,22 @@
//! Set auto capitalization state.
void setAutoCapitalization(bool state);
- /*! \brief Notify hardware keyboard about changed focus
+ /*! \brief Enable MHardwareKeyboard functionality
*
- * From the point of view of MHardwareKeyboard focus leaves a widget also when host's
- * state is changed from Hardware to OnScreen. If focus enters a widget while host's
- * state is OnScreen, MHardwareKeyboard won't be informed unless state changes from
- * OnScreen to Hardware.
+ * This implies that autorepeat is configured, modifier and other state is reset and
+ * key event redirection from input context is enabled.
*
- * \param focusIn true - focus has entered a widget, false - focus has left a widget
+ * You can call enable() again after enable() without calling disable() in between.
+ * This could be done e.g. when focus is changed from one widget to another.
*/
- void focusChanged(bool focusIn);
+ void enable();
+
+ /*! \brief Disable MHardwareKeyboard functionality
+ *
+ * This implies that autorepeat is enabled, modifier state is reset and key event
+ * redirection from input context is disabled.
+ */
+ void disable();
/*! \brief Reset internal state of the hardware keyboard code.
* \post modifiers in clear state
@@ -207,6 +213,18 @@
const QString &text,
quint32 nativeScanCode, quint32 nativeModifiers);
+
+ //! \brief Toggle custom autorepeat if \a enable is true, disable it otherwise
+ //!
+ //! Custom autorepeat means that only backspace and arrow keys have autorepeat
+ //! functionality. This also sets hardwired key repeat rate and delay and enables
+ //! detectable autorepeat (see \a MInputContextConnection::setDetectableAutoRepeat).
+ //!
+ //! Note: this doesn't aim to save and restore autorepeat configuration. With false
+ //! parameter autorepeat is simply enabled for all keys and detectable autorepeat is
+ //! disabled.
+ void toggleCustomAutoRepeat(bool enable);
+
M::TextContentType currentKeyboardType;
MXkb mXkb;
bool autoCaps;
@@ -218,8 +236,6 @@
//! An attribute of the last key event passed to filterKeyEvent.
Qt::Key lastKeyCode;
- // TODO: this isn't used at the moment but might serve as a starting point
- // for the key filtering feature later
typedef QHash<quint32, bool> PressedKeyMap; // key is native scan code / X keycode
PressedKeyMap pressedKeys;
--- m-keyboard/common/mxkb.cpp
+++ m-keyboard/common/mxkb.cpp
@@ -38,7 +38,6 @@
return;
}
- XSynchronize(display, 1);
// TODO: XkbUseCoreKbd may change in the device and it should be queried from xkb.
deviceSpec = XkbUseCoreKbd;
}
--- m-keyboard/common/toolbardata.cpp
+++ m-keyboard/common/toolbardata.cpp
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#include "toolbardata.h"
-
-#include <QFile>
-#include <QFileInfo>
-#include <QDomDocument>
-#include <QDebug>
-
-namespace
-{
- const QString ToolbarConfigurationPath = "/usr/share/meegotouch/imtoolbars/";
- const QString ImTagToolbar = QString("toolbar");
- const QString ImTagButton = QString("button");
- const QString ImTagLabel = QString("label");
- const QString ImTagActions = QString("actions");
- const QString ImTagName = QString("name");
- const QString ImTagGroup = QString("group");
- const QString ImTagPriority = QString("priority");
- const QString ImTagOrientation = QString("orientation");
- const QString ImTagShowOn = QString("showon");
- const QString ImTagHideOn = QString("hideon");
- const QString ImTagAlignment = QString("alignment");
- const QString ImTagIcon = QString("icon");
- const QString ImTagSize = QString("size");
- const QString ImTagText = QString("text");
- const QString ImTagTextId = QString("text_id");
- const QString ImTagToggle = QString("toggle");
- const QString ImTagPressed = QString("pressed");
- const QString ImTagSelectedText = QString("selectedtext");
- const QString ImTagAlways = QString("always");
- const QString ImTagLeft = QString("left");
- const QString ImTagRight = QString("right");
- const QString ImTagSendKeySequence = QString("sendkeysequence");
- const QString ImTagSendString = QString("sendstring");
- const QString ImTagSendCommand = QString("sendcommand");
- const QString ImTagCopy = QString("copy");
- const QString ImTagPaste = QString("paste");
- const QString ImTagShowGroup = QString("showgroup");
- const QString ImTagHideGroup = QString("hidegroup");
- const QString ImTagKeySequence = QString("keysequence");
- const QString ImTagString = QString("string");
- const QString ImTagCommand = QString("command");
- const QString ImTagOrientationLandscape = QString("landscape");
- const QString ImTagOrientationPortrait = QString("portrait");
-}
-
-struct TBParseParameters {
- //! Contains true if current XML tag was successfully parsed
- bool validTag;
-
- QString fileName;
-
- ToolbarWidget *currentWidget;
-
- TBParseParameters();
-};
-
-struct TBParseStructure {
- TBParseStructure(const QString &name, ToolbarData::TagParser p)
- : tagName(name),
- parser(p) {
- };
- QString tagName;
- ToolbarData::TagParser parser;
-};
-
-TBParseParameters::TBParseParameters()
- : validTag(true),
- fileName(""),
- currentWidget(0)
-{
-}
-
-ToolbarData::ToolbarData()
-{
-}
-
-ToolbarData::~ToolbarData()
-{
-}
-
-QString ToolbarData::fileName() const
-{
- return toolbarFileName;
-}
-
-bool ToolbarData::equal(const QString &toolbar) const
-{
- QString absoluteFileName = toolbar;
- QFileInfo info(toolbar);
- if (info.isRelative())
- absoluteFileName = ToolbarConfigurationPath + info.fileName();
- return (absoluteFileName == toolbarFileName);
-}
-
-bool ToolbarData::loadNokiaToolbarXml(const QString &fileName)
-{
- QString absoluteFileName = fileName;
- QFileInfo info(absoluteFileName);
- if (info.isRelative())
- absoluteFileName = ToolbarConfigurationPath + info.fileName();
- if (!QFile::exists(absoluteFileName)) {
- qDebug() << "can not find file:" << absoluteFileName;
- return false;
- }
-
- TBParseParameters params;
- params.fileName = absoluteFileName;
- toolbarFileName = absoluteFileName;
- bool valid = true;
- QFile infile(absoluteFileName);
- QString errorStr;
- int errorLine;
- int errorColumn;
- QDomDocument doc;
- if (!infile.open(QIODevice::ReadOnly)) {
- qWarning() << "Unable to open toolbar xml file" << absoluteFileName;
- return false;
- }
- if (!doc.setContent((QIODevice *)(&infile), true, &errorStr, &errorLine,
- &errorColumn)) {
- qWarning() << __PRETTY_FUNCTION__ << "can not parse xml" << absoluteFileName
- << "error line:" << errorLine << ", column:" << errorColumn;
- infile.close();
- return false;
- }
-
- const QDomElement root = doc.documentElement();
- //check the root tag
- if (!root.isNull() && root.tagName() != ImTagToolbar) {
- qWarning() << __PRETTY_FUNCTION__
- << "wrong format xml" << absoluteFileName << "for virtual keyboard tool bar";
- valid = false;
- } else {
- const TBParseStructure parsers[2] = {TBParseStructure(ImTagButton, &ToolbarData::parseTagButton),
- TBParseStructure(ImTagLabel, &ToolbarData::parseTagLabel)
- };
-
- parseChildren(root, params, parsers, 2);
- valid = params.validTag;
- }
-
- infile.close();
-
- return valid;
-}
-
-void ToolbarData::parseChildren(const QDomElement &element, TBParseParameters ¶ms,
- const TBParseStructure *parserList, int parserCount)
-{
- Q_ASSERT(parserCount > 0);
-
- for (QDomNode child = element.firstChild(); !child.isNull() && params.validTag;
- child = child.nextSibling()) {
- if (child.isElement()) {
- const QDomElement childElement = child.toElement();
- bool found = false;
- for (int i = 0; i < parserCount; ++i) {
- if (childElement.tagName() == parserList[i].tagName) {
- (this->*(parserList[i].parser))(childElement, params);
- found = true;
- break;
- }
- }
- if (!found) {
- qWarning() << "Unexpected tag" << childElement.tagName() << "on line"
- << childElement.lineNumber() << "column" << childElement.columnNumber()
- << "in layout file" << params.fileName;
- params.validTag = false;
- }
- }
- }
-}
-
-Qt::Alignment ToolbarData::alignment(const QString &alignmentString)
-{
- Qt::Alignment align = Qt::AlignRight;
- if (alignmentString == ImTagLeft)
- align = Qt::AlignLeft;
- else if (alignmentString == ImTagRight)
- align = Qt::AlignRight;
- return align;
-}
-
-M::Orientation ToolbarData::orientation(const QString &orientationString)
-{
- M::Orientation orient = M::Portrait;
- if (orientationString == ImTagOrientationLandscape)
- orient = M::Landscape;
- return orient;
-}
-
-ToolbarWidget::VisibleType ToolbarData::visibleType(const QString &visibleTypeString)
-{
- ToolbarWidget::VisibleType type = ToolbarWidget::Undefined;
- if (visibleTypeString == ImTagSelectedText)
- type = ToolbarWidget::WhenSelectingText;
- else if (visibleTypeString == ImTagAlways)
- type = ToolbarWidget::Always;
- return type;
-}
-
-void ToolbarData::parseTagButton(const QDomElement &element, TBParseParameters ¶ms)
-{
- const QString name = element.attribute(ImTagName);
- //check if the name is unique
- foreach(ToolbarWidget *tw, widgets) {
- if (tw->name().compare(name, Qt::CaseInsensitive) == 0) {
- return;
- }
- }
-
- ToolbarWidget *b = new ToolbarWidget(ToolbarWidget::Button);
- b->widgetName = name;
- b->group = element.attribute(ImTagGroup);
- b->priority = element.attribute(ImTagPriority).toInt();
- b->orientation = orientation(element.attribute(ImTagOrientation));
- b->showOn = visibleType(element.attribute(ImTagShowOn));
- b->hideOn = visibleType(element.attribute(ImTagHideOn));
- b->alignment = alignment(element.attribute(ImTagAlignment));
- b->text = element.attribute(ImTagText);
- b->textId = element.attribute(ImTagTextId);
- b->icon = element.attribute(ImTagIcon);
- bool ok;
- int size = element.attribute(ImTagSize).remove("%").toInt(&ok, 10);
- if (ok) {
- b->size = size;
- } else {
- b->size = 100;
- }
- b->toggle = (element.attribute(ImTagToggle) == "true") ? true : false;
- b->pressed = (element.attribute(ImTagPressed) == "true") ? true : false;
- widgets.append(b);
- params.currentWidget = b;
-
- const TBParseStructure parser(ImTagActions, &ToolbarData::parseTagActions);
- parseChildren(element, params, &parser);
-}
-
-void ToolbarData::parseTagLabel(const QDomElement &element, TBParseParameters ¶ms)
-{
- const QString name = element.attribute(ImTagName);
- //check if the name is unique
- foreach(ToolbarWidget *tw, widgets) {
- if (tw->name().compare(name, Qt::CaseInsensitive) == 0) {
- return;
- }
- }
-
- ToolbarWidget *label = new ToolbarWidget(ToolbarWidget::Label);
- label->widgetName = name;
- label->group = element.attribute(ImTagGroup);
- label->priority = element.attribute(ImTagPriority).toInt();
- label->orientation = orientation(element.attribute(ImTagOrientation));
- label->showOn = visibleType(element.attribute(ImTagShowOn));
- label->hideOn = visibleType(element.attribute(ImTagHideOn));
- label->alignment = alignment(element.attribute(ImTagAlignment));
- label->text = element.attribute(ImTagText);
- label->textId = element.attribute(ImTagTextId);
- widgets.append(label);
- params.currentWidget = label;
-}
-
-void ToolbarData::parseTagActions(const QDomElement &element, TBParseParameters ¶ms)
-{
- if (!params.currentWidget && (params.currentWidget->type() != ToolbarWidget::Button))
- return;
- const TBParseStructure parsers[7] = {TBParseStructure(ImTagSendKeySequence, &ToolbarData::parseTagSendKeySequence),
- TBParseStructure(ImTagSendString, &ToolbarData::parseTagSendString),
- TBParseStructure(ImTagSendCommand, &ToolbarData::parseTagSendCommand),
- TBParseStructure(ImTagCopy, &ToolbarData::parseTagCopy),
- TBParseStructure(ImTagPaste, &ToolbarData::parseTagPaste),
- TBParseStructure(ImTagShowGroup, &ToolbarData::parseTagShowGroup),
- TBParseStructure(ImTagHideGroup, &ToolbarData::parseTagHideGroup)
- };
- parseChildren(element, params, parsers, 7);
-}
-
-void ToolbarData::parseTagSendKeySequence(const QDomElement &element, TBParseParameters ¶ms)
-{
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::SendKeySequence);
- action->keys = element.attribute(ImTagKeySequence);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagSendString(const QDomElement &element, TBParseParameters ¶ms)
-{
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::SendString);
- action->text = element.attribute(ImTagString);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagSendCommand(const QDomElement &element, TBParseParameters ¶ms)
-{
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::SendCommand);
- action->command = element.attribute(ImTagCommand);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagCopy(const QDomElement &element, TBParseParameters ¶ms)
-{
- Q_UNUSED(element);
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::Copy);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagPaste(const QDomElement &element, TBParseParameters ¶ms)
-{
- Q_UNUSED(element);
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::Paste);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagShowGroup(const QDomElement &element, TBParseParameters ¶ms)
-{
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::ShowGroup);
- action->group = element.attribute(ImTagGroup);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
-
-void ToolbarData::parseTagHideGroup(const QDomElement &element, TBParseParameters ¶ms)
-{
- ToolbarWidget::Action *action = new ToolbarWidget::Action(ToolbarWidget::HideGroup);
- action->group = element.attribute(ImTagGroup);
- (static_cast<ToolbarWidget *>(params.currentWidget))->actions.append(action);
-}
--- m-keyboard/common/toolbardata.h
+++ m-keyboard/common/toolbardata.h
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#ifndef TOOLBARDATA_H
-#define TOOLBARDATA_H
-
-#include <QObject>
-#include <QList>
-#include "toolbarwidget.h"
-
-class QDomElement;
-struct TBParseParameters;
-struct TBParseStructure;
-
-/*!
- \brief ToolbarData corresponds to a toolbar defined in a XML file
- */
-class ToolbarData : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(ToolbarData)
-
-public:
- /*!
- * \brief Constructor
- */
- ToolbarData();
-
- /*!
- * \brief Destructor
- */
- ~ToolbarData();
-
- /*!
- * \brief Load a custom toolbar's content from \a fileName xml file.
- * \a fileName is the xml file name (with ".xml" postfix). And \a fileName could have absolute path.
- * If no absolute path specified, then it will be taken from the default path
- * "/usr/share/meegotouch/imtoolbars/".
- * \param fileName Name of the xml file which contains the content of a custom toolbar.
- */
- bool loadNokiaToolbarXml(const QString &fileName);
-
- /*!
- * \brief Returns the custom toolbar's xml file name.
- */
- QString fileName() const;
-
- /*!
- *\brief Returns true \a toolbar equal this custom toolbar.
- * \a toolbar is the xml file name.
- * \sa fileName(), \sa loadNokiaToolbarXml().
- */
- bool equal(const QString &toolbar) const;
-
-private:
- /*!
- * \brief Translate alignmentString to Qt::Alignment.
- */
- static Qt::Alignment alignment(const QString &alignmentString);
-
- /*!
- * \brief Translate orientationString to M::Orientation.
- */
- static M::Orientation orientation(const QString &orientationString);
-
- /*!
- * \brief Translate visibleTypeString to ToolbarWidget::VisibleType.
- */
- static ToolbarWidget::VisibleType visibleType(const QString &visibleTypeString);
-
- //! Parse XML tag for button.
- void parseTagButton(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for label.
- void parseTagLabel(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for action.
- void parseTagActions(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for SendKeySequence.
- void parseTagSendKeySequence(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for SendString
- void parseTagSendString(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for SendCommand
- void parseTagSendCommand(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for Copy
- void parseTagCopy(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for Paste
- void parseTagPaste(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for ShowGroup
- void parseTagShowGroup(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Parse XML tag for HideGroup
- void parseTagHideGroup(const QDomElement &element, TBParseParameters ¶ms);
-
- //! Type of tag parser methods
- typedef void (ToolbarData::*TagParser)(const QDomElement &, TBParseParameters &);
-
- /*!
- * \brief Helper method for parsing children of an element
- * \param element Element whose children are to be parsed
- * \param params Parsing state
- * \param parserList, a TBParseStructure array.
- * \param parserCount, the number of TBParseStructure in the array.
- */
- void parseChildren(const QDomElement &element, TBParseParameters ¶ms,
- const TBParseStructure *parserList, int parserCount = 1);
-protected:
- QList<ToolbarWidget *> widgets;
- QString toolbarFileName;
- friend class ToolbarManager;
- friend struct TBParseStructure;
- friend class Ut_MImToolbar;
-};
-
-#endif //TOOLBAR_H
--- m-keyboard/common/toolbarmanager.cpp
+++ m-keyboard/common/toolbarmanager.cpp
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#include "toolbarmanager.h"
-#include "toolbardata.h"
-#include "mtoolbarbutton.h"
-#include "mimtoolbar.h"
-#include <MGConfItem>
-#include <MButton>
-#include <MLabel>
-#include <MLocale>
-#include <QDebug>
-
-namespace
-{
- const QString ObjectNameToolbarButton("VirtualKeyboardToolbarButton");
- const QString ObjectNameToolbarLabel("VirtualKeyboardToolbarLabel");
- const int MaximumToolbarCount = 10;
-}
-
-const int ToolbarManager::widgetNameDataKey(1000);
-const int ToolbarManager::widgetTypeDataKey(1001);
-ToolbarManager *ToolbarManager::toolbarMgrInstance = 0;
-
-ToolbarManager::ToolbarManager()
- : current(cachedToolbars.end())
-{
-}
-
-ToolbarManager::~ToolbarManager()
-{
- qDeleteAll(cachedToolbars.values());
- cachedToolbars.clear();
- cachedToolbarIds.clear();
-
- qDeleteAll(toolbarWidgetPool);
- toolbarWidgetPool.clear();
-}
-
-void ToolbarManager::createInstance()
-{
- Q_ASSERT(!toolbarMgrInstance);
- if (!toolbarMgrInstance) {
- toolbarMgrInstance = new ToolbarManager;
- }
-}
-
-void ToolbarManager::destroyInstance()
-{
- Q_ASSERT(toolbarMgrInstance);
- delete toolbarMgrInstance;
- toolbarMgrInstance = 0;
-}
-
-int ToolbarManager::widgetCount() const
-{
- if (current != cachedToolbars.end())
- return current.value()->widgets.count();
- else
- return 0;
-}
-
-QList<ToolbarWidget *> ToolbarManager::widgetList() const
-{
- QList<ToolbarWidget *> list;
- if (current != cachedToolbars.end())
- list = current.value()->widgets;
-
- return list;
-}
-
-QList<ToolbarWidget *> ToolbarManager::widgetList(Qt::Alignment align) const
-{
- QList<ToolbarWidget *> list;
- if (current != cachedToolbars.end()) {
- foreach(ToolbarWidget *tw, current.value()->widgets) {
- if (tw->alignment == align) {
- //sort according priority
- bool inserted = false;
- for (int i = 0; i < list.count(); ++i) {
- if (((align == Qt::AlignLeft) && (list[i]->priority < tw->priority))
- || ((align == Qt::AlignRight) && (list[i]->priority > tw->priority)))
- continue;
- else {
- inserted = true;
- list.insert(i, tw);
- break;
- }
- }
- if (!inserted) {
- list.append(tw);
- continue;
- }
- }
- }
- }
- return list;
-}
-
-ToolbarWidget *ToolbarManager::toolbarWidget(qlonglong id, const QString &name) const
-{
- if (current != cachedToolbars.end() && current.key() == id) {
- return toolbarWidget(name);
- } else {
- CachedToolbarContainer::const_iterator iterator = cachedToolbars.find(id);
- if (iterator != cachedToolbars.end()) {
- foreach(ToolbarWidget *tw, iterator.value()->widgets) {
- if (tw->name() == name)
- return tw;
- }
- }
- }
- return 0;
-}
-
-ToolbarWidget *ToolbarManager::toolbarWidget(const QString &name) const
-{
- if (current != cachedToolbars.end()) {
- foreach(ToolbarWidget *tw, current.value()->widgets) {
- if (tw->name() == name)
- return tw;
- }
- }
- return 0;
-}
-
-ToolbarWidget *ToolbarManager::toolbarWidget(const MWidget *w) const
-{
- if (w)
- return toolbarWidget(w->data(widgetNameDataKey).toString());
- return 0;
-}
-
-MWidget *ToolbarManager::widget(const QString &name) const
-{
- MWidget *w = 0;
- for (int i = 0; i < toolbarWidgetPool.count(); i++) {
- if (toolbarWidgetPool[i] && toolbarWidgetPool[i]->data(widgetNameDataKey).toString() == name) {
- w = toolbarWidgetPool[i];
- break;
- }
- }
- return w;
-}
-
-QList<qlonglong> ToolbarManager::toolbarList() const
-{
- return cachedToolbars.keys();
-}
-
-qlonglong ToolbarManager::currentToolbar() const
-{
- if (current != cachedToolbars.end())
- return current.key();
- return -1;
-}
-
-bool ToolbarManager::loadToolbar(qlonglong id)
-{
- // sanity tests
- if (!toolbars.contains(id)) {
- qWarning() << "ToolbarsManager: toolbar load error: " << id;
- reset();
- return false;
- }
-
- //already load
- if ((current != cachedToolbars.end()) && (current.key() == id) && validateWidgetPool()) {
- return true;
- }
-
- current = cachedToolbars.find(id);
- if (current == cachedToolbars.end()) {
- ToolbarData * toolbarData = createToolbar(toolbars.value(id));
- if (toolbarData) {
- // if cached toolbars reach MaximumToolbarCount, then remove the most rarely used toolbar.
- if (cachedToolbarIds.count() >= MaximumToolbarCount) {
- // the last toolbar is the most rarely used one.
- delete cachedToolbars.take(cachedToolbarIds.takeLast());
- }
- current = cachedToolbars.insert(id, toolbarData);
- cachedToolbarIds.prepend(id);
- }
- } else {
- //move current (toolbar) to the beginning of cahced toolbars.
- cachedToolbarIds.move(cachedToolbarIds.indexOf(current.key()), 0);
- }
-
- if (current != cachedToolbars.end()) {
- loadToolbarWidgets();
- return true;
- } else {
- //can't find
- return false;
- }
-}
-
-ToolbarData *ToolbarManager::createToolbar(const QString &name)
-{
- // load a toolbar
- ToolbarData *toolbar = new ToolbarData;
- const bool loaded = toolbar->loadNokiaToolbarXml(name);
-
- if (!loaded) {
- qWarning() << "ToolbarsManager: toolbar load error: "
- << name;
- delete toolbar;
- toolbar = 0;
- }
-
- return toolbar;
-}
-
-void ToolbarManager::reset()
-{
- resetWidgetPool();
- current = cachedToolbars.end();
-}
-
-void ToolbarManager::loadToolbarWidgets()
-{
- qDebug() << __PRETTY_FUNCTION__;
- resetWidgetPool();
- foreach(const ToolbarWidget *tw, widgetList()) {
- createWidget(tw);
- }
-}
-
-void ToolbarManager::createWidget(const ToolbarWidget *tw)
-{
- if (!tw)
- return;
-
- QPointer<MWidget> w = widget(tw->name());
- //because name is the unique id, so if there is already created, then just use it
- if (!w) {
- //find the first unused pool item, or create a new one
- for (int i = 0; i < toolbarWidgetPool.count(); i++) {
- if (toolbarWidgetPool[i] && toolbarWidgetPool[i]->data(widgetNameDataKey).toString().isEmpty()
- && toolbarWidgetPool[i]->data(widgetTypeDataKey).toInt() == tw->type()) {
- w = toolbarWidgetPool[i];
- break;
- }
- }
- if (!w) {
- switch (tw->type()) {
- case ToolbarWidget::Button:
- w = new MToolbarButton();
- w->setObjectName(ObjectNameToolbarButton);
- break;
- case ToolbarWidget::Label:
- w = new MLabel();
- w->setObjectName(ObjectNameToolbarLabel);
- break;
- default:
- //unknown widget type.
- return;
- }
- toolbarWidgetPool.append(w);
- }
- }
- w->setData(widgetNameDataKey, tw->name());
- w->setData(widgetTypeDataKey, tw->type());
-
- switch (tw->type()) {
- case ToolbarWidget::Button: {
- MToolbarButton *b = qobject_cast<MToolbarButton*>(w);
- if (b) {
- if (!tw->textId.isEmpty()) {
- b->setText(qtTrId(tw->textId.toUtf8().data()));
- } else {
- b->setText(tw->text);
- }
- b->setIconFile(QString(tw->icon));
- b->setIconPercent(tw->size);
- b->setCheckable(tw->toggle);
- if (tw->toggle) {
- b->setChecked(tw->pressed);
- }
- connect(b, SIGNAL(clicked()), this, SLOT(handleButtonClick()));
- }
- break;
- }
- case ToolbarWidget::Label: {
- MLabel *l = qobject_cast<MLabel*>(w);
- if (!tw->textId.isEmpty()) {
- l->setText(qtTrId(tw->textId.toUtf8().data()));
- } else {
- l->setText(tw->text);
- }
- break;
- }
- default:
- break;
- }
-}
-
-void ToolbarManager::resetWidgetPool()
-{
- validateWidgetPool();
- for (int i = 0; i < toolbarWidgetPool.count(); i++) {
- toolbarWidgetPool[i]->setData(widgetNameDataKey, "");
- toolbarWidgetPool[i]->setVisible(false);
- toolbarWidgetPool[i]->disconnect();
- }
-}
-
-bool ToolbarManager::validateWidgetPool()
-{
- // Widgets in the widget pool could be destroyed outside by MImToolbar.
- // But QPointer can safely promise the pointers are already set to 0,
- // so remove all null widget from pool.
- bool valid = (toolbarWidgetPool.removeAll(0) > 0) ? false : true;
- return valid;
-}
-
-void ToolbarManager::handleButtonClick()
-{
- const MButton *button = qobject_cast<MButton *>(this->sender());
- Q_ASSERT(button);
-
- ToolbarWidget *tw = toolbarWidget(button);
- if (!tw)
- return;
- // records button's toggle state
- if (tw->toggle) {
- tw->pressed = button->isChecked();
- }
-
- emit buttonClicked(*tw);
-}
-
-void ToolbarManager::registerToolbar(qlonglong id, const QString &fileName)
-{
- qDebug() << __PRETTY_FUNCTION__;
- if ((id <= 0) || fileName.isEmpty() || toolbars.contains(id))
- return;
-
- toolbars.insert(id, fileName);
-
- ToolbarData * toolbarData = createToolbar(fileName);
- if (toolbarData) {
- // if cached toolbars reach MaximumToolbarCount, then remove the most rarely used toolbar.
- if (cachedToolbarIds.count() >= MaximumToolbarCount) {
- // the last toolbar is the most rarely used one.
- // FIXME: the removing of cached toolbar will lead to all the states changed by
- // setToolbarItemAttribute be lost. Can we avoid it?
- delete cachedToolbars.take(cachedToolbarIds.takeLast());
- }
- cachedToolbars.insert(id, toolbarData);
- cachedToolbarIds.prepend(id);
- }
-}
-
-void ToolbarManager::unregisterToolbar(qlonglong id)
-{
- qDebug() << __PRETTY_FUNCTION__;
- if (!toolbars.contains(id))
- return;
-
- if (cachedToolbars.contains(id)) {
- if (id == currentToolbar()) {
- reset();
- }
- delete cachedToolbars.take(id);
- cachedToolbarIds.removeOne(id);
- }
- toolbars.remove(id);
-}
-
-void ToolbarManager::setToolbarItemAttribute(qlonglong id, const QString &item, const QString &attribute, const QVariant &value)
-{
- qDebug() << __PRETTY_FUNCTION__;
- if ((id <= 0) || item.isEmpty() || attribute.isEmpty() || value.isNull())
- return;
-
- ToolbarWidget *tw = toolbarWidget(id, item);
- if (tw) {
- switch (tw->type()) {
- case ToolbarWidget::Button: {
- MToolbarButton *button = qobject_cast<MToolbarButton *>(widget(item));
- if (!button)
- return;
- if (attribute == "icon") {
- button->setIconFile(value.toString());
- tw->icon = value.toString();
- } else if (attribute == "text") {
- button->setText(value.toString());
- tw->text = value.toString();
- } else if (attribute == "textid") {
- button->setText(qtTrId(value.toString().toUtf8().data()));
- tw->textId = value.toString();
- } else if (attribute == "pressed" && tw->toggle) {
- button->setChecked(value.toBool());
- tw->pressed = value.toBool();
- }
- break;
- }
- case ToolbarWidget::Label: {
- MLabel *label = qobject_cast<MLabel *>(widget(item));
- if (!label)
- return;
- if (attribute == "text") {
- label->setText(value.toString());
- tw->text = value.toString();
- } else if (attribute == "textid") {
- label->setText(qtTrId(value.toString().toUtf8().data()));
- tw->textId = value.toString();
- }
- break;
- }
- default:
- break;
- }
- }
-}
-
--- m-keyboard/common/toolbarmanager.h
+++ m-keyboard/common/toolbarmanager.h
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-#ifndef TOOLBARMANAGER_H
-#define TOOLBARMANAGER_H
-
-#include <QObject>
-#include <QHash>
-#include <QPointer>
-#include "toolbarwidget.h"
-#include <memory>
-
-class ToolbarData;
-class MGConfItem;
-class MWidget;
-
-/*!
- \brief The ToolbarManager class manager the virtual keyboard toolbar.
-
- ToolbarManager loads and managers not only the toolbars which defined with GConf key
- "/meegotouch/inputmethods/toolbars",
- but also the copy/paste button and close button.
-*/
-class ToolbarManager : public QObject
-{
- Q_OBJECT
-
-public:
- /*!
- *\brief Destructor.
- */
- virtual ~ToolbarManager();
-
- //! \brief Get singleton instance
- //! \return singleton instance
- static ToolbarManager &instance();
-
- //! \brief Create singleton
- static void createInstance();
-
- //! \brief Destroy singleton
- static void destroyInstance();
-
- /*!
- * \brief Register an input method toolbar which is defined in \a fileName with the unique identifier \a id.
- * ToolbarManager can load a custom toolbar's content according \a id and \a fileName, and cache it for the
- * future use. The \a id should be unique, and the \a fileName is the absolute file name of the custom toolbar.
- */
- void registerToolbar(qlonglong id, const QString &fileName);
-
- /*!
- * \brief Unregister an input method \a toolbar which unique identifier is \a id.
- * ToolbarManager will remove the cached toolbar according \a id.
- */
- void unregisterToolbar(qlonglong id);
-
- /*!
- * \brief Sets the \a attribute for the \a item in the custom toolbar which has the unique \a id to \a value.
- */
- void setToolbarItemAttribute(qlonglong id, const QString &item, const QString &attribute, const QVariant &value);
-
- QRegion region(bool includeToolbar = true) const;
- /*!
- *\brief Returns the widget count in current loaded customized toolbar.
- */
- int widgetCount() const;
-
- /*!
- *\brief Returns the widget list in current loaded customized toolbar.
- */
- QList<ToolbarWidget *> widgetList() const;
-
- /*!
- *\brief Returns the widget list with \a align in current loaded customized toolbar.
- * And the widget list is already sorted by priorities
- */
- QList<ToolbarWidget *> widgetList(Qt::Alignment align) const;
-
- /*!
- *\brief Returns a ToolbarWidget pointer to the widget with \a name in cached customized toolbar with \a id.
- */
- ToolbarWidget *toolbarWidget(qlonglong id, const QString &name) const;
-
- /*!
- *\brief Returns a ToolbarWidget pointer to the widget with \a name in current loaded customized toolbar.
- */
- ToolbarWidget *toolbarWidget(const QString &name) const;
-
- /*!
- *\brief Returns a ToolbarWidget pointer to the widget with \a widget in current loaded customized toolbar.
- */
- ToolbarWidget *toolbarWidget(const MWidget *widget) const;
-
- /*!
- *\brief Returns a MWidget pointer to the widget with \a name in current loaded customized toolbar.
- */
- MWidget *widget(const QString &name) const;
-
- /*!
- *\brief Returns current loaded toolbar's identifier.
- */
- qlonglong currentToolbar() const;
-
- /*!
- * \brief Loads the toolbar according the unique \a id.
- * The \a uuid must be registered before by registerToolbar().
- * \return true if the toolbar \a name is loaded successfully or already cached before.
- * \sa registerToolbar().
- */
- bool loadToolbar(qlonglong id);
-
- /*!
- *\brief Reset current loaded customized toolbar to 0.
- */
- void reset();
-
-signals:
- //! Emitted when a button is clicked
- void buttonClicked(const ToolbarWidget &);
-
-private slots:
- void loadToolbarWidgets();
-
- void handleButtonClick();
-
-public:
- static const int widgetNameDataKey;
- static const int widgetTypeDataKey;
-
-private:
- /*!
- * \brief Default constructor.
- */
- ToolbarManager();
-
- /*!
- *\brief Returns a list of the name for all toolbars.
- */
- QList<qlonglong> toolbarList() const;
-
- const QString *widgetName(const MWidget *) const;
-
- void resetWidgetPool();
-
- bool validateWidgetPool();
-
- ToolbarData *createToolbar(const QString &name);
-
- void createWidget(const ToolbarWidget *b);
-
- typedef QHash<qlonglong, QString> ToolbarContainer;
- //! all registered toolbars
- ToolbarContainer toolbars;
-
- typedef QHash<qlonglong, ToolbarData *> CachedToolbarContainer;
- //! cached toolbars
- CachedToolbarContainer cachedToolbars;
-
- //! the list of identifier of the cached toolbars, sorted by used frequency.
- QList<qlonglong> cachedToolbarIds;
-
- //! current used toolbar iterator
- CachedToolbarContainer::const_iterator current;
-
- QList< QPointer<MWidget> > toolbarWidgetPool;
-
- //! Singleton instance
- static ToolbarManager *toolbarMgrInstance;
-
- friend class Ut_MImToolbar;
- friend class Ut_ToolbarManager;
-};
-
-inline ToolbarManager &ToolbarManager::instance()
-{
- Q_ASSERT(toolbarMgrInstance);
- return *toolbarMgrInstance;
-}
-
-#endif
--- m-keyboard/common/toolbarwidget.cpp
+++ m-keyboard/common/toolbarwidget.cpp
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#include <QtAlgorithms>
-#include "toolbarwidget.h"
-
-ToolbarWidget::ToolbarWidget(WidgetType t)
- : widgetType(t),
- orientation(M::Portrait),
- showOn(Always),
- hideOn(Undefined),
- alignment(Qt::AlignRight),
- visible(false),
- toggle(false),
- pressed(false)
-{
-}
-
-ToolbarWidget::Action::Action(ToolbarWidget::ActionType t)
- : type(t)
-{
-}
-
-ToolbarWidget::~ToolbarWidget()
-{
- qDeleteAll(actions);
-}
-
-ToolbarWidget::WidgetType ToolbarWidget::type() const
-{
- return widgetType;
-}
-
-QString ToolbarWidget::name() const
-{
- return widgetName;
-}
-
-bool ToolbarWidget::isVisible() const
-{
- return visible;
-}
-
-void ToolbarWidget::setVisible(bool v)
-{
- visible = v;
-}
--- m-keyboard/common/toolbarwidget.h
+++ m-keyboard/common/toolbarwidget.h
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-#ifndef TOOLBARWIDGET_H
-#define TOOLBARWIDGET_H
-
-#include <MNamespace>
-#include <QList>
-#include <QString>
-#include <QStringList>
-/*!
- * \brief ToolbarWidget represents a named widget in a customized toolbar for virtual keyboard.
- */
-class ToolbarWidget
-{
- Q_DISABLE_COPY(ToolbarWidget)
-
-public:
- //! Type of toolbar widget
- enum WidgetType {
- Button,
- Label,
- UndefinedWidgetType
- };
-
- //! Type of visible premiss for toolbar button
- enum VisibleType {
- WhenSelectingText,
- Always,
- Undefined
- };
-
- //! Type of action
- enum ActionType {
- SendKeySequence,
- SendString,
- SendCommand,
- Copy,
- Paste,
- ShowGroup,
- HideGroup,
- Unknown
- };
-
- /*!
- * \brief Constructor
- */
- ToolbarWidget(WidgetType type = UndefinedWidgetType);
-
- /*!
- * \brief Destructor
- */
- virtual ~ToolbarWidget();
-
- /*!
- * \brief Returns the WidgetType of the widget.
- * \sa WidgetType.
- */
- WidgetType type() const;
-
- /*!
- * \brief Returns the name of the widget.
- */
- QString name() const;
-
- /*!
- * \brief Returns visibility of the widget.
- */
- bool isVisible() const;
-
- /*!
- * \brief Sets the visibility of the widget.
- */
- void setVisible(bool);
-
-protected:
- WidgetType widgetType;
- //! The NAME attribute should be unique and it is used as a reference in the toolbar system.
- QString widgetName;
- //! The group name which the button belongs to
- QString group;
- int priority;
- M::Orientation orientation;
- VisibleType showOn;
- VisibleType hideOn;
- Qt::Alignment alignment;
- QString text;
- QString textId;
- bool visible;
-
- struct Action {
- Action(ActionType = Unknown);
- ActionType type;
- QString keys;
- QString text;
- QString command;
- QString group;
- };
-
- // below attributes are only valid for Button
- bool toggle;
- bool pressed;
- QString icon;
- int size;
- //! actions when clicking the widget
- QList<Action *> actions;
-
- friend class ToolbarData;
- friend class ToolbarManager;
- friend class MImToolbar;
- friend class ParseParameters;
- friend class Ut_MImToolbar;
-};
-
-#endif
--- m-keyboard/layouts/ar.xml
+++ m-keyboard/layouts/ar.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard version="1.0" title="الْعَرَبيّة" language="ar_SA" catalog="ar_SA">
+<keyboard version="1.0" title="العربية" language="ar" catalog="ar">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/cs.xml
+++ m-keyboard/layouts/cs.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Czech" version="1.0" catalog="cs" language="cs">
+<keyboard title="Čeština" version="1.0" catalog="cs" language="cs">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/da.xml
+++ m-keyboard/layouts/da.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Danish" version="1.0" catalog="da" language="da">
+<keyboard title="Dansk" version="1.0" catalog="da" language="da">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/de.xml
+++ m-keyboard/layouts/de.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Germany" version="1.0" catalog="de" language="de">
+<keyboard title="Deutsch" version="1.0" catalog="de" language="de">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/en.xml
+++ m-keyboard/layouts/en.xml
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="English (US)" version="1.0" catalog="en_US" language="en_US">
- <import file="en_default.xml"/>
- <import file="en_customer.xml"/>
-</keyboard>
--- m-keyboard/layouts/en_default.xml
+++ m-keyboard/layouts/en_default.xml
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="English (US)" version="1.0" catalog="en_US" language="en_US">
- <layout type="general" orientation="landscape">
- <section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
- <row>
- <key>
- <binding label="q"/>
- <binding shift="true" label="Q"/>
- </key>
- <key>
- <binding label="w"/>
- <binding shift="true" label="W"/>
- </key>
- <key>
- <binding label="e"/>
- <binding shift="true" label="E"/>
- </key>
- <key>
- <binding label="r"/>
- <binding shift="true" label="R"/>
- </key>
- <key>
- <binding label="t"/>
- <binding shift="true" label="T"/>
- </key>
- <key>
- <binding label="y"/>
- <binding shift="true" label="Y"/>
- </key>
- <key>
- <binding label="u"/>
- <binding shift="true" label="U"/>
- </key>
- <key>
- <binding label="i"/>
- <binding shift="true" label="I"/>
- </key>
- <key>
- <binding label="o"/>
- <binding shift="true" label="O"/>
- </key>
- <key>
- <binding label="p"/>
- <binding shift="true" label="P"/>
- </key>
- </row>
- <row>
- <key>
- <binding label="a"/>
- <binding shift="true" label="A"/>
- </key>
- <key>
- <binding label="s"/>
- <binding shift="true" label="S"/>
- </key>
- <key>
- <binding label="d"/>
- <binding shift="true" label="D"/>
- </key>
- <key>
- <binding label="f"/>
- <binding shift="true" label="F"/>
- </key>
- <key>
- <binding label="g"/>
- <binding shift="true" label="G"/>
- </key>
- <key>
- <binding label="h"/>
- <binding shift="true" label="H"/>
- </key>
- <key>
- <binding label="j"/>
- <binding shift="true" label="J"/>
- </key>
- <key>
- <binding label="k"/>
- <binding shift="true" label="K"/>
- </key>
- <key>
- <binding label="l"/>
- <binding shift="true" label="L"/>
- </key>
- </row>
- <row>
- <key>
- <binding label="z"/>
- <binding shift="true" label="Z"/>
- </key>
- <key>
- <binding label="x"/>
- <binding shift="true" label="X"/>
- </key>
- <key>
- <binding label="c"/>
- <binding shift="true" label="C"/>
- </key>
- <key>
- <binding label="v"/>
- <binding shift="true" label="V"/>
- </key>
- <key>
- <binding label="b"/>
- <binding shift="true" label="B"/>
- </key>
- <key>
- <binding label="n"/>
- <binding shift="true" label="N"/>
- </key>
- <key>
- <binding label="m"/>
- <binding shift="true" label="M"/>
- </key>
- </row>
- </section>
- <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
- <row>
- <key>
- <binding action="shift" label=""/>
- </key>
- <key>
- <binding action="sym" label="Sym" secondary_label="áçè"/>
- <binding shift="true" action="layout_menu" label=""/>
- </key>
- <key>
- <binding label="-"/>
- <binding shift="true" label="'"/>
- </key>
- <key>
- <binding action="space" label=""/>
- <binding shift="true" action="return" label=""/>
- </key>
- <key>
- <binding label="?"/>
- <binding shift="true" label="!"/>
- </key>
- <key>
- <binding label="."/>
- <binding shift="true" label=","/>
- </key>
- <key>
- <binding action="backspace" label=""/>
- </key>
- </row>
- </section>
- </layout>
- <layout type="general" orientation="portrait">
- <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
- <row>
- <key>
- <binding action="shift" label=""/>
- </key>
- <key>
- <binding action="sym" label="Sym" secondary_label="áçè"/>
- <binding shift="true" action="layout_menu" label=""/>
- </key>
- <key>
- <binding action="space" label=""/>
- <binding shift="true" action="return" label=""/>
- </key>
- <key>
- <binding label="."/>
- <binding shift="true" label=","/>
- </key>
- <key>
- <binding action="backspace" label=""/>
- </key>
- </row>
- </section>
- </layout>
- <import file="symbols_en_us.xml"/>
-</keyboard>
--- m-keyboard/layouts/en_gb.xml
+++ m-keyboard/layouts/en_gb.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard title="English (UK)" version="1.0" catalog="en_gb" language="en_gb">
+ <import file="en_gb_default.xml"/>
+ <import file="en_gb_customer.xml"/>
+</keyboard>
--- m-keyboard/layouts/en_gb_default.xml
+++ m-keyboard/layouts/en_gb_default.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard title="English (UK)" version="1.0" catalog="en_gb" language="en_gb">
+ <layout type="general" orientation="landscape">
+ <section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
+ <row>
+ <key>
+ <binding label="q"/>
+ <binding shift="true" label="Q"/>
+ </key>
+ <key>
+ <binding label="w"/>
+ <binding shift="true" label="W"/>
+ </key>
+ <key>
+ <binding label="e"/>
+ <binding shift="true" label="E"/>
+ </key>
+ <key>
+ <binding label="r"/>
+ <binding shift="true" label="R"/>
+ </key>
+ <key>
+ <binding label="t"/>
+ <binding shift="true" label="T"/>
+ </key>
+ <key>
+ <binding label="y"/>
+ <binding shift="true" label="Y"/>
+ </key>
+ <key>
+ <binding label="u"/>
+ <binding shift="true" label="U"/>
+ </key>
+ <key>
+ <binding label="i"/>
+ <binding shift="true" label="I"/>
+ </key>
+ <key>
+ <binding label="o"/>
+ <binding shift="true" label="O"/>
+ </key>
+ <key>
+ <binding label="p"/>
+ <binding shift="true" label="P"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding label="a"/>
+ <binding shift="true" label="A"/>
+ </key>
+ <key>
+ <binding label="s"/>
+ <binding shift="true" label="S"/>
+ </key>
+ <key>
+ <binding label="d"/>
+ <binding shift="true" label="D"/>
+ </key>
+ <key>
+ <binding label="f"/>
+ <binding shift="true" label="F"/>
+ </key>
+ <key>
+ <binding label="g"/>
+ <binding shift="true" label="G"/>
+ </key>
+ <key>
+ <binding label="h"/>
+ <binding shift="true" label="H"/>
+ </key>
+ <key>
+ <binding label="j"/>
+ <binding shift="true" label="J"/>
+ </key>
+ <key>
+ <binding label="k"/>
+ <binding shift="true" label="K"/>
+ </key>
+ <key>
+ <binding label="l"/>
+ <binding shift="true" label="L"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding label="z"/>
+ <binding shift="true" label="Z"/>
+ </key>
+ <key>
+ <binding label="x"/>
+ <binding shift="true" label="X"/>
+ </key>
+ <key>
+ <binding label="c"/>
+ <binding shift="true" label="C"/>
+ </key>
+ <key>
+ <binding label="v"/>
+ <binding shift="true" label="V"/>
+ </key>
+ <key>
+ <binding label="b"/>
+ <binding shift="true" label="B"/>
+ </key>
+ <key>
+ <binding label="n"/>
+ <binding shift="true" label="N"/>
+ </key>
+ <key>
+ <binding label="m"/>
+ <binding shift="true" label="M"/>
+ </key>
+ </row>
+ </section>
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding label="-"/>
+ <binding shift="true" label="'"/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="?"/>
+ <binding shift="true" label="!"/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <layout type="general" orientation="portrait">
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <import file="symbols.xml"/>
+</keyboard>
--- m-keyboard/layouts/en_us.xml
+++ m-keyboard/layouts/en_us.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard title="English (US)" version="1.0" catalog="en_us" language="en_us">
+ <import file="en_us_default.xml"/>
+ <import file="en_us_customer.xml"/>
+</keyboard>
--- m-keyboard/layouts/en_us_default.xml
+++ m-keyboard/layouts/en_us_default.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard title="English (US)" version="1.0" catalog="en_us" language="en_us">
+ <layout type="general" orientation="landscape">
+ <section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
+ <row>
+ <key>
+ <binding label="q"/>
+ <binding shift="true" label="Q"/>
+ </key>
+ <key>
+ <binding label="w"/>
+ <binding shift="true" label="W"/>
+ </key>
+ <key>
+ <binding label="e"/>
+ <binding shift="true" label="E"/>
+ </key>
+ <key>
+ <binding label="r"/>
+ <binding shift="true" label="R"/>
+ </key>
+ <key>
+ <binding label="t"/>
+ <binding shift="true" label="T"/>
+ </key>
+ <key>
+ <binding label="y"/>
+ <binding shift="true" label="Y"/>
+ </key>
+ <key>
+ <binding label="u"/>
+ <binding shift="true" label="U"/>
+ </key>
+ <key>
+ <binding label="i"/>
+ <binding shift="true" label="I"/>
+ </key>
+ <key>
+ <binding label="o"/>
+ <binding shift="true" label="O"/>
+ </key>
+ <key>
+ <binding label="p"/>
+ <binding shift="true" label="P"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding label="a"/>
+ <binding shift="true" label="A"/>
+ </key>
+ <key>
+ <binding label="s"/>
+ <binding shift="true" label="S"/>
+ </key>
+ <key>
+ <binding label="d"/>
+ <binding shift="true" label="D"/>
+ </key>
+ <key>
+ <binding label="f"/>
+ <binding shift="true" label="F"/>
+ </key>
+ <key>
+ <binding label="g"/>
+ <binding shift="true" label="G"/>
+ </key>
+ <key>
+ <binding label="h"/>
+ <binding shift="true" label="H"/>
+ </key>
+ <key>
+ <binding label="j"/>
+ <binding shift="true" label="J"/>
+ </key>
+ <key>
+ <binding label="k"/>
+ <binding shift="true" label="K"/>
+ </key>
+ <key>
+ <binding label="l"/>
+ <binding shift="true" label="L"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding label="z"/>
+ <binding shift="true" label="Z"/>
+ </key>
+ <key>
+ <binding label="x"/>
+ <binding shift="true" label="X"/>
+ </key>
+ <key>
+ <binding label="c"/>
+ <binding shift="true" label="C"/>
+ </key>
+ <key>
+ <binding label="v"/>
+ <binding shift="true" label="V"/>
+ </key>
+ <key>
+ <binding label="b"/>
+ <binding shift="true" label="B"/>
+ </key>
+ <key>
+ <binding label="n"/>
+ <binding shift="true" label="N"/>
+ </key>
+ <key>
+ <binding label="m"/>
+ <binding shift="true" label="M"/>
+ </key>
+ </row>
+ </section>
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding label="-"/>
+ <binding shift="true" label="'"/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="?"/>
+ <binding shift="true" label="!"/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <layout type="general" orientation="portrait">
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <import file="symbols_en_us.xml"/>
+</keyboard>
--- m-keyboard/layouts/es.xml
+++ m-keyboard/layouts/es.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Spanish" version="1.0" catalog="es" language="es">
+<keyboard title="Español" version="1.0" catalog="es" language="es">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/fr.xml
+++ m-keyboard/layouts/fr.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="French" version="1.0" catalog="fr" language="fr">
+<keyboard title="Français" version="1.0" catalog="fr" language="fr">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/fr_CA.xml
+++ m-keyboard/layouts/fr_CA.xml
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="French (Canadian)" version="1.0" catalog="fr_CA" language="fr_CA">
- <layout type="general" orientation="landscape">
- <section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
- <row>
- <key>
- <binding label="q"/>
- <binding shift="true" label="Q"/>
- </key>
- <key>
- <binding label="w"/>
- <binding shift="true" label="W"/>
- </key>
- <key>
- <binding accented_labels="èéêë" accents="`´^¨" label="e"/>
- <binding shift="true" accented_labels="ÈÉÊË" accents="`´^¨" label="E"/>
- </key>
- <key>
- <binding label="r"/>
- <binding shift="true" label="R"/>
- </key>
- <key>
- <binding label="t"/>
- <binding shift="true" label="T"/>
- </key>
- <key>
- <binding accented_labels="ýÿ" accents="´¨" label="y"/>
- <binding shift="true" accented_labels="ÝŸ" accents="´¨" label="Y"/>
- </key>
- <key>
- <binding accented_labels="ùúûü" accents="`´^¨" label="u"/>
- <binding shift="true" accented_labels="ÙÚÛÜ" accents="`´^¨" label="U"/>
- </key>
- <key>
- <binding accented_labels="ìíîï" accents="`´^¨" label="i"/>
- <binding shift="true" accented_labels="ÌÍÎÏ" accents="`´^¨" label="I"/>
- </key>
- <key>
- <binding accented_labels="òóôö" accents="`´^¨" label="o"/>
- <binding shift="true" accented_labels="ÒÓÔÖ" accents="`´^¨" label="O"/>
- </key>
- <key>
- <binding label="p"/>
- <binding shift="true" label="P"/>
- </key>
- <key>
- <binding dead="true" label="¨"/>
- </key>
- </row>
- <row>
- <key>
- <binding accented_labels="àáâä" accents="`´^¨" label="a"/>
- <binding shift="true" accented_labels="ÀÁÂÄ" accents="`´^¨" label="A"/>
- </key>
- <key>
- <binding label="s"/>
- <binding shift="true" label="S"/>
- </key>
- <key>
- <binding label="d"/>
- <binding shift="true" label="D"/>
- </key>
- <key>
- <binding label="f"/>
- <binding shift="true" label="F"/>
- </key>
- <key>
- <binding label="g"/>
- <binding shift="true" label="G"/>
- </key>
- <key>
- <binding label="h"/>
- <binding shift="true" label="H"/>
- </key>
- <key>
- <binding label="j"/>
- <binding shift="true" label="J"/>
- </key>
- <key>
- <binding label="k"/>
- <binding shift="true" label="K"/>
- </key>
- <key>
- <binding label="l"/>
- <binding shift="true" label="L"/>
- </key>
- <key>
- <binding dead="true" label="^"/>
- </key>
- </row>
- <row>
- <key>
- <binding label="z"/>
- <binding shift="true" label="Z"/>
- </key>
- <key>
- <binding label="x"/>
- <binding shift="true" label="X"/>
- </key>
- <key>
- <binding label="c"/>
- <binding shift="true" label="C"/>
- </key>
- <key>
- <binding label="v"/>
- <binding shift="true" label="V"/>
- </key>
- <key>
- <binding label="b"/>
- <binding shift="true" label="B"/>
- </key>
- <key>
- <binding label="n"/>
- <binding shift="true" label="N"/>
- </key>
- <key>
- <binding label="m"/>
- <binding shift="true" label="M"/>
- </key>
- <key>
- <binding label="ç"/>
- <binding shift="true" label="Ç"/>
- </key>
- <key>
- <binding dead="true" label="´"/>
- </key>
- <key>
- <binding dead="true" label="`"/>
- </key>
- </row>
- </section>
- <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
- <row>
- <key>
- <binding action="shift" label=""/>
- </key>
- <key>
- <binding action="sym" label="Sym" secondary_label="áçè"/>
- <binding shift="true" action="layout_menu" label=""/>
- </key>
- <key>
- <binding label="-"/>
- <binding shift="true" label="'"/>
- </key>
- <key>
- <binding action="space" label=""/>
- <binding shift="true" action="return" label=""/>
- </key>
- <key>
- <binding label="?"/>
- <binding shift="true" label="!"/>
- </key>
- <key>
- <binding label="."/>
- <binding shift="true" label=","/>
- </key>
- <key>
- <binding action="backspace" label=""/>
- </key>
- </row>
- </section>
- </layout>
- <layout type="general" orientation="portrait">
- <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
- <row>
- <key>
- <binding action="shift" label=""/>
- </key>
- <key>
- <binding action="sym" label="Sym" secondary_label="áçè"/>
- <binding shift="true" action="layout_menu" label=""/>
- </key>
- <key>
- <binding action="space" label=""/>
- <binding shift="true" action="return" label=""/>
- </key>
- <key>
- <binding label="."/>
- <binding shift="true" label=","/>
- </key>
- <key>
- <binding action="backspace" label=""/>
- </key>
- </row>
- </section>
- </layout>
- <import file="symbols.xml"/>
-</keyboard>
--- m-keyboard/layouts/fr_ca.xml
+++ m-keyboard/layouts/fr_ca.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
+<keyboard title="Français (Canada)" version="1.0" catalog="fr_CA" language="fr_CA">
+ <layout type="general" orientation="landscape">
+ <section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
+ <row>
+ <key>
+ <binding label="q"/>
+ <binding shift="true" label="Q"/>
+ </key>
+ <key>
+ <binding label="w"/>
+ <binding shift="true" label="W"/>
+ </key>
+ <key>
+ <binding accented_labels="èéêë" accents="`´^¨" label="e"/>
+ <binding shift="true" accented_labels="ÈÉÊË" accents="`´^¨" label="E"/>
+ </key>
+ <key>
+ <binding label="r"/>
+ <binding shift="true" label="R"/>
+ </key>
+ <key>
+ <binding label="t"/>
+ <binding shift="true" label="T"/>
+ </key>
+ <key>
+ <binding accented_labels="ýÿ" accents="´¨" label="y"/>
+ <binding shift="true" accented_labels="ÝŸ" accents="´¨" label="Y"/>
+ </key>
+ <key>
+ <binding accented_labels="ùúûü" accents="`´^¨" label="u"/>
+ <binding shift="true" accented_labels="ÙÚÛÜ" accents="`´^¨" label="U"/>
+ </key>
+ <key>
+ <binding accented_labels="ìíîï" accents="`´^¨" label="i"/>
+ <binding shift="true" accented_labels="ÌÍÎÏ" accents="`´^¨" label="I"/>
+ </key>
+ <key>
+ <binding accented_labels="òóôö" accents="`´^¨" label="o"/>
+ <binding shift="true" accented_labels="ÒÓÔÖ" accents="`´^¨" label="O"/>
+ </key>
+ <key>
+ <binding label="p"/>
+ <binding shift="true" label="P"/>
+ </key>
+ <key>
+ <binding dead="true" label="¨"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding accented_labels="àáâä" accents="`´^¨" label="a"/>
+ <binding shift="true" accented_labels="ÀÁÂÄ" accents="`´^¨" label="A"/>
+ </key>
+ <key>
+ <binding label="s"/>
+ <binding shift="true" label="S"/>
+ </key>
+ <key>
+ <binding label="d"/>
+ <binding shift="true" label="D"/>
+ </key>
+ <key>
+ <binding label="f"/>
+ <binding shift="true" label="F"/>
+ </key>
+ <key>
+ <binding label="g"/>
+ <binding shift="true" label="G"/>
+ </key>
+ <key>
+ <binding label="h"/>
+ <binding shift="true" label="H"/>
+ </key>
+ <key>
+ <binding label="j"/>
+ <binding shift="true" label="J"/>
+ </key>
+ <key>
+ <binding label="k"/>
+ <binding shift="true" label="K"/>
+ </key>
+ <key>
+ <binding label="l"/>
+ <binding shift="true" label="L"/>
+ </key>
+ <key>
+ <binding dead="true" label="^"/>
+ </key>
+ </row>
+ <row>
+ <key>
+ <binding label="z"/>
+ <binding shift="true" label="Z"/>
+ </key>
+ <key>
+ <binding label="x"/>
+ <binding shift="true" label="X"/>
+ </key>
+ <key>
+ <binding label="c"/>
+ <binding shift="true" label="C"/>
+ </key>
+ <key>
+ <binding label="v"/>
+ <binding shift="true" label="V"/>
+ </key>
+ <key>
+ <binding label="b"/>
+ <binding shift="true" label="B"/>
+ </key>
+ <key>
+ <binding label="n"/>
+ <binding shift="true" label="N"/>
+ </key>
+ <key>
+ <binding label="m"/>
+ <binding shift="true" label="M"/>
+ </key>
+ <key>
+ <binding label="ç"/>
+ <binding shift="true" label="Ç"/>
+ </key>
+ <key>
+ <binding dead="true" label="´"/>
+ </key>
+ <key>
+ <binding dead="true" label="`"/>
+ </key>
+ </row>
+ </section>
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding label="-"/>
+ <binding shift="true" label="'"/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="?"/>
+ <binding shift="true" label="!"/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <layout type="general" orientation="portrait">
+ <section id="functionkey" movable="false" horizontal_alignment="left" vertical_alignment="center">
+ <row>
+ <key>
+ <binding action="shift" label=""/>
+ </key>
+ <key>
+ <binding action="sym" label="Sym" secondary_label="áçè"/>
+ <binding shift="true" action="layout_menu" label=""/>
+ </key>
+ <key>
+ <binding action="space" label=""/>
+ <binding shift="true" action="return" label=""/>
+ </key>
+ <key>
+ <binding label="."/>
+ <binding shift="true" label=","/>
+ </key>
+ <key>
+ <binding action="backspace" label=""/>
+ </key>
+ </row>
+ </section>
+ </layout>
+ <import file="symbols.xml"/>
+</keyboard>
--- m-keyboard/layouts/it.xml
+++ m-keyboard/layouts/it.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Italian" version="1.0" catalog="it" language="it">
+<keyboard title="Italiano" version="1.0" catalog="it" language="it">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/nl.xml
+++ m-keyboard/layouts/nl.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Dutch" version="1.0" catalog="nl" language="nl">
+<keyboard title="Nederlands" version="1.0" catalog="nl" language="nl">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/no.xml
+++ m-keyboard/layouts/no.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Norwegian" version="1.0" catalog="no" language="no">
+<keyboard title="Norsk" version="1.0" catalog="no" language="no">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/pl.xml
+++ m-keyboard/layouts/pl.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Polish" version="1.0" catalog="pl" language="pl">
+<keyboard title="Polski" version="1.0" catalog="pl" language="pl">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/pt.xml
+++ m-keyboard/layouts/pt.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Portuguese" version="1.0" catalog="pt" language="pt">
+<keyboard title="Português" version="1.0" catalog="pt" language="pt">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/ru.xml
+++ m-keyboard/layouts/ru.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Russian" version="1.0" catalog="ru" language="ru">
+<keyboard title="Русский" version="1.0" catalog="ru" language="ru">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/layouts/sv.xml
+++ m-keyboard/layouts/sv.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE keyboard SYSTEM 'VirtualKeyboardLayout.dtd'>
-<keyboard title="Swedish" version="1.0" catalog="sv" language="sv">
+<keyboard title="Svenska" version="1.0" catalog="sv" language="sv">
<layout type="general" orientation="landscape">
<section id="main" movable="false" vertical_alignment="center" horizontal_alignment="center">
<row>
--- m-keyboard/m-keyboard.pro
+++ m-keyboard/m-keyboard.pro
@@ -9,7 +9,7 @@
# we have this line temporarily until new libmeegotouch without rpath is integrated
QT += xml
-CONFIG += plugin meegotouch duiimengine duiimenginewords meegoimframework meegoreactionmap
+CONFIG += plugin meegotouch meegoimengine meegoimenginewords meegoimframework meegoreactionmap
#CONFIG += mcontrolpanel
DEFINES += NOCONTROLPANEL
@@ -35,10 +35,12 @@
HEADERS += \
mkeyboardhost.h \
+ mkeyboardsettings.h \
mkeyboardplugin.h \
SOURCES += \
mkeyboardhost.cpp \
+ mkeyboardsettings.cpp \
mkeyboardplugin.cpp \
target.path += /usr/lib/meego-im-plugins
--- m-keyboard/mkeyboardhost.cpp
+++ m-keyboard/mkeyboardhost.cpp
@@ -17,6 +17,7 @@
#include "mkeyboardhost.h"
+#include "mvirtualkeyboardstyle.h"
#include "mvirtualkeyboard.h"
#include "mhardwarekeyboard.h"
#ifdef M_IM_DISABLE_TRANSLUCENCY
@@ -24,14 +25,13 @@
#endif
#include "mimcorrectioncandidatewidget.h"
#include "keyboarddata.h"
-#include "layoutmenu.h"
#include "layoutsmanager.h"
#include "symbolview.h"
-#include "toolbarmanager.h"
-#include <duiimenginewords.h>
+#include <mimenginewords.h>
#include <minputcontextconnection.h>
#include <mplainwindow.h>
+#include <mtoolbardata.h>
#include <mgconfitem.h>
#include <mtheme.h>
@@ -50,8 +50,8 @@
#include <MSceneWindow>
#include <MInfoBanner>
#include <MLibrary>
-M_LIBRARY // to avoid a crash from mtheme. FIXME - is this the proper way for us?
+M_LIBRARY
namespace
{
@@ -65,16 +65,16 @@
const int AutoBackspaceDelay = 500; // in ms
const int BackspaceRepeatInterval = 100; // in ms
const int MultitapTime = 1500; // in ms
- const char * const PixmapDirectory = "/usr/share/meegotouch/virtual-keyboard/images";
- const QString CssFile("/usr/share/meegotouch/virtual-keyboard/css/%1x%2.css");
- const QString DefaultCss = CssFile.arg(864).arg(480); // Default screen resolution is 864x480
const Qt::KeyboardModifier FnLevelModifier = Qt::GroupSwitchModifier;
const int ModifierLockOnInfoDuration = 1000; // in ms
+ // This GConf item defines whether multitouch is enabled or disabled
+ const char * const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
}
MKeyboardHost::MKeyboardHost(MInputContextConnection* icConnection, QObject *parent)
: MInputMethodBase(icConnection, parent),
+ vkbStyleContainer(0),
vkbWidget(0),
symbolView(0),
inputMethodCorrectionSettings(new MGConfItem(InputMethodCorrectionSetting)),
@@ -85,32 +85,26 @@
correctionEnabled(false),
feedbackPlayer(0),
autoCapsEnabled(true),
+ upperCase(false),
cursorPos(-1),
inputMethodMode(M::InputMethodModeNormal),
backSpaceTimer(this),
multitapIndex(0),
+ shiftHeldDown(false),
activeState(OnScreen),
modifierLockOnInfoBanner(0),
modifierLockOnTimer(this),
- haveFocus(false)
+ haveFocus(false),
+ savedShiftState(ModifierClearState),
+ savedUpperCase(false),
+ enableMultiTouch(false)
{
displayHeight = MPlainWindow::instance()->visibleSceneSize(M::Landscape).height();
displayWidth = MPlainWindow::instance()->visibleSceneSize(M::Landscape).width();
- //TODO get this from settings
- MTheme *theme = MTheme::instance();
- theme->addPixmapDirectory(PixmapDirectory);
-
- QString css = CssFile.arg(displayWidth, displayHeight);
-
- if (!QFile::exists(css)) {
- css = DefaultCss;
- }
-
- theme->loadCSS(css);
+ enableMultiTouch = MGConfItem(MultitouchSettings).value().toBool();
LayoutsManager::createInstance();
- ToolbarManager::createInstance();
sceneWindow = new MSceneWindow;
sceneWindow->setManagedManually(true); // we want the scene window to remain in origin
@@ -132,7 +126,11 @@
// 2) Add widgets directly to scene (detached from MSceneManager) and
// update their transformations by hand.
- vkbWidget = new MVirtualKeyboard(LayoutsManager::instance(), sceneWindow);
+ vkbStyleContainer = new MVirtualKeyboardStyleContainer;
+ vkbStyleContainer->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
+
+ vkbWidget = new MVirtualKeyboard(LayoutsManager::instance(), vkbStyleContainer, sceneWindow);
+ vkbWidget->setInputMethodMode(static_cast<M::InputMethodMode>(inputMethodMode));
connect(vkbWidget, SIGNAL(keyClicked(const KeyEvent &)),
this, SLOT(handleKeyClick(const KeyEvent &)));
@@ -145,7 +143,7 @@
connect(vkbWidget, SIGNAL(regionUpdated(const QRegion &)),
this, SLOT(handleRegionUpdate(const QRegion &)));
- connect(vkbWidget, SIGNAL(regionUpdated(const QRegion &)),
+ connect(vkbWidget, SIGNAL(inputMethodAreaUpdated(const QRegion &)),
this, SLOT(handleInputMethodAreaUpdate(const QRegion &)));
connect(vkbWidget, SIGNAL(userInitiatedHide()),
@@ -154,6 +152,7 @@
connect(vkbWidget, SIGNAL(pluginSwitchRequired(M::InputMethodSwitchDirection)),
this, SIGNAL(pluginSwitchRequired(M::InputMethodSwitchDirection)));
+ modifierLockOnTimer.setSingleShot(true);
modifierLockOnTimer.setInterval(ModifierLockOnInfoDuration);
connect(&modifierLockOnTimer, SIGNAL(timeout()), this, SLOT(hideLockOnInfoBanner()));
@@ -185,7 +184,7 @@
SIGNAL(orientationChangeFinished(M::Orientation)),
SLOT(finalizeOrientationChange()));
- symbolView = new SymbolView(LayoutsManager::instance(), &vkbWidget->style(),
+ symbolView = new SymbolView(LayoutsManager::instance(), vkbStyleContainer,
vkbWidget->selectedLanguage(), sceneWindow);
connect(symbolView, SIGNAL(regionUpdated(const QRegion &)),
this, SLOT(handleRegionUpdate(const QRegion &)));
@@ -208,19 +207,6 @@
connect(hardwareKeyboard, SIGNAL(shiftStateChanged()),
this, SLOT(updateSymbolViewLevel()));
- // Construct layout menu dialog
- layoutMenu = new LayoutMenu(&vkbWidget->style(), 0);
-
- connect(layoutMenu, SIGNAL(errorCorrectionToggled(bool)),
- this, SLOT(errorCorrectionToggled(bool)));
-
- connect(layoutMenu, SIGNAL(regionUpdated(const QRegion &)),
- this, SLOT(handleRegionUpdate(const QRegion &)));
-
- connect(layoutMenu, SIGNAL(languageSelected(int)), vkbWidget, SLOT(setLanguage(int)));
- // FIXME: connect something to layoutMenu::organizeContent()?
- // layout menu done
-
connect(vkbWidget, SIGNAL(copyPasteRequest(CopyPasteState)),
this, SLOT(sendCopyPaste(CopyPasteState)));
connect(vkbWidget, SIGNAL(sendKeyEventRequest(const QKeyEvent &)),
@@ -228,7 +214,7 @@
connect(vkbWidget, SIGNAL(sendStringRequest(const QString &)),
this, SLOT(sendString(const QString &)));
- imCorrectionEngine = DuiImEngineWords::instance();
+ imCorrectionEngine = MImEngineWords::instance();
if (!inputMethodCorrectionEngine->value().isNull()) {
@@ -258,7 +244,6 @@
connect(symbolView, SIGNAL(hidden()), vkbWidget, SLOT(showMainArea()));
}
-
MKeyboardHost::~MKeyboardHost()
{
hideLockOnInfoBanner();
@@ -266,10 +251,14 @@
hardwareKeyboard = 0;
delete vkbWidget;
vkbWidget = 0;
+ delete symbolView;
+ symbolView = 0;
delete correctionCandidateWidget;
correctionCandidateWidget = 0;
delete sceneWindow;
sceneWindow = 0;
+ delete vkbStyleContainer;
+ vkbStyleContainer = 0;
#ifdef M_IM_DISABLE_TRANSLUCENCY
delete correctionSceneWindow;
correctionSceneWindow = 0;
@@ -280,9 +269,7 @@
inputMethodCorrectionSettings = 0;
//TODO imCorrectionEngine is not deleted. memory loss
backSpaceTimer.stop();
- delete layoutMenu;
LayoutsManager::destroyInstance();
- ToolbarManager::destroyInstance();
}
void MKeyboardHost::createCorrectionCandidateWidget()
@@ -331,7 +318,13 @@
{
haveFocus = focusIn;
if (activeState == Hardware) {
- hardwareKeyboard->focusChanged(focusIn);
+ if (inputMethodMode != M::InputMethodModeDirect) {
+ if (focusIn) {
+ hardwareKeyboard->enable();
+ } else {
+ hardwareKeyboard->disable();
+ }
+ }
if (!focusIn) {
sendInputModeIndicator(MInputMethodBase::NoIndicator);
}
@@ -413,7 +406,15 @@
const int inputMethodModeValue = inputContextConnection()->inputMethodMode(valid);
if (valid) {
+ if (haveFocus && (activeState == Hardware) && (inputMethodMode != inputMethodModeValue)) {
+ if (inputMethodModeValue != M::InputMethodModeDirect) {
+ hardwareKeyboard->enable();
+ } else {
+ hardwareKeyboard->disable();
+ }
+ }
inputMethodMode = inputMethodModeValue;
+ vkbWidget->setInputMethodMode(static_cast<M::InputMethodMode>(inputMethodMode));
}
}
@@ -423,6 +424,8 @@
if (!autoCapsEnabled)
return;
+ upperCase = false;
+
// TODO: consider RTL language case
// Capitalization is determined by preedit and Auto Capitalization.
// If there are some preedit, it should be lower case.
@@ -430,15 +433,18 @@
// 1. at the beginning of one paragraph
// 2. after a sentence delimiter and one or more spaces
static const QRegExp autoCapsTrigger("[" + AutoCapsSentenceDelimiters + "] +$");
- const bool upperCase = ((preedit.length() == 0)
- && ((cursorPos == 0)
- || ((cursorPos > 0)
- && (cursorPos <= surroundingText.length())
- && surroundingText.left(cursorPos).contains(autoCapsTrigger))));
-
- if ((activeState == OnScreen) && (vkbWidget->shiftStatus() != MVirtualKeyboard::ShiftLock)) {
+ upperCase = ((preedit.length() == 0)
+ && ((cursorPos == 0)
+ || ((cursorPos > 0)
+ && (cursorPos <= surroundingText.length())
+ && surroundingText.left(cursorPos).contains(autoCapsTrigger))));
+
+ if ((activeState == OnScreen)
+ && (vkbWidget->shiftStatus() != ModifierLockedState)
+ && (!enableMultiTouch || !shiftHeldDown
+ || (vkbWidget->shiftStatus() != ModifierLatchedState))) {
vkbWidget->setShiftState(upperCase ?
- MVirtualKeyboard::ShiftOn : MVirtualKeyboard::ShiftOff);
+ ModifierLatchedState : ModifierClearState);
} else if ((activeState == Hardware) &&
(hardwareKeyboard->modifierState(Qt::ShiftModifier) != ModifierLockedState)) {
hardwareKeyboard->setAutoCapitalization(upperCase);
@@ -499,14 +505,14 @@
// If correction candidate widget was open we need to reposition it.
if (correctionCandidateWidget->isVisible()) {
bool success = false;
- QRect rect = inputContextConnection()->preeditRectangle(success);
+ const QRect rect = inputContextConnection()->preeditRectangle(success);
QRect localRect;
// Note: For Qt applications we don't have means to retrieve
// the correct coordinates for pre-edit rectangle, so rect here
// is null.
if (success && !rect.isNull() && rotateRect(rect, localRect)) {
- int bottomLimit = static_cast<int>(sceneWindow->mapRectFromScene(
- vkbWidget->region(false).boundingRect()).top());
+ const int bottomLimit = static_cast<int>(sceneWindow->mapRectFromScene(
+ vkbWidget->region(false).boundingRect()).top());
correctionCandidateWidget->setPosition(localRect, bottomLimit);
} else {
@@ -594,7 +600,7 @@
QRect localRect;
// Bottom limit for positioning candidate list widget. Keep above keyboard.
- int bottomLimit = static_cast<int>(vkbWidget->region(false).boundingRect().top());
+ const int bottomLimit = static_cast<int>(vkbWidget->region(false).boundingRect().top());
// Use preeditRect if one was passed (not null).
if (!preeditRect.isNull() && rotateRect(preeditRect, localRect)) {
@@ -665,16 +671,16 @@
} else {
static const KeyEvent event("\b", QEvent::KeyRelease, Qt::Key_Backspace,
KeyEvent::NotSpecial,
- vkbWidget->shiftStatus() != MVirtualKeyboard::ShiftOff
+ vkbWidget->shiftStatus() != ModifierClearState
? Qt::ShiftModifier : Qt::NoModifier);
inputContextConnection()->sendKeyEvent(KeyEvent(event, QEvent::KeyPress).toQKeyEvent());
inputContextConnection()->sendKeyEvent(event.toQKeyEvent());
}
// Backspace toggles shift off if it's on (not locked)
// except if autoCaps is on and cursor is at 0 position.
- if (vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn
+ if (vkbWidget->shiftStatus() == ModifierLatchedState
&& (!autoCapsEnabled || cursorPos != 0)) {
- vkbWidget->setShiftState(MVirtualKeyboard::ShiftOff);
+ vkbWidget->setShiftState(ModifierClearState);
}
}
@@ -686,6 +692,23 @@
void MKeyboardHost::handleKeyPress(const KeyEvent &event)
{
+ if (event.qtKey() == Qt::Key_Shift) {
+ if (shiftHeldDown) {
+ return; //ignore duplicated event
+ }
+
+ if (activeState == OnScreen && enableMultiTouch) {
+ shiftHeldDown = true;
+ savedShiftState = vkbWidget->shiftStatus();
+ savedUpperCase = upperCase;
+ // we need to invert shift state:
+ // * clear shift state if it is latched or locked, or
+ // * latch it, if it is cleared
+ const ModifierState newState = (savedShiftState == ModifierClearState) ? ModifierLatchedState : ModifierClearState;
+ vkbWidget->setShiftState(newState);
+ }
+ }
+
if (((inputMethodMode == M::InputMethodModeDirect)
&& (event.specialKey() == KeyEvent::NotSpecial))
|| (event.qtKey() == Qt::Key_plusminus)) { // plusminus key makes an exception
@@ -699,6 +722,31 @@
void MKeyboardHost::handleKeyRelease(const KeyEvent &event)
{
+ if (event.qtKey() == Qt::Key_Shift) {
+ if (!shiftHeldDown) {
+ return; //ignore duplicated event
+ }
+
+ if (activeState == OnScreen && enableMultiTouch) {
+ ModifierState newState = ModifierClearState;
+
+ shiftHeldDown = false;
+ // we need to update shift status:
+ // * restore old value if character case was not toggled by auto caps
+ // * latch shift key if upper case was enabled by auto caps
+ // * otherwise clear shift key
+ if (savedUpperCase == upperCase) {
+ newState = savedShiftState;
+ } else if (upperCase) {
+ newState = ModifierLatchedState;
+ } else {
+ newState = ModifierClearState;
+ }
+
+ vkbWidget->setShiftState(newState);
+ }
+ }
+
if (((inputMethodMode == M::InputMethodModeDirect)
&& (event.specialKey() == KeyEvent::NotSpecial))
|| (event.qtKey() == Qt::Key_plusminus)) { // plusminus key makes an exception
@@ -718,9 +766,7 @@
}
// Draw the reactive areas of first one of these who is visible.
- if (layoutMenu->isActive()) {
- layoutMenu->redrawReactionMaps();
- } else if (correctionCandidateWidget->isVisible()) {
+ if (correctionCandidateWidget->isVisible()) {
correctionCandidateWidget->redrawReactionMaps();
} else if (symbolView->isFullyVisible()) {
symbolView->redrawReactionMaps();
@@ -773,21 +819,33 @@
{
if (event.qtKey() == Qt::Key_Shift) {
switch (vkbWidget->shiftStatus()) {
- case MVirtualKeyboard::ShiftOn:
- vkbWidget->setShiftState(MVirtualKeyboard::ShiftLock);
+ case ModifierLatchedState:
+ // If current ShiftOn state is due to autocaps, go back to ShiftOff.
+ // Otherwise, lock it.
+ if (upperCase) {
+ vkbWidget->setShiftState(ModifierClearState);
+ } else {
+ vkbWidget->setShiftState(ModifierLockedState);
+ }
break;
- case MVirtualKeyboard::ShiftOff:
- vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
+ case ModifierClearState:
+ vkbWidget->setShiftState(ModifierLatchedState);
break;
- case MVirtualKeyboard::ShiftLock:
- vkbWidget->setShiftState(MVirtualKeyboard::ShiftOff);
+ case ModifierLockedState:
+ vkbWidget->setShiftState(ModifierClearState);
break;
}
- } else if (vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn
- && (event.qtKey() != Qt::Key_Backspace)) {
+ upperCase = false;
+ } else if (vkbWidget->shiftStatus() == ModifierLatchedState
+ && (event.qtKey() != Qt::Key_Backspace)
+ && (event.specialKey() != KeyEvent::Sym)
+ && (!shiftHeldDown || upperCase)) {
// Any key except shift toggles shift off if it's on (not locked).
- // backspace toggles shift off is handled in doBackspace().
- vkbWidget->setShiftState(MVirtualKeyboard::ShiftOff);
+ // Exceptions are:
+ // - backspace, toggles shift off is handled in doBackspace()
+ // - sym, pressing sym key keeps current shift state
+ // - shift, when held down don't bring level down, except with autocaps!
+ vkbWidget->setShiftState(ModifierClearState);
}
if (event.specialKey() == KeyEvent::LayoutMenu) {
@@ -940,17 +998,11 @@
qDebug() << __PRETTY_FUNCTION__ << "- used language:" << language;
- // TODO: wouldn't it be better if correction engine did this?
- QString shortLanguage(language);
- if (KeyboardData::isLanguageLongFormat(language)) {
- shortLanguage = KeyboardData::convertLanguageToShortFormat(language);
- }
-
- if (engineReady && (shortLanguage != imCorrectionEngine->language())) {
+ if (engineReady) {
// TODO: maybe we should check return values here and in case of failure
// be always in accurate mode, for example
- imCorrectionEngine->setKeyboardLayout(shortLanguage);
- imCorrectionEngine->setLanguage(shortLanguage, Dui::LanguagePriorityPrimary);
+ imCorrectionEngine->setKeyboardLayout(language);
+ imCorrectionEngine->setLanguage(language, M::LanguagePriorityPrimary);
synchronizeCorrectionSetting();
imCorrectionEngine->disablePrediction();
imCorrectionEngine->disableCompletion();
@@ -959,20 +1011,6 @@
}
}
-
-void MKeyboardHost::errorCorrectionToggled(bool on)
-{
- if (engineReady && (on != imCorrectionEngine->correctionEnabled())) {
- bool correction = true;
- if (!inputMethodCorrectionSettings->value().isNull())
- correction = inputMethodCorrectionSettings->value().toBool();
- if (on != correction) {
- inputMethodCorrectionSettings->set(QVariant(on));
- }
- }
-}
-
-
void MKeyboardHost::synchronizeCorrectionSetting()
{
bool correction = true;
@@ -981,10 +1019,8 @@
if (!correction) {
imCorrectionEngine->disableCorrection();
- layoutMenu->disableErrorCorrection();
} else {
imCorrectionEngine->enableCorrection();
- layoutMenu->enableErrorCorrection();
}
updateCorrectionState();
@@ -1038,17 +1074,7 @@
void MKeyboardHost::showLayoutMenu()
{
- const QStringList languageList = LayoutsManager::instance().languageList();
- const int currentIndex = languageList.indexOf(vkbWidget->selectedLanguage());
-
- // Update layout menu's list of language titles and current language.
- QStringList titles;
- foreach (const QString &language, languageList) {
- titles << LayoutsManager::instance().keyboardTitle(language);
- }
-
- layoutMenu->setLanguageList(titles, currentIndex);
- layoutMenu->show();
+ emit settingsRequested();
}
QRegion MKeyboardHost::combineRegionTo(RegionMap ®ionStore,
@@ -1086,32 +1112,15 @@
inputContextConnection()->sendCommitString(text);
}
-void MKeyboardHost::registerToolbar(qlonglong id, const QString &fileName)
-{
- ToolbarManager::instance().registerToolbar(id, fileName);
-}
-
-void MKeyboardHost::unregisterToolbar(qlonglong id)
+void MKeyboardHost::setToolbar(QSharedPointer<const MToolbarData> toolbar)
{
- ToolbarManager::instance().unregisterToolbar(id);
-}
-
-void MKeyboardHost::setToolbar(qlonglong id)
-{
- qDebug() << __PRETTY_FUNCTION__ << id;
- if (id >= 0) {
- vkbWidget->showToolbarWidget(id);
+ if (toolbar) {
+ vkbWidget->showToolbarWidget(toolbar);
} else {
vkbWidget->hideToolbarWidget();
}
}
-void MKeyboardHost::setToolbarItemAttribute(qlonglong id, const QString &item,
- const QString &attribute, const QVariant &value)
-{
- ToolbarManager::instance().setToolbarItemAttribute(id, item, attribute, value);
-}
-
void MKeyboardHost::processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
Qt::KeyboardModifiers modifiers, const QString &text,
bool autoRepeat, int count, quint32 nativeScanCode,
@@ -1149,6 +1158,10 @@
if (activeState == actualState)
return;
+ if ((activeState == OnScreen) && (correctedPreedit.length() > 0)) {
+ inputContextConnection()->sendCommitString(correctedPreedit);
+ }
+
// Resets before changing the activeState to make sure clear.
reset();
activeState = actualState;
@@ -1161,8 +1174,8 @@
sendInputModeIndicator(MInputMethodBase::NoIndicator);
disconnect(hardwareKeyboard, SIGNAL(modifierStateChanged(Qt::KeyboardModifier, ModifierState)),
this, SLOT(handleModifierStateChanged(Qt::KeyboardModifier, ModifierState)));
- if (haveFocus) {
- hardwareKeyboard->focusChanged(false);
+ if (haveFocus && (inputMethodMode != M::InputMethodModeDirect)) {
+ hardwareKeyboard->disable();
}
} else {
//TODO: this is a temporary method, should get the hw layout language, then find out the
@@ -1171,8 +1184,8 @@
symbolView->hideFunctionRow();
connect(hardwareKeyboard, SIGNAL(modifierStateChanged(Qt::KeyboardModifier, ModifierState)),
this, SLOT(handleModifierStateChanged(Qt::KeyboardModifier, ModifierState)));
- if (haveFocus) {
- hardwareKeyboard->focusChanged(true);
+ if (haveFocus && (inputMethodMode != M::InputMethodModeDirect)) {
+ hardwareKeyboard->enable();
}
}
@@ -1183,22 +1196,18 @@
void MKeyboardHost::handleSymbolKeyClick()
{
- if (!symbolView->isActive()) {
+ if (((activeState == Hardware) && !hardwareKeyboard->symViewAvailable())
+ || !vkbWidget->symViewAvailable()) {
+ return;
+ }
- if ((activeState == Hardware) && !hardwareKeyboard->symViewAvailable()) {
- return;
- } else if (!vkbWidget->symViewAvailable()) {
- return;
- }
+ // Toggle SymbolView.
+ if (!symbolView->isActive()) {
symbolView->showSymbolView();
//give the symbolview right shift level(for hardware state)
updateSymbolViewLevel();
} else {
- if (symbolView->currentPage() < (symbolView->pageCount() - 1)) {
- symbolView->switchToNextPage();
- } else {
- symbolView->hideSymbolView();
- }
+ symbolView->hideSymbolView();
}
}
@@ -1207,23 +1216,14 @@
if (!symbolView->isActive())
return;
- MVirtualKeyboard::ShiftLevel shiftLevel = MVirtualKeyboard::ShiftOff;
+ ModifierState shiftLevel = ModifierClearState;
if (activeState == OnScreen) {
shiftLevel = vkbWidget->shiftStatus();
} else {
- switch (hardwareKeyboard->modifierState(Qt::ShiftModifier)) {
- case ModifierLatchedState:
- shiftLevel = MVirtualKeyboard::ShiftOn;
- break;
- case ModifierLockedState:
- shiftLevel = MVirtualKeyboard::ShiftLock;
- break;
- default:
- break;
- }
+ shiftLevel = hardwareKeyboard->modifierState(Qt::ShiftModifier);
}
- symbolView->switchLevel(shiftLevel > 0 ? 1 : 0,
- shiftLevel == MVirtualKeyboard::ShiftLock);
+ symbolView->switchLevel(shiftLevel > 0 ? 1 : 0);
+ symbolView->setShiftStatus(shiftLevel > 0, shiftLevel == ModifierLockedState);
}
void MKeyboardHost::showSymbolView()
@@ -1314,24 +1314,40 @@
// notify the modifier is changed to locked state
// number and phone number content type always force FN key to be locked,
// don't need indicator lock notification.
- if (modifierLockOnInfoBanner) {
- modifierLockOnInfoBanner->setBodyText(lockOnNotificationLabel);
- modifierLockOnTimer.start();
- } else {
- modifierLockOnInfoBanner = new MInfoBanner(MInfoBanner::Information);
- modifierLockOnInfoBanner->setBodyText(lockOnNotificationLabel);
- MPlainWindow::instance()->sceneManager()->appearSceneWindow(modifierLockOnInfoBanner,
- MSceneWindow::DestroyWhenDone);
- modifierLockOnTimer.start();
- }
+ showLockOnInfoBanner(lockOnNotificationLabel);
} else if (modifierLockOnInfoBanner) {
- hideLockOnInfoBanner();
+ hideLockOnInfoBanner(false);
}
}
-void MKeyboardHost::hideLockOnInfoBanner()
+void MKeyboardHost::showLockOnInfoBanner(const QString ¬ification)
{
- if (modifierLockOnInfoBanner)
+ // current region maybe empty, we should request 1 pixel to make infobanner visible.
+ // FIXME: this request 1 pixel looks like hack way.
+ // maybe we should request system notification instead of showing our own infobanner.
+ emit regionUpdated(combineRegionTo(widgetRegions, QRegion(0, 0, 1, 1), *this));
+
+ if (modifierLockOnInfoBanner) {
+ modifierLockOnInfoBanner->setBodyText(notification);
+ modifierLockOnTimer.start();
+ } else {
+ modifierLockOnInfoBanner = new MInfoBanner(MInfoBanner::Information);
+ modifierLockOnInfoBanner->setBodyText(notification);
+ MPlainWindow::instance()->sceneManager()->appearSceneWindow(modifierLockOnInfoBanner,
+ MSceneWindow::DestroyWhenDone);
+ modifierLockOnTimer.start();
+ }
+}
+
+void MKeyboardHost::hideLockOnInfoBanner(bool updateRegion)
+{
+ if (modifierLockOnInfoBanner) {
MPlainWindow::instance()->sceneManager()->disappearSceneWindow(modifierLockOnInfoBanner);
+ }
modifierLockOnInfoBanner = 0;
+ // some time we don't need to update region at once (e.g. during changing modifier state frequently)
+ // when modifierLockOnTimer is timeout, this method will be called to update region
+ if (updateRegion) {
+ emit regionUpdated(combineRegionTo(widgetRegions, QRegion(), *this));
+ }
}
--- m-keyboard/mkeyboardhost.h
+++ m-keyboard/mkeyboardhost.h
@@ -32,10 +32,10 @@
class MImCorrectionCandidateWidget;
class MSceneWindow;
class MVirtualKeyboard;
+class MVirtualKeyboardStyleContainer;
class MHardwareKeyboard;
-class LayoutMenu;
class SymbolView;
-class DuiImEngineWords;
+class MImEngineWords;
class QWidget;
class MInfoBanner;
@@ -59,11 +59,7 @@
virtual void visualizationPriorityChanged(bool priority);
virtual void appOrientationChanged(int angle);
virtual void setCopyPasteState(bool copyAvailable, bool pasteAvailable);
- virtual void registerToolbar(qlonglong id, const QString &fileName);
- virtual void unregisterToolbar(qlonglong id);
- virtual void setToolbar(qlonglong id);
- virtual void setToolbarItemAttribute(qlonglong id, const QString &item,
- const QString &attribute, const QVariant &value);
+ virtual void setToolbar(QSharedPointer<const MToolbarData> toolbar);
virtual void setState(const QSet<MIMHandlerState> &state);
virtual void processKeyEvent(QEvent::Type keyType, Qt::Key keyCode,
Qt::KeyboardModifiers modifiers,
@@ -100,11 +96,6 @@
*/
void updatePreedit(const QString &string);
- /*!
- * Turn error correction on/off
- */
- void errorCorrectionToggled(bool on);
-
/*! \brief Prepares vkb for orientation change when application is about to rotate.
*
* This should hide vkb.
@@ -170,8 +161,11 @@
*/
void handleModifierStateChanged(Qt::KeyboardModifier modifier, ModifierState state);
- //! hide CapsLock infobanner
- void hideLockOnInfoBanner();
+ //! show FN/Caps Lock infobanner
+ void showLockOnInfoBanner(const QString ¬ification);
+
+ //! hide FN/Caps Lock infobanner
+ void hideLockOnInfoBanner(bool updateRegion = true);
private:
void createCorrectionCandidateWidget();
@@ -227,13 +221,14 @@
QString preedit;
QString correctedPreedit;
+ MVirtualKeyboardStyleContainer *vkbStyleContainer;
+
MImCorrectionCandidateWidget *correctionCandidateWidget;
MVirtualKeyboard *vkbWidget;
MHardwareKeyboard *hardwareKeyboard;
- LayoutMenu *layoutMenu;
SymbolView *symbolView;
- DuiImEngineWords *imCorrectionEngine;
+ MImEngineWords *imCorrectionEngine;
//! default input method error correction setting
MGConfItem *inputMethodCorrectionSettings;
MGConfItem *inputMethodCorrectionEngine;
@@ -255,6 +250,8 @@
//! FIXME: should we provide such a flag to on/off auto caps
bool autoCapsEnabled;
+ //! Contains true if autocapitalization decides to switch keyboard to upper case
+ bool upperCase;
QString surroundingText;
int cursorPos;
@@ -266,6 +263,9 @@
QTime lastClickEventTime;
unsigned int multitapIndex;
+ //! Keeps track of shift up/down status.
+ bool shiftHeldDown;
+
MSceneWindow *sceneWindow;
#ifdef M_IM_DISABLE_TRANSLUCENCY
QWidget *correctionWindow;
@@ -288,6 +288,15 @@
//! \sa focusChanged
bool haveFocus;
+ //! Saved shift key state before moment when it was pressed
+ ModifierState savedShiftState;
+
+ //! Saved auto capitalization state before press on shift button
+ bool savedUpperCase;
+
+ //! Contains true if multi-touch is enabled
+ bool enableMultiTouch;
+
#ifdef UNIT_TEST
friend class Ut_MKeyboardHost;
#endif
--- m-keyboard/mkeyboardplugin.cpp
+++ m-keyboard/mkeyboardplugin.cpp
@@ -16,13 +16,19 @@
+#include <MLocale>
#include "mkeyboardplugin.h"
#include "mkeyboardhost.h"
+#include "mkeyboardsettings.h"
#include <QtPlugin>
#include <mtimestamp.h>
+MKeyboardPlugin::MKeyboardPlugin()
+ : translationIsLoaded(false)
+{
+}
QString MKeyboardPlugin::name() const
{
@@ -39,12 +45,20 @@
MInputMethodBase *
MKeyboardPlugin::createInputMethod(MInputContextConnection *icConnection)
{
+ loadTranslation();
mTimestamp("MKeyboardPlugin", "start");
MInputMethodBase *inputMethod = new MKeyboardHost(icConnection);
mTimestamp("MKeyboardPlugin", "end");
return inputMethod;
}
+MInputMethodSettingsBase *MKeyboardPlugin::createInputMethodSettings()
+{
+ loadTranslation();
+ MInputMethodSettingsBase *inputMethodSettings = new MKeyboardSettings();
+ return inputMethodSettings;
+}
+
QSet<MIMHandlerState> MKeyboardPlugin::supportedStates() const
{
QSet<MIMHandlerState> result;
@@ -53,5 +67,15 @@
return result;
}
-Q_EXPORT_PLUGIN2(mvirtualkeyboard, MKeyboardPlugin)
+void MKeyboardPlugin::loadTranslation()
+{
+ if (!translationIsLoaded) {
+ MLocale locale;
+ // add virtual-keyboard catalog for the settings translation.
+ locale.installTrCatalog("virtual-keyboard");
+ MLocale::setDefault(locale);
+ translationIsLoaded = true;
+ }
+}
+Q_EXPORT_PLUGIN2(meego-keyboard, MKeyboardPlugin)
--- m-keyboard/mkeyboardplugin.h
+++ m-keyboard/mkeyboardplugin.h
@@ -35,12 +35,20 @@
Q_INTERFACES(MInputMethodPlugin)
public:
+ MKeyboardPlugin();
+
//! \reimp
virtual QString name() const;
virtual QStringList languages() const;
virtual MInputMethodBase *createInputMethod(MInputContextConnection *icConnection);
+ virtual MInputMethodSettingsBase *createInputMethodSettings();
virtual QSet<MIMHandlerState> supportedStates() const;
//! \reimp_end
+
+private:
+ void loadTranslation();
+
+ bool translationIsLoaded;
};
#endif
--- m-keyboard/mkeyboardsettings.cpp
+++ m-keyboard/mkeyboardsettings.cpp
+/* * This file is part of m-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "mkeyboardsettings.h"
+#include "mkeyboardsettingswidget.h"
+#include "keyboarddata.h"
+
+#include <QObject>
+#include <QGraphicsWidget>
+#include <QDir>
+#include <QFileInfo>
+#include <QDebug>
+
+namespace {
+ const QString SettingsIMCorrectionSetting("/meegotouch/inputmethods/correctionenabled");
+ const QString InputMethodLanguages("/meegotouch/inputmethods/languages");
+ const QString VKBConfigurationPath("/usr/share/meegotouch/virtual-keyboard/layouts/");
+ const QString VKBLayoutsFilterRule("*.xml");
+ const QString VKBLayoutsIgnoreRules("number|test"); // use as regexp to ignore number and test layouts
+};
+
+MKeyboardSettings::MKeyboardSettings()
+ : keyboardErrorCorrectionConf(SettingsIMCorrectionSetting, this),
+ selectedKeyboardsConf(InputMethodLanguages, this)
+{
+ readAvailableKeyboards();
+ connect(&keyboardErrorCorrectionConf, SIGNAL(valueChanged()),
+ this, SIGNAL(errorCorrectionChanged()));
+ connect(&selectedKeyboardsConf, SIGNAL(valueChanged()),
+ this, SIGNAL(selectedKeyboardsChanged()));
+}
+
+MKeyboardSettings::~MKeyboardSettings()
+{
+}
+
+QGraphicsWidget *MKeyboardSettings::createContentWidget(QGraphicsWidget *parent)
+{
+ // the pointer of returned QGraphicsWidget is owned by the caller,
+ // so we just always create a new containerWidget.
+ return new MKeyboardSettingsWidget(this, parent);
+}
+
+QString MKeyboardSettings::title()
+{
+ //% "Virtual keyboards";
+ return qtTrId("qtn_txts_virtual_keyboards");;
+}
+
+QString MKeyboardSettings::icon()
+{
+ return "";
+}
+
+void MKeyboardSettings::readAvailableKeyboards()
+{
+ availableKeyboardInfos.clear();
+ // available keyboard languages are determined by xml layouts that can be found
+ const QDir layoutsDir(VKBConfigurationPath, VKBLayoutsFilterRule);
+ QRegExp ignoreExp(VKBLayoutsIgnoreRules, Qt::CaseInsensitive);
+
+ foreach (QFileInfo keyboardFileInfo, layoutsDir.entryInfoList()) {
+ if (keyboardFileInfo.fileName().contains(ignoreExp))
+ continue;
+ KeyboardData keyboard;
+ if (keyboard.loadNokiaKeyboard(keyboardFileInfo.fileName())) {
+ if (keyboard.language().isEmpty() || keyboard.title().isEmpty())
+ continue;
+ bool duplicated = false;
+ foreach (const KeyboardInfo &info, availableKeyboardInfos) {
+ if (info.language == keyboard.language()) {
+ duplicated = true;
+ break;
+ }
+ }
+ if (!duplicated) {
+ KeyboardInfo keyboardInfo;
+ keyboardInfo.fileName = keyboardFileInfo.fileName();
+ keyboardInfo.language = keyboard.language();
+ keyboardInfo.title = keyboard.title();
+ availableKeyboardInfos.append(keyboardInfo);
+ }
+ }
+ }
+}
+
+QMap<QString, QString> MKeyboardSettings::availableKeyboards() const
+{
+ QMap<QString, QString> keyboards;
+ foreach (const KeyboardInfo &keyboardInfo, availableKeyboardInfos) {
+ keyboards.insert(keyboardInfo.language, keyboardInfo.title);
+ }
+ return keyboards;
+}
+
+QMap<QString, QString> MKeyboardSettings::selectedKeyboards() const
+{
+ QMap<QString, QString> keyboards;
+ foreach (const QString language, selectedKeyboardsConf.value().toStringList()) {
+ keyboards.insert(language, keyboardTitle(language));
+ }
+ return keyboards;
+}
+
+void MKeyboardSettings::setSelectedKeyboards(const QStringList &keyboardTitles)
+{
+ QStringList languages;
+ foreach (const QString &title, keyboardTitles) {
+ QString language = keyboardLanguage(title);
+ if (!language.isEmpty() && !languages.contains(language)) {
+ languages.append(language);
+ }
+ }
+ selectedKeyboardsConf.set(languages);
+}
+
+QString MKeyboardSettings::keyboardTitle(const QString &language) const
+{
+ QString title;
+ foreach (const KeyboardInfo &keyboardInfo, availableKeyboardInfos) {
+ if (keyboardInfo.language == language) {
+ title = keyboardInfo.title;
+ break;
+ }
+ }
+ return title;
+}
+
+QString MKeyboardSettings::keyboardLanguage(const QString &title) const
+{
+ QString language;
+ foreach (const KeyboardInfo &keyboardInfo, availableKeyboardInfos) {
+ if (keyboardInfo.title == title) {
+ language = keyboardInfo.language;
+ break;
+ }
+ }
+ return language;
+}
+
+bool MKeyboardSettings::errorCorrection() const
+{
+ return keyboardErrorCorrectionConf.value().toBool();
+}
+
+void MKeyboardSettings::setErrorCorrection(bool enabled)
+{
+ if (keyboardErrorCorrectionConf.value().toBool() != enabled)
+ keyboardErrorCorrectionConf.set(enabled);
+}
--- m-keyboard/mkeyboardsettings.h
+++ m-keyboard/mkeyboardsettings.h
+/* * This file is part of m-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef MKEYBOARDSETTINGS_H
+#define MKEYBOARDSETTINGS_H
+
+#include <QObject>
+#include <MWidget>
+#include <MGConfItem>
+#include <minputmethodsettingsbase.h>
+
+class QGraphicsWidget;
+
+/*!
+ * \brief MKeyboardSettings is the implemetation of meego-keyboard setting.
+ * MKeyboardSettings implement MInputMethodSettingsBase and create the meego-keyboard
+ * setting. It provides below functionalities: get/set error corretion, get/set
+ * installed (selected) keyboards.
+ */
+class MKeyboardSettings: public QObject, public MInputMethodSettingsBase
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(MKeyboardSettings)
+ friend class Ut_MKeyboardSettings;
+
+public:
+ MKeyboardSettings();
+
+ ~MKeyboardSettings();
+
+ //!\reimp
+ virtual QString title();
+ virtual QString icon();
+ virtual QGraphicsWidget *createContentWidget(QGraphicsWidget *parent = 0);
+ //! \reimp_end
+
+ //! Reads all available keyboards
+ void readAvailableKeyboards();
+
+ //! Returns a map with languages and titles for all available keyboards.
+ QMap<QString, QString> availableKeyboards() const;
+
+ //! Returns a map with languages and titles for all selected keyboards.
+ QMap<QString, QString> selectedKeyboards() const;
+
+ //! Sets selected keyboards with \a keyboardTitles.
+ void setSelectedKeyboards(const QStringList &keyboardTitles);
+
+ //! Returns the boolean value of error correction option.
+ bool errorCorrection() const;
+
+ //! Sets error correction option.
+ void setErrorCorrection(bool);
+
+Q_SIGNALS:
+ //! Emitted when selected keyboards are changed.
+ void selectedKeyboardsChanged();
+
+ //! Emitted when error correction option is changed.
+ void errorCorrectionChanged();
+
+private:
+ QString keyboardTitle(const QString &language) const;
+ QString keyboardLanguage(const QString &title) const;
+
+ struct KeyboardInfo {
+ QString fileName;
+ QString language;
+ QString title;
+ };
+
+ //! all available keyboards
+ QList<KeyboardInfo> availableKeyboardInfos;
+ MGConfItem keyboardErrorCorrectionConf;
+ MGConfItem selectedKeyboardsConf;
+};
+
+#endif
--- m-keyboard/theme/864x480.css
+++ m-keyboard/theme/864x480.css
- at const MARGIN_DOUBLE: 1.2mm;
- at const MARGIN_LARGE: 0.8mm;
- at const PADDING_MEDIUM: 0.6mm;
- at const PADDING_LARGE: 1.2mm;
-
-/*
- FlickUpButtonStyle is only used in conjunction with real button widgets as keyboard keys.
- This also applies to object names dedicated for these buttons such as #Backspace or #Enter.
-
- Alternative styling is used when the keyboard keys are not actual widgets, i.e. the
- "single widget" approach. These are defined in MVirtualKeyboardStyle.
-*/
-
-/* FlickUpButton related styling */
-
-FlickUpButtonStyle {
- background-image: "keyboard-key-background" 10px 10px 10px 10px;
- font: "Nokia Sans Light" 24;
- minimum-size: 30 56;
- preferred-size: 8.2mm 5.6mm;
- maximum-size: -1 -1;
- icon: ;
- releaseFeedback: ;
- pressFeedback: ;
- margin-top: 0;
- margin-bottom: 0;
- margin-left: 0;
- margin-right: 0;
-
- reactive-margin-left: 2;
- reactive-margin-right: 2;
- reactive-margin-top: 6;
- reactive-margin-bottom: 6;
-
- text-margin-left: 0;
- text-margin-right: 0;
-}
-
-FlickUpButtonStyle:pressed {
- background-image: "keyboard-key-background-pressed" 10px 10px 10px 10px;
-}
-
-FlickUpButtonStyle:selected {
- background-image: "keyboard-key-background-selected" 10px 10px 10px 10px;
-}
-
-#Backspace {
- icon-size: 48 26;
- icon: "icon-m-keyboard-backspace";
-}
-
-#LayoutMenu {
- icon-size: 64 33;
- icon: "icon-m-keyboard-menu";
-}
-
-#Enter {
- icon-size: 38 28;
- icon: "icon-m-keyboard-enter";
-}
-
-#ShiftNormal {
- icon-size: 38 38;
- icon: "icon-m-shift-lowercase";
-}
-
-#ShiftLatched {
- icon-size: 38 38;
- icon: "icon-m-shift-uppercase";
-}
-
-#ShiftLocked {
- icon-size: 38 38;
- icon: "icon-m-keyboard-shift-capslock";
-}
-
-/* End of FlickUpButton related styling */
-
-#VirtualKeyboardSymTabs {
- background-image: "keyboard-tabs-background" 10px 10px 10px 10px;
-}
-
-#VirtualKeyboardSymCloseButton {
- preferred-size: 10.6mm 5.1mm;
-}
-
-#VirtualKeyboardSymTabsButton {
- preferred-size: 100 48;
- maximum-size: 100 48;
- margin-left: 0;
- margin-right: 0;
- margin-top: 0;
- margin-bottom: 0;
- background-image: "keyboard-tab-optional" 10px 10px 10px 10px;
-}
-
-#VirtualKeyboardSymTabsButton:selected {
- background-image: "keyboard-tab-active" 10px 10px 10px 10px;
-}
-
-MVirtualKeyboardStyle {
- background-image: "keyboard-background" 10px 10px 10px 10px;
- font: "Nokia Sans Light" 24;
- font-opacity: 0.9;
- font-color: #FFFFFF;
- secondary-font: $FONT_SMALL;
-
- padding-top: $PADDING_LARGE;
- padding-bottom: $PADDING_LARGE;
-
- spacing-vertical: $MARGIN_DOUBLE;
- spacing-horizontal: 0.3mm;
-
- deadkey-locked-color: #FFA500;
-
- notification-font: "Nokia Sans Light" 24;
- notification-border-color: #808080;
- notification-background-color: #323232;
- notification-text-color: #FFFFFF;
- notification-opacity: 0.9;
-
- toolbar-background-image: "keyboard-toolbar-background" 10px 10px 10px 10px;
-
- releaseFeedback: ;
- pressFeedback: ;
-
- /* Single widget keyboard button styling */
- key-background-id: "keyboard-key-background";
- key-background-pressed-id: "keyboard-key-background-pressed";
- key-background-selected-id: "keyboard-key-background-selected";
-
- key-backspace-icon-size: 48 48;
- key-backspace-icon-id: "icon-m-common-backspace";
-
- key-menu-icon-size: 48 48;
- key-menu-icon-id: "icon-m-input-methods-menu";
-
- key-enter-icon-size: 48 48;
- key-enter-icon-id: "icon-m-input-methods-enter";
-
- key-shift-icon-size: 48 48;
- key-shift-icon-id: "icon-m-input-methods-shift";
- key-shift-uppercase-icon-id: "icon-m-input-methods-capslock";
- /* End of single widget keyboard button styling */
-}
-
-MVirtualKeyboardStyle.Portrait {
- keyboard-area-size: 480 280;
-
- label-margin-top: 2mm;
- label-margin-left-with-secondary: 4.6mm;
- secondary-label-separation: 0.9mm;
-
- padding-left: $PADDING_MEDIUM;
- padding-right: 0.7mm;
-
- tab-button-size: 91 70;
- menu-size: 470 342;
-
- /* Single widget keyboard button styling */
- key-normal-size: 4.4mm 8mm;
- key-phone-number-normal-size: 15.3mm 8mm;
- key-function-normal-size: 8mm 8mm;
- key-function-large-size: 8mm 8mm;
- key-number-backspace-size: 15.3mm 8mm;
- key-sym-normal-size: 7.5mm 8mm;
- /* End of single widget keyboard button styling */
-
- key-background-sym-indicator-sym: "keyboard-key-sym-selected-portrait";
- key-background-sym-indicator-ace: "keyboard-key-ace-selected-portrait";
-}
-
-MVirtualKeyboardStyle.Landscape {
- keyboard-area-size: 864 280;
-
- label-margin-top: $MARGIN_LARGE;
- label-margin-left-with-secondary: -1; /* not used, labels are centered horizontally */
- secondary-label-separation: 0;
-
- padding-left: $PADDING_LARGE;
- padding-right: 0.9mm;
-
- tab-button-size: 108 70;
-
- menu-size: 790 342;
-
- /* Single widget keyboard button styling */
- key-normal-size: 8.2mm 5.6mm;
- key-phone-number-normal-size: 8.2mm 8.4mm;
- key-function-normal-size: 8.2mm 5.6mm;
- key-function-large-size: 12.4mm 5.6mm;
- key-number-backspace-size: 12.4mm 5.6mm;
- key-sym-normal-size: 8.2mm 5.6mm;
- /* End of single widget keyboard button styling */
-
- key-background-sym-indicator-sym: "keyboard-key-sym-selected-landscape";
- key-background-sym-indicator-ace: "keyboard-key-ace-selected-landscape";
-}
-
-
-#MenuToggleButton {
- background-image: "Toggle-btn-normal" 0 0 0 0;
- background-opacity: 1.0;
- background-color: #000000;
- text-color: #FFFFFF;
-}
-
-
-#MenuToggleButton:pressed {
- background-image: "Toggle-btn-selected" 0 0 0 0;
- background-opacity: 1.0;
- background-color: #F9A427;
- text-color: #555555;
-}
-
-
-#MenuLanguageList {
- background-image: "Single-line-input-field" 0 0 0 0;
- text-left-offset: 12;
- text-right-offset: 12;
-
- font: "Nokia Sans" 20;
- text-color: #000000;
-
- preferred-size: 414 56;
- minimum-size: 414 56;
- maximum-size: 414 56;
-}
-
-#VirtualKeyboardToolbarButton {
- background-image: "keyboard-toolbar-button-background" 10px 10px 10px 10px;
- margin-left: 0;
- margin-right: 0;
- margin-top: 0;
- margin-bottom: 0;
- preferred-size: 100 48;
- maximum-size: 100 48;
- reactive-margin-left: 2;
- reactive-margin-right: 2;
- reactive-margin-top: 5;
- reactive-margin-bottom: 5;
-}
-
-#VirtualKeyboardToolbarButton:pressed {
- background-image: "keyboard-toolbar-button-background-pressed" 10px 10px 10px 10px;
-}
-
-#VirtualKeyboardToolbarButton:selected {
- background-image: "keyboard-toolbar-button-background-pressed" 10px 10px 10px 10px;
-}
-
-WidgetBarStyle {
- margin-left: 0;
- margin-top: 0;
- margin-right: 0;
- margin-bottom: 0;
-
- padding-top: 3;
- padding-left: 3;
- padding-right: 3;
-}
-
-#CorrectionCandidateList {
- margin-left: 0;
- margin-top: 0;
- margin-right: 0;
- margin-bottom: 0;
-}
-
-#CorrectionCandidateItem {
- preferred-size: -1 6.4mm;
- minimum-size: 10mm 6.4mm;
- maximum-size: 100% 6.4mm;
-
- title-object-name: "CorrectionCandidateItemTitle";
-}
-#CorrectionCandidateItemTitle {
- margin-left: 2.4mm;
- margin-right: 2.4mm;
-}
--- m-keyboard/theme/libmeego-keyboard.css
+++ m-keyboard/theme/libmeego-keyboard.css
+ at const MARGIN_DOUBLE: 1.2mm;
+ at const MARGIN_LARGE: 0.8mm;
+ at const PADDING_MEDIUM: 0.6mm;
+ at const PADDING_LARGE: 1.2mm;
+
+/*
+ FlickUpButtonStyle is only used in conjunction with real button widgets as keyboard keys.
+ This also applies to object names dedicated for these buttons such as #Backspace or #Enter.
+
+ Alternative styling is used when the keyboard keys are not actual widgets, i.e. the
+ "single widget" approach. These are defined in MVirtualKeyboardStyle.
+*/
+
+/* FlickUpButton related styling */
+
+FlickUpButtonStyle {
+ background-image: "keyboard-key" 10px 10px 10px 10px;
+ font: "Nokia Sans Light" 24;
+ minimum-size: 30 56;
+ preferred-size: 8.2mm 5.6mm;
+ maximum-size: -1 -1;
+ icon: ;
+ releaseFeedback: ;
+ pressFeedback: ;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ margin-right: 0;
+
+ reactive-margin-left: 2;
+ reactive-margin-right: 2;
+ reactive-margin-top: 6;
+ reactive-margin-bottom: 6;
+
+ text-margin-left: 0;
+ text-margin-right: 0;
+}
+
+FlickUpButtonStyle:pressed {
+ background-image: "keyboard-key-pressed" 10px 10px 10px 10px;
+}
+
+FlickUpButtonStyle:selected {
+ background-image: "keyboard-key-selected" 10px 10px 10px 10px;
+}
+
+#Backspace {
+ icon-size: 48 26;
+ icon: "icon-m-keyboard-backspace";
+}
+
+#LayoutMenu {
+ icon-size: 64 33;
+ icon: "icon-m-keyboard-menu";
+}
+
+#Enter {
+ icon-size: 38 28;
+ icon: "icon-m-keyboard-enter";
+}
+
+#ShiftNormal {
+ icon-size: 38 38;
+ icon: "icon-m-shift-lowercase";
+}
+
+#ShiftLatched {
+ icon-size: 38 38;
+ icon: "icon-m-shift-uppercase";
+}
+
+#ShiftLocked {
+ icon-size: 38 38;
+ icon: "icon-m-keyboard-shift-capslock";
+}
+
+/* End of FlickUpButton related styling */
+
+#VirtualKeyboardSymTabs {
+ /* id missing or needs renaming? */
+ background-image: "keyboard-tabs-background" 10px 10px 10px 10px;
+}
+
+#VirtualKeyboardSymCloseButton {
+ preferred-size: 10.6mm 5.1mm;
+}
+
+#VirtualKeyboardSymTabsButton {
+ preferred-size: 100 48;
+ maximum-size: 100 48;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ /* id missing or needs renaming? */
+ background-image: "keyboard-tab-optional" 10px 10px 10px 10px;
+}
+
+#VirtualKeyboardSymTabsButton:selected {
+ /* id missing or needs renaming? */
+ background-image: "keyboard-tab-active" 10px 10px 10px 10px;
+}
+
+MVirtualKeyboardStyle {
+ background-image: "meegotouch-keyboard-background" 10px 10px 10px 10px;
+ font: "Nokia Sans Light" 28;
+ font-opacity: 0.9;
+ font-color: #000000;
+
+ secondary-font: $FONT_SMALL;
+
+ padding-top: $PADDING_LARGE;
+ padding-bottom: $PADDING_LARGE;
+
+ spacing-vertical: $MARGIN_DOUBLE;
+ spacing-horizontal: 0.3mm;
+
+ deadkey-locked-color: #FFA500;
+
+ notification-font: "Nokia Sans Light" 24;
+ notification-border-color: #808080;
+ notification-background-color: #323232;
+ notification-text-color: #FFFFFF;
+ notification-opacity: 0.9;
+
+ toolbar-background-image: "meegotouch-keyboard-toolbar-background" 10px 10px 10px 10px;
+
+ releaseFeedback: ;
+ pressFeedback: ;
+
+ /* Single widget keyboard button styling */
+ key-background-border-left: 10;
+ key-background-border-right: 10;
+ key-background-border-top: 10;
+ key-background-border-bottom: 10;
+
+ key-backspace-icon-id: "icon-m-input-methods-backspace";
+ key-backspace-icon-size: 48 48;
+
+ key-menu-icon-size: 48 48;
+ key-menu-icon-id: "icon-m-input-methods-menu";
+
+ key-enter-icon-size: 48 48;
+ key-enter-icon-id: "icon-m-input-methods-enter";
+
+ key-shift-icon-size: 48 48;
+ key-shift-icon-id: "icon-m-input-methods-shift";
+ key-shift-uppercase-icon-id: "icon-m-input-methods-capslock";
+ /* End of single widget keyboard button styling */
+}
+
+MVirtualKeyboardStyle.Portrait {
+ keyboard-area-size: 480 280;
+
+ label-margin-top: 2.4mm;
+ label-margin-left-with-secondary: 4.6mm;
+ secondary-label-separation: 0.9mm;
+
+ padding-left: $PADDING_MEDIUM;
+ padding-right: 0.7mm;
+
+ tab-button-size: 91 70;
+ menu-size: 470 342;
+
+ /* Single widget keyboard button styling */
+ key-background-id: "meegotouch-keyboard-key-portrait";
+ key-background-pressed-id: "meegotouch-keyboard-key-pressed-portrait";
+ key-background-selected-id: "meegotouch-keyboard-key-selected-portrait";
+
+ key-normal-size: 4.4mm 8mm;
+
+ key-phone-number-normal-size: 15.3mm 8mm;
+ key-function-normal-size: 8mm 8mm;
+ key-function-large-size: 8mm 8mm;
+ key-number-backspace-size: 15.3mm 8mm;
+ key-sym-normal-size: 7.5mm 8mm;
+ /* End of single widget keyboard button styling */
+
+ key-background-sym-indicator-sym: "meegotouch-keyboard-key-sym-selected-portrait";
+ key-background-sym-indicator-ace: "meegotouch-keyboard-key-ace-selected-portrait";
+ key-background-sym-indicator-sym-pressed: "meegotouch-keyboard-key-sym-pressed-portrait";
+ key-background-sym-indicator-ace-pressed: "meegotouch-keyboard-key-ace-pressed-portrait";
+}
+
+MVirtualKeyboardStyle.Landscape {
+ keyboard-area-size: 864 280;
+
+ label-margin-top: 1.2mm;
+ label-margin-left-with-secondary: -1; /* not used, labels are centered horizontally */
+ secondary-label-separation: 0;
+
+ padding-left: $PADDING_LARGE;
+ padding-right: 0.9mm;
+
+ tab-button-size: 108 70;
+
+ menu-size: 790 342;
+
+ /* Single widget keyboard button styling */
+ key-background-id: "meegotouch-keyboard-key-landscape";
+ key-background-pressed-id: "meegotouch-keyboard-key-pressed-landscape";
+ key-background-selected-id: "meegotouch-keyboard-key-selected-landscape";
+
+ key-normal-size: 8.2mm 5.6mm;
+
+ key-phone-number-normal-size: 8.2mm 8.4mm;
+ key-function-normal-size: 8.2mm 5.6mm;
+ key-function-large-size: 12.4mm 5.6mm;
+ key-number-backspace-size: 12.4mm 5.6mm;
+ key-sym-normal-size: 8.2mm 5.6mm;
+ /* End of single widget keyboard button styling */
+
+ key-background-sym-indicator-sym: "meegotouch-keyboard-key-sym-selected-landscape";
+ key-background-sym-indicator-ace: "meegotouch-keyboard-key-ace-selected-landscape";
+ key-background-sym-indicator-sym-pressed: "meegotouch-keyboard-key-sym-pressed-landscape";
+ key-background-sym-indicator-ace-pressed: "meegotouch-keyboard-key-ace-pressed-landscape";
+}
+
+#InvisibleHandle.Portrait {
+ preferred-size: 480 2.5mm;
+ minimum-size: 480 2.5mm;
+ maximum-size: 480 2.5mm;
+}
+
+#InvisibleHandle.Landscape {
+ preferred-size: 864 2.5mm;
+ minimum-size: 480 2.5mm;
+ maximum-size: 864 2.5mm;
+}
+
+#KeyboardToolbarHandle {
+ background-image: "meegotouch-keyboard-handle-background";
+}
+
+#KeyboardToolbarHandle.Portrait {
+ preferred-size: 480 0.6mm;
+ minimum-size: 480 0.6mm;
+ maximum-size: 480 0.6mm;
+}
+
+#KeyboardToolbarHandle.Landscape {
+ preferred-size: 864 0.6mm;
+ minimum-size: 480 0.6mm;
+ maximum-size: 864 0.6mm;
+}
+
+#KeyboardHandle {
+ background-image: "meegotouch-keyboard-handle-background";
+}
+
+#KeyboardHandle.Landscape {
+ preferred-size: 864 0.6mm;
+ minimum-size: 480 0.6mm;
+ maximum-size: 864 0.6mm;
+}
+
+#KeyboardHandle.Portrait {
+ preferred-size: 480 0.6mm;
+ minimum-size: 480 0.6mm;
+ maximum-size: 480 0.6mm;
+}
+
+#MenuToggleButton {
+ background-image: "Toggle-btn-normal" 0 0 0 0;
+ background-opacity: 1.0;
+ background-color: #000000;
+ text-color: #FFFFFF;
+}
+
+
+#MenuToggleButton:pressed {
+ background-image: "Toggle-btn-selected" 0 0 0 0;
+ background-opacity: 1.0;
+ background-color: #F9A427;
+ text-color: #555555;
+}
+
+
+#MenuLanguageList {
+ background-image: "Single-line-input-field" 0 0 0 0;
+ text-left-offset: 12;
+ text-right-offset: 12;
+
+ font: "Nokia Sans" 20;
+ text-color: #000000;
+
+ preferred-size: 414 56;
+ minimum-size: 414 56;
+ maximum-size: 414 56;
+}
+
+MToolbarButtonStyle {
+ background-image: "meegotouch-keyboard-toolbar-button" 10px 10px 10px 10px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ preferred-size: 100 48;
+ maximum-size: 100 48;
+ reactive-margin-left: 2;
+ reactive-margin-right: 2;
+ reactive-margin-top: 5;
+ reactive-margin-bottom: 5;
+}
+
+MToolbarButtonStyle:pressed {
+ background-image: "meegotouch-keyboard-toolbar-button-pressed" 10px 10px 10px 10px;
+}
+
+MToolbarButtonStyle:selected {
+ background-image: "meegotouch-keyboard-toolbar-button-selected" 10px 10px 10px 10px;
+}
+
+WidgetBarStyle {
+ margin-left: 0;
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+
+ padding-top: 3;
+ padding-left: 3;
+ padding-right: 3;
+}
+
+#CorrectionCandidateList {
+ margin-left: 0;
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+}
+
+#CorrectionCandidateItem {
+ preferred-size: -1 6.4mm;
+ minimum-size: 10mm 6.4mm;
+ maximum-size: 100% 6.4mm;
+
+ title-object-name: "CorrectionCandidateItemTitle";
+}
+#CorrectionCandidateItemTitle {
+ margin-left: 2.4mm;
+ margin-right: 2.4mm;
+}
--- m-keyboard/theme/meegotouch-keyboard.svg
+++ m-keyboard/theme/meegotouch-keyboard.svg
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="meegotouch-keyboard-layer" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ x="0px" y="0px" width="500px" height="480px" viewBox="0 0 500 480" style="enable-background:new 0 0 500 480;"
+ xml:space="preserve">
+<g id="meegotouch-keyboard">
+ <g id="virtualmeegotouch-keyboardThemeTemplateHelper">
+ <g id="vkbhelperBackground">
+ <g>
+ <path style="fill:#B3B3B3;" d="M16,479c-8.271,0-15-6.729-15-15V16C1,7.729,7.729,1,16,1h468c8.271,0,15,6.729,15,15v448
+ c0,8.271-6.729,15-15,15H16z"/>
+ <g>
+ <path d="M484,2c7.72,0,14,6.28,14,14v448c0,7.72-6.28,14-14,14H16c-7.72,0-14-6.28-14-14V16C2,8.28,8.28,2,16,2H484 M484,0H16
+ C7.2,0,0,7.2,0,16v448c0,8.8,7.2,16,16,16h468c8.8,0,16-7.2,16-16V16C500,7.2,492.8,0,484,0L484,0z"/>
+ </g>
+ </g>
+ </g>
+ <g>
+ <path style="fill:#010101;" d="M145.746,43.409l-5.634-20.794h3.138l4.352,17.307l4.561-17.307h2.72l-5.83,20.794H145.746z"/>
+ <path style="fill:#010101;" d="M160.417,43.409h-2.971V29.128h-1.855v-1.938h4.826V43.409z M158.939,21.499
+ c0.456,0,0.849,0.167,1.179,0.502s0.495,0.729,0.495,1.186c0,0.465-0.163,0.862-0.488,1.192c-0.326,0.33-0.721,0.495-1.186,0.495
+ c-0.474,0-0.874-0.165-1.199-0.495c-0.326-0.33-0.488-0.728-0.488-1.192c0-0.474,0.163-0.874,0.488-1.2
+ C158.065,21.662,158.465,21.499,158.939,21.499z"/>
+ <path style="fill:#010101;" d="M166.303,27.189l0.683,2.705c0.902-1.906,2.473-2.859,4.714-2.859
+ c0.298,0,0.516,0.015,0.656,0.043v2.705c-0.232-0.019-0.581-0.027-1.046-0.027c-1.274,0-2.208,0.305-2.803,0.913
+ c-0.595,0.608-0.893,1.56-0.893,2.853v9.888h-2.971v-16.22H166.303z"/>
+ <path style="fill:#010101;" d="M178.98,43.633c-1.265,0-2.19-0.295-2.775-0.887c-0.586-0.59-0.879-1.531-0.879-2.824V29.128
+ h-2.134v-1.116l4.337-4.421h0.767v3.599h3.947v1.938h-3.947v10.307c0,0.884,0.144,1.467,0.433,1.75
+ c0.288,0.284,0.725,0.425,1.311,0.425c0.604,0,1.422-0.134,2.455-0.404v1.926C181.249,43.465,180.077,43.633,178.98,43.633z"/>
+ <path style="fill:#010101;" d="M189.65,43.633c-1.655,0-2.894-0.431-3.717-1.291c-0.823-0.859-1.234-2.149-1.234-3.869V27.189
+ h2.971v10.767c0,1.218,0.214,2.132,0.642,2.741c0.428,0.608,1.074,0.912,1.938,0.912c1.079,0,1.913-0.408,2.503-1.227
+ s0.886-1.883,0.886-3.193v-10h2.971v16.22h-1.646l-0.6-2.399C193.332,42.758,191.761,43.633,189.65,43.633z"/>
+ <path style="fill:#010101;" d="M209.078,41.066c-1.004,1.711-2.566,2.566-4.686,2.566c-1.479,0-2.629-0.416-3.452-1.248
+ c-0.823-0.832-1.234-1.997-1.234-3.494c0-1.543,0.423-2.693,1.269-3.452c0.846-0.757,1.859-1.231,3.041-1.423
+ c1.181-0.189,2.617-0.285,4.31-0.285v-1.911c0-1.888-1.009-2.831-3.026-2.831c-1.163,0-2.581,0.246-4.254,0.739v-2.078
+ c1.683-0.465,3.282-0.697,4.797-0.697c1.786,0,3.141,0.431,4.066,1.29c0.925,0.859,1.388,2.127,1.388,3.801v11.366h-1.618
+ L209.078,41.066z M208.325,35.502h-1.66c-1.33,0-2.327,0.281-2.992,0.844c-0.665,0.562-0.997,1.4-0.997,2.517
+ c0,0.911,0.202,1.593,0.606,2.044s1.011,0.676,1.82,0.676c1.022,0,1.815-0.325,2.378-0.977c0.562-0.65,0.844-1.533,0.844-2.649
+ V35.502z"/>
+ <path style="fill:#010101;" d="M215.298,43.409V21.332h2.971v22.077H215.298z"/>
+ <path style="fill:#010101;" d="M235.242,34.246l5.914,9.163h-3.515l-5.579-8.828v8.828h-2.971V21.332h2.971v13.193l5.495-7.336
+ h3.25L235.242,34.246z"/>
+ <path style="fill:#010101;" d="M253.066,40.927v2.022c-1.461,0.455-2.971,0.684-4.533,0.684c-2.269,0-3.966-0.684-5.091-2.051
+ s-1.688-3.473-1.688-6.318c0-2.5,0.544-4.512,1.632-6.031c1.088-1.521,2.641-2.28,4.658-2.28c1.636,0,2.866,0.435,3.689,1.304
+ c0.822,0.869,1.35,1.934,1.582,3.193c0.232,1.261,0.35,2.76,0.35,4.498h-8.759c0,1.889,0.335,3.304,1.004,4.247
+ c0.669,0.944,1.673,1.415,3.012,1.415C250.058,41.609,251.438,41.383,253.066,40.927z M244.907,34.121h5.844
+ c0-1.962-0.232-3.348-0.697-4.156s-1.134-1.214-2.008-1.214c-0.976,0-1.723,0.419-2.238,1.255
+ C245.291,30.844,244.991,32.215,244.907,34.121z"/>
+ <path style="fill:#010101;" d="M259.578,42.81l-4.435-15.62h3.054l3.543,13.444l3.695-13.444h2.678l-5.076,17.195
+ c-0.391,1.293-0.939,2.244-1.646,2.854c-0.706,0.607-1.627,0.912-2.761,0.912c-0.781,0-1.646-0.098-2.595-0.292v-2.05
+ c0.855,0.167,1.636,0.25,2.343,0.25c0.642,0,1.164-0.216,1.569-0.648c0.404-0.432,0.792-1.299,1.165-2.601H259.578z"/>
+ <path style="fill:#010101;" d="M273.303,21.332v7.363c1.06-1.162,2.375-1.743,3.947-1.743c1.812,0,3.174,0.669,4.086,2.009
+ c0.911,1.338,1.367,3.347,1.367,6.024s-0.614,4.774-1.842,6.29c-1.227,1.516-2.914,2.273-5.062,2.273
+ c-2.111,0-3.933-0.094-5.467-0.279V21.332H273.303z M273.303,35.236v6.15c0.864,0.111,1.637,0.168,2.314,0.168
+ c1.367,0,2.376-0.5,3.027-1.5c0.65-0.999,0.977-2.717,0.977-5.152c0-1.972-0.256-3.45-0.768-4.436
+ c-0.512-0.986-1.273-1.479-2.287-1.479c-0.986,0-1.716,0.298-2.189,0.893c-0.475,0.596-0.772,1.318-0.893,2.169
+ C273.363,32.9,273.303,33.963,273.303,35.236z"/>
+ <path style="fill:#010101;" d="M291.922,43.633c-2.186,0-3.822-0.717-4.91-2.148s-1.631-3.58-1.631-6.443
+ c0-2.492,0.564-4.463,1.693-5.913c1.131-1.45,2.746-2.176,4.848-2.176c2.119,0,3.739,0.716,4.859,2.147
+ c1.121,1.432,1.682,3.432,1.682,5.997c0,2.642-0.523,4.724-1.569,6.249C295.848,42.87,294.189,43.633,291.922,43.633z
+ M291.922,41.722c1.143,0,2.006-0.519,2.586-1.556c0.582-1.036,0.873-2.772,0.873-5.209c0-1.72-0.299-3.163-0.893-4.33
+ c-0.596-1.166-1.451-1.75-2.566-1.75c-1.135,0-1.994,0.525-2.58,1.576s-0.879,2.552-0.879,4.504c0,2.195,0.293,3.871,0.879,5.028
+ S290.787,41.722,291.922,41.722z"/>
+ <path style="fill:#010101;" d="M310.233,41.066c-1.004,1.711-2.566,2.566-4.687,2.566c-1.479,0-2.629-0.416-3.451-1.248
+ c-0.823-0.832-1.234-1.997-1.234-3.494c0-1.543,0.423-2.693,1.27-3.452c0.846-0.757,1.859-1.231,3.04-1.423
+ c1.181-0.189,2.617-0.285,4.31-0.285v-1.911c0-1.888-1.01-2.831-3.026-2.831c-1.163,0-2.581,0.246-4.254,0.739v-2.078
+ c1.683-0.465,3.282-0.697,4.798-0.697c1.785,0,3.141,0.431,4.065,1.29s1.388,2.127,1.388,3.801v11.366h-1.618L310.233,41.066z
+ M309.48,35.502h-1.66c-1.33,0-2.326,0.281-2.991,0.844s-0.997,1.4-0.997,2.517c0,0.911,0.202,1.593,0.606,2.044
+ s1.011,0.676,1.82,0.676c1.022,0,1.815-0.325,2.378-0.977c0.562-0.65,0.844-1.533,0.844-2.649V35.502z"/>
+ <path style="fill:#010101;" d="M318.113,27.189l0.684,2.705c0.901-1.906,2.473-2.859,4.713-2.859
+ c0.299,0,0.517,0.015,0.656,0.043v2.705c-0.232-0.019-0.581-0.027-1.046-0.027c-1.274,0-2.208,0.305-2.804,0.913
+ c-0.595,0.608-0.893,1.56-0.893,2.853v9.888h-2.971v-16.22H318.113z"/>
+ <path style="fill:#010101;" d="M336.383,43.409l-0.627-1.994c-0.855,1.478-2.32,2.218-4.394,2.218
+ c-1.925,0-3.373-0.682-4.345-2.043c-0.971-1.363-1.457-3.49-1.457-6.381c0-2.428,0.518-4.41,1.555-5.949
+ c1.037-1.538,2.508-2.308,4.414-2.308c1.562,0,2.734,0.47,3.516,1.409v-7.029h2.971v22.077H336.383z M335.143,36.018
+ l-0.015-0.921c0-2.417-0.272-4.049-0.815-4.896c-0.545-0.846-1.318-1.269-2.322-1.269c-1.115,0-1.953,0.517-2.511,1.548
+ c-0.558,1.032-0.837,2.58-0.837,4.645c0,2.166,0.27,3.789,0.809,4.867s1.349,1.617,2.428,1.617c1.051,0,1.856-0.39,2.42-1.171
+ C334.861,39.658,335.143,38.184,335.143,36.018z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-handle-decoration">
+ <circle style="fill:#6E6F71;" cx="96" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="104.167" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="112.337" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="120.505" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="128.675" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="136.843" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="145.013" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="153.181" cy="377.999" r="2"/>
+ <circle style="fill:#6E6F71;" cx="161.351" cy="377.999" r="2"/>
+ </g>
+ <g id="meegotouch-keyboard-handle-background">
+ <rect x="94" y="389.999" style="fill:#F2F2F2;" width="64" height="6"/>
+ </g>
+ <g id="meegotouch-keyboard-background">
+ <rect x="20" y="80" style="fill:#F2F2F2;" width="64" height="64"/>
+ </g>
+ <g id="meegotouch-keyboard-toolbar-background">
+ <rect x="20" y="154" style="fill:#F2F2F2;" width="64" height="64"/>
+ </g>
+ <g id="meegotouch-keyboard-toolbar-button-pressed-selected">
+ <g>
+ <path style="fill:#333333;" d="M94,311.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v29c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V311.999z"/>
+ </g>
+ <g style="opacity:0.8;">
+ <path style="fill:#FFFFFF;" d="M94,313.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v29c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V313.999z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="125.9995" y1="351.999" x2="125.9995" y2="302.999">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_1_);" d="M158,341.999c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-29c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V341.999z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-toolbar-button-selected">
+ <g>
+ <path style="fill:#333333;" d="M158,269c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-29c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V269z"/>
+ </g>
+ <g>
+ <path style="fill:#CCCCCC;" d="M158,267c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-29c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V267z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="125.9995" y1="278" x2="125.9995" y2="229.0005">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_2_);" d="M158,268c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-29c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V268z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-toolbar-button-pressed">
+ <g>
+ <path style="fill:#333333;" d="M94,164c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v29c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10
+ V164z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M94,166c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v29c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10
+ V166z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="125.9995" y1="155" x2="125.9995" y2="204">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_3_);" d="M158,194c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-29c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V194z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-toolbar-button">
+ <g>
+ <path style="fill:#808080;" d="M158,121c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V92c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V121z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M158,119c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V90c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V119z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="125.9995" y1="81" x2="125.9995" y2="130">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_4_);" d="M158,120c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V91c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V120z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-pressed-selected-portrait">
+ <g>
+ <path style="fill:#333333;" d="M238,355.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v58c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V355.999z"/>
+ </g>
+ <g style="opacity:0.8;">
+ <path style="fill:#FFFFFF;" d="M238,357.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v58c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V357.999z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="270" y1="424.999" x2="270" y2="346.999">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_5_);" d="M302,414.999c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-58c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V414.999z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-selected-portrait">
+ <g>
+ <path style="fill:#333333;" d="M302,329c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-58c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V329z"/>
+ </g>
+ <g>
+ <path style="fill:#CCCCCC;" d="M302,327c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-58c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V327z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="270" y1="338" x2="270" y2="260">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_6_);" d="M302,328c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-58c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V328z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-pressed-portrait">
+ <g>
+ <path style="fill:#333333;" d="M238,178c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v58c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V178z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M238,180c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v58c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V180z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="270" y1="169" x2="270" y2="247.0005">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_7_);" d="M302,237c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-58c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V237z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-portrait">
+ <g>
+ <path style="fill:#808080;" d="M302,150c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V92c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V150z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M302,148c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V90c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V148z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="270" y1="81" x2="270" y2="159">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_8_);" d="M302,149c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V91c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V149z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-sym-selected-landscape">
+ <g>
+ <path style="fill:#CCCCCC;" d="M473.996,170h-61.992c-5.503,0-10.004,4.406-10.004,9.792v19.228h82v-19.228
+ C484,174.406,479.498,170,473.996,170z"/>
+ <linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="443" y1="199.0195" x2="443" y2="170.9795">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_9_);" d="M473.996,170.979h-61.992c-5.503,0-10.004,4.406-10.004,9.792v18.248h82v-18.248
+ C484,175.386,479.498,170.979,473.996,170.979z"/>
+ </g>
+ <g>
+ <path style="fill:#808080;" d="M402,199.02v17.189c0,5.385,4.501,9.791,10.004,9.791h61.992c5.502,0,10.004-4.406,10.004-9.791
+ V199.02H402z"/>
+ <linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="443" y1="199.0195" x2="443" y2="225.0215">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_10_);" d="M402,199.02v16.209c0,5.387,4.501,9.793,10.004,9.793h61.992
+ c5.502,0,10.004-4.406,10.004-9.793V199.02H402z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-ace-selected-landscape">
+ <g>
+ <path style="fill:#FFFFFF;" d="M473.998,81h-61.996C406.5,81,402,85.406,402,90.793v19.227h82V90.793
+ C484,85.406,479.498,81,473.998,81z"/>
+ <linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="443" y1="81.9785" x2="443" y2="110.0195">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_11_);" d="M473.998,81.979h-61.996c-5.502,0-10.002,4.407-10.002,9.793v18.248h82V91.771
+ C484,86.386,479.498,81.979,473.998,81.979z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M402,110.02v17.188c0,5.387,4.5,9.793,10.002,9.793h61.996c5.5,0,10.002-4.406,10.002-9.793
+ V110.02H402z"/>
+ <linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="443" y1="136.0215" x2="443" y2="110.0195">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_12_);" d="M402,110.02v16.209c0,5.386,4.5,9.793,10.002,9.793h61.996
+ c5.5,0,10.002-4.407,10.002-9.793V110.02H402z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-sym-selected-portrait">
+ <g>
+ <path style="fill:#CCCCCC;" d="M382,170h-60c-5.5,0-10,4.5-10,10v29h80v-29C392,174.5,387.5,170,382,170z"/>
+ <linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="352" y1="209" x2="352" y2="171">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_13_);" d="M382,171h-60c-5.5,0-10,4.5-10,10v28h80v-28C392,175.5,387.5,171,382,171z"/>
+ </g>
+ <g>
+ <path style="fill:#808080;" d="M312,209v31.001c0,5.5,4.5,9.999,10,9.999h60c5.5,0,10-4.499,10-9.999V209H312z"/>
+ <linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="352" y1="209" x2="352" y2="249.0005">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_14_);" d="M312,209v30.001c0,5.5,4.5,9.999,10,9.999h60c5.5,0,10-4.499,10-9.999V209H312z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-ace-selected-portrait">
+ <g>
+ <path style="fill:#FFFFFF;" d="M382,80h-60c-5.5,0-10,4.5-10,10v29h80V90C392,84.5,387.5,80,382,80z"/>
+ <linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="352" y1="81" x2="352" y2="119">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_15_);" d="M382,81h-60c-5.5,0-10,4.5-10,10v28h80V91C392,85.5,387.5,81,382,81z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M312,119v31c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-31H312z"/>
+ <linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="352" y1="159" x2="352" y2="119">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_16_);" d="M312,119v30c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-30H312z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-sym-pressed-landscape">
+ <g>
+ <path style="fill:#333333;" d="M473.969,349H412c-5.5,0-10,4.5-10,10v19.635h81.969V359C483.969,353.5,479.469,349,473.969,349z"
+ />
+ <linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="442.9844" y1="378.6348" x2="442.9844" y2="350">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_17_);" d="M473.969,350H412c-5.5,0-10,4.5-10,10v18.635h81.969V360
+ C483.969,354.5,479.469,350,473.969,350z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M402,378.635v17.553c0,5.5,4.5,10,10,10h61.969c5.5,0,10-4.5,10-10v-17.553H402z"/>
+ <linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="442.9844" y1="378.6348" x2="442.9844" y2="405.1875">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_18_);" d="M402,378.635v16.553c0,5.5,4.5,10,10,10h61.969c5.5,0,10-4.5,10-10v-16.553H402z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-ace-pressed-landscape">
+ <g>
+ <path style="fill:#333333;" d="M473.998,260h-61.996C406.5,260,402,264.406,402,269.793v19.227h82v-19.227
+ C484,264.406,479.498,260,473.998,260z"/>
+ <linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="443" y1="260.9785" x2="443" y2="289.0195">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_19_);" d="M473.998,260.979h-61.996c-5.502,0-10.002,4.407-10.002,9.793v18.248h82v-18.248
+ C484,265.386,479.498,260.979,473.998,260.979z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M402,289.02v17.188c0,5.387,4.5,9.793,10.002,9.793h61.996c5.5,0,10.002-4.406,10.002-9.793
+ V289.02H402z"/>
+ <linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="443" y1="315.0215" x2="443" y2="289.0195">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_20_);" d="M402,289.02v16.209c0,5.386,4.5,9.793,10.002,9.793h61.996
+ c5.5,0,10.002-4.407,10.002-9.793V289.02H402z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-sym-pressed-portrait">
+ <g>
+ <path style="fill:#333333;" d="M382,349h-60c-5.5,0-10,4.5-10,10v29h80v-29C392,353.5,387.5,349,382,349z"/>
+ <linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="352" y1="388" x2="352" y2="350">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_21_);" d="M382,350h-60c-5.5,0-10,4.5-10,10v28h80v-28C392,354.5,387.5,350,382,350z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M312,388v31c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-31H312z"/>
+ <linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="352" y1="388" x2="352" y2="428">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_22_);" d="M312,388v30c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-30H312z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-ace-pressed-portrait">
+ <g>
+ <path style="fill:#333333;" d="M382,260h-60c-5.5,0-10,4.5-10,10v29h80v-29C392,264.5,387.5,260,382,260z"/>
+ <linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="352" y1="261" x2="352" y2="299">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_23_);" d="M382,261h-60c-5.5,0-10,4.5-10,10v28h80v-28C392,265.5,387.5,261,382,261z"/>
+ </g>
+ <g>
+ <path style="fill:#333333;" d="M312,299v31c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-31H312z"/>
+ <linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="352" y1="339" x2="352" y2="299">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_24_);" d="M312,299v30c0,5.5,4.5,10,10,10h60c5.5,0,10-4.5,10-10v-30H312z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-pressed-selected-landscape">
+ <g>
+ <path style="fill:#333333;" d="M165,311.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v34c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V311.999z"/>
+ </g>
+ <g style="opacity:0.8;">
+ <path style="fill:#FFFFFF;" d="M165,313.999c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v34c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V313.999z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_25_" gradientUnits="userSpaceOnUse" x1="196.9995" y1="356.999" x2="196.9995" y2="302.999">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#1F749A"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_25_);" d="M229,346.999c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-34c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V346.999z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-selected-landscape">
+ <g>
+ <path style="fill:#333333;" d="M229,274c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-34c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V274z"/>
+ </g>
+ <g>
+ <path style="fill:#CCCCCC;" d="M229,272c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-34c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V272z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_26_" gradientUnits="userSpaceOnUse" x1="196.9995" y1="283" x2="196.9995" y2="229.0005">
+ <stop offset="0" style="stop-color:#2AAAE2"/>
+ <stop offset="1" style="stop-color:#83D5F7"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_26_);" d="M229,273c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-34c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V273z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-pressed-landscape">
+ <g>
+ <path style="fill:#333333;" d="M165,164c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v34c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V164z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M165,166c0-5.5,4.5-10,10-10h44c5.5,0,10,4.5,10,10v34c0,5.5-4.5,10-10,10h-44
+ c-5.5,0-10-4.5-10-10V166z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_27_" gradientUnits="userSpaceOnUse" x1="196.9995" y1="155" x2="196.9995" y2="209">
+ <stop offset="0" style="stop-color:#4D4D4D"/>
+ <stop offset="1" style="stop-color:#B3B3B3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_27_);" d="M229,199c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10v-34c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V199z"/>
+ </g>
+ </g>
+ <g id="meegotouch-keyboard-key-landscape">
+ <g>
+ <path style="fill:#808080;" d="M229,126c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V92c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V126z"/>
+ </g>
+ <g>
+ <path style="fill:#FFFFFF;" d="M229,124c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V90c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V124z"/>
+ </g>
+ <g>
+ <linearGradient id="SVGID_28_" gradientUnits="userSpaceOnUse" x1="196.9995" y1="81" x2="196.9995" y2="135">
+ <stop offset="0" style="stop-color:#F2F2F2"/>
+ <stop offset="1" style="stop-color:#D2D3D3"/>
+ </linearGradient>
+ <path style="fill:url(#SVGID_28_);" d="M229,125c0,5.5-4.5,10-10,10h-44c-5.5,0-10-4.5-10-10V91c0-5.5,4.5-10,10-10h44
+ c5.5,0,10,4.5,10,10V125z"/>
+ </g>
+ </g>
+</g>
+</svg>
--- m-keyboard/theme/theme.pri
+++ m-keyboard/theme/theme.pri
@@ -1,9 +1,9 @@
-IMAGES_DATA = theme/*.svg
-images_data.path = /usr/share/meegotouch/virtual-keyboard/images
+IMAGES_DATA = theme/meegotouch-keyboard.svg
+images_data.path = /usr/share/themes/base/meegotouch/svg
images_data.files = $$IMAGES_DATA
-CSS_DATA = theme/*.css
-css_data.path = /usr/share/meegotouch/virtual-keyboard/css
+CSS_DATA = theme/libmeego-keyboard.css
+css_data.path = /usr/share/themes/base/meegotouch/libmeego-keyboard/style
css_data.files = $$CSS_DATA
INSTALLS += \
--- m-keyboard/widgets/flickgesture.cpp
+++ m-keyboard/widgets/flickgesture.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "flickgesture.h"
+
+FlickGesture::FlickGesture(QObject *parent)
+ : QGesture(parent)
+{
+}
+
+FlickGesture::~FlickGesture()
+{
+}
+
+QPointF FlickGesture::positionDifference() const
+{
+ return endStartDifference;
+}
+
+void FlickGesture::setPositionDifference(const QPointF &positionDifference)
+{
+ endStartDifference = positionDifference;
+}
+
+FlickGesture::Direction FlickGesture::direction() const
+{
+ return gestureDirection;
+}
+
+void FlickGesture::setDirection(const Direction newDirection)
+{
+ gestureDirection = newDirection;
+}
+
--- m-keyboard/widgets/flickgesture.h
+++ m-keyboard/widgets/flickgesture.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef FLICKGESTURE_H
+#define FLICKGESTURE_H
+
+#include <QGesture>
+#include <QPointF>
+
+/*!
+ \brief Meego keyboard flick gesture.
+
+ Flick gestures are simple swipe gestures, made with just one finger.
+*/
+class FlickGesture : public QGesture
+{
+ Q_OBJECT
+
+public:
+ //! Possible gesture directions
+ enum Direction {
+ Left,
+ Right,
+ Up,
+ Down
+ };
+
+ //! Constructor
+ FlickGesture(QObject *parent = 0);
+
+ //! Destructor
+ virtual ~FlickGesture();
+
+ //! \return difference between end and start points
+ QPointF positionDifference() const;
+
+ //! Set difference between end and start points
+ void setPositionDifference(const QPointF &positionDifference);
+
+ //! \return gesture direction as determined from the position difference by the
+ //! recognizer. Detailed x & y movement can be inspected via positionDifference().
+ Direction direction() const;
+
+ //! Set gesture direction
+ void setDirection(Direction newDirection);
+
+private:
+ //! Difference between end and start points
+ QPointF endStartDifference;
+
+ Direction gestureDirection;
+};
+
+#endif
--- m-keyboard/widgets/grip.cpp
+++ m-keyboard/widgets/grip.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "grip.h"
+#include "mvirtualkeyboardstyle.h"
+
+Grip::Grip(QGraphicsWidget *parent)
+ : Handle(parent)
+{
+ // TODO: decoration and spacers when we get the correct graphics
+}
+
+Grip::~Grip()
+{
+}
--- m-keyboard/widgets/grip.h
+++ m-keyboard/widgets/grip.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef GRIP_H
+#define GRIP_H
+
+#include "handle.h"
+
+class QGraphicsWidget;
+
+/*!
+ \brief Handle with a visual representation of a grip
+*/
+class Grip : public Handle
+{
+ Q_OBJECT
+
+public:
+ /*!
+ * \brief Constructor
+ * \param parent Parent object.
+ */
+ explicit Grip(QGraphicsWidget *parent = 0);
+
+ //! Destructor
+ virtual ~Grip();
+};
+
+#endif
--- m-keyboard/widgets/handle.cpp
+++ m-keyboard/widgets/handle.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "handle.h"
+#include <QGraphicsSceneMouseEvent>
+#include "flickgesture.h"
+
+#include <QDebug>
+#include <QGraphicsLinearLayout>
+
+Handle::Handle(QGraphicsWidget *parent)
+ : MStylableWidget(parent),
+ mainLayout(*new QGraphicsLinearLayout(Qt::Vertical, this))
+{
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
+ mainLayout.setContentsMargins(0, 0, 0, 0);
+}
+
+Handle::~Handle()
+{
+}
+
+bool Handle::event(QEvent *e)
+{
+ const QGraphicsSceneMouseEvent *ev(dynamic_cast<const QGraphicsSceneMouseEvent *>(e));
+
+ if (e->type() == QEvent::GraphicsSceneMousePress) {
+ e->setAccepted(true);
+ startPosition = ev->pos();
+ return true;
+ } else if (e->type() == QEvent::GraphicsSceneMouseRelease) {
+ e->setAccepted(true);
+
+ const qreal MovementTresholdX(20);
+ const qreal MovementTresholdY(20);
+ const QPointF diff(ev->pos() - startPosition);
+
+ FlickGesture gesture;
+ gesture.setPositionDifference(diff);
+
+ if ((abs(diff.x()) > MovementTresholdX)
+ && (abs(diff.x()) > abs(diff.y()))) {
+ gesture.setDirection(diff.x() > 0 ? FlickGesture::Right : FlickGesture::Left);
+ flickGestureEvent(gesture);
+ } else if ((abs(diff.y()) > MovementTresholdY)) {
+ gesture.setDirection(diff.y() > 0 ? FlickGesture::Down : FlickGesture::Up);
+ flickGestureEvent(gesture);
+ }
+
+ return true;
+ }
+ return MStylableWidget::event(e);
+}
+
+void Handle::setChild(QGraphicsLayoutItem *widget)
+{
+ if (mainLayout.itemAt(0)) {
+ mainLayout.removeAt(0);
+ }
+ mainLayout.insertItem(0, widget);
+}
+
+typedef void (Handle::*FlickEmitter)(const FlickGesture &gesture);
+
+void Handle::flickGestureEvent(FlickGesture &gesture)
+{
+ static const FlickEmitter emitters[4] = { &Handle::flickLeft, &Handle::flickRight,
+ &Handle::flickUp, &Handle::flickDown };
+ (this->*emitters[static_cast<int>(gesture.direction())])(gesture);
+}
--- m-keyboard/widgets/handle.h
+++ m-keyboard/widgets/handle.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef HANDLE_H
+#define HANDLE_H
+
+#include "handlestyle.h"
+#include <MStylableWidget>
+
+class QGraphicsLinearLayout;
+class FlickGesture;
+
+/*!
+ \brief Handle is a wrapper widget of zero or one child that reacts to flick gestures.
+
+ Handle doesn't have any non-default content except the child if one is set.
+*/
+class Handle : public MStylableWidget
+{
+ Q_OBJECT
+
+public:
+ /*!
+ * \brief Constructor
+ * \param parent Parent object.
+ */
+ explicit Handle(QGraphicsWidget *parent = 0);
+
+ //! Destructor
+ virtual ~Handle();
+
+ //! Set the one child object that Handle can contain.
+ void setChild(QGraphicsLayoutItem *widget);
+
+ //! \reimp
+ bool event(QEvent *e);
+ //! \reimp_end
+
+signals:
+ void flickUp(const FlickGesture &gesture);
+ void flickDown(const FlickGesture &gesture);
+ void flickLeft(const FlickGesture &gesture);
+ void flickRight(const FlickGesture &gesture);
+
+protected:
+ M_STYLABLE_WIDGET(HandleStyle)
+
+private:
+ void flickGestureEvent(FlickGesture &gesture);
+
+private:
+ QGraphicsLinearLayout &mainLayout;
+
+ QPointF startPosition; // TODO: temporary
+};
+
+#endif
--- m-keyboard/widgets/handlestyle.h
+++ m-keyboard/widgets/handlestyle.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef HANDLESTYLE_H
+#define HANDLESTYLE_H
+
+#include <MWidgetStyle>
+
+/*!
+ * \brief This defines style that is common to all Handle class based widgets.
+ */
+class M_EXPORT HandleStyle : public MWidgetStyle
+{
+ Q_OBJECT
+ M_STYLE(HandleStyle)
+};
+
+class M_EXPORT HandleStyleContainer : public MWidgetStyleContainer
+{
+ M_STYLE_CONTAINER(HandleStyle)
+
+ M_STYLE_MODE(Landscape)
+ M_STYLE_MODE(Portrait)
+
+ friend class Handle;
+};
+
+
+#endif
--- m-keyboard/widgets/horizontalswitcher.cpp
+++ m-keyboard/widgets/horizontalswitcher.cpp
@@ -52,7 +52,7 @@
slides.clear();
}
-void HorizontalSwitcher::switchTo(Direction direction)
+void HorizontalSwitcher::switchTo(SwitchDirection direction)
{
if (isRunning())
finishAnimation();
@@ -110,31 +110,7 @@
animTimeLine.start();
}
-void HorizontalSwitcher::switchTo(int index)
-{
- if (slides.count() > 1) {
- if (!isVisible()) {
- setCurrent(index);
- } else if (index == currentIndex - 1)
- switchTo(Left);
- else if (index == currentIndex + 1)
- switchTo(Right);
- else if (index != currentIndex) {
- // TODO: support animated switching over multiple slides?
- setCurrent(index);
- }
- } else {
- setCurrent(index);
- }
-}
-
-void HorizontalSwitcher::switchTo(QGraphicsWidget *widget)
-{
- Q_ASSERT(widget && slides.contains(widget));
- switchTo(slides.indexOf(widget));
-}
-
-bool HorizontalSwitcher::isAtBoundary(Direction direction) const
+bool HorizontalSwitcher::isAtBoundary(SwitchDirection direction) const
{
if (direction == Right) {
if (currentIndex == slides.count() - 1) {
@@ -157,21 +133,24 @@
void HorizontalSwitcher::setCurrent(int index)
{
- if (index >= 0 && index < slides.count() && index != currentIndex) {
+ if (isValidIndex(index) && index != currentIndex) {
int oldIndex = -1;
- QGraphicsWidget *old = NULL;
- if (currentIndex >= 0 && currentIndex < slides.count()) {
+ QGraphicsWidget *old = 0;
+
+ if (isValidIndex(currentIndex)) {
oldIndex = currentIndex;
old = slides.at(currentIndex);
}
+
currentIndex = index;
+
QGraphicsWidget *widget = slides.at(index);
widget->setPos(0, 0);
widget->resize(size());
widget->show();
- emit switchStarting(oldIndex, currentIndex);
- emit switchStarting(old, widget);
- emit switchDone(oldIndex, currentIndex);
+
+ // Ultimately might lead to a reaction map update in MKeyboardHost,
+ // has no other purpose:
emit switchDone(old, widget);
updateGeometry();
@@ -234,24 +213,10 @@
slides.append(widget);
widget->hide();
- }
-}
-void HorizontalSwitcher::removeWidget(QGraphicsWidget *widget)
-{
- if (widget && slides.contains(widget)) {
- if (widget->isVisible() && isRunning())
- finishAnimation();
-
- widget->setParentItem(0);
- if (widget->scene())
- widget->scene()->removeItem(widget);
- slides.removeOne(widget);
-
- if (!slides.isEmpty()) {
- if (--currentIndex < 0)
- currentIndex += slides.count();
- setCurrent(currentIndex);
+ // HS was empty before, this was the first widget added:
+ if (slides.size() == 1) {
+ setCurrent(0);
}
}
}
@@ -260,10 +225,14 @@
{
foreach(QGraphicsWidget * slide, slides) {
slide->setParentItem(0);
- if (slide->scene())
+
+ if (slide->scene()) {
slide->scene()->removeItem(slide);
+ }
}
+
slides.clear();
+ currentIndex = -1;
updateGeometry();
}
@@ -325,3 +294,8 @@
emit switchDone(oldIndex, currentIndex);
emit switchDone(old, slides.at(currentIndex));
}
+
+bool HorizontalSwitcher::isValidIndex(int index) const
+{
+ return (index >= 0 && index < slides.size());
+}
--- m-keyboard/widgets/horizontalswitcher.h
+++ m-keyboard/widgets/horizontalswitcher.h
@@ -28,11 +28,9 @@
Q_OBJECT
public:
- /*! SwitchDirection tells which direction we want to
- * move the "camera", that is, the contents will
- * slide in opposite direction.
- */
- enum Direction {
+ //! SwitchDirection tells which neighbour should be shown next.
+ //! \sa switchTo()
+ enum SwitchDirection {
Left, Right
};
@@ -44,21 +42,14 @@
//! Does nothing if less than two widgets added.
//! Does not loop by default if end reached. You can use setLooping()
//! method to change this behaviour.
- void switchTo(Direction direction);
-
- //! \brief Slide from current widget to one with given index.
- void switchTo(int index);
-
- //! \brief Slide from current widget to the given widget.
- //! Widget must exist in the switcher.
- void switchTo(QGraphicsWidget *widget);
+ void switchTo(SwitchDirection direction);
/*!
* \brief Returns true if it is not possible to switch to the next
* widget of current with given direction without looping.
* \param direction Direction of switching
*/
- bool isAtBoundary(Direction direction) const;
+ bool isAtBoundary(SwitchDirection direction) const;
//! \brief Show given widget without animation.
//! The widget must be already added.
@@ -92,15 +83,18 @@
//! \brief Add widget to switcher. Takes ownership.
//!
//! Indices for widgets are added in the order they were added.
+ //! If the container was empty (index at -1), then addWidget updates the
+ //! current index to point to widget and shows it.
void addWidget(QGraphicsWidget *widget);
- //! \brief Remove widget from switcher. Ownership changed to caller.
- void removeWidget(QGraphicsWidget *widget);
-
//! \brief Remove all widgets. Ownership changed to caller.
+ //!
+ //! Sets current index to -1.
void removeAll();
- /// \brief Deletes all widgets
+ //! \brief Deletes all widgets
+ //!
+ //! Sets current index to -1.
void deleteAll();
signals:
@@ -133,6 +127,8 @@
void finishAnimation();
private:
+ bool isValidIndex(int index) const;
+
int currentIndex;
QList<QGraphicsWidget *> slides;
QGraphicsItemAnimation enterAnim;
--- m-keyboard/widgets/keybuttonarea.cpp
+++ m-keyboard/widgets/keybuttonarea.cpp
@@ -25,6 +25,8 @@
#include <MApplication>
#include <MComponentData>
#include <MFeedbackPlayer>
+#include <MSceneManager>
+#include <MGConfItem>
#include <QDebug>
#include <QEvent>
#include <QGraphicsLinearLayout>
@@ -35,45 +37,49 @@
namespace
{
- const int FlickTime = 150;
- const int LongPressTime = 1000;
-
- const int FlickDownThreshold = 50;
- const int FlickUpThreshold = 50;
- const int FlickLeftRightVerticalThreshold = 50;
- const int FlickLeftRightHorizontalThreshold = 50;
+ const int GestureTimeOut = 1000;
+ const int LongPressTime = 0;
+ const qreal ZValueButtons = 0.0;
// Minimal distinguishable cursor/finger movement
const qreal MovementThreshold = 5.0;
- const qreal ZValueButtons = 0.0;
-};
+ // For gesture thresholds: How many pixels translate to one counted move event.
+ const qreal PixelsToMoveEventsFactor = 0.02;
+
+ // This GConf item defines whether multitouch is enabled or disabled
+ const char * const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
+}
+
+int KeyButtonArea::swipeGestureTouchPoints = 1;
+
+M::InputMethodMode KeyButtonArea::InputMethodMode;
-KeyButtonArea::KeyButtonArea(MVirtualKeyboardStyleContainer *style,
+KeyButtonArea::KeyButtonArea(const MVirtualKeyboardStyleContainer *style,
QSharedPointer<const LayoutSection> sectionModel,
ButtonSizeScheme buttonSizeScheme,
bool usePopup,
QGraphicsWidget *parent)
: MWidget(parent),
- shiftButton(0),
currentLevel(0),
popup(PopupFactory::instance()->createPopup(*style, this)),
styleContainer(style),
- flickTimer(new LimitedTimer(this)),
+ newestTouchPointId(-1),
longPressTimer(new LimitedTimer(this)),
accurateMode(false),
- flicked(false),
+ wasGestureTriggered(false),
+ enableMultiTouch(MGConfItem(MultitouchSettings).value().toBool()),
activeDeadkey(0),
- activeKey(0),
- flickedKey(0),
feedbackPlayer(0),
section(sectionModel),
buttonSizeScheme(buttonSizeScheme),
- usePopup(usePopup)
+ usePopup(usePopup),
+ swipeGestureCount(0)
{
- flickTimer->setSingleShot(true);
- flickTimer->setInterval(FlickTime);
- connect(flickTimer, SIGNAL(timeout()), this, SLOT(flickCheck()));
+ // By default multi-touch is disabled
+ if (enableMultiTouch) {
+ setAcceptTouchEvents(true);
+ }
longPressTimer->setSingleShot(true);
longPressTimer->setInterval(LongPressTime);
@@ -83,15 +89,23 @@
popup->hidePopup();
feedbackPlayer = MComponentData::feedbackPlayer();
+
+ connect(MTheme::instance(), SIGNAL(themeChangeCompleted()),
+ this, SLOT(onThemeChangeCompleted()),
+ Qt::UniqueConnection);
}
KeyButtonArea::~KeyButtonArea()
{
- delete flickTimer;
delete longPressTimer;
delete popup;
}
+void KeyButtonArea::setInputMethodMode(M::InputMethodMode inputMethodMode)
+{
+ InputMethodMode = inputMethodMode;
+}
+
void KeyButtonArea::buttonInformation(int row, int column, const VKBDataKey *&dataKey, QSize &size, bool &stretchesHorizontally)
{
// We share the same button instance with different key bindings.
@@ -123,7 +137,7 @@
ISymIndicator *KeyButtonArea::symIndicator()
{
- return 0;
+ return 0;
}
void KeyButtonArea::updatePopup(const QPoint &pointerPosition, const IKeyButton *key)
@@ -167,22 +181,31 @@
void
KeyButtonArea::onHide()
{
+ clearActiveKeys();
unlockDeadkeys();
}
void
-KeyButtonArea::switchLevel(int level, bool capslock)
+KeyButtonArea::switchLevel(int level)
{
- currentLevel = level;
+ if (level != currentLevel) {
+ currentLevel = level;
+
+ // Update uppercase / lowercase
+ updateButtonModifiers();
- if (shiftButton) {
- shiftButton->setSelected(capslock);
+ update();
}
+}
- // Update uppercase / lowercase
- updateButtonModifiers();
+int KeyButtonArea::level() const
+{
+ return currentLevel;
+}
- update();
+void KeyButtonArea::setShiftStatus(bool /*shiftOn*/, bool /*capslock*/)
+{
+ // Empty default implementation
}
bool
@@ -193,255 +216,308 @@
return movement >= MovementThreshold;
}
-KeyEvent KeyButtonArea::keyToKeyEvent(const IKeyButton &key, QKeyEvent::Type eventType) const
+void KeyButtonArea::resizeEvent(QGraphicsSceneResizeEvent *event)
{
- Qt::KeyboardModifiers modifiers = (currentLevel == 1) ? Qt::ShiftModifier : Qt::NoModifier;
- KeyEvent event;
+ const int newWidth = static_cast<int>(event->newSize().width());
- if (activeDeadkey != NULL) {
- event = key.key().toKeyEvent(eventType, activeDeadkey->label().at(0), modifiers);
- } else {
- event = key.key().toKeyEvent(eventType, modifiers);
+ if (newWidth != static_cast<int>(event->oldSize().width())) {
+ updateButtonGeometriesForWidth(newWidth);
}
+}
- return event;
+void
+KeyButtonArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (!enableMultiTouch) {
+ // Qt always assigns zero to the first touch point, so pass id = 0.
+ touchPointPressed(event->pos().toPoint(), 0);
+ }
}
-void KeyButtonArea::resizeEvent(QGraphicsSceneResizeEvent *event)
+
+void
+KeyButtonArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- const int newWidth = static_cast<int>(event->newSize().width());
- if (newWidth != static_cast<int>(event->oldSize().width())) {
- // All main keyboards should take the whole available width so we restrict
- // the button width here. This is applied only if we have equal button width.
- int equalButtonWidth = -1; // the new width if it's same for all
- if ((buttonSizeScheme == ButtonSizeEqualExpanding)
- || (buttonSizeScheme == ButtonSizeEqualExpandingPhoneNumber)) {
- const int HorizontalSpacing = style()->spacingHorizontal();
- const int MaxButtonWidth = qRound(static_cast<qreal>(newWidth + HorizontalSpacing)
- / static_cast<qreal>(section->maxColumns())
- - HorizontalSpacing);
+ if (scene()->mouseGrabberItem() == this) {
+ // Ungrab mouse explicitly since we probably used grabMouse() to get it.
+ ungrabMouse();
+ }
- equalButtonWidth = MaxButtonWidth;
- }
- updateButtonGeometries(newWidth, equalButtonWidth);
+ if (!enableMultiTouch) {
+ touchPointReleased(event->pos().toPoint(), 0);
}
}
-void
-KeyButtonArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
+
+void KeyButtonArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
- pointerPos = event->pos().toPoint();
+ if (!enableMultiTouch) {
+ touchPointMoved(event->pos().toPoint(), 0);
+ }
+}
- IKeyButton *key = keyAt(pointerPos);
+void KeyButtonArea::setActiveKey(IKeyButton *key, TouchPointInfo &tpi)
+{
+ // Selected buttons are currently skipped.
+ QString accent;
- if (!key) {
- event->ignore();
- return;
+ if (activeDeadkey) {
+ accent = activeDeadkey->label();
}
- mTimestamp("KeyButtonArea", key->label());
+ if (tpi.activeKey && (tpi.activeKey != key)) {
+ // Release key
+ tpi.activeKey->setDownState(false);
+ // odd level numbers are upper case,
+ // even level numbers are lower case
+ emit keyReleased(tpi.activeKey, accent, level() % 2);
+ tpi.activeKey = 0;
+ }
- fingerInsideArea = true;
+ if (key && (tpi.activeKey != key)) {
+ // Press key
+ tpi.activeKey = key;
+ tpi.activeKey->setDownState(true);
+ emit keyPressed(tpi.activeKey, accent, level() % 2);
+ }
+}
- longPressTimer->start();
+void KeyButtonArea::clearActiveKeys()
+{
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ setActiveKey(0, touchPoints[i]);
+ }
+}
+
+void KeyButtonArea::click(IKeyButton *key)
+{
+ if (!key->isDeadKey()) {
+ QString accent;
+
+ if (activeDeadkey) {
+ accent = activeDeadkey->label();
+ }
- // Stop accurate mode if pressed key makes accurate mode irrelevant
- if (accurateMode)
+ // Check if we need to disable accurate mode
accurateCheckContent(key->label());
- // Check if accurate mode is still on.
- if (accurateMode) {
- // Show popup in accurate mode.
- if (usePopup) {
- updatePopup(pointerPos, key);
+ unlockDeadkeys();
+
+ emit keyClicked(key, accent, level() % 2);
+ } else if (key == activeDeadkey) {
+ unlockDeadkeys();
+ } else {
+ // Deselect previous dead key, if any
+ if (activeDeadkey) {
+ activeDeadkey->setSelected(false);
}
- }
- if (flickTimer->isActive()) {
- flickTimer->stop();
- }
+ activeDeadkey = key;
+ activeDeadkey->setSelected(true);
- flicked = false;
- flickStartPos = pointerPos;
- flickedKey = key;
- flickTimer->start();
+ updateButtonModifiers();
+ }
+}
- setActiveKey(key);
+QVariant KeyButtonArea::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ if (change == QGraphicsItem::ItemVisibleChange && !value.toBool()) {
+ onHide();
+ }
+ return QGraphicsItem::itemChange(change, value);
}
+void KeyButtonArea::grabMouseEvent(QEvent */*event*/)
+{
+ // If keybuttonarea is hidden without mouseReleaseEvent
+ // the enabled <flicked> would stay true if mouse
+ // grab is obtained again without mousePressEvent.
+ // This would ignore mouseReleaseEvent and would not cause keyClicked.
+ wasGestureTriggered = false;
+}
-void
-KeyButtonArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+void KeyButtonArea::ungrabMouseEvent(QEvent */*event*/)
{
- bool flickTimerActive = flickTimer->isActive();
+ // longPressTimer is running if flicked without releasing
+ // (or releasing after this keybuttonarea is hidden)
longPressTimer->stop();
- flickTimer->stop();
- fingerInsideArea = false;
- popup->hidePopup();
- pointerPos = event->pos().toPoint();
+ // Make sure popup is hidden even if mouse grab
+ // is lost without mouse release event.
+ popup->hidePopup();
+}
- IKeyButton *key = keyAt(pointerPos);
+bool KeyButtonArea::sceneEvent(QEvent *event)
+{
+ if (event->type() == QEvent::TouchBegin
+ || event->type() == QEvent::TouchUpdate
+ || event->type() == QEvent::TouchEnd) {
+ QTouchEvent *touch = static_cast<QTouchEvent*>(event);
+
+ if (event->type() == QEvent::TouchBegin) {
+ touchPoints.clear();
+ }
+
+ foreach (const QTouchEvent::TouchPoint &tp, touch->touchPoints()) {
+
+ switch (tp.state()) {
+ case Qt::TouchPointPressed:
+ touchPointPressed(tp.pos().toPoint(), tp.id());
+ break;
+ case Qt::TouchPointMoved:
+ touchPointMoved(tp.pos().toPoint(), tp.id());
+ break;
+ case Qt::TouchPointReleased:
+ touchPointReleased(tp.pos().toPoint(), tp.id());
+ break;
+ default:
+ break;
+ }
+ }
- if (key) {
- mTimestamp("KeyButtonArea", key->label());
+ return true;
}
- // It's presumably possible that we're getting this release event on top
- // of another after press event (of another key) without first getting a
- // move event (or at least such move event that we handle). Which means
- // that we must send release event for the previous key and press event
- // for this key before sending release and clicked events for this key.
- if (key && (key != activeKey)) {
- setActiveKey(key);
- }
+ return MWidget::sceneEvent(event);
+}
- if (scene()->mouseGrabberItem() == this) {
- // Ungrab mouse explicitly since we probably used grabMouse() to get it.
- // Ungrab event handler will clear active key.
- ungrabMouse();
- } else {
- setActiveKey(0);
- }
+void KeyButtonArea::touchPointPressed(const QPoint &pos, int id)
+{
+ newestTouchPointId = id;
+
+ // Create new TouchPointInfo structure and overwrite any previous one.
+ touchPoints[id] = TouchPointInfo();
+ TouchPointInfo &tpi = touchPoints[id];
+ tpi.pos = pos;
+ tpi.initialPos = pos;
+
+ // Reset gesture checks.
+ wasGestureTriggered = false;
+
+ // Reset long-press check.
+ longPressTimer->start();
- // Check if keyboard was flicked or
- // release happens fast and far enough from the start
- if (flicked || (flickTimerActive && flickCheck() == true)) {
+ IKeyButton *key = keyAt(pos);
+ if (!key) {
return;
}
- // Handle click
- if (key) {
- if (!key->isDeadKey()) {
- KeyEvent clickEvent = keyToKeyEvent(*key, QEvent::KeyRelease);
+ mTimestamp("KeyButtonArea", key->label());
- unlockDeadkeys();
+ tpi.initialKey = key;
+ tpi.fingerInsideArea = true;
- // Check if we need to disable accurate mode
- accurateCheckContent(key->label());
+ swipeGestureCount = 0;
- emit keyClicked(clickEvent);
- } else {
- clickAtDeadkey(key);
- update();
+ if (accurateMode) {
+ // Stop accurate mode if pressed key makes accurate mode irrelevant
+ accurateCheckContent(key->label());
+
+ // Check if accurate mode is still on.
+ // Show popup in accurate mode.
+ if (accurateMode && usePopup && (id == newestTouchPointId)) {
+ updatePopup(pos, key);
}
}
-}
+ setActiveKey(key, tpi);
+}
-void KeyButtonArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+void KeyButtonArea::touchPointMoved(const QPoint &pos, int id)
{
- if (!isObservableMove(pointerPos, event->pos()))
+ TouchPointInfo &tpi = touchPoints[id];
+
+ if (!isObservableMove(tpi.pos, pos))
return;
- pointerPos = event->pos().toPoint();
+ tpi.pos = pos;
+ ++tpi.moveEventCount;
- // Check if finger is on a key.
- IKeyButton *key = keyAt(pointerPos);
- if (!key) {
-
- // Finger has slid off the keys
- if (fingerInsideArea) {
- if (accurateMode && feedbackPlayer)
- feedbackPlayer->play(MFeedbackPlayer::Cancel);
+ if (isSwipeGesture(tpi)) {
+ return;
+ }
- popup->hidePopup();
+ // Check if finger is on a key.
+ IKeyButton *key = keyAt(pos);
+ if (key) {
+ tpi.fingerInsideArea = true;
- // Don't show button as pressed, and send release event.
- setActiveKey(0);
+ if ((tpi.activeKey != key) && accurateMode && feedbackPlayer) {
+ // Finger has slid from a key to an adjacent one.
+ feedbackPlayer->play(MFeedbackPlayer::Press);
}
- fingerInsideArea = false;
- longPressTimer->stop();
- } else {
- fingerInsideArea = true;
-
// If popup is visible, always update the position,
// even if accurate mode is not enabled. This is for
// Sym view, who doesn't care about accurate mode.
- if (usePopup && (accurateMode || popup->isPopupVisible())) {
- updatePopup(pointerPos, key);
+ if (usePopup
+ && (id == newestTouchPointId)
+ && (accurateMode || popup->isPopupVisible())) {
+ updatePopup(pos, key);
}
- if (activeKey != key) {
- setActiveKey(key);
-
- if (accurateMode && feedbackPlayer) {
- // Finger has slid from a key to an adjacent one.
- feedbackPlayer->play(MFeedbackPlayer::Press);
- }
-
+ if (tpi.activeKey != key) {
// Use has to keep finger still to generate long press.
// isObservableMove() makes this task easier for the user.
if (longPressTimer->isActive())
longPressTimer->start();
}
- } // inside area
-}
-
-void KeyButtonArea::setActiveKey(IKeyButton *key)
-{
- // Selected buttons are currently skipped.
+ } else {
+ if (tpi.fingerInsideArea && accurateMode && feedbackPlayer) {
+ feedbackPlayer->play(MFeedbackPlayer::Cancel);
+ }
+ // Finger has slid off the keys
+ if (tpi.fingerInsideArea && (id == newestTouchPointId)) {
+ popup->hidePopup();
+ }
- if (activeKey && (activeKey != key)) {
- // Release key
- activeKey->setDownState(false);
- KeyEvent releaseEvent = keyToKeyEvent(*activeKey, QEvent::KeyRelease);
- emit keyReleased(releaseEvent);
- activeKey = 0;
+ longPressTimer->stop();
+ tpi.fingerInsideArea = false;
}
- if (key && (activeKey != key)) {
- // Press key
- activeKey = key;
- activeKey->setDownState(true);
- KeyEvent pressEvent = keyToKeyEvent(*activeKey, QEvent::KeyPress);
- emit keyPressed(pressEvent);
- }
+ setActiveKey(key, tpi);
}
-QVariant KeyButtonArea::itemChange(GraphicsItemChange change, const QVariant &value)
+void KeyButtonArea::touchPointReleased(const QPoint &pos, int id)
{
- if (change == QGraphicsItem::ItemVisibleChange && !value.toBool()) {
- onHide();
- }
- return QGraphicsItem::itemChange(change, value);
-}
+ TouchPointInfo &tpi = touchPoints[id];
-void KeyButtonArea::grabMouseEvent(QEvent */*event*/)
-{
- // If keybuttonarea is hidden without mouseReleaseEvent
- // the enabled <flicked> would stay true if mouse
- // grab is obtained again without mousePressEvent.
- // This would ignore mouseReleaseEvent and would not cause keyClicked.
- flicked = false;
-}
+ tpi.fingerInsideArea = false;
-void KeyButtonArea::ungrabMouseEvent(QEvent */*event*/)
-{
- // longPressTimer is running if flicked without releasing
- // (or releasing after this keybuttonarea is hidden)
+ // No more long-press triggerings, although would still be possible to make
+ // with another touch point.
longPressTimer->stop();
- // Make sure popup is hidden even if mouse grab
- // is lost without mouse release event.
- popup->hidePopup();
+ // Same thing here, hide popup although otherwise could be shown on
+ // another touch point.
+ if (id == newestTouchPointId) {
+ popup->hidePopup();
+ }
- // Release any key we have currently active
- setActiveKey(0);
-}
+ IKeyButton *key = keyAt(pos);
-void
-KeyButtonArea::clickAtDeadkey(const IKeyButton *deadKey)
-{
- Q_ASSERT(deadKey);
+ if (key) {
+ mTimestamp("KeyButtonArea", key->label());
- if (deadKey == activeDeadkey) {
- unlockDeadkeys();
+ // It's presumably possible that we're getting this release event on top
+ // of another after press event (of another key) without first getting a
+ // move event (or at least such move event that we handle). Which means
+ // that we must send release event for the previous key and press event
+ // for this key before sending release and clicked events for this key.
+ setActiveKey(key, tpi); // in most cases, does nothing
+ setActiveKey(0, tpi); // release key
+
+ // Check if keyboard was swiped or
+ // release happens fast and far enough from the start.
+ // If so, then skip click.
+ // Altough we associate flick gesture with the newest touch point
+ // it can still mistrigger because sometimes, when clicked nearly
+ // simultaneously, we receive a single move between two pressed points.
+ if (id != newestTouchPointId || !wasGestureTriggered) {
+ click(key);
+ }
} else {
- activeDeadkey = deadKey;
-
- updateButtonModifiers();
+ setActiveKey(0, tpi);
}
}
@@ -449,6 +525,7 @@
KeyButtonArea::unlockDeadkeys()
{
if (activeDeadkey) {
+ activeDeadkey->setSelected(false);
activeDeadkey = 0;
updateButtonModifiers();
}
@@ -456,8 +533,8 @@
void KeyButtonArea::popupStart()
{
- if (usePopup) {
- updatePopup(pointerPos);
+ if (usePopup && touchPoints.contains(newestTouchPointId)) {
+ updatePopup(touchPoints[newestTouchPointId].pos);
}
}
@@ -511,45 +588,89 @@
}
bool
-KeyButtonArea::flickCheck()
+KeyButtonArea::isSwipeGesture(const TouchPointInfo &tpi)
{
- if (flicked)
+ if ((InputMethodMode == M::InputMethodModeDirect) || wasGestureTriggered
+ || tpi.gestureTimer.elapsed() > GestureTimeOut) {
return false;
+ }
+
+ const QPointF deltaPos = tpi.initialPos - tpi.pos;
+ const qreal ScalingFactor = .5;
+ int HorizontalThreshold = static_cast<int>(boundingRect().width() * ScalingFactor);
+ int VerticalThreshold = static_cast<int>(boundingRect().height() * ScalingFactor);
+
+ bool result = isHorizontalSwipeGesture(deltaPos, HorizontalThreshold, VerticalThreshold,
+ tpi.moveEventCount);
+ if (!result) {
+ result = isVerticalSwipeGesture(deltaPos, HorizontalThreshold, VerticalThreshold,
+ tpi.moveEventCount, tpi.initialKey);
+ }
- bool res = false;
- QPointF diff = flickStartPos - pointerPos;
+ if (result) {
+ popup->hidePopup();
+ wasGestureTriggered = true;
+ swipeGestureCount = 0;
+ }
+
+ return result;
+}
- if (diff.y() > -FlickLeftRightVerticalThreshold &&
- diff.y() < FlickLeftRightVerticalThreshold) {
- if (diff.x() > FlickLeftRightHorizontalThreshold) {
- res = true;
- emit flickLeft();
- } else if (diff.x() < -FlickLeftRightHorizontalThreshold) {
- res = true;
- emit flickRight();
- }
- } else if (diff.x() > - FlickDownThreshold && diff.x() < FlickDownThreshold) {
- if (diff.y() < - FlickDownThreshold) {
- res = true;
- emit flickDown();
- } else if (diff.y() > FlickUpThreshold) {
- const KeyBinding *binding = 0;
- res = true;
- if (flickedKey) {
- binding = &flickedKey->binding();
- flickedKey = 0;
+bool KeyButtonArea::isHorizontalSwipeGesture(const QPointF &delta, int absHorizontalThreshold,
+ int absVerticalThreshold, int moveEventCount)
+{
+ const int requiredEventCount = qMax(2, static_cast<int>(absHorizontalThreshold *
+ PixelsToMoveEventsFactor));
+ bool result = false;
+
+ if ((qAbs(delta.y()) < absVerticalThreshold) &&
+ (moveEventCount >= requiredEventCount)) {
+ if (delta.x() > absHorizontalThreshold) {
+ if (++swipeGestureCount >= swipeGestureTouchPoints) {
+ result = true;
+ emit flickLeft();
+ }
+ } else if (delta.x() < -absHorizontalThreshold) {
+ if (++swipeGestureCount >= swipeGestureTouchPoints) {
+ result = true;
+ emit flickRight();
}
- emit flickUp(binding);
}
}
- if (res) {
- popup->hidePopup();
- flicked = true;
+ return result;
+}
+
+bool KeyButtonArea::isVerticalSwipeGesture(const QPointF &delta, int absHorizontalThreshold,
+ int absVerticalThreshold, int moveEventCount,
+ const IKeyButton* button)
+{
+ const int requiredEventCount = qMax(2, static_cast<int>(absVerticalThreshold *
+ PixelsToMoveEventsFactor));
+ bool result = false;
+
+ if ((qAbs(delta.x()) < absHorizontalThreshold) &&
+ (moveEventCount >= requiredEventCount)) {
+ if (delta.y() < -absVerticalThreshold) {
+ if (++swipeGestureCount >= swipeGestureTouchPoints) {
+ result = true;
+ emit flickDown();
+ }
+ } else if (delta.y() > absVerticalThreshold) {
+ if (++swipeGestureCount >= swipeGestureTouchPoints) {
+ // TODO: Replace flickUp gesture will be replaced by longpress anyway.
+ if (button) {
+ result = true;
+ emit flickUp(button->binding());
+ }
+ }
+ }
}
- return res;
+
+ return result;
}
+
const MVirtualKeyboardStyleContainer &KeyButtonArea::style() const
{
return *styleContainer;
@@ -607,3 +728,37 @@
{
// Empty default implementation
}
+
+void KeyButtonArea::onThemeChangeCompleted()
+{
+ updateButtonGeometriesForWidth(size().width());
+}
+
+void KeyButtonArea::updateButtonGeometriesForWidth(int widthOfArea)
+{
+ // All main keyboards should take the whole available width so we restrict
+ // the button width here. This is applied only if we have equal button width.
+ int equalButtonWidth = -1; // the new width if it's same for all
+ if ((buttonSizeScheme == ButtonSizeEqualExpanding)
+ || (buttonSizeScheme == ButtonSizeEqualExpandingPhoneNumber)) {
+ const int HorizontalSpacing = style()->spacingHorizontal();
+ const int MaxButtonWidth = qRound(static_cast<qreal>(widthOfArea + HorizontalSpacing)
+ / static_cast<qreal>(section->maxColumns())
+ - HorizontalSpacing);
+
+ equalButtonWidth = MaxButtonWidth;
+ }
+ updateButtonGeometries(widthOfArea, equalButtonWidth);
+}
+
+KeyButtonArea::TouchPointInfo::TouchPointInfo()
+ : fingerInsideArea(false),
+ activeKey(0),
+ initialKey(0),
+ initialPos(),
+ pos(),
+ gestureTimer(),
+ moveEventCount(0)
+{
+ gestureTimer.start();
+}
--- m-keyboard/widgets/keybuttonarea.h
+++ m-keyboard/widgets/keybuttonarea.h
@@ -29,6 +29,8 @@
#include <QHash>
#include <QList>
#include <QStringList>
+#include <QTouchEvent>
+#include <QTime>
class MFeedbackPlayer;
class MReactionMap;
@@ -73,7 +75,7 @@
* \param usePopup Sets whether popup should be used when long press occurs.
* \param parent The widget's parent.
*/
- KeyButtonArea(MVirtualKeyboardStyleContainer *,
+ KeyButtonArea(const MVirtualKeyboardStyleContainer *,
QSharedPointer<const LayoutSection> section,
ButtonSizeScheme buttonSizeScheme = ButtonSizeEqualExpanding,
bool usePopup = false,
@@ -104,11 +106,19 @@
//! Allows sym indicator to be controlled from outside.
virtual ISymIndicator *symIndicator();
+ //! Returns current level of this layout.
+ int level() const;
+
+ //! Set input method mode for all KeyButtonArea instances
+ static void setInputMethodMode(M::InputMethodMode inputMethodMode);
+
public slots:
/*!
* This slot is used to switch levels
*/
- void switchLevel(int level, bool capslock);
+ void switchLevel(int level);
+
+ virtual void setShiftStatus(bool shiftOn, bool capslock);
/*!
* \brief Shows popup
@@ -120,11 +130,6 @@
*/
void accurateStart();
- /*!
- * \brief Return true if the keyboard is flicked to left/right/down
- */
- bool flickCheck();
-
virtual void drawReactiveAreas(MReactionMap *reactionMap, QGraphicsView *view);
/*!
@@ -144,24 +149,30 @@
* \brief Emitted when key is pressed
* Note that this happens also when user keeps finger down/mouse
* button pressed and moves over another key (event is about the new key)
- * \param event key event
+ * \param key describes pressed button
+ * \param accent label of pressed dead key if any
+ * \param upperCase contains true if key is in uppercase state
*/
- void keyPressed(const KeyEvent &event);
+ void keyPressed(const IKeyButton *key, const QString &accent, bool upperCase);
/*!
* \brief Emitted when key is released
* Note that this happens also when user keeps finger down/mouse
* button pressed and moves over another key (event is about the old key)
- * \param event key event
+ * \param key describes released button
+ * \param accent label of pressed dead key if any
+ * \param upperCase contains true if key is in uppercase state
*/
- void keyReleased(const KeyEvent &event);
+ void keyReleased(const IKeyButton *key, const QString &accent, bool upperCase);
/*!
* \brief Emitted when user releases mouse button/lifts finger
* Except when done on a dead key
- * \param event key event
+ * \param key describes clicked button
+ * \param accent label of pressed dead key if any
+ * \param upperCase contains true if key is in uppercase state
*/
- void keyClicked(const KeyEvent &event);
+ void keyClicked(const IKeyButton *key, const QString &accent, bool upperCase);
//! Emitted when flicked right
void flickRight();
@@ -176,9 +187,36 @@
* \brief Emitted when flicked up
* \param binding Information about the key where mouse button was pressed
*/
- void flickUp(const KeyBinding *binding);
+ void flickUp(const KeyBinding &binding);
protected:
+ //! Stores touch point specific information.
+ struct TouchPointInfo {
+ TouchPointInfo();
+
+ //! True if finger is held down and is inside the layout's area.
+ bool fingerInsideArea;
+
+ //! Currently held down key
+ IKeyButton *activeKey;
+
+ //! Key that this touch point was first pressed on, if any.
+ const IKeyButton *initialKey;
+
+ //! Initial position of the touch point when it was first pressed.
+ QPoint initialPos;
+
+ //! Last known position of the touch point
+ QPoint pos;
+
+ //! Used to check whether gesture recognition happens within the
+ //! specified time frame.
+ QTime gestureTimer;
+
+ //! Counts move events between press & release
+ int moveEventCount;
+ };
+
//! \brief Returns data and size information of a button in given \a row and \a column.
void buttonInformation(int row, int column,
const VKBDataKey *&dataKey,
@@ -193,6 +231,7 @@
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
virtual void grabMouseEvent(QEvent *e);
virtual void ungrabMouseEvent(QEvent *e);
+ virtual bool sceneEvent(QEvent *event);
/*! \reimp_end */
//! Called when widget is about to lose visibility.
@@ -203,12 +242,6 @@
void updatePopup(const QPoint &pos, const IKeyButton *key = 0);
/*!
- * \brief click at deadKey
- * \param key pointer to deadkey
- */
- void clickAtDeadkey(const IKeyButton *key);
-
- /*!
* \brief Verifies should we process cursor movement or not
* \param pos QPointF new cursor position
* \return bool
@@ -216,6 +249,14 @@
bool isObservableMove(const QPointF &prevPos, const QPointF &pos);
/*!
+ * \brief Return true if the keyboard is swiped to the left/right/down/up
+ *
+ * Once a gesture is recognized it will return false unless the next
+ * touchpoint is pressed. This is supposed to prevent conflicting gestures.
+ */
+ bool isSwipeGesture(const TouchPointInfo &tpi);
+
+ /*!
* \brief Get level count of the virtual keyboard.
* \return int. The level count.
*/
@@ -253,18 +294,45 @@
const PopupBase &popupWidget() const;
//! Sets button state and sends release & press events.
- void setActiveKey(IKeyButton *key);
+ void setActiveKey(IKeyButton *key, TouchPointInfo &tpi);
- //! Derived classes must set this if they have shift button and want it be locked.
- IKeyButton *shiftButton;
+ void clearActiveKeys();
-private:
- //! Turn key button into a KeyEvent, considering current dead key and modifier state
- KeyEvent keyToKeyEvent(const IKeyButton &key, QKeyEvent::Type eventType) const;
+protected slots:
+ //! Update background images, text layouts, etc. when the theme changed.
+ virtual void onThemeChangeCompleted();
+private:
//! Check whether given character will stop accurate mode.
void accurateCheckContent(const QString &content);
+ //! \brief Touch point press handler.
+ //! \param id Touch point identifier defined by the system.
+ void touchPointPressed(const QPoint &pos, int id);
+
+ //! \brief Touch point move handler.
+ //! \param id Touch point identifier defined by the system.
+ void touchPointMoved(const QPoint &pos, int id);
+
+ //! \brief Touch point release handler.
+ //! \param id Touch point identifier defined by the system.
+ void touchPointReleased(const QPoint &pos, int id);
+
+ void click(IKeyButton *key);
+
+ //! \brief Horizontal swipe gesture recognizer
+ //! \return Whether a horizontal swipe gesture was recognized
+ bool isHorizontalSwipeGesture(const QPointF &delta, int absHorizontalThreshold, int absVerticalThreshold,
+ int moveEventCount);
+
+ //! \brief Vertical swipe gesture recognizer
+ //! \return Whether a vertical swipe gesture was recognized
+ bool isVerticalSwipeGesture(const QPointF &delta, int absHorizontalThreshold, int absVerticalThreshold,
+ int moveEventCount, const IKeyButton* button);
+
+ //! \brief Computes the new button width and updates their geometries
+ void updateButtonGeometriesForWidth(int widthOfArea);
+
//! Current level
int currentLevel;
@@ -272,19 +340,10 @@
PopupBase *popup;
//! style
- MVirtualKeyboardStyleContainer *styleContainer;
+ const MVirtualKeyboardStyleContainer *styleContainer;
- //! Flicktimer
- LimitedTimer *flickTimer;
-
- //! Floating point flickStart position
- QPointF flickStartPos;
-
- //! Current pointer position
- QPoint pointerPos;
-
- //! True if finger is held down and is inside the layout's area.
- bool fingerInsideArea;
+ //! Touch point id of the most recent press event.
+ int newestTouchPointId;
//! Timer to detect long mouse press.
LimitedTimer *longPressTimer;
@@ -298,17 +357,16 @@
//! List of accent labels
QList<QStringList> accentLabels;
- //! Contains true if keyboard was flicked after last mouse press
- bool flicked;
+ //! Whether a gesture was already triggered for any active touch point.
+ bool wasGestureTriggered;
- //! Activated dead key
- const IKeyButton *activeDeadkey;
+ //! Keys are QTouchEvent::TouchPoint id
+ QMap<int, TouchPointInfo> touchPoints;
- //! Currently held down key
- IKeyButton *activeKey;
+ bool enableMultiTouch;
- //! Key that was pressed when flick gesture began.
- const IKeyButton *flickedKey;
+ //! Activated dead key
+ IKeyButton *activeDeadkey;
/*!
* Feedback player instance
@@ -322,6 +380,14 @@
const bool usePopup;
+ //! How many separate swipe gestures (one for each touchpoint) have been recognized.
+ int swipeGestureCount;
+
+ //! Controls the amount of touchpoints required by a gesture.
+ static int swipeGestureTouchPoints;
+
+ static M::InputMethodMode InputMethodMode;
+
#ifdef UNIT_TEST
friend class MReactionMapTester;
friend class Ut_KeyButtonArea;
@@ -336,9 +402,9 @@
class ISymIndicator
{
public:
- virtual void activateSymIndicator() = 0;
- virtual void activateAceIndicator() = 0;
- virtual void deactivateIndicator() = 0;
+ virtual void activateSymIndicator() = 0;
+ virtual void activateAceIndicator() = 0;
+ virtual void deactivateIndicator() = 0;
};
#endif
--- m-keyboard/widgets/layoutmenu.cpp
+++ m-keyboard/widgets/layoutmenu.cpp
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#include "layoutmenu.h"
-#include "mvirtualkeyboardstyle.h"
-
-#include <MButtonGroup>
-
-#ifndef NOCONTROLPANEL
-#include <MControlPanelIf>
-#endif
-
-#include <MButton>
-#include <MDialog>
-#include <MGridLayoutPolicy>
-#include <MLabel>
-#include <MLayout>
-#include <MLinearLayoutPolicy>
-#include <MLocale>
-#include <MPopupList>
-#include <MSceneManager>
-#include <MTheme>
-#include <MNamespace>
-#include <MWidget>
-#include <mreactionmap.h>
-#include <mplainwindow.h>
-
-#include <QDebug>
-#include <QGraphicsItemAnimation>
-#include <QGraphicsLinearLayout>
-#include <QGraphicsSceneMouseEvent>
-#include <QPainter>
-#include <QStringListModel>
-
-namespace
-{
- //! spacing for language menue items
- const int Spacing = 10;
-
- //! Control panel language page name
- const QString CpLanguagePage("Language");
-};
-
-// FIXME: when menu is shown and a click is made outside it (that is, on the keyboard)
-// the menu disappears and bottom button isn't shown
-
-// FIXME: parent
-
-LayoutMenu::LayoutMenu(MVirtualKeyboardStyleContainer *style,
- QGraphicsWidget */* parent */)
- : styleContainer(style),
- active(false),
- savedActive(false),
- centralWidget(0),
- titleLabel(0),
- errorCorrectionLabel(0),
- errorCorrectionButton(0),
- layoutListLabel(0),
- layoutListHeader(0),
- layoutList(0),
- languageSettingLabel(0),
- languageSettingButton(0),
- keyboardOptionDialog(0),
- menuWidget(0),
- mainLayout(0),
- correctionAndLanguageLandscapeLayout(0)
-{
- setObjectName("LayoutMenu");
- getStyleValues();
-
- loadLanguageMenu();
-}
-
-
-void LayoutMenu::loadLanguageMenu()
-{
- //create dialog and widgets
- centralWidget = new MWidget;
- centralWidget->setGeometry(0, 0, baseSize.width(), baseSize.height() + buttonSize.height());
-
- //% "Keyboard options"
- keyboardOptionDialog = new MDialog(qtTrId("qtn_vkb_keyboard_options"), M::NoButton);
- keyboardOptionDialog->setCentralWidget(centralWidget);
- // Note: current (pre 0.20) libmeegotouch doesn't have dialog hidden on construction.
- // do that explicitly here so the signals are emitted correctly
- keyboardOptionDialog->hide();
-
- connect(keyboardOptionDialog, SIGNAL(visibleChanged()), SLOT(visibleChangeHandler()));
-
- /* Create widgets and put then into the layout policy */
-
- //% "Error correction"
- errorCorrectionLabel = new MLabel(qtTrId("qtn_vkb_error_correction"),
- centralWidget);
- errorCorrectionLabel->setAlignment(Qt::AlignCenter);
- errorCorrectionLabel->setWordWrap(true);
-
- //% "On"
- errorCorrectionButton = new MButton(qtTrId("qtn_comm_on"), centralWidget);
- errorCorrectionButton->setObjectName("MenuToggleButton");
- errorCorrectionButton->setCheckable(true);
- errorCorrectionButton->setChecked(true);
- errorCorrectionButton->setMaximumWidth(baseSize.width() / 2);
- connect(errorCorrectionButton, SIGNAL(clicked()), this, SLOT(synchronizeErrorCorrection()));
-
- //% "Input language"
- layoutListLabel = new MLabel(qtTrId("qtn_vkb_input_language"), centralWidget);
- layoutListLabel->setAlignment(Qt::AlignCenter);
-
- layoutListHeader = new MButton(centralWidget);
- layoutListHeader->setMaximumWidth(baseSize.width() / 2);
-
- layoutList = new MPopupList();
- layoutList->setItemModel(new QStringListModel());
-
- connect(layoutListHeader, SIGNAL(clicked()), this, SLOT(showLanguageList()));
-
- //% "To modify the input languages, go to"
- languageSettingLabel = new MLabel(qtTrId("qtn_vkb_language_setting_label"), centralWidget);
- languageSettingLabel->setAlignment(Qt::AlignHCenter);
-
- //TODO: connect languageSettingButton with language setting
- //% "Language settings"
- languageSettingButton = new MButton(qtTrId("qtn_vkb_language_setting"), centralWidget);
- languageSettingButton->setMaximumWidth(baseSize.width() / 2);
- connect(languageSettingButton, SIGNAL(clicked()), this, SLOT(openLanguageApplet()));
-
- //create layout
- QGraphicsLinearLayout *correctionLayout = new QGraphicsLinearLayout(Qt::Vertical);
- correctionLayout->setSpacing(Spacing);
- correctionLayout->addItem(errorCorrectionLabel);
- correctionLayout->addItem(errorCorrectionButton);
- correctionLayout->setAlignment(errorCorrectionLabel, Qt::AlignCenter);
- correctionLayout->setAlignment(errorCorrectionButton, Qt::AlignCenter);
-
- QGraphicsLinearLayout *languageLayout = new QGraphicsLinearLayout(Qt::Vertical);
- languageLayout->setSpacing(Spacing);
- languageLayout->addItem(layoutListLabel);
- languageLayout->addItem(layoutListHeader);
- languageLayout->setAlignment(layoutListLabel, Qt::AlignCenter);
- languageLayout->setAlignment(layoutListHeader, Qt::AlignCenter);
-
- correctionAndLanguageLandscapeLayout = new QGraphicsLinearLayout(Qt::Horizontal);
- correctionAndLanguageLandscapeLayout->setSpacing(Spacing);
- correctionAndLanguageLandscapeLayout->addItem(correctionLayout);
- correctionAndLanguageLandscapeLayout->addItem(languageLayout);
-
- QGraphicsLinearLayout *languageSettingLayout = new QGraphicsLinearLayout(Qt::Vertical);
- languageSettingLayout->setSpacing(Spacing);
- languageSettingLayout->addItem(languageSettingLabel);
- languageSettingLayout->addItem(languageSettingButton);
- languageSettingLayout->setAlignment(languageSettingLabel, Qt::AlignCenter);
- languageSettingLayout->setAlignment(languageSettingButton, Qt::AlignCenter);
-
- mainLayout = new MLayout;
-
- //for landscape
- MLinearLayoutPolicy *landscapePolicy = new MLinearLayoutPolicy(mainLayout, Qt::Vertical);
- landscapePolicy->setSpacing(2 * Spacing);
- landscapePolicy->addItem(correctionAndLanguageLandscapeLayout);
- landscapePolicy->addItem(languageSettingLayout);
-
- //for portrait
- MLinearLayoutPolicy *portraitPolicy = new MLinearLayoutPolicy(mainLayout, Qt::Vertical);
- portraitPolicy->setSpacing(2 * Spacing);
- portraitPolicy->addItem(correctionLayout);
- portraitPolicy->addItem(languageLayout);
- portraitPolicy->addItem(languageSettingLayout);
-
- centralWidget->setLayout(mainLayout);
- mainLayout->setLandscapePolicy(landscapePolicy);
- mainLayout->setPortraitPolicy(portraitPolicy);
-
- // layoutList seems to be initially visible before calling appear()
- layoutList->hide();
-}
-
-
-LayoutMenu::~LayoutMenu()
-{
- //clear correctionAndLanguageLandscapeLayout manually
- for (int i = 0; i < correctionAndLanguageLandscapeLayout->count(); i++)
- correctionAndLanguageLandscapeLayout->removeAt(i);
- //mainlayout will delete correctionAndLanguageLandscapeLayout within removeItem
- mainLayout->removeItem(correctionAndLanguageLandscapeLayout);
-
- // MPopupList does not take ownership of its model
- if (layoutList->itemModel()) {
- QAbstractItemModel *model = layoutList->itemModel();
- layoutList->setItemModel(0);
- delete model;
- }
-
- delete languageSettingLabel;
- delete languageSettingButton;
- delete titleLabel;
- delete errorCorrectionLabel;
- delete errorCorrectionButton;
- delete menuWidget;
- delete layoutListLabel;
- delete layoutListHeader;
- delete layoutList;
-
- // MDialog's view will destroy centralWidget
- delete keyboardOptionDialog;
-}
-
-
-void LayoutMenu::setLanguageList(const QStringList &titles, int selected)
-{
- QStringListModel *model = qobject_cast<QStringListModel *>(layoutList->itemModel());
-
- model->setStringList(titles);
- QModelIndex index = model->index(selected);
- layoutList->setCurrentIndex(index);
- layoutListHeader->setText(index.data().toString());
-}
-
-
-void
-LayoutMenu::show()
-{
- if (!active) {
- active = true;
- QSize visibleSceneSize = MPlainWindow::instance()->visibleSceneSize();
- centralWidget->setPos(0, visibleSceneSize.height() - baseSize.height());
-
- MPlainWindow::instance()->sceneManager()->execDialog(keyboardOptionDialog);
- }
-}
-
-void LayoutMenu::visibleChangeHandler()
-{
- QGraphicsObject *dialog = qobject_cast<QGraphicsObject *>(sender());
- Q_ASSERT(dialog);
- bool visibility = dialog->isVisible();
-
- if (!visibility) {
- active = false;
- emit hidden();
- emit regionUpdated(QRegion());
- } else {
- const QSize visibleSceneSize = MPlainWindow::instance()->visibleSceneSize();
- emit regionUpdated(QRegion(0, 0, visibleSceneSize.width(), visibleSceneSize.height()));
- }
-}
-
-bool
-LayoutMenu::isActive() const
-{
- return active;
-}
-
-
-void LayoutMenu::save()
-{
- savedActive = active;
-}
-
-
-void LayoutMenu::restore()
-{
- if (savedActive) {
- savedActive = false;
- show();
- }
-}
-
-
-void
-LayoutMenu::getStyleValues()
-{
- baseSize = style()->menuSize();
- buttonSize = style()->tabButtonSize();
-}
-
-
-void LayoutMenu::organizeContent(M::Orientation /* orientation */)
-{
- getStyleValues();
- keyboardOptionDialog->reject();
-}
-
-
-void LayoutMenu::enableErrorCorrection()
-{
- if (!errorCorrectionButton->isChecked()) {
- errorCorrectionButton->click();
- }
-}
-
-
-void LayoutMenu::disableErrorCorrection()
-{
- if (errorCorrectionButton->isChecked()) {
- errorCorrectionButton->click();
- }
-}
-
-
-void LayoutMenu::redrawReactionMaps()
-{
- if (!keyboardOptionDialog || !keyboardOptionDialog->scene())
- return;
-
- foreach (QGraphicsView *view, keyboardOptionDialog->scene()->views()) {
- MReactionMap *reactionMap = MReactionMap::instance(view);
- if (!reactionMap)
- continue;
-
- // Clear all with inactive color.
- reactionMap->setInactiveDrawingValue();
- reactionMap->setTransform(QTransform());
- reactionMap->fillRectangle(0, 0, reactionMap->width(), reactionMap->height());
-
- // We have no active areas, buttons take care of feedback playing.
- }
-}
-
-
-MVirtualKeyboardStyleContainer &LayoutMenu::style()
-{
- return *styleContainer;
-}
-
-
-void LayoutMenu::showLanguageList()
-{
- if (layoutList && layoutListHeader) {
- MPlainWindow::instance()->sceneManager()->execDialog(layoutList);
- QModelIndex index = layoutList->currentIndex();
- layoutListHeader->setText(index.data(Qt::DisplayRole).toString());
- emit languageSelected(index.row()); // QStringListModel has only rows.
- }
-}
-
-
-void LayoutMenu::synchronizeErrorCorrection()
-{
- if (errorCorrectionButton->isChecked()) {
- emit errorCorrectionToggled(true);
- //% "On"
- errorCorrectionButton->setText(qtTrId("qtn_comm_on"));
- } else {
- emit errorCorrectionToggled(false);
- //% "Off"
- errorCorrectionButton->setText(qtTrId("qtn_comm_off"));
- }
-}
-
-void LayoutMenu::openLanguageApplet()
-{
-#ifndef NOCONTROLPANEL
- MControlPanelIf *dcpIf = new MControlPanelIf();
- if (dcpIf->isValid()) {
- dcpIf->appletPage(CpLanguagePage);
- }
- delete dcpIf;
- dcpIf = NULL;
-#endif
-}
--- m-keyboard/widgets/layoutmenu.h
+++ m-keyboard/widgets/layoutmenu.h
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#ifndef LAYOUTMENU_H
-#define LAYOUTMENU_H
-
-#include <QObject>
-#include <MNamespace>
-
-class QGraphicsLinearLayout;
-class QGraphicsWidget;
-class MLayout;
-class MLabel;
-class MButton;
-class MButtonGroup;
-class MPopupList;
-class MVirtualKeyboardStyleContainer;
-class MDialog;
-class MWidget;
-
-
-/*!
- * \brief Virtual keyboard configuration dialog
- */
-class LayoutMenu : public QObject
-{
- Q_OBJECT
- friend class Ut_MKeyboardHost;
-
-public:
- /*!
- * \brief Constructor
- * \param style style container
- * \param parent parent widget -- currently unused
- */
- LayoutMenu(MVirtualKeyboardStyleContainer *style, QGraphicsWidget *parent = 0);
-
- /*!
- * Destructor
- */
- ~LayoutMenu();
-
- //! Sets the list of available languages. These should
- //! be descriptive titles, not language codes.
- void setLanguageList(const QStringList &titles, int selected);
-
- //! organize content when orientation is changed
- void organizeContent(M::Orientation orientation);
-
- //! Save state before rotation
- void save();
-
- //! Restore state after rotation
- void restore();
-
- /*!
- * enable/disable error correction
- */
- void enableErrorCorrection();
- void disableErrorCorrection();
-
- //! Whether layout menu is displayed
- bool isActive() const;
-
-public slots:
- /*!
- * \brief Open the dialog if not open already.
- *
- * Returns only when user dismisses the dialog.
- */
- void show();
-
- /*!
- * Draw the reactive areas of this dialog
- */
- void redrawReactionMaps();
-
-
-signals:
- //! Emitted when turn on/off error correction
- void errorCorrectionToggled(bool on);
-
- //! Emitted when layoutmenu is hidden
- void hidden();
-
- //! Emitted when interactive region of the menu has changed
- void regionUpdated(const QRegion &);
-
- //! Signals that user has selected a language. Index refers to
- //! a language in language list the menu was given.
- void languageSelected(int index);
-
-private slots:
- void synchronizeErrorCorrection();
-
- void showLanguageList();
-
- //! Opens language settings page in mcontrolpanel.
- void openLanguageApplet();
-
- void visibleChangeHandler();
-
-private:
- /*!
- * Method to Show animation
- */
-
- void setupShowAndHide();
- void getStyleValues();
-
- /*!
- * load language menu
- */
- void loadLanguageMenu();
-
- //! Getter for style container
- MVirtualKeyboardStyleContainer &style();
-
- //! Style attributes
- MVirtualKeyboardStyleContainer *styleContainer;
-
- QSize buttonSize;
-
- //! To check if menu is active
- bool active;
-
- //! to check if menu is active after rotation
- bool savedActive;
-
- //! baseSize
- QSize baseSize;
-
- //! Menu item
- MWidget *centralWidget;
- MLabel *titleLabel;
- MLabel *errorCorrectionLabel;
- MButton *errorCorrectionButton;
- MButtonGroup *errorCorectionButtonGroup;
- MLabel *layoutListLabel;
- MButton *layoutListHeader;
- MPopupList *layoutList;
- MLabel *languageSettingLabel;
- MButton *languageSettingButton;
-
- MDialog *keyboardOptionDialog;
- MWidget *menuWidget;
- MLayout *mainLayout;
- QGraphicsLinearLayout *correctionAndLanguageLandscapeLayout;
-};
-
-#endif
--- m-keyboard/widgets/mbuttonarea.cpp
+++ m-keyboard/widgets/mbuttonarea.cpp
@@ -56,7 +56,7 @@
MButtonArea::~MButtonArea()
{
// Release any key that might be pressed before destroying them.
- setActiveKey(0);
+ clearActiveKeys();
setLayout(0);
qDeleteAll(buttons);
@@ -130,10 +130,6 @@
FlickUpButton *button = new FlickUpButton(*dataKey);
- if (dataKey->binding()->action() == KeyBinding::ActionShift) {
- shiftButton = button;
- }
-
if (stretchesHorizontally) {
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
} else {
--- m-keyboard/widgets/mimcorrectioncandidatewidget.cpp
+++ m-keyboard/widgets/mimcorrectioncandidatewidget.cpp
@@ -21,7 +21,6 @@
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QString>
-#include <QFontMetrics>
#include <MSceneManager>
#include <mreactionmap.h>
@@ -50,20 +49,13 @@
/*! \reimp */
virtual MWidget *createCell(const QModelIndex &index, MWidgetRecycler &recycler) const;
virtual void updateCell(const QModelIndex &index, MWidget *cell) const;
- virtual QSizeF cellSize() const;
/*! \reimp_end */
private:
void updateContentItemMode(const QModelIndex &index, MContentItem *contentItem) const;
-
- QSizeF size;
};
MImCorrectionContentItemCreator::MImCorrectionContentItemCreator()
{
- // Initializes size
- MContentItem cell(MContentItem::SingleTextLabel);
- cell.setObjectName(CandidatesItemObjectName);
- size = cell.effectiveSizeHint(Qt::PreferredSize);
}
MWidget *MImCorrectionContentItemCreator::createCell(const QModelIndex &index, MWidgetRecycler &recycler) const
@@ -91,11 +83,6 @@
updateContentItemMode(index, contentItem);
}
-QSizeF MImCorrectionContentItemCreator::cellSize() const
-{
- return size;
-}
-
void MImCorrectionContentItemCreator::updateContentItemMode(const QModelIndex &index,
MContentItem *contentItem) const
{
@@ -114,7 +101,6 @@
: MWidget(parent),
rotationInProgress(false),
candidatePosition(0, 0),
- fontMetrics(0),
sceneManager(MPlainWindow::instance()->sceneManager()),
containerWidget(new MWidget(this)),
candidatesWidget(new MList(containerWidget)),
@@ -137,19 +123,11 @@
candidatesWidget->setCellCreator(cellCreator);
candidatesWidget->setItemModel(candidatesModel);
connect(candidatesWidget, SIGNAL(itemClicked(const QModelIndex &)), this, SLOT(select(const QModelIndex &)));
-
- //TODO: This is a hack way to get font information from MList.
- //Could be refined later if MList provides other better way.
- MLabel label;
- label.setObjectName(CandidatesItemLabelObjectName);
- fontMetrics = new QFontMetrics(label.font());
}
MImCorrectionCandidateWidget::~MImCorrectionCandidateWidget()
{
- delete fontMetrics;
- fontMetrics = 0;
delete candidatesModel;
}
@@ -173,10 +151,16 @@
// Calculate the width for MContentItem dynamically.
// To ensure the whole words in candidate list could be shown.
candidateWidth = 0;
+ MLabel label;
+ label.setObjectName(CandidatesItemLabelObjectName);
foreach (const QString &candidate, filteredCandidateList) {
- candidateWidth = qMax(candidateWidth, fontMetrics->width(candidate));
+ label.setText(candidate);
+ candidateWidth = qMax(candidateWidth, label.preferredSize().width());
}
- candidateWidth += candidatesWidget->preferredWidth();
+
+ qreal left, top, right, bottom;
+ label.getContentsMargins(&left, &top, &right, &bottom);
+ candidateWidth += left + right;
}
void MImCorrectionCandidateWidget::setPreeditString(const QString &string)
--- m-keyboard/widgets/mimcorrectioncandidatewidget.h
+++ m-keyboard/widgets/mimcorrectioncandidatewidget.h
@@ -26,7 +26,6 @@
class MList;
class MImCorrectionContentItemCreator;
class QStringListModel;
-class QFontMetrics;
/*!
\class MImCorrectionCandidateWidget
@@ -135,13 +134,12 @@
bool rotationInProgress;
QString m_preeditString;
QPoint candidatePosition;
- QFontMetrics *fontMetrics;
MSceneManager *sceneManager;
MWidget *containerWidget;
MList *candidatesWidget;
MImCorrectionContentItemCreator *cellCreator;
QStringListModel *candidatesModel;
- int candidateWidth;
+ qreal candidateWidth;
Q_DISABLE_COPY(MImCorrectionCandidateWidget)
};
--- m-keyboard/widgets/mimtoolbar.cpp
+++ m-keyboard/widgets/mimtoolbar.cpp
@@ -17,12 +17,14 @@
#include "mimtoolbar.h"
-#include "toolbardata.h"
-#include "toolbarmanager.h"
-#include "toolbarwidget.h"
#include "layoutsmanager.h"
#include "mhardwarekeyboard.h"
#include "mvirtualkeyboardstyle.h"
+#include "mtoolbarbutton.h"
+#include "mtoolbarlabel.h"
+
+#include <mtoolbardata.h>
+#include <mtoolbaritem.h>
#include <MNamespace>
#include <MButton>
@@ -37,19 +39,17 @@
namespace
{
//!object name for toolbar buttons
- const QString ObjectNameToolbarButtons("VirtualKeyboardToolbarButton");
- const QString ObjectNameCloseButton("VirtualKeyboardCloseButton");
const QString ObjectNameToolbar("MImToolbar");
const QString ObjectNameToolbarLeft("VirtualKeyboardToolbarLeft");
const QString ObjectNameToolbarRight("VirtualKeyboardToolbarRight");
- const QString IconNameCloseButton("icon-m-input-methods-close");
+ const QString NameToolbarCopyPasteButton("VirtualKeyboardCopyPasteButton");
};
-MImToolbar::MImToolbar(MVirtualKeyboardStyleContainer &style, QGraphicsWidget *parent)
+MImToolbar::MImToolbar(const MVirtualKeyboardStyleContainer &style, QGraphicsWidget *parent)
: MWidget(parent),
- toolbarMgr(ToolbarManager::instance()),
textSelected(false),
- copyPaste(new MButton),
+ copyPasteItem(new MToolbarItem(NameToolbarCopyPasteButton, MInputMethod::ItemButton)),
+ copyPaste(new MToolbarButton(copyPasteItem, this)),
copyPasteStatus(InputMethodNoCopyPaste),
leftBar(true, this),
rightBar(true, this),
@@ -57,41 +57,30 @@
shiftState(ModifierClearState),
fnState(ModifierClearState)
{
- // Empty button bars are hidden.
- leftBar.hide();
- rightBar.hide();
-
- setObjectName(ObjectNameToolbar);
leftBar.setObjectName(ObjectNameToolbarLeft);
rightBar.setObjectName(ObjectNameToolbarRight);
+ setObjectName(ObjectNameToolbar);
setupLayout();
loadDefaultButtons();
connect(this, SIGNAL(visibleChanged()), this, SLOT(updateVisibility()));
-
- connect(&toolbarMgr, SIGNAL(buttonClicked(ToolbarWidget)), this, SLOT(handleButtonClick(ToolbarWidget)));
}
MImToolbar::~MImToolbar()
{
- delete copyPaste;
- copyPaste = 0;
}
void MImToolbar::setupLayout()
{
- QGraphicsLinearLayout *mainLayout = new QGraphicsLinearLayout(Qt::Horizontal, this);
+ QGraphicsLinearLayout *mainLayout = new QGraphicsLinearLayout(Qt::Vertical, this);
mainLayout->setContentsMargins(0, 0, 0, 0);
- // Add the left and right side WidgetBar widgets with a stretch item in between.
- mainLayout->addItem(&leftBar);
- mainLayout->addStretch();
- mainLayout->addItem(&rightBar);
+ QGraphicsLinearLayout *rowLayout = new QGraphicsLinearLayout(Qt::Horizontal, mainLayout);
- mainLayout->setAlignment(&leftBar, Qt::AlignBottom);
- mainLayout->setAlignment(&rightBar, Qt::AlignBottom);
+ setupRowLayout(rowLayout, &leftBar, &rightBar);
+ mainLayout->insertItem(0, rowLayout);
resize(geometry().width(), layout()->preferredHeight());
}
@@ -99,7 +88,6 @@
void MImToolbar::loadDefaultButtons()
{
// Setup copy/paste button.
- copyPaste->setObjectName(ObjectNameToolbarButtons);
copyPaste->setVisible(false);
//% "Copy"
copyPaste->setText(qtTrId("qtn_comm_copy"));
@@ -116,35 +104,35 @@
return region;
}
-void MImToolbar::handleButtonClick(const ToolbarWidget &button)
+void MImToolbar::handleButtonClick(MToolbarItem *item)
{
- if (button.type() != ToolbarWidget::Button)
+ if (!item || item->type() != MInputMethod::ItemButton)
return;
- foreach(const ToolbarWidget::Action *action, button.actions) {
- switch (action->type) {
- case ToolbarWidget::SendKeySequence:
- sendKeySequence(action->keys);
+ foreach(QSharedPointer<const MToolbarItemAction> action, item->actions()) {
+ switch (action->type()) {
+ case MInputMethod::ActionSendKeySequence:
+ sendKeySequence(action->keys());
break;
- case ToolbarWidget::SendString:
- sendStringRequest(action->text);
+ case MInputMethod::ActionSendString:
+ sendStringRequest(action->text());
break;
- case ToolbarWidget::SendCommand:
+ case MInputMethod::ActionSendCommand:
//TODO:not support yet
break;
- case ToolbarWidget::Copy:
+ case MInputMethod::ActionCopy:
emit copyPasteRequest(InputMethodCopy);
break;
- case ToolbarWidget::Paste:
+ case MInputMethod::ActionPaste:
emit copyPasteRequest(InputMethodPaste);
break;
- case ToolbarWidget::ShowGroup:
- showGroup(action->group);
+ case MInputMethod::ActionShowGroup:
+ showGroup(action->group());
break;
- case ToolbarWidget::HideGroup:
- hideGroup(action->group);
+ case MInputMethod::ActionHideGroup:
+ hideGroup(action->group());
break;
- case ToolbarWidget::Unknown:
+ case MInputMethod::ActionUndefined:
break;
}
}
@@ -161,96 +149,193 @@
void MImToolbar::updateVisibility()
{
- qDebug() << __PRETTY_FUNCTION__;
- //set widget's visibility according showOn and hideOn premiss and current selection status
- foreach(ToolbarWidget *w, toolbarMgr.widgetList()) {
- if ((textSelected && w->hideOn != ToolbarWidget::WhenSelectingText)
- || (w->showOn == ToolbarWidget::Always)) {
- w->setVisible(true);
- } else {
- w->setVisible(false);
+ if (currentToolbar) {
+ foreach (const QSharedPointer<MToolbarItem> item, currentToolbar->allItems())
+ {
+ if ((item->showOn() == MInputMethod::VisibleAlways)
+ || (textSelected && item->showOn() == MInputMethod::VisibleWhenSelectingText)
+ || (!textSelected && item->hideOn() == MInputMethod::VisibleWhenSelectingText)) {
+ item->setVisible(true);
+ }
+
+ if ((!textSelected && item->showOn() == MInputMethod::VisibleWhenSelectingText)
+ || (textSelected && item->hideOn() == MInputMethod::VisibleWhenSelectingText)) {
+ item->setVisible(false);
+ }
}
}
-
- // Update widgets according to toolbar models.
- updateWidgets();
+ arrangeWidgets();
}
-void MImToolbar::loadCustomWidgets(Qt::Alignment align)
+void MImToolbar::loadCustomWidgets()
{
- qDebug() << __PRETTY_FUNCTION__ << align;
- //the widgets gotten from toolbarMgr are already ordered acording their priority with alignment.
- QList<ToolbarWidget *> widgets = toolbarMgr.widgetList(align);
- //show widgets according their status and priority
- int widgetCount = 0;
- foreach(ToolbarWidget *toolbarWidget, widgets) {
- MWidget *widget = toolbarMgr.widget(toolbarWidget->name());
- if (!widget)
- continue;
- if (toolbarWidget->isVisible()) {
- widget->setVisible(true);
- //if widget is Visible, then insert it to the right position
- insertItem(widgetCount, widget, align);
- ++widgetCount;
- } else {
- widget->setVisible(false);
- removeItem(widget);
+ if (!currentToolbar) {
+ return;
+ }
+
+ const M::Orientation orientation = MPlainWindow::instance()->sceneManager()->orientation();
+ QSharedPointer<const MToolbarLayout> layout = currentToolbar->layout(orientation);
+ QGraphicsLinearLayout *mainLayout = static_cast<QGraphicsLinearLayout*>(this->layout());
+
+ QList<QSharedPointer<const MToolbarRow> > rows = layout->rows();
+
+ //create additional rows if necessary
+ for (int n = 0; n < rows.count() - 1; ++n) {
+ QSharedPointer<const MToolbarRow> row = rows[n];
+ QGraphicsLinearLayout *rowLayout = new QGraphicsLinearLayout(Qt::Horizontal, mainLayout);
+ WidgetBar *leftWidget = new WidgetBar(true, this);
+ WidgetBar *rightWidget = new WidgetBar(true, this);
+
+ leftWidget->setObjectName(ObjectNameToolbarLeft);
+ rightWidget->setObjectName(ObjectNameToolbarRight);
+ setupRowLayout(rowLayout, leftWidget, rightWidget);
+ mainLayout->insertItem(n, rowLayout);
+
+ foreach (QSharedPointer<MToolbarItem> item , row->items()) {
+ createAndAppendWidget(item, leftWidget, rightWidget);
}
}
+
+ //add custom items to bottom row
+ QSharedPointer<const MToolbarRow> row = rows.last();
+ foreach (QSharedPointer<MToolbarItem> item, row->items()) {
+ createAndAppendWidget(item, &leftBar, &rightBar);
+ }
+
+ int buttonIndex = rightBar.indexOf(copyPaste);
+ if (buttonIndex >= 0 && buttonIndex != rightBar.count() - 1) {
+ // copy button position is inccorect now,
+ // so we move it to correcrt place
+ removeItem(copyPaste);
+ insertItem(rightBar.count(), copyPaste, Qt::AlignRight);
+ }
+ mainLayout->invalidate();
}
-void MImToolbar::unloadCustomWidgets(Qt::Alignment align)
+void MImToolbar::createAndAppendWidget(QSharedPointer<MToolbarItem> item,
+ WidgetBar *leftWidget,
+ WidgetBar *rightWidget)
{
- QList<ToolbarWidget *> widgets = toolbarMgr.widgetList(align);
- foreach(ToolbarWidget *toolbarWidget, widgets) {
- MWidget *widget = toolbarMgr.widget(toolbarWidget->name());
- if (!widget)
- continue;
- widget->setVisible(false);
- removeItem(widget);
+ MWidget *widget = 0;
+ WidgetBar *sidebar = 0;
+
+ if (item->alignment() == Qt::AlignLeft) {
+ sidebar = leftWidget;
+ } else {
+ sidebar = rightWidget;
+ }
+ if (item->type() == MInputMethod::ItemButton) {
+ widget = new MToolbarButton(item, sidebar);
+
+ connect(widget, SIGNAL(clicked(MToolbarItem*)),
+ this, SLOT(handleButtonClick(MToolbarItem*)));
+ } else {
+ widget = new MToolbarLabel(item, sidebar);
+ }
+ customWidgets.append(widget);
+ sidebar->append(widget);
+ if (sidebar->count() == 1) {
+ sidebar->show();
}
}
-void MImToolbar::updateWidgets(bool customWidgetsChanged)
+void MImToolbar::setupRowLayout(QGraphicsLinearLayout *rowLayout,
+ WidgetBar *leftWidget,
+ WidgetBar *rightWidget)
+{
+ rowLayout->setContentsMargins(0, 0, 0, 0);
+ rowLayout->setMaximumWidth(MPlainWindow::instance()->visibleSceneSize().width());
+ rowLayout->setPreferredWidth(MPlainWindow::instance()->visibleSceneSize().width());
+
+ // Empty button bars are hidden.
+ leftWidget->hide();
+ rightWidget->hide();
+ // Add the left and right side WidgetBar widgets with a stretch item in between.
+ rowLayout->addItem(leftWidget);
+ rowLayout->addStretch();
+ rowLayout->addItem(rightWidget);
+
+ rowLayout->setAlignment(leftWidget, Qt::AlignBottom);
+ rowLayout->setAlignment(rightWidget, Qt::AlignBottom);
+}
+
+void MImToolbar::unloadCustomWidgets()
{
- if (customWidgetsChanged) {
- loadCustomWidgets(Qt::AlignLeft);
- loadCustomWidgets(Qt::AlignRight);
+ QGraphicsLinearLayout *mainLayout = static_cast<QGraphicsLinearLayout*>(layout());
+ QList<QGraphicsLinearLayout*> rows;
+
+ //delete all dynamically created rows
+ for (int n = 0; n < mainLayout->count() - 1; ++n) {
+ QGraphicsLinearLayout *rowLayout = dynamic_cast<QGraphicsLinearLayout*>(mainLayout->itemAt(n));
+
+ if (rowLayout) {
+ WidgetBar *leftBar = dynamic_cast<WidgetBar*>(rowLayout->itemAt(0));
+ WidgetBar *rightBar = dynamic_cast<WidgetBar*>(rowLayout->itemAt(1));
+
+ delete leftBar;
+ delete rightBar;
+ rows << rowLayout;
+ }
}
+ qDeleteAll(rows);
+ qDeleteAll(customWidgets);
+ customWidgets.clear();
+ leftBar.cleanup();
+ rightBar.cleanup();
+}
+
+void MImToolbar::arrangeWidgets()
+{
if (isVisible()) {
layout()->invalidate();
+ layout()->activate();
+ resize(geometry().width(), layout()->preferredHeight());
}
emit regionUpdated();
+ emit availabilityChanged((rightBar.count() != 0) || (leftBar.count() != 0));
}
void MImToolbar::showGroup(const QString &group)
{
bool changed = false;
- foreach(ToolbarWidget *w, toolbarMgr.widgetList()) {
- if (w->group == group && !(w->isVisible())) {
- w->setVisible(true);
+
+ if (!currentToolbar) {
+ return;
+ }
+
+ foreach (const QSharedPointer<MToolbarItem> item, currentToolbar->allItems())
+ {
+ if (item->group() == group && !(item->isVisible())) {
+ item->setVisible(true);
changed = true;
}
}
if (changed) {
- updateWidgets();
+ arrangeWidgets();
}
}
void MImToolbar::hideGroup(const QString &group)
{
bool changed = false;
- foreach(ToolbarWidget *w, toolbarMgr.widgetList()) {
- if (w->group == group && w->isVisible()) {
- w->setVisible(false);
+
+ if (!currentToolbar) {
+ return;
+ }
+
+ foreach (const QSharedPointer<MToolbarItem> item, currentToolbar->allItems())
+ {
+ if (item->group() == group && item->isVisible()) {
+ item->setVisible(false);
changed = true;
}
}
+
if (changed) {
- updateWidgets(true);
+ arrangeWidgets();
}
}
@@ -289,26 +374,26 @@
return modify;
}
-void MImToolbar::showToolbarWidget(qlonglong id)
+void MImToolbar::showToolbarWidget(QSharedPointer<const MToolbarData> toolbar)
{
- qDebug() << __PRETTY_FUNCTION__ << id;
- if (id != toolbarMgr.currentToolbar()) {
- unloadCustomWidgets(Qt::AlignLeft);
- unloadCustomWidgets(Qt::AlignRight);
+ if (toolbar == currentToolbar) {
+ return;
}
- ToolbarManager::instance().loadToolbar(id);
+
+ unloadCustomWidgets();
+
+ currentToolbar = toolbar;
+ loadCustomWidgets();
+
if (isVisible())
updateVisibility();
}
void MImToolbar::hideToolbarWidget()
{
- qDebug() << __PRETTY_FUNCTION__;
- unloadCustomWidgets(Qt::AlignLeft);
- unloadCustomWidgets(Qt::AlignRight);
- ToolbarManager::instance().reset();
- if (isVisible())
- updateVisibility();
+ currentToolbar.clear();
+ unloadCustomWidgets();
+ arrangeWidgets();
}
void MImToolbar::copyPasteButtonHandler()
@@ -366,8 +451,7 @@
break;
}
if (changed) {
- // Update only positions.
- updateWidgets(false);
+ arrangeWidgets();
}
qDebug() << __PRETTY_FUNCTION__ << copyPaste->isVisible();
}
@@ -417,15 +501,23 @@
// Draw all widgets geometries.
reactionMap->setReactiveDrawingValue();
- for (int j = 0; j < 2; ++j) {
- WidgetBar *sidebar = ((j == 0) ? &leftBar : &rightBar);
- if (!sidebar->isVisible()) {
- continue;
- }
- reactionMap->setTransform(sidebar, view);
+ for (int n = 0; n < layout()->count(); ++n) {
+ QGraphicsLinearLayout *row = dynamic_cast<QGraphicsLinearLayout*>(layout()->itemAt(n));
- for (int i = 0; i < sidebar->count(); ++i) {
- reactionMap->fillRectangle(sidebar->widgetAt(i)->geometry());
+ if (row) {
+ for (int j = 0; j < row->count(); ++j) {
+ WidgetBar *sidebar = dynamic_cast<WidgetBar*>(row->itemAt(j));
+ if (!sidebar || !sidebar->isVisible()) {
+ continue;
+ }
+ reactionMap->setTransform(sidebar, view);
+
+ for (int i = 0; i < sidebar->count(); ++i) {
+ if (sidebar->widgetAt(i) && sidebar->widgetAt(i)->isVisible()) {
+ reactionMap->fillRectangle(sidebar->widgetAt(i)->geometry());
+ }
+ }
+ }
}
}
}
@@ -439,6 +531,13 @@
}
}
+void MImToolbar::reload()
+{
+ //use brute force: destroy everything and construct it again
+ unloadCustomWidgets();
+ loadCustomWidgets();
+}
+
void MImToolbar::clearReactiveAreas()
{
if (!scene())
@@ -453,6 +552,18 @@
reactionMap->setTransform(this, view);
reactionMap->setInactiveDrawingValue();
- reactionMap->fillRectangle(leftBar.geometry());
- reactionMap->fillRectangle(rightBar.geometry());
+
+ for (int n = 0; n < layout()->count(); ++n) {
+ QGraphicsLinearLayout *row = dynamic_cast<QGraphicsLinearLayout*>(layout()->itemAt(n));
+
+ if (row) {
+ for (int j = 0; j < row->count(); ++j) {
+ WidgetBar *sidebar = dynamic_cast<WidgetBar*>(row->itemAt(j));
+ if (sidebar) {
+ reactionMap->fillRectangle(sidebar->geometry());
+ }
+ }
+ }
+ }
}
+
--- m-keyboard/widgets/mimtoolbar.h
+++ m-keyboard/widgets/mimtoolbar.h
@@ -22,12 +22,19 @@
#include <MWidget>
#include "widgetbar.h"
#include "mkeyboardcommon.h"
+#include <minputmethodnamespace.h>
+
+#include <QPointer>
+#include <QSharedPointer>
class MReactionMap;
class ToolbarManager;
class MVirtualKeyboardStyleContainer;
-class MButton;
+class MToolbarButton;
+class MToolbarItem;
class ToolbarWidget;
+class MToolbarData;
+class MToolbarItem;
/*!
\brief MImToolbar implement the toolbar for virtualkeyboard.
@@ -55,7 +62,7 @@
* \param style Styling information.
* \param parent Parent object.
*/
- explicit MImToolbar(MVirtualKeyboardStyleContainer &style,
+ explicit MImToolbar(const MVirtualKeyboardStyleContainer &style,
QGraphicsWidget *parent = 0);
//! Destructor
@@ -72,7 +79,7 @@
* the toolbar will be visible when show().
* \param id Unique identifier of the custom toolbar.
*/
- void showToolbarWidget(qlonglong id);
+ void showToolbarWidget(QSharedPointer<const MToolbarData> toolbar);
/*!
* \brief Hides all custom toolbars, this also means they are removed from visible virtual keyboard.
@@ -85,6 +92,9 @@
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *);
//! \reimp_end
+ //! Reload toolbar if it should be updated
+ void reload();
+
public slots:
/*!
* \brief Sets the status if there are some selection text.
@@ -100,17 +110,22 @@
private slots:
- void handleButtonClick(const ToolbarWidget &);
+ //! Invoked when custom button on toolbar is clicked
+ void handleButtonClick(MToolbarItem *item);
- void showGroup(const QString &);
+ //! Show all widgets belong to given \a group
+ void showGroup(const QString &group);
- void hideGroup(const QString &);
+ //! Hide all widgets belong to given \a group
+ void hideGroup(const QString &group);
- void sendKeySequence(const QString &);
+ //! Send key events corresponding to given \a keys.
+ void sendKeySequence(const QString &keys);
//! Invoked when copy/paste button is clicked
void copyPasteButtonHandler();
+ //! Show or hide buttons according to toolbar definition and text tselection status
void updateVisibility();
signals:
@@ -132,6 +147,10 @@
*/
void copyPasteClicked(CopyPasteState action);
+ //! \brief Emitted when toolbar availability changes
+ //! \param available true when there are widgets in the toolbar; false otherwise
+ void availabilityChanged(bool available);
+
private:
void setupLayout();
@@ -139,14 +158,20 @@
void updateRegion();
- void loadCustomWidgets(Qt::Alignment align);
+ void loadCustomWidgets();
- void unloadCustomWidgets(Qt::Alignment align);
+ void unloadCustomWidgets();
- void updateWidgets(bool customWidgetsChanged = true);
+ void arrangeWidgets();
Qt::KeyboardModifiers keyModifiers(int key) const;
+ void setupRowLayout(QGraphicsLinearLayout *rowLayout, WidgetBar *leftBar,
+ WidgetBar *rightBar);
+
+ void createAndAppendWidget(QSharedPointer<MToolbarItem> item, WidgetBar *leftWidget,
+ WidgetBar *rightWidget);
+
/*!
* \brief Inserts item to \a align part of the toolbar at index,
* or before any item that is currently at index in \a align part of the toolbar.
@@ -167,17 +192,25 @@
void clearReactiveAreas();
- const ToolbarManager &toolbarMgr;
bool textSelected;
+
+ //! ToolbarItem for Copy/Paste button.
+ // Don't call any method belongs to MToolbarItem which attributes are managed internally.
+ QSharedPointer<MToolbarItem> copyPasteItem;
+
//! Copy/Paste button
- MButton *copyPaste;
+ MToolbarButton *copyPaste;
//! Copy/paste button status
CopyPasteState copyPasteStatus;
WidgetBar leftBar; //! Widget to hold left-aligned toolbar widgets
WidgetBar rightBar; //! Widget to hold right-aligned toolbar widgets
- MVirtualKeyboardStyleContainer &style; //! Styling information
+ QSharedPointer<const MToolbarData> currentToolbar; //! Pointer to definition of current toolbar
+
+ QList<QPointer<MWidget> > customWidgets; //! All custom widgets in this toolbar
+
+ const MVirtualKeyboardStyleContainer &style; //! Styling information
friend class Ut_MImToolbar;
--- m-keyboard/widgets/mkeyboardsettingswidget.cpp
+++ m-keyboard/widgets/mkeyboardsettingswidget.cpp
+/* * This file is part of m-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "mkeyboardsettingswidget.h"
+
+#include <MButton>
+#include <MLabel>
+#include <MLayout>
+#include <MLocale>
+#include <MGridLayoutPolicy>
+#include <MLinearLayoutPolicy>
+#include <MContentItem>
+#include <MAbstractCellCreator>
+#include <MList>
+#include <MDialog>
+#include <MInfoBanner>
+
+#include <QObject>
+#include <QGraphicsLinearLayout>
+#include <QStandardItemModel>
+#include <QItemSelectionModel>
+#include <QTimer>
+#include <QDebug>
+
+class MKeyboardCellCreator: public MAbstractCellCreator<MContentItem>
+{
+public:
+ /*! \reimp */
+ virtual MWidget *createCell (const QModelIndex &index,
+ MWidgetRecycler &recycler) const;
+ virtual void updateCell(const QModelIndex &index, MWidget *cell) const;
+ /*! \reimp_end */
+private:
+ void updateContentItemMode(const QModelIndex &index, MContentItem *contentItem) const;
+};
+
+MWidget *MKeyboardCellCreator::createCell (const QModelIndex &index,
+ MWidgetRecycler &recycler) const
+{
+ MContentItem *cell = qobject_cast<MContentItem *>(recycler.take("MContentItem"));
+ if (!cell) {
+ cell = new MContentItem(MContentItem::SingleTextLabel);
+ }
+ updateCell(index, cell);
+ return cell;
+}
+
+void MKeyboardCellCreator::updateCell(const QModelIndex &index, MWidget *cell) const
+{
+ MContentItem *contentItem = qobject_cast<MContentItem *>(cell);
+
+ QString langId = index.data(Qt::UserRole + 1).toString();
+ contentItem->setTitle(langId);
+}
+
+void MKeyboardCellCreator::updateContentItemMode(const QModelIndex &index,
+ MContentItem *contentItem) const
+{
+ const int row = index.row();
+ bool thereIsNextRow = index.sibling(row + 1, 0).isValid();
+ if (row == 0) {
+ contentItem->setItemMode(MContentItem::SingleColumnTop);
+ } else if (thereIsNextRow) {
+ contentItem->setItemMode(MContentItem::SingleColumnCenter);
+ } else {
+ contentItem->setItemMode(MContentItem::SingleColumnBottom);
+ }
+}
+
+MKeyboardSettingsWidget::MKeyboardSettingsWidget(MKeyboardSettings *settings, QGraphicsItem *parent)
+ : MWidget(parent),
+ settingsObject(settings),
+ keyboardDialog(0),
+ keyboardList(0)
+{
+ MLayout *layout = new MLayout(this);
+
+ landscapePolicy = new MGridLayoutPolicy(layout);
+ landscapePolicy->setContentsMargins(0, 0, 0, 0);
+ landscapePolicy->setSpacing(0);
+ //To make sure that both columns have the same width, give them the same preferred width.
+ landscapePolicy->setColumnPreferredWidth(0, 800);
+ landscapePolicy->setColumnPreferredWidth(1, 800);
+ portraitPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
+ portraitPolicy->setContentsMargins(0, 0, 0, 0);
+ portraitPolicy->setSpacing(0);
+
+ layout->setLandscapePolicy(landscapePolicy);
+ layout->setPortraitPolicy(portraitPolicy);
+
+ buildUi();
+ syncErrorCorrectionState();
+ retranslateUi();
+ connectSlots();
+}
+
+MKeyboardSettingsWidget::~MKeyboardSettingsWidget()
+{
+ delete keyboardDialog;
+ keyboardDialog = 0;
+}
+
+void MKeyboardSettingsWidget::buildUi()
+{
+ selectedKeyboardsItem = new MContentItem(MContentItem::TwoTextLabels, this);
+ connect(selectedKeyboardsItem, SIGNAL(clicked()), this, SLOT(showKeyboardList()));
+ addItem(selectedKeyboardsItem);
+
+ errorCorrectionSwitch = new MButton(this);
+ errorCorrectionSwitch->setViewType(MButton::switchType);
+ errorCorrectionSwitch->setCheckable(true);
+ errorCorrectionLabel = new MLabel(this);
+ //% "Error correction"
+ errorCorrectionLabel->setText(qtTrId("qtn_txts_error_correction"));
+ errorCorrectionLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(Qt::Horizontal);
+ l->addItem(errorCorrectionLabel);
+ l->addItem(errorCorrectionSwitch);
+ l->setAlignment(errorCorrectionSwitch, Qt::AlignCenter);
+ (qobject_cast<MKeyboardSettingsWidget *>(this))->addItem(l);
+}
+
+void MKeyboardSettingsWidget::addItem(QGraphicsLayoutItem *item)
+{
+ int count = landscapePolicy->count();
+ int row = count / 2;
+ int column = count % 2;
+
+ landscapePolicy->addItem(item, row, column);
+ portraitPolicy->addItem(item);
+}
+
+void MKeyboardSettingsWidget::retranslateUi()
+{
+ updateTitle();
+ MWidget::retranslateUi();
+}
+
+void MKeyboardSettingsWidget::updateTitle()
+{
+ if (!settingsObject || !selectedKeyboardsItem)
+ return;
+ QStringList keyboards = settingsObject->selectedKeyboards().values();
+ //% "Installed keyboards (%1)"
+ QString title = qtTrId("qtn_txts_installed_keyboards")
+ .arg(keyboards.count());
+ selectedKeyboardsItem->setTitle(title);
+ QString brief;
+ if (keyboards.count() > 0) {
+ foreach(const QString &keyboard, keyboards) {
+ if (!brief.isEmpty())
+ brief += QString(", ");
+ brief += keyboard;
+ }
+ } else {
+ //% "No keyboards installed"
+ brief = qtTrId("qtn_txts_no_keyboards");
+ }
+ selectedKeyboardsItem->setSubtitle(brief);
+
+ if (keyboardDialog) {
+ keyboardDialog->setTitle(title);
+ }
+}
+
+void MKeyboardSettingsWidget::connectSlots()
+{
+ connect(this, SIGNAL(visibleChanged()),
+ this, SLOT(handleVisibilityChanged()));
+
+ if (!settingsObject || !errorCorrectionSwitch)
+ return;
+
+ connect(errorCorrectionSwitch, SIGNAL(toggled(bool)),
+ this, SLOT(setErrorCorrectionState(bool)));
+ connect(settingsObject, SIGNAL(errorCorrectionChanged()),
+ this, SLOT(syncErrorCorrectionState()));
+ connect(settingsObject, SIGNAL(selectedKeyboardsChanged()),
+ this, SLOT(updateTitle()));
+ connect(settingsObject, SIGNAL(selectedKeyboardsChanged()),
+ this, SLOT(updateKeyboardSelectionModel()));
+}
+
+void MKeyboardSettingsWidget::showKeyboardList()
+{
+ if (!settingsObject || !keyboardDialog) {
+ QStringList keyboards = settingsObject->selectedKeyboards().values();
+ //% "Installed keyboards (%1)"
+ QString keyboardTitle = qtTrId("qtn_txts_installed_keyboards")
+ .arg(keyboards.count());
+ keyboardDialog = new MDialog(keyboardTitle, M::NoStandardButton);
+
+ keyboardList = new MList(keyboardDialog);
+ MKeyboardCellCreator *cellCreator = new MKeyboardCellCreator();
+ keyboardList->setCellCreator(cellCreator);
+ QStandardItemModel *model = new QStandardItemModel();
+ model->sort(0);
+ keyboardList->setItemModel(model);
+ keyboardList->setSelectionMode(MList::MultiSelection);
+ keyboardList->setSelectionModel(new QItemSelectionModel(model, this));
+ keyboardDialog->setCentralWidget(keyboardList);
+
+ connect(keyboardList, SIGNAL(itemClicked(const QModelIndex &)),
+ this, SLOT(updateSelectedKeyboards(const QModelIndex &)));
+ }
+ updateKeyboardModel();
+ keyboardDialog->exec();
+}
+
+void MKeyboardSettingsWidget::updateKeyboardModel()
+{
+ if (!settingsObject || !keyboardList)
+ return;
+ //always reload available layouts in case user install/remove some layouts
+ settingsObject->readAvailableKeyboards();
+ QStandardItemModel *model = static_cast<QStandardItemModel*> (keyboardList->itemModel());
+ model->clear();
+ foreach (QString keyboard, settingsObject->availableKeyboards()) {
+ QStandardItem *item = new QStandardItem(keyboard);
+ item->setData(keyboard);
+ model->appendRow(item);
+ }
+ updateKeyboardSelectionModel();
+}
+
+void MKeyboardSettingsWidget::updateKeyboardSelectionModel()
+{
+ if (!settingsObject || !keyboardList)
+ return;
+ QStandardItemModel *model = static_cast<QStandardItemModel*> (keyboardList->itemModel());
+ foreach (const QString &keyboard, settingsObject->selectedKeyboards().values()) {
+ QList<QStandardItem *> items = model->findItems(keyboard);
+ foreach (const QStandardItem *item, items) {
+ keyboardList->selectionModel()->select(item->index(), QItemSelectionModel::Select);
+ }
+ }
+}
+
+void MKeyboardSettingsWidget::updateSelectedKeyboards(const QModelIndex &index)
+{
+ if (!settingsObject || !index.isValid() || !keyboardList
+ || !keyboardList->selectionModel())
+ return;
+
+ QStringList updatedKeyboardTitles;
+ foreach (const QModelIndex &i, keyboardList->selectionModel()->selectedIndexes()) {
+ updatedKeyboardTitles << i.data(Qt::DisplayRole).toString();
+ }
+ if (updatedKeyboardTitles.isEmpty()) {
+ notifyNoKeyboards();
+ }
+ settingsObject->setSelectedKeyboards(updatedKeyboardTitles);
+ //update titles
+ retranslateUi();
+}
+
+void MKeyboardSettingsWidget::setErrorCorrectionState(bool toggled)
+{
+ if (!settingsObject)
+ return;
+ if (toggled != settingsObject->errorCorrection())
+ settingsObject->setErrorCorrection(toggled) ;
+}
+
+void MKeyboardSettingsWidget::syncErrorCorrectionState()
+{
+ if (!settingsObject)
+ return;
+ const bool errorCorrectionState = settingsObject->errorCorrection();
+ if (errorCorrectionSwitch
+ && errorCorrectionSwitch->isChecked() != errorCorrectionState) {
+ errorCorrectionSwitch->setChecked(errorCorrectionState);
+ }
+}
+
+void MKeyboardSettingsWidget::notifyNoKeyboards()
+{
+ MInfoBanner *noKeyboardsNotification = new MInfoBanner(MInfoBanner::Information);
+ //% "No keyboards installed"
+ noKeyboardsNotification->setBodyText(qtTrId("qtn_txts_no_keyboards"));
+ noKeyboardsNotification->appear(MSceneWindow::DestroyWhenDone);
+ QTimer::singleShot(1000, noKeyboardsNotification, SLOT(disappear()));
+}
+
+void MKeyboardSettingsWidget::handleVisibilityChanged()
+{
+ // This is a workaround to hide settings dialog when keyboard is hidden.
+ // And it could be removed when NB#177922 is fixed.
+ if (!isVisible() && keyboardDialog && keyboardDialog->isVisible()) {
+ // reject settings dialog if the visibility of settings widget
+ // is changed from shown to hidden.
+ keyboardDialog->reject();
+ }
+}
--- m-keyboard/widgets/mkeyboardsettingswidget.h
+++ m-keyboard/widgets/mkeyboardsettingswidget.h
+/* * This file is part of m-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef MKEYBOARDSETTINGSWIDGET_H
+#define MKEYBOARDSETTINGSWIDGET_H
+
+#include <QObject>
+#include <MWidget>
+#include "mkeyboardsettings.h"
+
+class QGraphicsItem;
+class QGraphicsLayoutItem;
+class MContentItem;
+class MButton;
+class MLabel;
+class MDialog;
+class MList;
+class QModelIndex;
+class MGridLayoutPolicy;
+class MLinearLayoutPolicy;
+
+class MKeyboardSettingsWidget : public MWidget
+{
+ Q_OBJECT
+public:
+ MKeyboardSettingsWidget(MKeyboardSettings *, QGraphicsItem *parent = 0);
+ virtual ~MKeyboardSettingsWidget();
+
+protected:
+ //! reimp
+ virtual void retranslateUi();
+ //! reimp_end
+
+private slots:
+ void showKeyboardList();
+ void updateTitle();
+ void updateKeyboardSelectionModel();
+ void updateSelectedKeyboards(const QModelIndex &);
+ void setErrorCorrectionState(bool toggled);
+ void syncErrorCorrectionState();
+ void handleVisibilityChanged();
+
+private:
+ void buildUi();
+ void addItem(QGraphicsLayoutItem *item);
+ void updateKeyboardModel();
+ void notifyNoKeyboards();
+ void connectSlots();
+
+ MKeyboardSettings *settingsObject;
+ MGridLayoutPolicy *landscapePolicy;
+ MLinearLayoutPolicy *portraitPolicy;
+ MButton *errorCorrectionSwitch;
+ MLabel *errorCorrectionLabel;
+ MDialog *keyboardDialog;
+ MList *keyboardList;
+ MContentItem *selectedKeyboardsItem;
+};
+
+#endif
--- m-keyboard/widgets/mtoolbarbutton.cpp
+++ m-keyboard/widgets/mtoolbarbutton.cpp
@@ -15,16 +15,47 @@
*/
#include "mtoolbarbutton.h"
+#include "mtoolbarbuttonview.h"
+#include <mtoolbaritem.h>
#include <MButton>
#include <QFileInfo>
#include <QPixmap>
#include <QDebug>
-MToolbarButton::MToolbarButton(QGraphicsItem *parent)
+MToolbarButton::MToolbarButton(QSharedPointer<MToolbarItem> item,
+ QGraphicsItem *parent)
: MButton(parent),
icon(0),
- sizePercent(100)
+ sizePercent(100),
+ itemPtr(item)
{
+ setView(new MToolbarButtonView(this));
+
+ if (!item->iconId().isEmpty()){
+ setIconID(item->iconId());
+ } else {
+ sizePercent = itemPtr->size();
+ setIconFile(itemPtr->icon());
+ }
+
+ if (!item->textId().isEmpty()) {
+ setText(qtTrId(itemPtr->textId().toUtf8().data()));
+ } else {
+ setText(itemPtr->text());
+ }
+ setCheckable(item->toggle());
+ if (itemPtr->toggle()) {
+ setChecked(itemPtr->pressed());
+
+ connect(this, SIGNAL(clicked(bool)),
+ itemPtr.data(), SLOT(setPressed(bool)));
+ }
+ setVisible(item->isVisible());
+
+ connect(this, SIGNAL(clicked(bool)),
+ this, SLOT(onClick()));
+ connect(itemPtr.data(), SIGNAL(propertyChanged(const QString&)),
+ this, SLOT(updateData(const QString&)));
}
MToolbarButton::~MToolbarButton()
@@ -65,7 +96,8 @@
// kludge controller shouldn't really do painting.
// but this is neccesary now to support drawing the custom icon on the button.
MButton::paint(painter, option, widget);
- if (icon) {
+ if (iconID().isEmpty() && icon) {
+ // TODO: to use style specified in css.
// scale the icon to limit it insize button according sizePercent and button boundingRect
// but keep the icon's origin ratio.
QSizeF size = boundingRect().size();
@@ -78,3 +110,35 @@
painter->drawPixmap(iconRect, *icon, QRectF(icon->rect()));
}
}
+
+QSharedPointer<MToolbarItem> MToolbarButton::item()
+{
+ return itemPtr;
+}
+
+void MToolbarButton::updateData(const QString &attribute)
+{
+ if (attribute == "icon") {
+ setIconFile(itemPtr->icon());
+ } else if (attribute == "iconId") {
+ setIconID(itemPtr->iconId());
+ } else if (attribute == "text") {
+ setText(itemPtr->text());
+ } else if (attribute == "textId") {
+ setText(qtTrId(itemPtr->textId().toUtf8().data()));
+ } else if (attribute == "pressed" && itemPtr->toggle()) {
+ setChecked(itemPtr->pressed());
+ } else if (attribute == "visible") {
+ setVisible(itemPtr->isVisible());
+ emit availabilityChanged();
+ } else if (attribute == "size") {
+ sizePercent = itemPtr->size();
+ update();
+ }
+}
+
+void MToolbarButton::onClick()
+{
+ emit clicked(itemPtr.data());
+}
+
--- m-keyboard/widgets/mtoolbarbutton.h
+++ m-keyboard/widgets/mtoolbarbutton.h
@@ -18,24 +18,29 @@
#define MTOOLBARBUTTON_H
#include <MButton>
+#include <QSharedPointer>
+
/*!
* \class MToolbarWidget
* \brief MToolbarWidget is provide for the buttons in the input method toolbar.
*
- * MToolbarWidget is inherit from MButton. It can use the icon which is not in current theme,
- * by setIcon() with the absolute file name of the icon. And the icon will be scaled according
- * setIconPercent() and button size.
+ * MToolbarWidget inherits from MButton. It can not only use the iconID, but also use the icon
+ * which is not in current theme, by setIcon() with the absolute file name of the icon, and the
+ * icon will be scaled according setIconPercent() and button size.
*/
class QPixmap;
+class MToolbarItem;
class MToolbarButton : public MButton
{
Q_OBJECT
+ Q_DISABLE_COPY(MToolbarButton)
+
public:
/*!
* \Brief Constructor
*/
- explicit MToolbarButton(QGraphicsItem *parent = 0);
+ explicit MToolbarButton(QSharedPointer<MToolbarItem> item, QGraphicsItem *parent = 0);
//! Destructor
virtual ~MToolbarButton();
@@ -61,10 +66,36 @@
QWidget *widget = 0);
//! \reimp_end
+ //! Return pointer to corresponding toolbar item.
+ QSharedPointer<MToolbarItem> item();
+
+signals:
+ /*!
+ * \brief Emitted when button is clicked.
+ * \param item Pointer to corresponding toolbar item.
+ *
+ * Warning: do not store pointer which is used as parameter for this signal,
+ * call MToolbarItem::item() if you need to get pointer to toolbar item.
+ */
+ void clicked(MToolbarItem *item);
+
+ //! \brief Emitted when visibility (in a sense of the button being available
+ //! or not) changes.
+ void availabilityChanged();
+
+private slots:
+ //! Update button's properties when properties of toolbar item are updated.
+ void updateData(const QString &attribute);
+
+ //! Emits clicked(MToolbarItem *) when base class emits clicked(bool)
+ void onClick();
+
private:
QPixmap *icon;
QString iconFile;
int sizePercent;
+ QSharedPointer<MToolbarItem> itemPtr;
+
friend class Ut_MImToolbar;
};
--- m-keyboard/widgets/mtoolbarbuttonstyle.h
+++ m-keyboard/widgets/mtoolbarbuttonstyle.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef TOOLBAR_BUTTON_H
+#define TOOLBAR_BUTTON_H
+
+#include <mbuttoniconstyle.h>
+
+// Inheriting from MWidgetStyle crashes when it tries to set the button's label font!
+class M_EXPORT MToolbarButtonStyle : public MButtonIconStyle
+{
+ Q_OBJECT
+ M_STYLE(MToolbarButtonStyle)
+};
+
+class M_EXPORT MToolbarButtonStyleContainer : public MButtonIconStyleContainer
+{
+ M_STYLE_CONTAINER(MToolbarButtonStyle)
+};
+
+#endif
+
--- m-keyboard/widgets/mtoolbarbuttonview.cpp
+++ m-keyboard/widgets/mtoolbarbuttonview.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "mtoolbarbuttonview.h"
+#include "mtoolbarbutton.h"
+
+MToolbarButtonView::MToolbarButtonView(MToolbarButton *controller)
+ : MButtonView(controller)
+{
+}
+
--- m-keyboard/widgets/mtoolbarbuttonview.h
+++ m-keyboard/widgets/mtoolbarbuttonview.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef MTOOLBARBUTTONVIEW_H
+#define MTOOLBARBUTTONVIEW_H
+
+#include <MButtonView>
+#include "mtoolbarbuttonstyle.h"
+
+class MToolbarButton;
+
+class MToolbarButtonView : public MButtonView
+{
+ Q_OBJECT
+ M_VIEW(MButtonModel, MToolbarButtonStyle)
+
+public:
+ explicit MToolbarButtonView(MToolbarButton *controller);
+};
+
+#endif
+
--- m-keyboard/widgets/mtoolbarlabel.cpp
+++ m-keyboard/widgets/mtoolbarlabel.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "mtoolbarlabel.h"
+#include <mtoolbaritem.h>
+
+MToolbarLabel::MToolbarLabel(QSharedPointer<MToolbarItem> item,
+ QGraphicsItem *parent)
+ : MLabel(parent),
+ itemPtr(item)
+{
+ if (!item->textId().isEmpty()) {
+ setText(qtTrId(item->textId().toUtf8().data()));
+ } else {
+ setText(item->text());
+ }
+ setVisible(item->isVisible());
+
+ connect(item.data(), SIGNAL(propertyChanged(const QString&)),
+ this, SLOT(updateData(const QString&)));
+}
+
+MToolbarLabel::~MToolbarLabel()
+{
+}
+
+QSharedPointer<MToolbarItem> MToolbarLabel::item()
+{
+ return itemPtr;
+}
+
+void MToolbarLabel::updateData(const QString &attribute)
+{
+ if (attribute == "text") {
+ setText(itemPtr->text());
+ } else if (attribute == "textId") {
+ setText(qtTrId(itemPtr->textId().toUtf8().data()));
+ } else if (attribute == "visible") {
+ setVisible(itemPtr->isVisible());
+ emit availabilityChanged();
+ }
+}
+
--- m-keyboard/widgets/mtoolbarlabel.h
+++ m-keyboard/widgets/mtoolbarlabel.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef MTOOLBARLABEL_H
+#define MTOOLBARLABEL_H
+
+#include <MLabel>
+#include <QSharedPointer>
+
+/*!
+ * \class MToolbarLabel
+ * \brief MToolbarLabel is provided for the labelss in the input method toolbar.
+ *
+ * MToolbarLabel is inherit from MLabel. It is used to show text only.
+ */
+class MToolbarItem;
+
+class MToolbarLabel : public MLabel
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(MToolbarLabel)
+
+public:
+ /*!
+ * \Brief Constructor
+ */
+ explicit MToolbarLabel(QSharedPointer<MToolbarItem> item, QGraphicsItem *parent = 0);
+
+ //! Destructor
+ virtual ~MToolbarLabel();
+
+ //! Return pointer to corresponding toolbar item.
+ QSharedPointer<MToolbarItem> item();
+
+signals:
+ //! \brief Emitted when visibility (in a sense of the label being available
+ //! or not) changes.
+ void availabilityChanged();
+
+private slots:
+ //! Update label's properties when properties of toolbar item are updated.
+ void updateData(const QString &attribute);
+
+private:
+ //! MToolbarItem is used as model for this label.
+ QSharedPointer<MToolbarItem> itemPtr;
+};
+
+#endif
+
--- m-keyboard/widgets/mvirtualkeyboard.cpp
+++ m-keyboard/widgets/mvirtualkeyboard.cpp
@@ -25,6 +25,13 @@
#include "notification.h"
#include "vkbdatakey.h"
#include "mimtoolbar.h"
+#include "ikeybutton.h"
+#include "keyevent.h"
+#include "keyeventhandler.h"
+#include "grip.h"
+#include "sharedhandlearea.h"
+
+#include <mtoolbardata.h>
#include <QDebug>
#include <QPainter>
@@ -41,19 +48,26 @@
#include <MApplication>
+namespace
+{
+ // This GConf item defines whether multitouch is enabled or disabled
+ const char * const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
+}
+
const QString MVirtualKeyboard::WordSeparators("-.,!? \n");
MVirtualKeyboard::MVirtualKeyboard(const LayoutsManager &layoutsManager,
- QGraphicsWidget *parent)
+ const MVirtualKeyboardStyleContainer *styleContainer,
+ QGraphicsWidget *parent)
: MWidget(parent),
mainLayout(new QGraphicsLinearLayout(Qt::Vertical, this)),
currentLevel(0),
numLevels(2),
activity(Inactive),
- styleContainer(0),
+ styleContainer(styleContainer),
sceneManager(MPlainWindow::instance()->sceneManager()),
- shiftLevel(ShiftOff),
+ shiftLevel(ModifierClearState),
currentLayoutType(LayoutData::General),
currentOrientation(sceneManager->orientation()),
hideShowByFadingOnly(false),
@@ -72,14 +86,21 @@
setObjectName("MVirtualKeyboard");
hide();
- styleContainer = new MVirtualKeyboardStyleContainer;
- styleContainer->initialize(objectName(), "MVirtualKeyboardView", 0);
-
notification = new Notification(styleContainer, this);
- createSwitcher();
+ eventHandler = new KeyEventHandler(this);
+ connect(eventHandler, SIGNAL(keyPressed(const KeyEvent &)),
+ this, SIGNAL(keyPressed(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(keyReleased(const KeyEvent &)),
+ this, SIGNAL(keyReleased(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(keyClicked(const KeyEvent &)),
+ this, SIGNAL(keyClicked(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(shiftPressed(bool)),
+ this, SLOT(setFunctionRowState(bool)));
- createToolbar();
+ enableMultiTouch = MGConfItem(MultitouchSettings).value().toBool();
+
+ createSwitcher();
setupTimeLine();
@@ -88,10 +109,23 @@
setMinimumWidth(0);
// add stuff to the layout
+
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
- mainLayout->addItem(imToolbar);
- mainLayout->setAlignment(imToolbar, Qt::AlignCenter);
+
+ createToolbar();
+
+ sharedHandleArea = new SharedHandleArea(*imToolbar);
+ sharedHandleArea->setZValue(-1); // popup should be on top of sharedHandleArea
+ connect(sharedHandleArea, SIGNAL(regionUpdated()), this, SLOT(organizeContentAndSendRegion()));
+ mainLayout->addItem(sharedHandleArea);
+ connectHandle(*sharedHandleArea);
+
+ Grip &keyboardGrip = *new Grip(this);
+ keyboardGrip.setZValue(-1); // popup should be on top of keyboardGrip
+ keyboardGrip.setObjectName("KeyboardHandle");
+ mainLayout->addItem(&keyboardGrip);
+ connectHandle(keyboardGrip);
mainLayout->addItem(mainKeyboardSwitcher); // start in qwerty
@@ -122,9 +156,24 @@
delete notification;
notification = 0;
+}
+
+
+template <class T>
+void MVirtualKeyboard::connectHandle(const T &handle)
+{
+ connect(&handle, SIGNAL(flickLeft(const FlickGesture &)), this, SLOT(flickLeftHandler()));
+ connect(&handle, SIGNAL(flickRight(const FlickGesture &)), this, SLOT(flickRightHandler()));
+ connect(&handle, SIGNAL(flickDown(const FlickGesture &)), this, SLOT(handleHandleFlickDown(const FlickGesture &)));
+}
+
- delete styleContainer;
- styleContainer = 0;
+void MVirtualKeyboard::handleHandleFlickDown(const FlickGesture &/* gesture */)
+{
+ if (activeState == OnScreen) {
+ hideKeyboard();
+ emit userInitiatedHide();
+ }
}
@@ -157,15 +206,13 @@
void MVirtualKeyboard::createToolbar()
{
- imToolbar = new MImToolbar(style(), this);
+ imToolbar = new MImToolbar(style());
// Set z value below default level (0.0) so popup will be on top of toolbar.
// More correct way to fix this, though more difficult, would be to have only one
// popup instance in dvkb and set its z value higher.
imToolbar->setZValue(-1.0);
- connect(imToolbar, SIGNAL(regionUpdated()),
- this, SLOT(sendVKBRegion()));
connect(imToolbar, SIGNAL(copyPasteRequest(CopyPasteState)),
this, SIGNAL(copyPasteRequest(CopyPasteState)));
connect(imToolbar, SIGNAL(sendKeyEventRequest(const QKeyEvent &)),
@@ -176,9 +223,9 @@
this, SIGNAL(copyPasteClicked(CopyPasteState)));
}
-void MVirtualKeyboard::showToolbarWidget(qlonglong id)
+void MVirtualKeyboard::showToolbarWidget(QSharedPointer<const MToolbarData> toolbar)
{
- imToolbar->showToolbarWidget(id);
+ imToolbar->showToolbarWidget(toolbar);
}
void MVirtualKeyboard::hideToolbarWidget()
@@ -192,7 +239,7 @@
mTimestamp("MVirtualKeyboard", "start");
// The second item in layout holds the currently used keyboard. Draw under it.
- const QRectF backgroundGeometry = layout()->itemAt(1)->geometry();
+ const QRectF backgroundGeometry = layout()->itemAt(KeyboardIndex)->geometry();
if (MApplication::softwareRendering()) {
if (backgroundPixmap.isNull()
@@ -233,35 +280,39 @@
MVirtualKeyboard::switchLevel()
{
switch (shiftLevel) {
- case ShiftOff:
+ case ModifierClearState:
currentLevel = 0;
break;
- case ShiftOn:
+ case ModifierLatchedState:
currentLevel = 1;
break;
- case ShiftLock:
+ case ModifierLockedState:
currentLevel = 1;
break;
}
- const bool capsLock = (shiftLevel == ShiftLock);
+ const bool capsLock = (shiftLevel == ModifierLockedState);
for (int i = 0; i < mainKeyboardSwitcher->count(); ++i) {
// the subwidgets have main section as first item in their layout, function row as second.
// handling main section:
static_cast<KeyButtonArea *>(mainKeyboardSwitcher->widget(i)->layout()->itemAt(0))->
- switchLevel(currentLevel, capsLock);
+ switchLevel(currentLevel);
- // TODO: When introducing multitouch we should make function row to change level
- // according to pressed state of the shift button rather than general level.
+ // Function row shift update, level does not change for the layout.
static_cast<KeyButtonArea *>(mainKeyboardSwitcher->widget(i)->layout()->itemAt(1))->
- switchLevel(currentLevel, capsLock);
+ setShiftStatus(currentLevel == 1, capsLock);
+
+ if (!enableMultiTouch) {
+ static_cast<KeyButtonArea *>(mainKeyboardSwitcher->widget(i)->layout()->itemAt(1))->
+ switchLevel(currentLevel);
+ }
}
}
void
-MVirtualKeyboard::setShiftState(ShiftLevel level)
+MVirtualKeyboard::setShiftState(ModifierState level)
{
if (shiftLevel != level) {
shiftLevel = level;
@@ -286,7 +337,7 @@
void
MVirtualKeyboard::flickLeftHandler()
{
- if (!mainKeyboardSwitcher->isRunning()) {
+ if ((activeState == OnScreen) && !mainKeyboardSwitcher->isRunning()) {
if (mainKeyboardSwitcher->isAtBoundary(HorizontalSwitcher::Right)) {
emit pluginSwitchRequired(M::SwitchForward);
return;
@@ -299,9 +350,9 @@
void
-MVirtualKeyboard::flickUpHandler(const KeyBinding *binding)
+MVirtualKeyboard::flickUpHandler(const KeyBinding &binding)
{
- if (binding && binding->action() == KeyBinding::ActionSym) {
+ if (binding.action() == KeyBinding::ActionSym) {
emit showSymbolViewRequested();
}
}
@@ -310,7 +361,7 @@
void
MVirtualKeyboard::flickRightHandler()
{
- if (!mainKeyboardSwitcher->isRunning()) {
+ if ((activeState == OnScreen) && !mainKeyboardSwitcher->isRunning()) {
if (mainKeyboardSwitcher->isAtBoundary(HorizontalSwitcher::Left)) {
emit pluginSwitchRequired(M::SwitchBackward);
return;
@@ -324,6 +375,7 @@
void MVirtualKeyboard::showKeyboard(bool fadeOnly)
{
+ qDebug() << __PRETTY_FUNCTION__ << fadeOnly;
organizeContent(sceneManager->orientation());
if (activity == Active) {
@@ -360,8 +412,9 @@
// something else changes during the animation. But normally the region should be
// the same as the one we send now. We do this initial region sending after
// show() so that we can use region(). We cannot use sendVKBRegion() since region
- // updates are suppressed.
- emit regionUpdated(region().translated(0, regionOffset));
+ // updates are suppressed and because we want to apply the offset.
+ emit regionUpdated(region(true, true).translated(0, regionOffset));
+ emit inputMethodAreaUpdated(region().translated(0, regionOffset));
} else if (hideShowByFadingOnly) {
// fade() doesn't alter the position when we're just fading
setPos(0, sceneManager->visibleSceneSize().height() - actualHeight());
@@ -397,7 +450,7 @@
void MVirtualKeyboard::resetState()
{
// Default state for shift is ShiftOff.
- setShiftState(ShiftOff);
+ setShiftState(ModifierClearState);
// Dead keys are unlocked in KeyButtonArea::onHide().
// As long as this method is private, and only called from
@@ -420,7 +473,7 @@
int result = size().height();
if ((activeState != OnScreen)) {
- result = imToolbar->size().height();
+ result = dynamic_cast<QGraphicsWidget *>(mainLayout->itemAt(SharedHandleAreaIndex))->size().height();
}
return result;
@@ -436,12 +489,15 @@
recreateKeyboards();
mainKeyboardSwitcher->setCurrent(index);
+ // load proper layout
+ imToolbar->reload();
+
// invalidate layouts so we get updated size infos
- mainLayout->invalidate();
numberKeyboard->layout()->invalidate();
phoneNumberKeyboard->layout()->invalidate();
}
+ mainLayout->invalidate();
resize(MPlainWindow::instance()->visibleSceneSize().width(), mainLayout->preferredHeight());
if ((activity == Active) && (showHideTimeline.state() != QTimeLine::Running)) {
setPos(0, sceneManager->visibleSceneSize().height() - actualHeight());
@@ -487,6 +543,15 @@
}
+void MVirtualKeyboard::organizeContentAndSendRegion()
+{
+ if (isVisible()) {
+ organizeContent(currentOrientation);
+ sendVKBRegion();
+ }
+}
+
+
void MVirtualKeyboard::sendVKBRegion()
{
regionUpdateRequested = true;
@@ -494,24 +559,30 @@
if (!sendRegionUpdates)
return;
- emit regionUpdated(region());
+ emit regionUpdated(region(true, true));
+ emit inputMethodAreaUpdated(region());
}
-QRegion MVirtualKeyboard::region(const bool includeToolbar) const
+QRegion MVirtualKeyboard::region(const bool notJustMainKeyboardArea,
+ const bool includeExtraInteractiveAreas) const
{
QRegion region;
if (isVisible()) {
imToolbar->layout()->activate();
mainLayout->activate();
- if (includeToolbar) {
- region |= imToolbar->region();
+ if (notJustMainKeyboardArea) {
+ region |= sharedHandleArea->region(includeExtraInteractiveAreas);
}
// Main keyboard area (qwerty/number/etc.)
if (activeState == OnScreen) {
mainLayout->activate();
- region |= mapRectToScene(mainLayout->itemAt(1)->geometry()).toRect();
+ qDebug() << __PRETTY_FUNCTION__ << mainLayout->itemAt(KeyboardIndex)->geometry();
+ region |= mapRectToScene(mainLayout->itemAt(KeyboardIndex)->geometry()).toRect();
+ if (notJustMainKeyboardArea) {
+ region |= mapRectToScene(mainLayout->itemAt(KeyboardHandleIndex)->geometry()).toRect();
+ }
}
}
@@ -525,15 +596,10 @@
}
activeState = newState;
- qDebug() << __PRETTY_FUNCTION__ << newState << imToolbar->geometry() << imToolbar->region();
resetState();
- qDebug() << __PRETTY_FUNCTION__ << imToolbar->geometry() << imToolbar->region();
- static_cast<QGraphicsWidget *>(mainLayout->itemAt(1))->setVisible(newState == OnScreen);
- organizeContent(currentOrientation);
- if (isVisible()) {
- sendVKBRegion();
- }
+ static_cast<QGraphicsWidget *>(mainLayout->itemAt(KeyboardIndex))->setVisible(newState == OnScreen);
+ organizeContentAndSendRegion();
}
MIMHandlerState MVirtualKeyboard::keyboardState() const
@@ -550,8 +616,8 @@
// such as qwerty + function row.
QGraphicsLayout *keyboardLayout = 0;
- QGraphicsLayoutItem *item = mainLayout->itemAt(1);
- if (item == mainKeyboardSwitcher) {
+ QGraphicsLayoutItem *item = mainLayout->itemAt(KeyboardIndex);
+ if (item == mainKeyboardSwitcher && mainKeyboardSwitcher->currentWidget()) {
keyboardLayout = mainKeyboardSwitcher->currentWidget()->layout();
} else {
keyboardLayout = static_cast<QGraphicsWidget *>(item)->layout();
@@ -598,7 +664,8 @@
// Draw keyboard area with inactive color to prevent transparent holes.
reactionMap->setInactiveDrawingValue();
reactionMap->setTransform(this, view);
- reactionMap->fillRectangle(layout()->itemAt(1)->geometry());
+ reactionMap->fillRectangle(layout()->itemAt(KeyboardIndex)->geometry());
+ reactionMap->fillRectangle(layout()->itemAt(KeyboardHandleIndex)->geometry());
if (activeState == OnScreen) {
drawButtonsReactionMaps(reactionMap, view);
@@ -611,7 +678,7 @@
}
-MVirtualKeyboardStyleContainer &MVirtualKeyboard::style()
+const MVirtualKeyboardStyleContainer &MVirtualKeyboard::style() const
{
return *styleContainer;
}
@@ -640,7 +707,7 @@
currentLayoutType = newLayoutType;
// remove what currently is in the keyboard position in the main layout
- QGraphicsLayoutItem *previousItem = mainLayout->itemAt(1);
+ QGraphicsLayoutItem *previousItem = mainLayout->itemAt(KeyboardIndex);
mainLayout->removeItem(previousItem);
static_cast<QGraphicsWidget *>(previousItem)->hide();
@@ -658,7 +725,7 @@
break;
}
- mainLayout->insertItem(1, newWidget);
+ mainLayout->insertItem(KeyboardIndex, newWidget);
if (activeState == OnScreen) {
newWidget->show();
} else {
@@ -666,11 +733,7 @@
}
// resize and update keyboards if needed
- organizeContent(currentOrientation);
-
- if (isVisible()) {
- sendVKBRegion();
- }
+ organizeContentAndSendRegion();
}
void MVirtualKeyboard::suppressRegionUpdate(bool suppress)
@@ -701,9 +764,9 @@
}
-MVirtualKeyboard::ShiftLevel MVirtualKeyboard::shiftStatus() const
+ModifierState MVirtualKeyboard::shiftStatus() const
{
- return ShiftLevel(shiftLevel);
+ return ModifierState(shiftLevel);
}
@@ -747,7 +810,7 @@
// NOTE: Switcher already has correct index if language change was
// initiated by a flick gesture.
if (mainKeyboardSwitcher->count() >= languageIndex) {
- mainKeyboardSwitcher->switchTo(languageIndex);
+ mainKeyboardSwitcher->setCurrent(languageIndex);
}
}
}
@@ -775,6 +838,12 @@
languageIndex = 0;
}
}
+
+ // TODO: we should simplify the whole languageReset(). Now
+ // MVirtualKeyboard manages currentLanguage and HorizontalSwitcher also
+ // manages its current widget index. We always have to synchronize
+ // both of them if one is changed (in the right order, too).
+ currentLanguage = "";
}
recreateKeyboards();
@@ -824,7 +893,7 @@
// All sections may not be of the same height so we send a region just in
// case. That also causes reaction maps to be redrawn.
- sendVKBRegion();
+ organizeContentAndSendRegion();
}
@@ -857,14 +926,12 @@
KeyButtonArea *mainSection = createMainSectionView(language, LayoutData::General,
currentOrientation);
- mainSection->setObjectName("VirtualKeyboardMainRow");
KeyButtonArea *functionRow = createSectionView(language, LayoutData::General,
currentOrientation,
LayoutData::functionkeySection,
KeyButtonArea::ButtonSizeFunctionRow,
false, languagePage);
- functionRow->setObjectName("VirtualKeyboardFunctionRow");
if (mainSection == 0 || functionRow == 0) {
qCritical("Problem loading language to switcher");
@@ -874,6 +941,9 @@
continue;
}
+ mainSection->setObjectName("VirtualKeyboardMainRow");
+ functionRow->setObjectName("VirtualKeyboardFunctionRow");
+
languageLayout->addItem(mainSection);
languageLayout->addItem(functionRow);
@@ -919,33 +989,29 @@
KeyButtonArea *view = new SingleWidgetButtonArea(styleContainer, layoutSection,
sizeScheme, usePopup, parent);
- Q_ASSERT(view);
- connect(view, SIGNAL(keyPressed(const KeyEvent &)),
- this, SIGNAL(keyPressed(const KeyEvent &)));
-
- connect(view, SIGNAL(keyReleased(const KeyEvent &)),
- this, SIGNAL(keyReleased(const KeyEvent &)));
-
- connect(view, SIGNAL(keyClicked(const KeyEvent &)),
- this, SIGNAL(keyClicked(const KeyEvent &)));
+ eventHandler->addEventSource(view);
connect(view, SIGNAL(flickDown()), this, SLOT(hideKeyboard()));
connect(view, SIGNAL(flickDown()), this, SIGNAL(userInitiatedHide()));
- connect(view, SIGNAL(flickUp(const KeyBinding *)),
- this, SLOT(flickUpHandler(const KeyBinding *)));
+ connect(view, SIGNAL(flickUp(KeyBinding)),
+ this, SLOT(flickUpHandler(KeyBinding)));
return view;
}
+void MVirtualKeyboard::setFunctionRowState(bool shiftPressed)
+{
+ if (enableMultiTouch) {
+ //TODO: time treshold to avoid flickering?
+ static_cast<KeyButtonArea *>(mainKeyboardSwitcher->currentWidget()->layout()->itemAt(1))->
+ switchLevel(shiftPressed ? 1 : 0);
+ }
+}
void MVirtualKeyboard::setCopyPasteButton(bool copyAvailable, bool pasteAvailable)
{
imToolbar->setCopyPasteButton(copyAvailable, pasteAvailable);
- organizeContent(currentOrientation);
- if (isVisible()) {
- sendVKBRegion();
- }
}
void MVirtualKeyboard::setSelectionStatus(bool hasSelection)
@@ -978,13 +1044,11 @@
currentOrientation, LayoutData::mainSection,
KeyButtonArea::ButtonSizeEqualExpanding,
false, numberKeyboard);
- numberArea->setObjectName("VirtualKeyboardNumberMainRow");
KeyButtonArea *numberFunctionRow
= createSectionView(defaultLanguage, LayoutData::Number, currentOrientation,
LayoutData::functionkeySection, KeyButtonArea::ButtonSizeFunctionRowNumber,
false, numberKeyboard);
- numberFunctionRow->setObjectName("VirtualKeyboardNumberFunctionRow");
numberLayout->addItem(numberArea);
numberLayout->addItem(numberFunctionRow);
@@ -994,13 +1058,11 @@
currentOrientation, LayoutData::mainSection,
KeyButtonArea::ButtonSizeEqualExpandingPhoneNumber,
false, phoneNumberKeyboard);
- phoneArea->setObjectName("VirtualKeyboardPhoneMainRow");
KeyButtonArea *phoneFunctionArea
= createSectionView(defaultLanguage, LayoutData::PhoneNumber, currentOrientation,
LayoutData::functionkeySection, KeyButtonArea::ButtonSizeFunctionRowNumber,
false, phoneNumberKeyboard);
- phoneFunctionArea->setObjectName("VirtualKeyboardPhoneFunctionRow");
phoneNumberLayout->addItem(phoneArea);
phoneNumberLayout->addItem(phoneFunctionArea);
@@ -1009,6 +1071,11 @@
if (numberArea == 0 || numberFunctionRow == 0 || phoneArea == 0 || phoneFunctionArea == 0) {
qFatal("Error loading number keyboard");
}
+
+ numberArea->setObjectName("VirtualKeyboardNumberMainRow");
+ numberFunctionRow->setObjectName("VirtualKeyboardNumberFunctionRow");
+ phoneArea->setObjectName("VirtualKeyboardPhoneMainRow");
+ phoneFunctionArea->setObjectName("VirtualKeyboardPhoneFunctionRow");
}
void MVirtualKeyboard::showToolbar()
@@ -1067,7 +1134,7 @@
void MVirtualKeyboard::hideMainArea()
{
- QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(mainLayout->itemAt(1));
+ QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(mainLayout->itemAt(KeyboardIndex));
if (item) {
item->hide();
}
@@ -1076,9 +1143,14 @@
void MVirtualKeyboard::showMainArea()
{
- QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(mainLayout->itemAt(1));
+ QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(mainLayout->itemAt(KeyboardIndex));
if (item) {
item->show();
}
}
+void MVirtualKeyboard::setInputMethodMode(M::InputMethodMode mode)
+{
+ KeyButtonArea::setInputMethodMode(mode);
+ sharedHandleArea->setInputMethodMode(mode);
+}
--- m-keyboard/widgets/mvirtualkeyboard.h
+++ m-keyboard/widgets/mvirtualkeyboard.h
@@ -25,7 +25,9 @@
#include "layoutdata.h"
#include <mimhandlerstate.h>
#include <mimdirection.h>
+#include <minputmethodnamespace.h>
#include <MWidget>
+#include <MNamespace>
#include <QPixmap>
#include <QSharedPointer>
#include <QTimeLine>
@@ -45,6 +47,12 @@
class VkbToolbar;
class MImToolbar;
class MReactionMap;
+class KeyEventHandler;
+class MToolbarData;
+class Handle;
+class Grip;
+class FlickGesture;
+class SharedHandleArea;
/*!
\class MVirtualKeyboard
@@ -62,19 +70,13 @@
friend class Ut_MKeyboardHost;
public:
- //! Shift key states
- typedef enum {
- ShiftOff,
- ShiftOn,
- ShiftLock
- } ShiftLevel;
-
-
/*!
* \brief Constructor for creating an virtual keyboard object.
* \param parent Parent object.
*/
- MVirtualKeyboard(const LayoutsManager &layoutsManager, QGraphicsWidget *parent = 0);
+ MVirtualKeyboard(const LayoutsManager &layoutsManager,
+ const MVirtualKeyboardStyleContainer *styleContainer,
+ QGraphicsWidget *parent = 0);
//! Destructor
~MVirtualKeyboard();
@@ -103,15 +105,12 @@
*/
QString selectedLanguage() const;
- //! Getter for style container
- MVirtualKeyboardStyleContainer &style();
-
//! Sets keyboard type according text entry type, type matches M::TextContentType
void setKeyboardType(const int type);
// for unit tests
//! Returns shift key status
- ShiftLevel shiftStatus() const;
+ ModifierState shiftStatus() const;
//! Characters defines word boundaries
static const QString WordSeparators;
@@ -142,19 +141,17 @@
void finalizeOrientationChange();
/*!
- * \brief Shows a custom toolbar with unique \a id.
- * Loads a custom toolbar according \a id, if successfuly loads,
- * the toolbar will be visible when virtual keyboard is shown.
- * \param id Unique identifier of the custom toolbar.
+ * \brief Creates widgets to visualize given \a toolbar.
+ * \param toolbar Pointer to toolbar definition.
*/
- void showToolbarWidget(qlonglong id);
+ void showToolbarWidget(QSharedPointer<const MToolbarData> toolbar);
/*!
* \brief Hides all custom toolbars, this means they are removed from visible virtual keyboard.
*/
void hideToolbarWidget();
- QRegion region(bool includeToolbar = true) const;
+ QRegion region(bool notJustMainKeyboardArea = true, bool includeExtraInteractiveAreas = false) const;
/*!
* \brief Shows or hides some keyboard's widgets depending on keyboard state.
@@ -181,6 +178,9 @@
*/
void switchLanguage(M::InputMethodSwitchDirection direction, bool enableAnimation);
+ //! Set input method mode
+ void setInputMethodMode(M::InputMethodMode mode);
+
public slots:
/*!
* Method to switch level. Changes into next possible level.
@@ -191,7 +191,7 @@
/*!
* Method to set shift state
*/
- void setShiftState(ShiftLevel level);
+ void setShiftState(ModifierState level);
/*!
* Method to Show the keyboard
@@ -230,6 +230,12 @@
private slots:
/*!
+ * \brief Switch function row to upper/lower case
+ * according to given parameter
+ */
+ void setFunctionRowState(bool shiftPressed);
+
+ /*!
* Handler for Right flick operation
*/
void flickRightHandler();
@@ -243,7 +249,7 @@
* \brief Handler for upward flick operation
* \param binding Key binding
*/
- void flickUpHandler(const KeyBinding *binding);
+ void flickUpHandler(const KeyBinding &binding);
/*!
* Method to fade the vkb during transition
@@ -264,12 +270,18 @@
void onSectionSwitched(QGraphicsWidget *previous, QGraphicsWidget *current);
/*!
- * Send \a regionUpdated signal with the current region of this widget and
- * its children combined, unless \a suppressRegionUpdate has been used to
- * suppress updates.
+ * Send \a regionUpdated and \a inputMethodAreaUpdated signals with the
+ * current region of this widget and its children combined, unless \a
+ * suppressRegionUpdate has been used to suppress updates.
*/
void sendVKBRegion();
+ //! \brief Call organizeContent() and sendVKBRegion() if the vkb is visible
+ void organizeContentAndSendRegion();
+
+ //! Handle flick down gesture signals from handle areas
+ void handleHandleFlickDown(const FlickGesture &gesture);
+
signals:
/*!
* \brief Emitted when key is pressed
@@ -297,6 +309,9 @@
//! \see MInputMethodBase::regionUpdated()
void regionUpdated(const QRegion &);
+ //! \see MInputMethodBase::inputMethodAreaUpdated()
+ void inputMethodAreaUpdated(const QRegion &);
+
//! This signal is emitted when input language is changed
//! \param language this is always the language from XML file in unmodified form
void languageChanged(const QString &language);
@@ -344,6 +359,9 @@
private:
+ //! Getter for style container
+ const MVirtualKeyboardStyleContainer &style() const;
+
const LayoutData *currentLayoutModel() const;
/*!
@@ -411,7 +429,18 @@
// keyboard
int actualHeight() const;
+ //! Connect signals from a \a handle widget or whatever provides identical flick signals
+ template <class T>
+ void connectHandle(const T &handleLike);
+
private:
+ //! Main layout indices
+ enum LayoutIndex {
+ SharedHandleAreaIndex,
+ KeyboardHandleIndex,
+ KeyboardIndex
+ };
+
//! Keyboard state wrt. \a showKeyboard / \a hideKeyboard calls.
enum Activity {
Active, // After showKeyboard call
@@ -445,7 +474,7 @@
Activity activity;
//! Current Style being used
- MVirtualKeyboardStyleContainer *styleContainer;
+ const MVirtualKeyboardStyleContainer *styleContainer;
//! Scene manager to get the device width and height
MSceneManager *sceneManager;
@@ -487,7 +516,15 @@
QSharedPointer<QPixmap> backgroundPixmap;
MIMHandlerState activeState;
+
+ KeyEventHandler *eventHandler;
+
+ //! Contains true if multi-touch is enabled
+ bool enableMultiTouch;
+
+ //! Handle area (to be) shared between symbol view and virtual keyboard
+ //! TODO: move this to host
+ SharedHandleArea *sharedHandleArea;
};
#endif
-
--- m-keyboard/widgets/mvirtualkeyboardstyle.h
+++ m-keyboard/widgets/mvirtualkeyboardstyle.h
@@ -69,9 +69,15 @@
M_STYLE_ATTRIBUTE(QString, keyBackgroundId, KeyBackgroundId)
M_STYLE_ATTRIBUTE(QString, keyBackgroundPressedId, KeyBackgroundPressedId)
M_STYLE_ATTRIBUTE(QString, keyBackgroundSelectedId, KeyBackgroundSelectedId)
+ M_STYLE_ATTRIBUTE(int, keyBackgroundBorderLeft, KeyBackgroundBorderLeft)
+ M_STYLE_ATTRIBUTE(int, keyBackgroundBorderRight, KeyBackgroundBorderRight)
+ M_STYLE_ATTRIBUTE(int, keyBackgroundBorderTop, KeyBackgroundBorderTop)
+ M_STYLE_ATTRIBUTE(int, keyBackgroundBorderBottom, KeyBackgroundBorderBottom)
M_STYLE_PTR_ATTRIBUTE(MScalableImage *, keyBackgroundSymIndicatorSym, KeyBackgroundSymIndicatorSym)
M_STYLE_PTR_ATTRIBUTE(MScalableImage *, keyBackgroundSymIndicatorAce, KeyBackgroundSymIndicatorAce)
+ M_STYLE_PTR_ATTRIBUTE(MScalableImage *, keyBackgroundSymIndicatorSymPressed, KeyBackgroundSymIndicatorSymPressed)
+ M_STYLE_PTR_ATTRIBUTE(MScalableImage *, keyBackgroundSymIndicatorAcePressed, KeyBackgroundSymIndicatorAcePressed)
M_STYLE_ATTRIBUTE(QSize, keyBackspaceIconSize, KeyBackspaceIconSize)
M_STYLE_ATTRIBUTE(QString, keyBackspaceIconId, KeyBackspaceIconId)
--- m-keyboard/widgets/notification.cpp
+++ m-keyboard/widgets/notification.cpp
@@ -35,7 +35,7 @@
};
-Notification::Notification(MVirtualKeyboardStyleContainer *style, QGraphicsWidget *parent)
+Notification::Notification(const MVirtualKeyboardStyleContainer *style, QGraphicsWidget *parent)
: MWidget(parent),
styleContainer(style)
{
--- m-keyboard/widgets/notification.h
+++ m-keyboard/widgets/notification.h
@@ -42,7 +42,7 @@
* \brief Constructor for creating notification object.
* \param parent QGraphicsWidget.
*/
- Notification(MVirtualKeyboardStyleContainer *style, QGraphicsWidget *parent);
+ Notification(const MVirtualKeyboardStyleContainer *style, QGraphicsWidget *parent);
//! Destructor
~Notification();
@@ -91,7 +91,7 @@
QFont font;
//! CSS style container
- MVirtualKeyboardStyleContainer *styleContainer;
+ const MVirtualKeyboardStyleContainer *styleContainer;
//! CSS attributes
QColor border;
--- m-keyboard/widgets/sharedhandlearea.cpp
+++ m-keyboard/widgets/sharedhandlearea.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "grip.h"
+#include "handle.h"
+#include "mimtoolbar.h"
+#include "sharedhandlearea.h"
+
+#include <QDebug>
+#include <QGraphicsLinearLayout>
+
+
+SharedHandleArea::SharedHandleArea(MImToolbar &toolbar, QGraphicsWidget *parent)
+ : MWidget(parent),
+ mainLayout(*new QGraphicsLinearLayout(Qt::Vertical, this)),
+ invisibleHandle(*new Handle(this)),
+ toolbarGrip(*new Grip(this)),
+ zeroSizeToolbarGrip(*new QGraphicsWidget(this)),
+ zeroSizeInvisibleHandle(*new QGraphicsWidget(this))
+{
+ mainLayout.setContentsMargins(0, 0, 0, 0);
+ mainLayout.setSpacing(0);
+
+ invisibleHandle.setObjectName("InvisibleHandle");
+ invisibleHandle.hide();
+ zeroSizeInvisibleHandle.setMaximumSize(0, 0);
+ zeroSizeInvisibleHandle.show();
+ mainLayout.addItem(&zeroSizeInvisibleHandle);
+ connectHandle(invisibleHandle);
+
+ toolbarGrip.setObjectName("KeyboardToolbarHandle");
+ toolbarGrip.hide();
+ zeroSizeToolbarGrip.setMaximumSize(0, 0);
+ zeroSizeToolbarGrip.show();
+ mainLayout.addItem(&zeroSizeToolbarGrip);
+ connectHandle(toolbarGrip);
+
+ connect(&toolbar, SIGNAL(availabilityChanged(bool)), this, SLOT(handleToolbarAvailability(bool)));
+
+ Handle &toolbarHandle = *new Handle(this);
+ toolbarHandle.setObjectName("KeyboardToolbarBackgroundHandle");
+ toolbarHandle.setChild(&toolbar);
+ connectHandle(toolbarHandle);
+
+ mainLayout.addItem(&toolbarHandle);
+ mainLayout.setAlignment(&toolbarHandle, Qt::AlignCenter);
+
+ connect(&toolbar, SIGNAL(regionUpdated()), this, SIGNAL(regionUpdated()));
+}
+
+
+SharedHandleArea::~SharedHandleArea()
+{
+}
+
+
+void SharedHandleArea::handleToolbarAvailability(const bool available)
+{
+ QGraphicsWidget &previousItem(*dynamic_cast<QGraphicsWidget *>(
+ mainLayout.itemAt(ToolbarHandleIndex)));
+ mainLayout.removeItem(&previousItem);
+ previousItem.hide();
+ QGraphicsWidget &newItem(available ? toolbarGrip : zeroSizeToolbarGrip);
+ mainLayout.insertItem(ToolbarHandleIndex, &newItem);
+ newItem.setVisible(available);
+ emit regionUpdated();
+}
+
+
+void SharedHandleArea::connectHandle(const Handle &handle)
+{
+ connect(&handle, SIGNAL(flickLeft(const FlickGesture &)), this, SIGNAL(flickLeft(const FlickGesture &)));
+ connect(&handle, SIGNAL(flickRight(const FlickGesture &)), this, SIGNAL(flickRight(const FlickGesture &)));
+ connect(&handle, SIGNAL(flickUp(const FlickGesture &)), this, SIGNAL(flickUp(const FlickGesture &)));
+ connect(&handle, SIGNAL(flickDown(const FlickGesture &)), this, SIGNAL(flickDown(const FlickGesture &)));
+}
+
+
+void SharedHandleArea::setInputMethodMode(const M::InputMethodMode mode)
+{
+ // Toggle invisible gesture handle area on/off
+ QGraphicsWidget &previousItem(*dynamic_cast<QGraphicsWidget *>(
+ mainLayout.itemAt(InvisibleHandleIndex)));
+ mainLayout.removeItem(&previousItem);
+ previousItem.hide();
+ QGraphicsWidget &newItem(mode == M::InputMethodModeDirect ? invisibleHandle : zeroSizeInvisibleHandle);
+ mainLayout.insertItem(InvisibleHandleIndex, &newItem);
+ newItem.setVisible(mode == M::InputMethodModeDirect);
+ emit regionUpdated();
+}
+
+
+QRegion SharedHandleArea::region(const bool includeExtraInteractiveAreas) const
+{
+ QRegion region(mapRectToScene(mainLayout.itemAt(ToolbarHandleIndex)->geometry()).toRect());
+
+ region |= mapRectToScene(mainLayout.itemAt(ToolbarIndex)->geometry()).toRect();
+
+ if (includeExtraInteractiveAreas) {
+ region |= mapRectToScene(mainLayout.itemAt(InvisibleHandleIndex)->geometry()).toRect();
+ }
+
+ return region;
+}
--- m-keyboard/widgets/sharedhandlearea.h
+++ m-keyboard/widgets/sharedhandlearea.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef SHAREDHANDLEAREA_H
+#define SHAREDHANDLEAREA_H
+
+#include <MWidget>
+#include <MNamespace>
+
+class QGraphicsLinearLayout;
+class FlickGesture;
+class MImToolbar;
+class Handle;
+class Grip;
+
+/*!
+ \brief SharedHandleArea represents the handle area shared between the vkb and the symbol
+ view
+
+ The shared handle area contains an invisible handle, toolbar grip and the toolbar (as a
+ child of a handle), in that order.
+*/
+class SharedHandleArea : public MWidget
+{
+ Q_OBJECT
+
+public:
+ /*!
+ * \brief Constructor
+ * \param toolbar toolbar widget
+ * \param parent Parent object.
+ */
+ explicit SharedHandleArea(MImToolbar &toolbar, QGraphicsWidget *parent = 0);
+
+ //! Destructor
+ virtual ~SharedHandleArea();
+
+ //! Set input method mode
+ void setInputMethodMode(M::InputMethodMode mode);
+
+ //! \return region of the widget, including the invisible handle if
+ //! \a includeExtraInteractiveAreas is true
+ QRegion region(bool includeExtraInteractiveAreas = false) const;
+
+signals:
+ void flickUp(const FlickGesture &gesture);
+ void flickDown(const FlickGesture &gesture);
+ void flickLeft(const FlickGesture &gesture);
+ void flickRight(const FlickGesture &gesture);
+
+ void regionUpdated();
+
+private slots:
+ //! Handle changes in toolbar availability
+ void handleToolbarAvailability(bool available);
+
+private:
+ //! Connect signals from a \a handle widget
+ void connectHandle(const Handle &handle);
+
+private:
+ enum LayoutIndex {
+ InvisibleHandleIndex,
+ ToolbarHandleIndex,
+ ToolbarIndex,
+ };
+
+ QGraphicsLinearLayout &mainLayout;
+
+ //! Invisible gesture handle used only in direct mode
+ Handle &invisibleHandle;
+
+ //! Toolbar grip
+ Grip &toolbarGrip;
+
+ //! Dummy widget we use in place of toolbarGrip in the layout when it's not visible
+ QGraphicsWidget &zeroSizeToolbarGrip;
+
+ //! Dummy widget we use in place of the invisible gesture handle when it's
+ //! not ... err, visible (in its usual invisible way)
+ QGraphicsWidget &zeroSizeInvisibleHandle;
+};
+
+#endif
--- m-keyboard/widgets/singlewidgetbutton.cpp
+++ m-keyboard/widgets/singlewidgetbutton.cpp
@@ -27,7 +27,8 @@
SingleWidgetButton::SingleWidgetButton(const VKBDataKey &key,
const MVirtualKeyboardStyleContainer &style,
QGraphicsItem &parent)
- : dataKey(key),
+ : width(0),
+ dataKey(key),
shift(false),
currentLabel(dataKey.binding(false)->label()),
currentState(Normal),
--- m-keyboard/widgets/singlewidgetbuttonarea.cpp
+++ m-keyboard/widgets/singlewidgetbuttonarea.cpp
@@ -37,7 +37,7 @@
#include <mreactionmap.h>
#include <MTheme>
-SingleWidgetButtonArea::SingleWidgetButtonArea(MVirtualKeyboardStyleContainer *style,
+SingleWidgetButtonArea::SingleWidgetButtonArea(const MVirtualKeyboardStyleContainer *style,
QSharedPointer<const LayoutSection> sectionModel,
ButtonSizeScheme buttonSizeScheme,
bool usePopup,
@@ -47,7 +47,7 @@
rowList(sectionModel->rowCount()),
symState(SymIndicatorInactive),
symIndicatorButton(0),
- shiftCapsLock(false),
+ shiftButton(0),
pixmap1(0),
pixmap2(0),
pixmap3(0),
@@ -98,21 +98,22 @@
pixmap2 = MTheme::pixmap(style()->keyBackgroundPressedId(), defaultSize);
pixmap3 = MTheme::pixmap(style()->keyBackgroundSelectedId(), defaultSize);
- keyBackgrounds[0].setPixmap(pixmap1); // normal
- keyBackgrounds[1].setPixmap(pixmap2); // pressed
- keyBackgrounds[2].setPixmap(pixmap3); // selected
-
- // Border size 10 is suitable for all sane size buttons we're using.
- const int border = 10;
- keyBackgrounds[0].setBorders(border, border, border, border);
- keyBackgrounds[1].setBorders(border, border, border, border);
- keyBackgrounds[2].setBorders(border, border, border, border);
+ keyBackgrounds[NormalBackground].setPixmap(pixmap1);
+ keyBackgrounds[KeyPressedBackground].setPixmap(pixmap2);
+ keyBackgrounds[KeySelectedBackground].setPixmap(pixmap3);
+
+ for (int idx = 0; idx < KeyBackgroundTypeCount; ++idx) {
+ keyBackgrounds[idx].setBorders(style()->keyBackgroundBorderLeft(),
+ style()->keyBackgroundBorderRight(),
+ style()->keyBackgroundBorderTop(),
+ style()->keyBackgroundBorderBottom());
+ }
}
SingleWidgetButtonArea::~SingleWidgetButtonArea()
{
// Release any key that might be pressed before destroying them.
- setActiveKey(0);
+ clearActiveKeys();
for (RowIterator rowIter(rowList.begin()); rowIter != rowList.end(); ++rowIter) {
qDeleteAll(rowIter->buttons);
@@ -385,6 +386,7 @@
buildTextLayout();
}
// Draw text next.
+ painter->setPen(style()->fontColor());
textLayout.draw(painter, QPoint());
}
@@ -431,11 +433,22 @@
return 0;
}
+void SingleWidgetButtonArea::setShiftStatus(bool shiftOn, bool capslock)
+{
+ if (shiftButton) {
+ shiftButton->setModifiers(shiftOn);
+ shiftButton->setSelected(capslock);
+ }
+}
+
void SingleWidgetButtonArea::modifiersChanged(const bool shift, const QChar accent)
{
for (RowIterator row(rowList.begin()); row != rowList.end(); ++row) {
foreach (SingleWidgetButton *button, row->buttons) {
- button->setModifiers(shift, accent);
+ // Shift button is separated from the normal level changing.
+ if (button != this->shiftButton) {
+ button->setModifiers(shift, accent);
+ }
}
}
@@ -534,42 +547,33 @@
ISymIndicator *SingleWidgetButtonArea::symIndicator()
{
- return this;
+ return this;
}
// ISymIndicator implementation
void SingleWidgetButtonArea::activateSymIndicator()
{
- // Use same image for all button states for now. Some different graphics may
- // be introduced later for the intermediate step between sym and ace modes.
- // while holding button down.
- const MScalableImage *image = style()->keyBackgroundSymIndicatorSym();
- symIndicatorBackgrounds[0] = image;
- symIndicatorBackgrounds[1] = image;
- symIndicatorBackgrounds[2] = image;
- update();
+ updateIndicatorBackgrounds(style()->keyBackgroundSymIndicatorSym(),
+ style()->keyBackgroundSymIndicatorSymPressed());
if (symState == SymIndicatorInactive) {
// We have changed the text. Sym has two-line text in active mode.
textDirty = true;
}
- symState = AceActive;
+ symState = SymActive;
}
// ISymIndicator implementation
void SingleWidgetButtonArea::activateAceIndicator()
{
- const MScalableImage *image = style()->keyBackgroundSymIndicatorAce();
- symIndicatorBackgrounds[0] = image;
- symIndicatorBackgrounds[1] = image;
- symIndicatorBackgrounds[2] = image;
- update();
+ updateIndicatorBackgrounds(style()->keyBackgroundSymIndicatorAce(),
+ style()->keyBackgroundSymIndicatorAcePressed());
if (symState == SymIndicatorInactive) {
// We have changed the text. Sym has two-line text in active mode.
textDirty = true;
}
- symState = SymActive;
+ symState = AceActive;
}
// ISymIndicator implementation
@@ -583,3 +587,28 @@
}
}
+void SingleWidgetButtonArea::updateIndicatorBackgrounds(const MScalableImage *normal, const MScalableImage *pressed)
+{
+ // Use same image for all button states for now. Some different graphics may
+ // be introduced later for the intermediate step between sym and ace modes.
+ // while holding button down.
+ symIndicatorBackgrounds[NormalBackground] = normal;
+ symIndicatorBackgrounds[KeyPressedBackground] = pressed;
+ symIndicatorBackgrounds[KeySelectedBackground] = normal;
+ update();
+}
+
+void SingleWidgetButtonArea::onThemeChangeCompleted()
+{
+ KeyButtonArea::onThemeChangeCompleted();
+
+ if (symState == SymActive) {
+ updateIndicatorBackgrounds(style()->keyBackgroundSymIndicatorSym(),
+ style()->keyBackgroundSymIndicatorSymPressed());
+ } else if (symState == AceActive) {
+ updateIndicatorBackgrounds(style()->keyBackgroundSymIndicatorAce(),
+ style()->keyBackgroundSymIndicatorAcePressed());
+ }
+
+ buildTextLayout();
+}
--- m-keyboard/widgets/singlewidgetbuttonarea.h
+++ m-keyboard/widgets/singlewidgetbuttonarea.h
@@ -33,7 +33,16 @@
class SingleWidgetButtonArea : public KeyButtonArea, public ISymIndicator
{
public:
- SingleWidgetButtonArea(MVirtualKeyboardStyleContainer *,
+ //! Used to differentiate background images of a button.
+ enum KeyBackgroundType {
+ NormalBackground = 0,
+ KeyPressedBackground = 1,
+ KeySelectedBackground = 2,
+
+ KeyBackgroundTypeCount
+ };
+
+ SingleWidgetButtonArea(const MVirtualKeyboardStyleContainer *,
QSharedPointer<const LayoutSection>,
ButtonSizeScheme buttonSizeScheme = ButtonSizeEqualExpanding,
bool usePopup = false,
@@ -45,6 +54,7 @@
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *view);
virtual QRectF boundingRect() const;
virtual ISymIndicator *symIndicator();
+ virtual void setShiftStatus(bool shiftOn, bool capslock);
// From ISymIndicator
virtual void activateSymIndicator();
@@ -59,6 +69,7 @@
virtual void updateButtonGeometries(int availableWidth, int equalButtonWidth);
virtual IKeyButton *keyAt(const QPoint &pos) const;
virtual void modifiersChanged(bool shift, QChar accent = QChar());
+ virtual void onThemeChangeCompleted();
/*! \reimp_end */
private:
@@ -78,6 +89,9 @@
//! \brief Fetches optimum size image from MTheme to be used in MScalableImage.
void fetchOptimumSizeButtonBackgrounds(QSize size);
+ //! \brief Update indicator backgrounds from current theme.
+ void updateIndicatorBackgrounds(const MScalableImage *normal, const MScalableImage *pressed);
+
struct ButtonRow {
QList<SingleWidgetButton*> buttons;
@@ -89,7 +103,7 @@
int offset;
int cachedWidth; // includes left & right margin
};
-
+
typedef QVector<ButtonRow> ButtonRowList;
typedef ButtonRowList::iterator RowIterator;
typedef ButtonRowList::const_iterator ConstRowIterator;
@@ -98,10 +112,10 @@
ButtonRowList rowList;
//! Normal button backgrounds
- MScalableImage keyBackgrounds[3];
+ MScalableImage keyBackgrounds[KeyBackgroundTypeCount];
//! Special set of button backgrounds for sym state indicator.
- const MScalableImage *symIndicatorBackgrounds[3];
+ const MScalableImage *symIndicatorBackgrounds[KeyBackgroundTypeCount];
//! Current state of the sym indicator
SymIndicatorState symState;
@@ -110,7 +124,8 @@
//! if such exists in the current layout.
const SingleWidgetButton *symIndicatorButton;
- bool shiftCapsLock;
+ //! Shift button is stored here if current layout has a shift button.
+ SingleWidgetButton *shiftButton;
const QPixmap *pixmap1;
const QPixmap *pixmap2;
@@ -123,6 +138,7 @@
#ifdef UNIT_TEST
friend class Ut_KeyButtonArea;
+ friend class Ut_KeyEventHandler;
friend class Bm_KeyButtonArea; //benchmarks
#endif
--- m-keyboard/widgets/symbolview.cpp
+++ m-keyboard/widgets/symbolview.cpp
@@ -20,6 +20,8 @@
#include "horizontalswitcher.h"
#include "layoutsmanager.h"
#include "symbolview.h"
+#include "keyeventhandler.h"
+#include "grip.h"
#include <MSceneManager>
#include <MScalableImage>
@@ -49,11 +51,14 @@
const QString ObjectNameCloseButton("VirtualKeyboardCloseButton");
const QString SymCloseIcon("icon-m-input-methods-close");
+
+ // This GConf item defines whether multitouch is enabled or disabled
+ const char * const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
};
-SymbolView::SymbolView(const LayoutsManager &layoutsManager, MVirtualKeyboardStyleContainer *style,
+SymbolView::SymbolView(const LayoutsManager &layoutsManager, const MVirtualKeyboardStyleContainer *style,
const QString &language, QGraphicsWidget *parent)
: MWidget(parent),
styleContainer(style),
@@ -62,6 +67,8 @@
activity(Inactive),
activePage(0),
shift(0),
+ shiftHeldDown(false),
+ ignoreShiftClick(false),
layoutsMgr(layoutsManager),
pageSwitcher(0),
functionRow(0),
@@ -71,6 +78,18 @@
verticalLayout(*new QGraphicsLinearLayout(Qt::Vertical, this)),
keyAreaLayout(*new QGraphicsLinearLayout(Qt::Vertical))
{
+ eventHandler = new KeyEventHandler(this);
+ connect(eventHandler, SIGNAL(keyPressed(const KeyEvent &)),
+ this, SIGNAL(keyPressed(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(keyReleased(const KeyEvent &)),
+ this, SIGNAL(keyReleased(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(keyClicked(const KeyEvent &)),
+ this, SIGNAL(keyClicked(const KeyEvent &)));
+ connect(eventHandler, SIGNAL(shiftPressed(bool)),
+ this, SLOT(setFunctionRowState(bool)));
+
+ enableMultiTouch = MGConfItem(MultitouchSettings).value().toBool();
+
hide();
setupShowAndHide();
setupLayout();
@@ -99,6 +118,11 @@
verticalLayout.setSpacing(0);
verticalLayout.setContentsMargins(0, 0, 0, 0);
+ Grip &symbolViewGrip = *new Grip(this);
+ symbolViewGrip.setObjectName("KeyboardHandle");
+ verticalLayout.addItem(&symbolViewGrip);
+ connectHandle(symbolViewGrip);
+
keyAreaLayout.setSpacing(style()->spacingVertical());
keyAreaLayout.setContentsMargins(style()->paddingLeft(), style()->paddingTop(),
style()->paddingRight(), style()->paddingBottom());
@@ -106,6 +130,14 @@
verticalLayout.addItem(&keyAreaLayout);
}
+
+void SymbolView::connectHandle(const Handle &handle)
+{
+ connect(&handle, SIGNAL(flickLeft(const FlickGesture &)), this, SLOT(switchToNextPage()));
+ connect(&handle, SIGNAL(flickRight(const FlickGesture &)), this, SLOT(switchToPrevPage()));
+ connect(&handle, SIGNAL(flickDown(const FlickGesture &)), this, SLOT(hideSymbolView()));
+}
+
void SymbolView::reloadContent()
{
// Get layout model which for current language and orientation.
@@ -280,11 +312,6 @@
showTimeLine->start();
- if (mode == FollowMouseShowMode) {
- pageSwitcher->currentWidget()->grabMouse();
- mouseDownKeyArea = true;
- }
-
emit showingUp();
}
@@ -317,8 +344,9 @@
pageSwitcher->setCurrent(0);
showSymbolView();
} else {
+ pageSwitcher->switchTo(id < activePage ? HorizontalSwitcher::Left
+ : HorizontalSwitcher::Right);
activePage = id;
- pageSwitcher->switchTo(activePage);
}
selectedLayout = qobject_cast<KeyButtonArea *>(pageSwitcher->currentWidget());
@@ -381,9 +409,9 @@
functionRow = createKeyButtonArea(layout.section(LayoutData::functionkeySection),
KeyButtonArea::ButtonSizeFunctionRow, false);
- functionRow->setObjectName("SymbolFunctionRow");
if (functionRow) {
+ functionRow->setObjectName("SymbolFunctionRow");
functionRow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
keyAreaLayout.addItem(functionRow);
}
@@ -392,9 +420,12 @@
void SymbolView::addPage(QSharedPointer<const LayoutSection> symbolSection)
{
KeyButtonArea *page = createKeyButtonArea(symbolSection);
- page->setObjectName("SymbolMainRow");
if (page) {
+ page->setObjectName("SymbolMainRow");
+
+ connect(this, SIGNAL(levelSwitched(int)), page, SLOT(switchLevel(int)));
+
connect(page, SIGNAL(flickLeft()), SLOT(switchToNextPage()));
connect(page, SIGNAL(flickRight()), SLOT(switchToPrevPage()));
connect(page, SIGNAL(flickDown()), SLOT(hideSymbolView()));
@@ -420,14 +451,7 @@
keysWidget = new SingleWidgetButtonArea(styleContainer, section, sizeScheme, enablePopup);
keysWidget->setFont(style()->font());
- connect(this, SIGNAL(levelSwitched(int, bool)), keysWidget, SLOT(switchLevel(int, bool)));
-
- connect(keysWidget, SIGNAL(keyClicked(const KeyEvent &)),
- SIGNAL(keyClicked(const KeyEvent &)));
- connect(keysWidget, SIGNAL(keyPressed(const KeyEvent &)),
- SIGNAL(keyPressed(const KeyEvent &)));
- connect(keysWidget, SIGNAL(keyReleased(const KeyEvent &)),
- SIGNAL(keyReleased(const KeyEvent &)));
+ eventHandler->addEventSource(keysWidget);
}
return keysWidget;
}
@@ -449,14 +473,23 @@
reposition(size().toSize().height());
}
-
-void SymbolView::switchLevel(int level, bool capslock)
+void SymbolView::switchLevel(int level)
{
shift = level;
- emit levelSwitched(shift, capslock);
+ if (!enableMultiTouch && functionRow) {
+ functionRow->switchLevel(level);
+ }
+ emit levelSwitched(shift);
updateSymIndicator();
}
+void SymbolView::setShiftStatus(bool shiftOn, bool capslock)
+{
+ if (functionRow) {
+ functionRow->setShiftStatus(shiftOn, capslock);
+ }
+}
+
int SymbolView::currentLevel() const
{
return shift;
@@ -464,7 +497,7 @@
void SymbolView::setLanguage(const QString &lang)
{
- if (lang != currentLanguage) {
+ if (lang != currentLanguage && layoutsMgr.languageList().contains(lang)) {
currentLanguage = lang;
reloadContent();
}
@@ -529,6 +562,13 @@
}
}
+void SymbolView::setFunctionRowState(bool shiftPressed)
+{
+ if (enableMultiTouch && functionRow) {
+ functionRow->switchLevel(shiftPressed ? 1 : 0);
+ }
+}
+
void SymbolView::redrawReactionMaps()
{
if (!scene()) {
@@ -567,7 +607,7 @@
}
-MVirtualKeyboardStyleContainer &SymbolView::style()
+const MVirtualKeyboardStyleContainer &SymbolView::style() const
{
return *styleContainer;
}
@@ -605,7 +645,7 @@
ISymIndicator *symIndicator = functionRow->symIndicator();
if (symIndicator) {
- if (currentLevel() == 0) {
+ if (functionRow->level() == 0) {
QString title = pageTitle(activePage);
if (title == SymLabel) {
@@ -627,8 +667,7 @@
// SymbolView always occupies the same area if opened.
if (isActive()) {
- // add sym characters and function row
- region |= mapRectToScene(keyAreaLayout.geometry()).toRect();
+ region |= mapRectToScene(verticalLayout.geometry()).toRect();
}
return region;
--- m-keyboard/widgets/symbolview.h
+++ m-keyboard/widgets/symbolview.h
@@ -39,7 +39,8 @@
class KeyEvent;
class LayoutSection;
class SymIndicatorButton;
-
+class KeyEventHandler;
+class Handle;
/*!
* \brief SymbolView is used to show different layouts symbols/upper case/lower case
@@ -64,7 +65,7 @@
* \param baseSize QSize
* \param parent Parent object.
*/
- SymbolView(const LayoutsManager &layoutsManager, MVirtualKeyboardStyleContainer *,
+ SymbolView(const LayoutsManager &layoutsManager, const MVirtualKeyboardStyleContainer *,
const QString &language, QGraphicsWidget *parent = 0);
/*!
@@ -77,11 +78,12 @@
void finalizeOrientationChange();
/*!
- * Method to switch layout when shift button is pressed
+ * Method to switch layout level when shift button is pressed
* \param level int 1 for upper case, otherwise 0
- * \param capslock Shift locked state
*/
- void switchLevel(int level, bool capslock);
+ void switchLevel(int level);
+
+ void setShiftStatus(bool shiftOn, bool capslock);
//! Returns current level.
int currentLevel() const;
@@ -156,7 +158,7 @@
signals:
//! Used to broadcast shift state to all pages/KeyButtonAreas.
- void levelSwitched(int, bool);
+ void levelSwitched(int);
/*!
* Emitted on clicked on layout
@@ -203,6 +205,12 @@
void onSwitchStarting(QGraphicsWidget *current, QGraphicsWidget *next);
void switchDone();
+ /*!
+ * \brief Switch function row to upper/lower case
+ * according to given parameter
+ */
+ void setFunctionRowState(bool shiftPressed);
+
private:
//! symbol view state wrt. \a showSymbolView / \a hideSymbolView calls.
enum Activity {
@@ -245,7 +253,7 @@
bool enablePopup = true);
//! Getter for style container
- MVirtualKeyboardStyleContainer &style();
+ const MVirtualKeyboardStyleContainer &style() const;
//! Retrieves title of a symbol section from given page.
QString pageTitle(int pageIndex) const;
@@ -253,9 +261,12 @@
//! \brief Updates the Sym button to visually indicate the current active page.
void updateSymIndicator();
+ //! Connect signals from a \a handle widget
+ void connectHandle(const Handle &handle);
+
private:
//! Current style being used.
- MVirtualKeyboardStyleContainer *styleContainer;
+ const MVirtualKeyboardStyleContainer *styleContainer;
//! Manage animation
QGraphicsItemAnimation *showAnimation;
@@ -279,6 +290,12 @@
//! Case selector: 0 for lower case, 1 for upper case
int shift;
+ //! Keeps track of shift up/down status.
+ bool shiftHeldDown;
+
+ //! When this is set true the next shift click is ignored.
+ bool ignoreShiftClick;
+
const LayoutsManager &layoutsMgr;
HorizontalSwitcher *pageSwitcher;
@@ -300,6 +317,12 @@
//! This layout holds symbol characters and function row.
QGraphicsLinearLayout &keyAreaLayout;
+ //! Pointer to handler for button events
+ KeyEventHandler *eventHandler;
+
+ //! Contains true if multi-touch is enabled
+ bool enableMultiTouch;
+
#ifdef UNIT_TEST
friend class Ut_SymbolView;
#endif
--- m-keyboard/widgets/widgetbar.cpp
+++ m-keyboard/widgets/widgetbar.cpp
@@ -63,6 +63,11 @@
mainLayout.insertItem(index, widget);
mainLayout.setAlignment(widget, Qt::AlignVCenter); // In case we have widgets that differs in height.
+
+ if (-1 != widget->metaObject()->indexOfSignal("availabilityChanged()")) {
+ connect(widget, SIGNAL(availabilityChanged()),
+ this, SLOT(updateLayout()));
+ }
}
void WidgetBar::append(MWidget *widget)
@@ -74,10 +79,17 @@
{
mainLayout.removeItem(widget);
widgets.removeOne(widget);
+ disconnect(widget, 0, this, 0);
}
void WidgetBar::clear()
{
+ foreach (QPointer<MWidget> widget, widgets) {
+ if (widget) {
+ disconnect(widget, 0, this, 0);
+ }
+ }
+
widgets.clear();
while (mainLayout.count() > 0) {
mainLayout.removeAt(0);
@@ -103,6 +115,11 @@
return widgets.indexOf(const_cast<MWidget *>(widget));
}
+void WidgetBar::cleanup()
+{
+ widgets.removeAll(QPointer<MWidget>());
+}
+
void WidgetBar::mousePressEvent(QGraphicsSceneMouseEvent *)
{
// Stop propagating
@@ -114,3 +131,61 @@
style()->paddingRight(), 0);
}
+QSizeF WidgetBar::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ // if there is no visible items in the widgetbar, just return empty size.
+ if (count() <= 0)
+ return QSizeF(0, 0);
+ else
+ return MStylableWidget::sizeHint(which, constraint);
+}
+
+void WidgetBar::updateLayout()
+{
+ MWidget *widget = qobject_cast<MWidget *>(sender());
+
+ if (!widget) {
+ return;
+ }
+
+ int index = widgets.indexOf(widget);
+
+ if (index < 0) {
+ return;
+ }
+
+ if (!widget->isVisible()) {
+ //widget is hidden, so just remove it from layout
+ mainLayout.removeItem(widget);
+ } else {
+ //widget is shown, so put it into layout before closest
+ //visible neighbor on right side
+
+ //find next visible widget
+ ++index;
+ while (index < widgets.count() && !widgets.at(index)->isVisible()) {
+ ++index;
+ }
+ int layoutIndex = 0;
+ if (index < widgets.count()) {
+ //get index of found widget from the layout
+ layoutIndex = layoutIndexOf(widgets.at(index));
+ } else {
+ layoutIndex = mainLayout.count();
+ }
+ mainLayout.insertItem(layoutIndex, widget);
+ }
+}
+
+int WidgetBar::layoutIndexOf(const MWidget *widget) const
+{
+ int layoutIndex = 0;
+
+ while (layoutIndex < mainLayout.count()
+ && mainLayout.itemAt(layoutIndex) != widget) {
+ ++layoutIndex;
+ }
+
+ return layoutIndex;
+}
+
--- m-keyboard/widgets/widgetbar.h
+++ m-keyboard/widgets/widgetbar.h
@@ -24,6 +24,7 @@
#include <MStylableWidget>
#include <QList>
+#include <QPointer>
class MWidget;
class QGraphicsLinearLayout;
@@ -47,6 +48,8 @@
int count() const;
//! \brief Inserts a \a widget to specified \a index.
+ //!
+ //! \a widget must provide availabilityChanged() signal.
void insert(int index, MWidget *widget);
//! \brief Appends \a widget to the right end of the row.
@@ -68,6 +71,19 @@
// if widget was not found
int indexOf(const MWidget *widget) const;
+ //! Remove all pointers to destroyed widgets from
+ // internal lists
+ void cleanup();
+
+public:
+ //! \reimp
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+ //! \reimp_end
+
+private slots:
+ //! Update layout when some child widget is shown or hidden.
+ void updateLayout();
+
protected:
//! \reimp
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
@@ -75,7 +91,11 @@
//! \reimp_end
private:
- typedef QList<MWidget *> WidgetList;
+ //! Return index of given \a widget inside layout
+ int layoutIndexOf(const MWidget *widget) const;
+
+private:
+ typedef QList<QPointer<MWidget> > WidgetList;
QGraphicsLinearLayout &mainLayout;
@@ -84,6 +104,8 @@
WidgetList widgets;
M_STYLABLE_WIDGET(WidgetBarStyle)
+
+ friend class Ut_WidgetBar;
};
#endif
--- m-keyboard/widgets/widgets.pri
+++ m-keyboard/widgets/widgets.pri
@@ -10,6 +10,8 @@
$$WIDGETS_DIR/widgetbarstyle.h \
$$WIDGETS_DIR/flickupbuttonstyle.h \
$$WIDGETS_DIR/mvirtualkeyboardstyle.h \
+ $$WIDGETS_DIR/handlestyle.h \
+ $$WIDGETS_DIR/mtoolbarbuttonstyle.h \
HEADERS += \
$$STYLE_HEADERS \
@@ -21,7 +23,6 @@
$$WIDGETS_DIR/flickupbutton.h \
$$WIDGETS_DIR/flickupbuttonview.h \
$$WIDGETS_DIR/horizontalswitcher.h \
- $$WIDGETS_DIR/layoutmenu.h \
$$WIDGETS_DIR/notification.h \
$$WIDGETS_DIR/symbolview.h \
$$WIDGETS_DIR/keybuttonarea.h \
@@ -33,6 +34,13 @@
$$WIDGETS_DIR/popupfactory.h \
$$WIDGETS_DIR/popupplugin.h \
$$WIDGETS_DIR/mtoolbarbutton.h \
+ $$WIDGETS_DIR/mtoolbarbuttonview.h \
+ $$WIDGETS_DIR/mtoolbarlabel.h \
+ $$WIDGETS_DIR/handle.h \
+ $$WIDGETS_DIR/grip.h \
+ $$WIDGETS_DIR/flickgesture.h \
+ $$WIDGETS_DIR/sharedhandlearea.h \
+ $$WIDGETS_DIR/mkeyboardsettingswidget.h \
SOURCES += \
@@ -44,7 +52,6 @@
$$WIDGETS_DIR/flickupbutton.cpp \
$$WIDGETS_DIR/flickupbuttonview.cpp \
$$WIDGETS_DIR/horizontalswitcher.cpp \
- $$WIDGETS_DIR/layoutmenu.cpp \
$$WIDGETS_DIR/notification.cpp \
$$WIDGETS_DIR/symbolview.cpp \
$$WIDGETS_DIR/keybuttonarea.cpp \
@@ -54,6 +61,13 @@
$$WIDGETS_DIR/popupbase.cpp \
$$WIDGETS_DIR/popupfactory.cpp \
$$WIDGETS_DIR/mtoolbarbutton.cpp \
+ $$WIDGETS_DIR/mtoolbarbuttonview.cpp \
+ $$WIDGETS_DIR/mtoolbarlabel.cpp \
+ $$WIDGETS_DIR/handle.cpp \
+ $$WIDGETS_DIR/grip.cpp \
+ $$WIDGETS_DIR/flickgesture.cpp \
+ $$WIDGETS_DIR/sharedhandlearea.cpp \
+ $$WIDGETS_DIR/mkeyboardsettingswidget.cpp \
INCLUDEPATH += $$WIDGETS_DIR
DEPENDPATH += $$WIDGETS_DIR
--- meego-keyboard.schemas
+++ meego-keyboard.schemas
@@ -7,7 +7,7 @@
<owner>meegotouch</owner>
<type>list</type>
<list_type>string</list_type>
- <default>[en,ar,cs,da,de,en,es,fi,fr,it,nl,no,pl,pt,ru,sv]</default>
+ <default>[en_gb,da,de,es,fi,fr,it,ru,sv]</default>
<locale name="C">
<short>Language list</short>
<long>Language list</long>
@@ -19,7 +19,7 @@
<applyto>/meegotouch/inputmethods/languages/default</applyto>
<owner>meegotouch</owner>
<type>string</type>
- <default>en</default>
+ <default>en_gb</default>
<locale name="C">
<short>Default language</short>
<long>Default language</long>
@@ -31,7 +31,7 @@
<applyto>/meegotouch/inputmethods/correctionenabled</applyto>
<owner>meegotouch</owner>
<type>bool</type>
- <default>true</default>
+ <default>false</default>
<locale name="C">
<short>Whether error correction is enabled</short>
<long>Whether error correction is enabled</long>
--- translations
+++ translations
+(directory)
--- translations/translations.pro
+++ translations/translations.pro
+LANGUAGES =
+CATALOGNAME = virtual-keyboard
+SOURCEDIR = $$PWD/../m-keyboard/ $$PWD/../m-keyboard/widgets/ $$PWD/../m-keyboard/common/
+TRANSLATIONDIR = $$PWD
+TRANSLATION_INSTALLDIR = /usr/share/l10n/meegotouch
+
+CONFIG += meegotouch_defines meegotouch_translations
--- unit_test/bm_keybuttonarea/bm_keybuttonarea.cpp
+++ unit_test/bm_keybuttonarea/bm_keybuttonarea.cpp
@@ -36,7 +36,6 @@
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
}
--- unit_test/bm_symbols/bm_symbols.cpp
+++ unit_test/bm_symbols/bm_symbols.cpp
@@ -36,7 +36,6 @@
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
}
--- unit_test/common_check.pri
+++ unit_test/common_check.pri
@@ -8,7 +8,7 @@
check-xml.commands = ../rt.sh $$TARGET
check-xml.depends += $$TARGET
-QMAKE_CLEAN += *.log *.xml *~
+QMAKE_CLEAN += *.log *~
target.path = /usr/lib/meego-keyboard-tests/$$TARGET
INSTALLS += target
--- unit_test/stubs/mreactionmap_stub.h
+++ unit_test/stubs/mreactionmap_stub.h
@@ -154,6 +154,7 @@
*/
MReactionMap::MReactionMap(QWidget *topLevelWidget, const QString &appIdentifier, QObject *parent)
+ : d(0)
{
gMReactionMapStub->mreactionMapConstructor(topLevelWidget, appIdentifier, parent);
}
--- unit_test/unit_test.pro
+++ unit_test/unit_test.pro
@@ -15,7 +15,6 @@
ut_horizontalswitcher \
ut_layoutsmanager \
ut_mimtoolbar \
- ut_toolbarmanager \
ut_mhardwarekeyboard \
ut_hwkbcharloopsmanager \
bm_keybuttonarea \
--- unit_test/ut_horizontalswitcher/ut_horizontalswitcher.cpp
+++ unit_test/ut_horizontalswitcher/ut_horizontalswitcher.cpp
@@ -20,7 +20,7 @@
#include <QApplication>
#include <QPointer>
-Q_DECLARE_METATYPE(HorizontalSwitcher::Direction);
+Q_DECLARE_METATYPE(HorizontalSwitcher::SwitchDirection);
Q_DECLARE_METATYPE(QGraphicsWidget *);
void Ut_HorizontalSwitcher::initTestCase()
@@ -52,35 +52,30 @@
}
}
-void Ut_HorizontalSwitcher::testAddRemoveWidgets()
+void Ut_HorizontalSwitcher::testAddWidgets()
{
- const int numberOfWidgets = 5;
-
- QList<QGraphicsWidget *> widgets;
- QGraphicsWidget *w;
-
QVERIFY(subject->count() == 0);
+ QVERIFY(subject->current() == -1);
+ QVERIFY(subject->currentWidget() == 0);
- for (int i = 0; i < numberOfWidgets; ++i) {
- w = new QGraphicsWidget();
- widgets.append(w);
- subject->addWidget(w);
- QCOMPARE(subject->count(), i + 1);
- }
+ const int numberOfWidgets = 5;
- for (int i = numberOfWidgets - 1; i >= 0; --i) {
- w = widgets.at(i);
- subject->removeWidget(w);
- QCOMPARE(subject->count(), i);
+ for (int i = 0; i < numberOfWidgets; ++i) {
+ QGraphicsWidget *w = 0;
+ subject->addWidget(w = new QGraphicsWidget);
+ QVERIFY(!w->isVisible() || w == subject->currentWidget());
+ QVERIFY(w->parentItem() == subject);
+ QVERIFY(w->scene() == subject->scene());
}
- // Add again and remove with removeAll()
- for (int i = 0; i < numberOfWidgets; ++i)
- subject->addWidget(widgets.at(i));
- subject->removeAll();
- QCOMPARE(subject->count(), 0);
+ QVERIFY(subject->count() == numberOfWidgets);
+ QVERIFY((subject->current() >= 0) && (subject->current() < subject->count()));
+ QVERIFY(subject->currentWidget() != 0);
+ QVERIFY(subject->currentWidget()->isVisible());
- qDeleteAll(widgets);
+ subject->deleteAll();
+ QVERIFY(subject->count() == 0);
+ QVERIFY(subject->current() == -1);
}
void Ut_HorizontalSwitcher::testShowWidgets()
@@ -112,30 +107,31 @@
QTest::addColumn<int>("current");
QTest::addColumn<int>("expected");
- QTest::newRow("Empty1") << 0 << 0 << -1;
- QTest::newRow("Invalid0") << 0 << -1 << -1;
- QTest::newRow("Invalid1") << 1 << -1 << -1;
- QTest::newRow("Invalid2") << 2 << -1 << -1;
+ QTest::newRow("Empty1") << 0 << 0 << -1;
+ QTest::newRow("Invalid0") << 0 << -1 << -1;
+ QTest::newRow("AddOne") << 1 << -1 << 0;
+ QTest::newRow("AddTwo") << 2 << -1 << 0;
QTest::newRow("3 widgets1") << 3 << 0 << 0;
QTest::newRow("3 widgets2") << 3 << 1 << 1;
}
+// FIXME: This test tests more about addWidget than it tests about setCurrent ...
void Ut_HorizontalSwitcher::testSetCurrent()
{
+ QVERIFY(subject->count() == 0);
+
QFETCH(int, numWidgets);
QFETCH(int, current);
QFETCH(int, expected);
- QGraphicsWidget *expectedWidget = NULL;
- QList<QGraphicsWidget *> widgets;
+
+ QGraphicsWidget *expectedWidget = 0;
for (int i = 0; i < numWidgets; ++i) {
- QGraphicsWidget *widget = new QGraphicsWidget();
- widgets.append(widget);
- subject->addWidget(widget);
+ subject->addWidget(new QGraphicsWidget);
}
if (expected >= 0) {
- expectedWidget = widgets.at(expected);
+ expectedWidget = subject->widget(expected);
}
subject->setCurrent(current);
@@ -146,7 +142,7 @@
void Ut_HorizontalSwitcher::testSwitchLeftRight_data()
{
QTest::addColumn<int>("widgetCount");
- QTest::addColumn<HorizontalSwitcher::Direction>("direction");
+ QTest::addColumn<HorizontalSwitcher::SwitchDirection>("direction");
QTest::addColumn<bool>("loop");
QTest::addColumn<int>("currentIndex");
QTest::addColumn<int>("expectedIndex");
@@ -163,7 +159,7 @@
void Ut_HorizontalSwitcher::testSwitchLeftRight()
{
QFETCH(int, widgetCount);
- QFETCH(HorizontalSwitcher::Direction, direction);
+ QFETCH(HorizontalSwitcher::SwitchDirection, direction);
QFETCH(bool, loop);
QFETCH(int, currentIndex);
QFETCH(int, expectedIndex);
@@ -240,7 +236,7 @@
{
QCOMPARE(subject->current(), -1);
subject->addWidget(new QGraphicsWidget());
- subject->switchTo(0);
+ subject->setCurrent(0);
QCOMPARE(subject->current(), 0);
QVERIFY(subject->currentWidget()->isVisible());
}
@@ -250,7 +246,7 @@
QCOMPARE(subject->current(), -1);
subject->addWidget(new QGraphicsWidget());
- subject->switchTo(0);
+ subject->setCurrent(0);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Left) == true);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Right) == true);
@@ -259,11 +255,11 @@
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Left) == true);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Right) == false);
- subject->switchTo(1);
+ subject->setCurrent(1);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Left) == false);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Right) == false);
- subject->switchTo(2);
+ subject->setCurrent(2);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Left) == false);
QVERIFY(subject->isAtBoundary(HorizontalSwitcher::Right) == true);
}
--- unit_test/ut_horizontalswitcher/ut_horizontalswitcher.h
+++ unit_test/ut_horizontalswitcher/ut_horizontalswitcher.h
@@ -36,7 +36,7 @@
void initTestCase();
void cleanupTestCase();
- void testAddRemoveWidgets();
+ void testAddWidgets();
void testSetCurrent_data();
void testSetCurrent();
void testShowWidgets();
--- unit_test/ut_keybutton/ut_keybutton.cpp
+++ unit_test/ut_keybutton/ut_keybutton.cpp
@@ -37,7 +37,6 @@
// Avoid waiting if im server is not responding
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
--- unit_test/ut_keybuttonarea/ut_keybuttonarea.cpp
+++ unit_test/ut_keybuttonarea/ut_keybuttonarea.cpp
@@ -33,13 +33,18 @@
#include <QDir>
#include <QGraphicsLayout>
#include <QGraphicsSceneMouseEvent>
+#include <QTouchEvent>
+
+#include <algorithm>
namespace
{
- const int LongPressTime = 1000; // same as in keybuttonarea.cpp
+ const int LongPressTime = 0; // same as in keybuttonarea.cpp
}
Q_DECLARE_METATYPE(KeyEvent);
+Q_DECLARE_METATYPE(IKeyButton*);
+Q_DECLARE_METATYPE(const IKeyButton*);
typedef KeyButtonArea *(*KBACreator)(MVirtualKeyboardStyleContainer *styleContainer,
QSharedPointer<const LayoutSection> section,
@@ -48,6 +53,7 @@
QGraphicsWidget *parent);
Q_DECLARE_METATYPE(KBACreator);
+Q_DECLARE_METATYPE(IKeyButton::ButtonState);
KeyButtonArea *createSingleWidgetKeyButtonArea(MVirtualKeyboardStyleContainer *styleContainer,
QSharedPointer<const LayoutSection> section,
@@ -77,11 +83,13 @@
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
qRegisterMetaType<KeyEvent>();
+ qRegisterMetaType<const IKeyButton*>();
+ qRegisterMetaType<IKeyButton*>();
+ qRegisterMetaType<IKeyButton::ButtonState>();
new MPlainWindow; // Create singleton
}
@@ -143,7 +151,7 @@
subject->resize(defaultLayoutSize());
for (int level = 0; level < 2; level++) {
- subject->switchLevel(level, false);
+ subject->switchLevel(level);
box = keyAt(0, 0)->buttonRect().size();
qDebug() << "Current level" << level << "; Box size=" << box;
@@ -188,7 +196,7 @@
subject->resize(defaultLayoutSize());
for (int level = 0; level < 2; level++) {
- subject->switchLevel(level, false);
+ subject->switchLevel(level);
box = keyAt(0, 0)->buttonRect().size();
qDebug() << "Current level" << level << "; Box size=" << box << subject->size();
@@ -219,7 +227,7 @@
const IKeyButton *button = 0;
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding,
false, 0);
@@ -259,72 +267,54 @@
void Ut_KeyButtonArea::testFlickCheck_data()
{
QTest::addColumn<KBACreator>("createKba");
- QTest::newRow("SingleWidgetArea") << &createSingleWidgetKeyButtonArea;
- QTest::newRow("MButtonArea") << &createMButtonArea;
+ QTest::addColumn<bool>("directMode");
+ QTest::newRow("SingleWidgetArea") << &createSingleWidgetKeyButtonArea << false;
+ QTest::newRow("SingleWidgetArea") << &createSingleWidgetKeyButtonArea << true;
+ QTest::newRow("MButtonArea") << &createMButtonArea << false;
+ QTest::newRow("MButtonArea") << &createMButtonArea << true;
}
void Ut_KeyButtonArea::testFlickCheck()
{
QFETCH(KBACreator, createKba);
+ QFETCH(bool, directMode);
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding,
false, 0);
+ KeyButtonArea::setInputMethodMode(directMode ? M::InputMethodModeDirect : M::InputMethodModeNormal);
+ MPlainWindow::instance()->scene()->addItem(subject);
subject->resize(defaultLayoutSize());
- QList<QPointF> positions;
- QList<int> left;
- QList<int> right;
- QList<int> down;
- QList<int> up;
- QList<bool> outcome;
- QSignalSpy spyLeft(subject, SIGNAL(flickLeft()));
- QSignalSpy spyRight(subject, SIGNAL(flickRight()));
- QSignalSpy spyDown(subject, SIGNAL(flickDown()));
- QSignalSpy spyUp(subject, SIGNAL(flickUp(const KeyBinding *)));
- bool result;
-
- QVERIFY(spyLeft.isValid());
- QVERIFY(spyRight.isValid());
- QVERIFY(spyDown.isValid());
- QVERIFY(spyUp.isValid());
-
- positions << QPointF(0, 0)
- << QPointF(25, 25)
- << QPointF(75, 75)
- << QPointF(25, -75)
- << QPointF(-75, 5)
- << QPointF(75, 5)
- << QPointF(0, 75);
- left << 0 << 0 << 0 << 0 << 0 << 1 << 0;
- right << 0 << 0 << 0 << 0 << 1 << 0 << 0;
- down << 0 << 0 << 0 << 1 << 0 << 0 << 0;
- up << 0 << 0 << 0 << 0 << 0 << 0 << 1;
- outcome << false << false << false
- << true << true << true
- << true;
-
- QVERIFY(positions.count() == outcome.count());
- QVERIFY(positions.count() == left.count());
- subject->pointerPos = QPoint(0, 0);
-
- for (int n = 0; n < positions.count(); ++n) {
- spyLeft.clear();
- spyRight.clear();
- spyDown.clear();
- spyUp.clear();
- qDebug() << "test position" << positions.at(n);
- subject->flickStartPos = positions.at(n);
- subject->flicked = false;
- result = subject->flickCheck();
- QCOMPARE(result, outcome.at(n));
- QCOMPARE(left.at(n), spyLeft.count());
- QCOMPARE(right.at(n), spyRight.count());
- QCOMPARE(down.at(n), spyDown.count());
- QCOMPARE(up.at(n), spyUp.count());
- }
+ // A series of touch points that will not create a gesture yet:
+ PointList base;
+ for (int idx = 0; idx < 8; ++idx) {
+ // But each new point has to overcome the movement threshold:
+ base << QPoint(idx * 6, idx * 6);
+ }
+ recognizeGesture(base, NoGesture);
+
+ PointList rightSwipe0 = PointList(base);
+ rightSwipe0 << QPoint(600, 0);
+ recognizeGesture(rightSwipe0, directMode ? NoGesture : SwipeRightGesture);
+ recognizeGesture(reversed(rightSwipe0), directMode ? NoGesture : SwipeLeftGesture);
+
+ // A swipe does not have to be a strictly increasing sequence:
+ PointList rightSwipe1 = PointList(base);
+ rightSwipe1 << QPoint(0, 0) << QPoint(600, 0);
+ recognizeGesture(rightSwipe1, directMode ? NoGesture : SwipeRightGesture);
+ recognizeGesture(reversed(rightSwipe1), directMode ? NoGesture : SwipeLeftGesture);
+
+ PointList downSwipe = PointList(base);
+ downSwipe << QPoint(0, 800);
+ recognizeGesture(downSwipe, directMode ? NoGesture : SwipeDownGesture);
+ recognizeGesture(reversed(downSwipe), NoGesture); // No key set - can't swipe up ...
+
+ PointList conflictingSwipe = PointList(base);
+ conflictingSwipe << QPoint(800, 800);
+ recognizeGesture(conflictingSwipe, NoGesture);
}
void Ut_KeyButtonArea::testSceneEvent_data()
@@ -340,18 +330,26 @@
//initialization
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding,
false, 0);
MPlainWindow::instance()->scene()->addItem(subject);
subject->resize(defaultLayoutSize());
+ // Skip test for multitouch, since there are no mouse events:
+ if (subject->acceptTouchEvents()) {
+ return;
+ }
+
QGraphicsSceneMouseEvent *press = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMousePress);
QGraphicsSceneMouseEvent *release = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseRelease);
QGraphicsSceneMouseEvent *move = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseMove);
- QSignalSpy spy(subject, SIGNAL(keyClicked(const KeyEvent &)));
- QSignalSpy spyPressed(subject, SIGNAL(keyPressed(const KeyEvent &)));
+ QSignalSpy spy(subject, SIGNAL(keyClicked(const IKeyButton*, const QString&, bool)));
+ QSignalSpy spyPressed(subject, SIGNAL(keyPressed(const IKeyButton*, const QString&, bool)));
+
+ QVERIFY(spy.isValid());
+ QVERIFY(spyPressed.isValid());
press->setPos(QPoint(1, 1));
release->setPos(QPoint(10, 10));
@@ -386,18 +384,18 @@
//at least we should not chrash here
QImage *image = new QImage(QSize(864, 480), QImage::Format_ARGB32_Premultiplied);
QPainter painter;
- QVERIFY(painter.begin(image) == true);
+ QVERIFY(painter.begin(image));
//initialization
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding,
false, 0);
subject->resize(defaultLayoutSize());
- subject->pointerPos = QPoint(20, 20); // top left button
- subject->fingerInsideArea = true;
- subject->accurateStart();
+ MPlainWindow::instance()->scene()->addItem(subject);
+
+ subject->touchPointPressed(QPoint(20, 20), 0); // top left button
//actual testing
subject->paint(&painter, 0, 0);
}
@@ -420,12 +418,14 @@
false, 0);
MPlainWindow::instance()->scene()->addItem(subject);
subject->resize(defaultLayoutSize());
- QSignalSpy spy(subject, SIGNAL(keyClicked(const KeyEvent &)));
- const IKeyButton *key = 0;
+ QSignalSpy spy(subject, SIGNAL(keyClicked(const IKeyButton*, const QString&, bool)));
+ IKeyButton *key = 0;
QList<int> positions;
int i;
positions << 0 << 1 << 2 << 5 << 6;
+ QVERIFY(spy.isValid());
+
//!!! z is the character that won't be changed when deadkey is locked
QStringList lowerUnicodes;
lowerUnicodes << QChar('a') << QChar('z') << QChar('e') << QChar('y') << QChar('u');
@@ -450,7 +450,7 @@
QVERIFY(key->isDeadKey());
QString c = QChar(0x00B4);
QCOMPARE(key->label(), c);
- subject->clickAtDeadkey(key);
+ subject->click(key);
//click at deadkey for the first time, just lock the deadkey, won't emit cliked() signal
QCOMPARE(spy.count(), 0);
@@ -460,7 +460,7 @@
}
//test for shift status
- subject->switchLevel(1, false);
+ subject->switchLevel(1);
for (i = 0; i < positions.count(); i++) {
QCOMPARE(keyAt(0, positions[i])->label(), upperDKUnicodes.at(i));
}
@@ -472,27 +472,72 @@
}
//test for shift off status
- subject->switchLevel(0, false);
+ subject->switchLevel(0);
for (i = 0; i < positions.count(); i++) {
QCOMPARE(keyAt(0, positions[i])->label(), lowerUnicodes.at(i));
}
// Lock deadkey again.
- subject->clickAtDeadkey(key);
+ subject->click(key);
for (i = 0; i < positions.count(); i++) {
QCOMPARE(keyAt(0, positions[i])->label(), lowerDKUnicodes.at(i));
}
- QGraphicsSceneMouseEvent *release = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseRelease);
- release->setPos(QPointF(keyAt(0, 0)->buttonBoundingRect().x() + 1.0, 1.0)); // on some valid key
- subject->mouseReleaseEvent(release);
+ subject->click(keyAt(0, 0));
//key release on not deadkey, will emit clicked() signal
QCOMPARE(spy.count(), 1);
//any keypress, the deadkey should be unlocked
for (i = 0; i < positions.count(); i++) {
QCOMPARE(keyAt(0, positions[i])->label(), lowerUnicodes.at(i));
}
- delete release;
+}
+
+void Ut_KeyButtonArea::testSelectedDeadkeys()
+{
+ keyboard = new KeyboardData;
+ QVERIFY(keyboard->loadNokiaKeyboard("fr.xml"));
+ subject = createSingleWidgetKeyButtonArea(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
+ KeyButtonArea::ButtonSizeEqualExpanding,
+ false, 0);
+ MPlainWindow::instance()->scene()->addItem(subject);
+
+ // Pick two deadkeys to play around with.
+ IKeyButton *deadkey1 = keyAt(2, 7); // row 3, column 7
+ IKeyButton *deadkey2 = keyAt(2, 8); // row 3, column 8
+ IKeyButton *regularKey = keyAt(0, 0); // first key, top left
+
+ QVERIFY(deadkey1 && deadkey1->isDeadKey());
+ QVERIFY(deadkey2 && deadkey2->isDeadKey());
+ QVERIFY(regularKey && !regularKey->isDeadKey());
+
+ QCOMPARE(deadkey1->state(), IKeyButton::Normal);
+ QCOMPARE(deadkey2->state(), IKeyButton::Normal);
+ QCOMPARE(regularKey->state(), IKeyButton::Normal);
+
+ // Press dead key down
+ subject->click(deadkey1);
+ QCOMPARE(deadkey1->state(), IKeyButton::Selected);
+
+ // Release it by clicking regular key
+ subject->click(regularKey);
+ QCOMPARE(deadkey1->state(), IKeyButton::Normal);
+
+ // Down again
+ subject->click(deadkey1);
+ QCOMPARE(deadkey1->state(), IKeyButton::Selected);
+
+ // Release it by clicking itself again.
+ subject->click(deadkey1);
+ QCOMPARE(deadkey1->state(), IKeyButton::Normal);
+
+ // Down again
+ subject->click(deadkey1);
+ QCOMPARE(deadkey1->state(), IKeyButton::Selected);
+
+ // Release it by clicking the other dead key.
+ subject->click(deadkey2);
+ QCOMPARE(deadkey1->state(), IKeyButton::Normal);
+ QCOMPARE(deadkey2->state(), IKeyButton::Selected);
}
void Ut_KeyButtonArea::testImportedLayouts_data()
@@ -555,7 +600,7 @@
QFETCH(KBACreator, createKba);
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding, true, 0);
MPlainWindow::instance()->scene()->addItem(subject);
@@ -572,21 +617,25 @@
subject->accurateStop();
// make long press
- QGraphicsSceneMouseEvent mouseEvent;
- mouseEvent.setPos(QPointF(20.0f, 20.0f)); // approximately the top left key on layout
- subject->mousePressEvent(&mouseEvent);
+ const QPoint mousePos(20, 20); // approximately the top left key on layout
+ const int touchId = 0;
+
+ //popup should be shown immediately, so we comment out this part of test
+#if 0
+ subject->touchPointPressed(mousePos, touchId);
QTest::qWait(LongPressTime - 100); // not enough time
- subject->mouseReleaseEvent(&mouseEvent);
+ subject->touchPointReleased(mousePos, touchId);
QVERIFY(!subject->isAccurateMode());
+#endif
- subject->mousePressEvent(&mouseEvent);
+ subject->touchPointPressed(mousePos, touchId);
QTest::qWait(LongPressTime + 100); // long enough
// When accurate mode is on and mouse down we should have popup enabled
QVERIFY(subject->isPopupActive());
- subject->mouseReleaseEvent(&mouseEvent);
+ subject->touchPointReleased(mousePos, touchId);
QVERIFY(subject->isAccurateMode());
}
@@ -602,33 +651,42 @@
QFETCH(KBACreator, createKba);
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding, true, 0);
MPlainWindow::instance()->scene()->addItem(subject);
subject->resize(defaultLayoutSize());
+ const QPoint mousePos(20, 20); // approximately the top left key on layout
+ const int touchId = 0;
+
// Test popup activation
// direct call
+
+ // Popup won't show up unless it is given a position. We give it via a mouse press.
+
+ //popup should be shown immediately, so we comment out this part of test
+#if 0
+ subject->touchPointPressed(mousePos, touchId);
subject->popupStart();
QVERIFY(subject->isPopupActive());
subject->popup->hidePopup();
QVERIFY(!subject->isPopupActive());
+ subject->touchPointReleased(mousePos, touchId);
// make long press
- QGraphicsSceneMouseEvent mouseEvent;
- mouseEvent.setPos(QPointF(20.0f, 20.0f)); // approximately the top left key on layout
- subject->mousePressEvent(&mouseEvent);
+ subject->touchPointPressed(mousePos, touchId);
QTest::qWait(LongPressTime - 100); // not enough time
- subject->mouseReleaseEvent(&mouseEvent);
QVERIFY(!subject->isPopupActive());
+ subject->touchPointReleased(mousePos, touchId);
+#endif
- subject->mousePressEvent(&mouseEvent);
+ subject->touchPointPressed(mousePos, touchId);
QTest::qWait(LongPressTime + 100); // long enough
QVERIFY(subject->isPopupActive());
- subject->mouseReleaseEvent(&mouseEvent);
+ subject->touchPointReleased(mousePos, touchId);
}
void Ut_KeyButtonArea::testInitialization_data()
@@ -642,7 +700,7 @@
{
QFETCH(KBACreator, createKba);
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
subject = createKba(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::mainSection),
KeyButtonArea::ButtonSizeEqualExpanding,
false, 0);
@@ -694,37 +752,120 @@
QVERIFY(buttonFoundFromRight); // button should be found from right side
}
-void Ut_KeyButtonArea::testShiftCapsLock_data()
-{
- QTest::addColumn<KBACreator>("createKba");
- QTest::newRow("SingleWidgetArea") << &createSingleWidgetKeyButtonArea;
- QTest::newRow("MButtonArea") << &createMButtonArea;
-}
-
void Ut_KeyButtonArea::testShiftCapsLock()
{
- QFETCH(KBACreator, createKba);
-
// Load any layout that has function row with shift
keyboard = new KeyboardData;
- QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
const LayoutData *layout = keyboard->layout(LayoutData::General, M::Landscape);
QVERIFY(layout);
QSharedPointer<const LayoutSection> functionRowSection = layout->section(LayoutData::functionkeySection);
- subject = createKba(style, functionRowSection, KeyButtonArea::ButtonSizeFunctionRow, false, 0);
+ subject = createSingleWidgetKeyButtonArea(style, functionRowSection,
+ KeyButtonArea::ButtonSizeFunctionRow,
+ false, 0);
- IKeyButton *shiftButton = subject->shiftButton;
+ SingleWidgetButton *shiftButton = static_cast<SingleWidgetButtonArea *>(subject)->shiftButton;
QVERIFY(shiftButton);
QVERIFY(shiftButton->state() == IKeyButton::Normal);
- subject->switchLevel(0, true);
+ subject->setShiftStatus(true, true);
QVERIFY(shiftButton->state() == IKeyButton::Selected);
- subject->switchLevel(0, false);
+ subject->setShiftStatus(true, false);
QVERIFY(shiftButton->state() == IKeyButton::Normal);
}
+void Ut_KeyButtonArea::testMultiTouch()
+{
+ keyboard = new KeyboardData;
+ QVERIFY(keyboard->loadNokiaKeyboard("en_us.xml"));
+ const LayoutData *layout = keyboard->layout(LayoutData::General, M::Landscape);
+ QVERIFY(layout);
+ QSharedPointer<const LayoutSection> functionRowSection = layout->section(LayoutData::mainSection);
+
+ subject = createSingleWidgetKeyButtonArea(style, functionRowSection,
+ KeyButtonArea::ButtonSizeFunctionRow,
+ false, 0);
+ MPlainWindow::instance()->scene()->addItem(subject);
+ subject->resize(defaultLayoutSize());
+
+ const IKeyButton *key0 = keyAt(0, 0);
+ const IKeyButton *key1 = keyAt(1, 0);
+ const IKeyButton *key2 = keyAt(0, 1);
+
+ QVERIFY(key0);
+ QVERIFY(key1);
+ QVERIFY(key2);
+
+ QSignalSpy pressed(subject, SIGNAL(keyPressed(const IKeyButton*, const QString&, bool)));
+ QSignalSpy released(subject, SIGNAL(keyReleased(const IKeyButton*, const QString&, bool)));
+ QSignalSpy clicked(subject, SIGNAL(keyClicked(const IKeyButton*, const QString&, bool )));
+
+ QVERIFY(pressed.isValid());
+ QVERIFY(released.isValid());
+ QVERIFY(clicked.isValid());
+
+ const QPoint pos0 = key0->buttonRect().center();
+ const QPoint pos1 = key1->buttonRect().center();
+ const QPoint pos2 = key2->buttonRect().center();
+
+ /*
+ * Verify following conditions:
+ * 1) signals are emitted in correct order
+ * 2) every signal corresponds to correct key
+ */
+ subject->touchPointPressed(pos0, 0);
+ QCOMPARE(pressed.count(), 1);
+ QVERIFY(pressed.at(0).first().value<const IKeyButton*>() == key0);
+ QCOMPARE(released.count(), 0);
+ QCOMPARE(clicked.count(), 0);
+
+ subject->touchPointPressed(pos1, 1);
+ QCOMPARE(pressed.count(), 2);
+ QVERIFY(pressed.at(1).first().value<const IKeyButton*>() == key1);
+ QCOMPARE(released.count(), 0);
+ QCOMPARE(clicked.count(), 0);
+
+ subject->touchPointReleased(pos0, 0);
+ subject->touchPointReleased(pos1, 1);
+ QCOMPARE(pressed.count(), 2);
+ QCOMPARE(released.count(), 2);
+ QVERIFY(released.at(0).first().value<const IKeyButton*>() == key0);
+ QVERIFY(released.at(1).first().value<const IKeyButton*>() == key1);
+ QCOMPARE(clicked.count(), 2);
+ QVERIFY(clicked.at(0).first().value<const IKeyButton*>() == key0);
+ QVERIFY(clicked.at(1).first().value<const IKeyButton*>() == key1);
+
+ pressed.clear();
+ released.clear();
+ clicked.clear();
+
+ // Verify if could click on some keys while other key is pressed
+ subject->touchPointPressed(pos0, 0);
+ subject->touchPointPressed(pos1, 1);
+ subject->touchPointReleased(pos0, 0);
+ subject->touchPointPressed(pos2, 0);
+ subject->touchPointReleased(pos2, 0);
+ subject->touchPointReleased(pos1, 1);
+
+ QCOMPARE(pressed.count(), 3);
+ QCOMPARE(released.count(), 3);
+ QCOMPARE(clicked.count(), 3);
+
+ QVERIFY(pressed.at(0).first().value<const IKeyButton*>() == key0);
+ QVERIFY(pressed.at(1).first().value<const IKeyButton*>() == key1);
+ QVERIFY(pressed.at(2).first().value<const IKeyButton*>() == key2);
+
+ QVERIFY(released.at(0).first().value<const IKeyButton*>() == key0);
+ QVERIFY(released.at(1).first().value<const IKeyButton*>() == key2);
+ QVERIFY(released.at(2).first().value<const IKeyButton*>() == key1);
+
+ QVERIFY(clicked.at(0).first().value<const IKeyButton*>() == key0);
+ QVERIFY(clicked.at(1).first().value<const IKeyButton*>() == key2);
+ QVERIFY(clicked.at(2).first().value<const IKeyButton*>() == key1);
+}
+
void Ut_KeyButtonArea::changeOrientation(M::OrientationAngle angle)
{
if (MPlainWindow::instance()->orientationAngle() != angle) {
@@ -743,14 +884,14 @@
}
// Helper method to get key in certain row and column from current subject.
-const IKeyButton *Ut_KeyButtonArea::keyAt(unsigned int row, unsigned int column) const
+IKeyButton *Ut_KeyButtonArea::keyAt(unsigned int row, unsigned int column) const
{
// If this fails there is something wrong with the test.
Q_ASSERT(subject
&& (row < static_cast<unsigned int>(subject->rowCount()))
&& (column < static_cast<unsigned int>(subject->sectionModel()->columnsAt(row))));
- const IKeyButton *key = 0;
+ IKeyButton *key = 0;
if (dynamic_cast<MButtonArea *>(subject)) {
MButtonArea *buttonArea = static_cast<MButtonArea *>(subject);
@@ -767,5 +908,38 @@
return key;
}
+void Ut_KeyButtonArea::recognizeGesture(const PointList &pl, GestureType gt, int touchPointId)
+{
+ QSignalSpy leftSwipeSpy(subject, SIGNAL(flickLeft()));
+ QSignalSpy rightSwipeSpy(subject, SIGNAL(flickRight()));
+ QSignalSpy upSwipeSpy(subject, SIGNAL(flickUp(KeyBinding)));
+ QSignalSpy downSwipeSpy(subject, SIGNAL(flickDown()));
+
+ subject->touchPointPressed(pl[0], touchPointId);
+
+ for (int n = 1; n < pl.count(); ++n) {
+ subject->touchPointMoved(pl[n], touchPointId);
+ }
+
+ // Not needed for the gesture, but we don't want to leave a pressed touch
+ // point without a release:
+ subject->touchPointReleased(pl[pl.count() - 1], touchPointId);
+
+ qDebug() << "gesture type = " << gt;
+ QCOMPARE(leftSwipeSpy.count(),
+ gt == SwipeLeftGesture ? 1 : 0);
+ QCOMPARE(rightSwipeSpy.count(),
+ gt == SwipeRightGesture ? 1 : 0);
+ QCOMPARE(upSwipeSpy.count(),
+ gt == SwipeUpGesture ? 1 : 0);
+ QCOMPARE(downSwipeSpy.count(),
+ gt == SwipeDownGesture ? 1 : 0);
+}
+
+Ut_KeyButtonArea::PointList Ut_KeyButtonArea::reversed(const PointList &in) const {
+ PointList result;
+ std::reverse_copy(in.begin(), in.end(), std::back_inserter(result));
+ return result;
+}
QTEST_APPLESS_MAIN(Ut_KeyButtonArea);
--- unit_test/ut_keybuttonarea/ut_keybuttonarea.h
+++ unit_test/ut_keybuttonarea/ut_keybuttonarea.h
@@ -56,6 +56,7 @@
void testPaint();
void testDeadkeys_data();
void testDeadkeys();
+ void testSelectedDeadkeys();
void testImportedLayouts_data();
void testImportedLayouts();
void testAccurateMode_data();
@@ -66,13 +67,26 @@
void testInitialization();
void testFunctionRowAlignmentBug_data();
void testFunctionRowAlignmentBug();
- void testShiftCapsLock_data();
void testShiftCapsLock();
+ void testMultiTouch();
private:
+ enum GestureType {
+ NoGesture = 0,
+ SwipeLeftGesture = 1,
+ SwipeRightGesture = 2,
+ SwipeUpGesture = 3,
+ SwipeDownGesture = 4
+ };
+
+ typedef QList<QPoint> PointList;
+
void changeOrientation(M::OrientationAngle angle);
QSize defaultLayoutSize();
- const IKeyButton *keyAt(unsigned int row, unsigned int column) const;
+ void recognizeGesture(const PointList &pl, GestureType gt, int touchPointId = 0);
+ PointList reversed(const PointList &in) const;
+
+ IKeyButton *keyAt(unsigned int row, unsigned int column) const;
};
#endif // UT_KEYBUTTONAREA_H
--- unit_test/ut_keyeventhandler
+++ unit_test/ut_keyeventhandler
+(directory)
--- unit_test/ut_keyeventhandler/ut_keyeventhandler.cpp
+++ unit_test/ut_keyeventhandler/ut_keyeventhandler.cpp
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#include "ut_keyeventhandler.h"
+#include "keyeventhandler.h"
+#include "mvirtualkeyboardstyle.h"
+#include "singlewidgetbuttonarea.h"
+#include "singlewidgetbutton.h"
+#include "flickupbutton.h"
+#include "mbuttonarea.h"
+#include "keyboarddata.h"
+#include "vkbdatakey.h"
+#include "mplainwindow.h"
+#include "popupbase.h"
+
+#include <MApplication>
+#include <MScene>
+#include <MSceneManager>
+#include <MTheme>
+
+#include <QDir>
+#include <QGraphicsLayout>
+#include <QGraphicsSceneMouseEvent>
+#include <QTouchEvent>
+
+namespace
+{
+// const int LongPressTime = 1000; // same as in keybuttonarea.cpp
+}
+
+Q_DECLARE_METATYPE(KeyEvent);
+Q_DECLARE_METATYPE(IKeyButton*);
+
+
+void Ut_KeyEventHandler::initTestCase()
+{
+ static int argc = 1;
+ static char *app_name[1] = { (char *) "ut_keybuttonarea" };
+
+ // Avoid waiting if im server is not responding
+ MApplication::setLoadMInputContext(false);
+ app = new MApplication(argc, app_name);
+
+ style = new MVirtualKeyboardStyleContainer;
+ style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
+
+ qRegisterMetaType<KeyEvent>();
+ qRegisterMetaType<IKeyButton*>();
+
+ new MPlainWindow; // Create singleton
+}
+
+void Ut_KeyEventHandler::cleanupTestCase()
+{
+ delete MPlainWindow::instance();
+ delete style;
+ style = 0;
+ delete app;
+ app = 0;
+}
+
+void Ut_KeyEventHandler::init()
+{
+ keyboard = new KeyboardData;
+ QVERIFY(keyboard->loadNokiaKeyboard("en.xml"));
+ keyArea = new SingleWidgetButtonArea(style, keyboard->layout(LayoutData::General, M::Landscape)->section(LayoutData::functionkeySection),
+ KeyButtonArea::ButtonSizeEqualExpanding,
+ false, 0);
+ MPlainWindow::instance()->scene()->addItem(keyArea);
+
+ keyArea->resize(defaultLayoutSize());
+
+ subject = new KeyEventHandler();
+
+ space = findKey(KeyBinding::ActionSpace);
+ QVERIFY(space);
+
+ shift = findKey(KeyBinding::ActionShift);
+ QVERIFY(shift);
+}
+
+void Ut_KeyEventHandler::cleanup()
+{
+ delete subject;
+ delete keyArea;
+ delete keyboard;
+ subject = 0;
+ keyArea = 0;
+ keyboard = 0;
+ space = 0;
+ shift = 0;
+}
+
+void Ut_KeyEventHandler::testKeyPress()
+{
+ QSignalSpy spyKeyPressed(subject, SIGNAL(keyPressed(const KeyEvent&)));
+ QSignalSpy spyShiftPressed(subject, SIGNAL(shiftPressed(bool)));
+
+ QVERIFY(spyKeyPressed.isValid());
+ QVERIFY(spyShiftPressed.isValid());
+
+ subject->handleKeyPress(space, "", false);
+
+ QCOMPARE(spyKeyPressed.count(), 1);
+ QCOMPARE(spyShiftPressed.count(), 0);
+
+ subject->handleKeyPress(shift, "", false);
+
+ QCOMPARE(spyKeyPressed.count(), 2);
+ QCOMPARE(spyShiftPressed.count(), 1);
+ QVERIFY(spyShiftPressed.first().first().toBool() == true);
+}
+
+void Ut_KeyEventHandler::testKeyRelease()
+{
+ QSignalSpy spyKeyReleased(subject, SIGNAL(keyReleased(const KeyEvent&)));
+ QSignalSpy spyShiftReleased(subject, SIGNAL(shiftPressed(bool)));
+
+ QVERIFY(spyKeyReleased.isValid());
+ QVERIFY(spyShiftReleased.isValid());
+
+ subject->handleKeyPress(space, "", false);
+ subject->handleKeyRelease(space, "", false);
+
+ QCOMPARE(spyKeyReleased.count(), 1);
+ QCOMPARE(spyShiftReleased.count(), 0);
+
+ subject->handleKeyRelease(shift, "", false);
+
+ QCOMPARE(spyKeyReleased.count(), 2);
+ QCOMPARE(spyShiftReleased.count(), 0);
+
+ subject->handleKeyPress(shift, "", false);
+ spyShiftReleased.clear();
+ subject->handleKeyRelease(shift, "", false);
+
+ QCOMPARE(spyKeyReleased.count(), 3);
+ QCOMPARE(spyShiftReleased.count(), 1);
+ QVERIFY(spyShiftReleased.first().first().toBool() == false);
+}
+
+void Ut_KeyEventHandler::testKeyClick()
+{
+ QSignalSpy spyKeyClicked(subject, SIGNAL(keyClicked(const KeyEvent&)));
+
+ QVERIFY(spyKeyClicked.isValid());
+
+ subject->handleKeyPress(shift, "", false);
+ subject->handleKeyRelease(shift, "", false);
+ subject->handleKeyClick(shift, "", false);
+
+ QCOMPARE(spyKeyClicked.count(), 1);
+ QVERIFY(spyKeyClicked.first().first().value<KeyEvent>().qtKey() == Qt::Key_Shift);
+ spyKeyClicked.clear();
+
+ subject->handleKeyPress(shift, "", false);
+ subject->handleKeyPress(space, "", false);
+ subject->handleKeyRelease(space, "", false);
+ subject->handleKeyClick(space, "", false);
+ subject->handleKeyRelease(shift, "", false);
+ subject->handleKeyClick(shift, "", false);
+
+ QCOMPARE(spyKeyClicked.count(), 1);
+ QVERIFY(spyKeyClicked.first().first().value<KeyEvent>().qtKey() != Qt::Key_Shift);
+}
+
+QSize Ut_KeyEventHandler::defaultLayoutSize()
+{
+ // Take visible scene size as layout size, but reduce keyboard's paddings first from its width.
+ // The height value is ignored since KeyButtonAreas determine their own height.
+ return MPlainWindow::instance()->visibleSceneSize()
+ - QSize((*style)->paddingLeft() + (*style)->paddingRight(), 0);
+}
+
+// Helper method to get key
+const IKeyButton *Ut_KeyEventHandler::findKey(KeyBinding::KeyAction action)
+{
+ SingleWidgetButtonArea *buttonArea = dynamic_cast<SingleWidgetButtonArea *>(keyArea);
+ Q_ASSERT(buttonArea);
+
+ foreach (const SingleWidgetButtonArea::ButtonRow &row, buttonArea->rowList) {
+ foreach (SingleWidgetButton *button, row.buttons) {
+ if (button->binding().action() == action) {
+ return button;
+ }
+ }
+ }
+ return 0;
+}
+
+
+QTEST_APPLESS_MAIN(Ut_KeyEventHandler);
--- unit_test/ut_keyeventhandler/ut_keyeventhandler.h
+++ unit_test/ut_keyeventhandler/ut_keyeventhandler.h
+/* * This file is part of meego-keyboard *
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * Contact: Nokia Corporation (directui at nokia.com)
+ *
+ * If you have questions regarding the use of this file, please contact
+ * Nokia at directui at nokia.com.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * and appearing in the file LICENSE.LGPL included in the packaging
+ * of this file.
+ */
+
+#ifndef UT_KEYEVENTHANDLER_H
+#define UT_KEYEVENTHANDLER_H
+
+#include <QtTest/QtTest>
+#include <QObject>
+#include "mnamespace.h"
+#include "vkbdatakey.h"
+
+class MApplication;
+class MVirtualKeyboardStyleContainer;
+class KeyButtonArea;
+class KeyboardData;
+class IKeyButton;
+class KeyEventHandler;
+
+class Ut_KeyEventHandler : public QObject
+{
+ Q_OBJECT
+
+private:
+ MApplication *app;
+ MVirtualKeyboardStyleContainer *style;
+ KeyButtonArea *keyArea;
+ KeyboardData *keyboard;
+ KeyEventHandler *subject;
+ const IKeyButton *space;
+ const IKeyButton *shift;
+
+private slots:
+ void init();
+ void cleanup();
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testKeyPress();
+ void testKeyRelease();
+ void testKeyClick();
+
+private:
+ QSize defaultLayoutSize();
+ const IKeyButton *findKey(KeyBinding::KeyAction);
+};
+
+#endif // UT_KEYEVENTHANDLER_H
+
--- unit_test/ut_keyeventhandler/ut_keyeventhandler.pro
+++ unit_test/ut_keyeventhandler/ut_keyeventhandler.pro
+TEMPLATE = app
+CONFIG += QtTest meegotouch MImServer meegoimframework
+DEPENDPATH += .
+INCLUDEPATH += . \
+
+LIBS += -L/usr/lib -Wl,-rpath=/usr/lib/meego-im-plugins/ -lmeego-keyboard
+#LIBS += -L/usr/lib -Wl,-rpath=/usr/lib/meego-im-plugins/ -lmeego-keyboard
+
+
+# Input
+HEADERS += ut_keyeventhandler.h
+SOURCES += ut_keyeventhandler.cpp
+
+include(../common_check.pri)
--- unit_test/ut_layoutsmanager/ut_layoutsmanager.cpp
+++ unit_test/ut_layoutsmanager/ut_layoutsmanager.cpp
@@ -79,11 +79,6 @@
void Ut_LayoutsManager::initTestCase()
{
- MGConfItem languageListSetting(LanguageListSettingName);
-
- QStringList langlist;
- langlist << "fi" << "ru" << "ar_SA";
- languageListSetting.set(QVariant(langlist));
}
void Ut_LayoutsManager::cleanupTestCase()
@@ -93,6 +88,11 @@
void Ut_LayoutsManager::init()
{
LoadableKeyboards.clear();
+ LoadableKeyboards << "fi.xml" << "ru.xml" << "ar.xml";
+ MGConfItem languageListSetting(LanguageListSettingName);
+ QStringList langlist;
+ langlist << "fi" << "ru" << "ar";
+ languageListSetting.set(QVariant(langlist));
}
void Ut_LayoutsManager::cleanup()
@@ -102,6 +102,21 @@
// Tests.....................................................................
+void Ut_LayoutsManager::testLayouts()
+{
+ LoadableKeyboards.clear();
+ LoadableKeyboards << "fi.xml" << "ru.xml" << "ar.xml" << "en_GB.xml";
+ MGConfItem languageListSetting(LanguageListSettingName);
+ QStringList langlist;
+ langlist << "Fi" << "rU" << "AR" << "en_GB";
+ languageListSetting.set(QVariant(langlist));
+ std::auto_ptr<LayoutsManager> subject(new LayoutsManager);
+ foreach (const QString &lang, langlist) {
+ // stored language code should be lowercase
+ QVERIFY(subject->languageList().contains(lang.toLower()));
+ }
+}
+
void Ut_LayoutsManager::testNumberLayouts()
{
std::auto_ptr<LayoutsManager> subject(new LayoutsManager);
@@ -155,7 +170,7 @@
// Asking with Arabic language shouldn't make a difference as this
// stuff works solely based on the number format setting.
layout = dynamic_cast<const TestLayoutModel *>(
- subject->layout("ar_SA", LayoutData::Number, M::Landscape));
+ subject->layout("ar", LayoutData::Number, M::Landscape));
QVERIFY(!layout);
// If, however, number format is set to Arabic and we can load it,
@@ -167,7 +182,7 @@
QVERIFY(layout);
QCOMPARE(layout->modelId, NumberKeyboardFileArabic);
layout = dynamic_cast<const TestLayoutModel *>(
- subject->layout("ar_SA", LayoutData::Number, M::Landscape));
+ subject->layout("ar", LayoutData::Number, M::Landscape));
QVERIFY(layout);
QCOMPARE(layout->modelId, NumberKeyboardFileArabic);
@@ -243,7 +258,7 @@
QCOMPARE(layout->modelId, PhoneNumberKeyboardFileLatin);
displayLanguageSetting.set("ar");
layout = dynamic_cast<const TestLayoutModel *>(
- subject->layout("ar_SA", LayoutData::PhoneNumber, M::Landscape));
+ subject->layout("ar", LayoutData::PhoneNumber, M::Landscape));
QVERIFY(layout);
QCOMPARE(layout->modelId, PhoneNumberKeyboardFileLatin);
@@ -264,7 +279,7 @@
// ...and of course for Arabic.
displayLanguageSetting.set("ar");
layout = dynamic_cast<const TestLayoutModel *>(
- subject->layout("ar_SA", LayoutData::PhoneNumber, M::Landscape));
+ subject->layout("ar", LayoutData::PhoneNumber, M::Landscape));
QVERIFY(layout);
QCOMPARE(layout->modelId, PhoneNumberKeyboardFileArabic);
}
--- unit_test/ut_layoutsmanager/ut_layoutsmanager.h
+++ unit_test/ut_layoutsmanager/ut_layoutsmanager.h
@@ -32,6 +32,7 @@
void init();
void cleanup();
+ void testLayouts();
void testNumberLayouts();
void testPhoneNumberLayouts();
};
--- unit_test/ut_mhardwarekeyboard/hwkbcharloopsmanager_stub.h
+++ unit_test/ut_mhardwarekeyboard/hwkbcharloopsmanager_stub.h
@@ -41,7 +41,8 @@
};
HwKbCharLoopsManager::HwKbCharLoopsManager()
- : configLanguage(SystemDisplayLanguage)
+ : current(0),
+ configLanguage(SystemDisplayLanguage)
{
}
--- unit_test/ut_mhardwarekeyboard/testinputcontextconnection.h
+++ unit_test/ut_mhardwarekeyboard/testinputcontextconnection.h
@@ -74,6 +74,10 @@
{
}
+ virtual void setDetectableAutoRepeat(bool /* enabled */)
+ {
+ }
+
virtual void setGlobalCorrectionEnabled(bool)
{
}
--- unit_test/ut_mhardwarekeyboard/ut_mhardwarekeyboard.cpp
+++ unit_test/ut_mhardwarekeyboard/ut_mhardwarekeyboard.cpp
@@ -112,7 +112,7 @@
inputContextConnection = new TestInputContextConnection;
m_hkb = new MHardwareKeyboard(*inputContextConnection, 0);
m_hkb->reset();
- m_hkb->focusChanged(true);
+ m_hkb->enable();
m_hkb->setKeyboardType(M::FreeTextContentType);
}
@@ -380,7 +380,7 @@
QCOMPARE(shiftSpy.count(), 0);
modifierSpy.clear();
- m_hkb->focusChanged(true);
+ m_hkb->enable();
m_hkb->setKeyboardType(M::NumberContentType);
countBeforeAutoCaps = modifierSpy.count();
m_hkb->setAutoCapitalization(true);
@@ -389,7 +389,7 @@
QVERIFY(checkLockedState(ShiftMask | LockMask | FnModifierMask, FnModifierMask));
QCOMPARE(modifierSpy.count(), countBeforeAutoCaps);
QCOMPARE(shiftSpy.count(), 0);
- m_hkb->focusChanged(true);
+ m_hkb->enable();
m_hkb->setKeyboardType(M::FreeTextContentType);
modifierSpy.clear();
@@ -443,7 +443,7 @@
QVERIFY(modifierSpy.isValid());
// State is cleared on focus in...
- m_hkb->focusChanged(true);
+ m_hkb->enable();
QVERIFY(checkLatchedState(ShiftMask | FnModifierMask, 0));
QVERIFY(checkLockedState(ShiftMask | LockMask | FnModifierMask, 0));
QVERIFY(!m_hkb->autoCaps);
@@ -457,7 +457,7 @@
// Modifiers are also unlatched/unlocked on focus out. We don't care about
// notifications.
setState(state);
- m_hkb->focusChanged(false);
+ m_hkb->disable();
QVERIFY(checkLatchedState(ShiftMask | FnModifierMask, 0));
QVERIFY(checkLockedState(ShiftMask | LockMask | FnModifierMask, 0));
QVERIFY(!m_hkb->autoCaps);
@@ -500,6 +500,7 @@
QVERIFY(checkLockedState(ShiftMask | LockMask | FnModifierMask, FnModifierMask));
}
+
void Ut_MHardwareKeyboard::testShiftShiftCapsLock_data()
{
QTest::addColumn<int>("state");
@@ -577,7 +578,7 @@
// Press+release gives us signal
QVERIFY(!filterKeyPress(SymKey, Qt::NoModifier, "", KeycodeNonCharacter, 0));
- QVERIFY(filterKeyRelease(SymKey, Qt::NoModifier, "", KeycodeNonCharacter, SymModifierMask));
+ QVERIFY(!filterKeyRelease(SymKey, Qt::NoModifier, "", KeycodeNonCharacter, SymModifierMask));
QCOMPARE(symSpy.count(), 1);
symSpy.clear();
@@ -632,6 +633,7 @@
QCOMPARE(symSpy.count(), 0);
}
+
void Ut_MHardwareKeyboard::testSymPlusCharSwitchs()
{
QSignalSpy symSpy(m_hkb, SIGNAL(symbolKeyClicked()));
@@ -658,11 +660,72 @@
QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int >(0));
QVERIFY(filterKeyRelease(Qt::Key_O, Qt::NoModifier, "b", KeycodeCharacter, SymModifierMask));
QCOMPARE(inputContextConnection->lastCommitString(), QString(QChar(0x00F6)));
- QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int >(1));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int >(2));
QVERIFY(!filterKeyRelease(SymKey, Qt::NoModifier, "", KeycodeNonCharacter, SymModifierMask));
QCOMPARE(symSpy.count(), 0);
}
+
+void Ut_MHardwareKeyboard::testReleaseEvents()
+{
+ // Ordinary character
+ QVERIFY(filterKeyPress(Qt::Key_A, Qt::NoModifier, "a", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(0));
+ QVERIFY(filterKeyRelease(Qt::Key_A, Qt::NoModifier, "a", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(2));
+ QCOMPARE(inputContextConnection->lastKeyEvent().type(), QEvent::KeyRelease);
+
+ // Backspace with autocapitalization change (which we don't do, we just simulate the
+ // event that would be generated because of that) between press and release events
+ QVERIFY(!filterKeyPress(Qt::Key_Backspace, Qt::NoModifier, "\b", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(2));
+ QVERIFY(filterKeyRelease(Qt::Key_Delete, Qt::ShiftModifier, "\177", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(3));
+ QCOMPARE(inputContextConnection->lastKeyEvent().type(), QEvent::KeyRelease);
+ QCOMPARE(inputContextConnection->lastKeyEvent().key(), static_cast<int>(Qt::Key_Backspace));
+ QCOMPARE(inputContextConnection->lastKeyEvent().modifiers(), Qt::ShiftModifier);
+ QCOMPARE(inputContextConnection->lastKeyEvent().text(), QString("\b"));
+}
+
+
+void Ut_MHardwareKeyboard::testDelete_data()
+{
+ QTest::addColumn<int>("state");
+ QTest::newRow("Clear") << 0;
+ QTest::newRow("Shift latched") << 1;
+ QTest::newRow("Shift locked") << 2;
+ QTest::newRow("Fn latched") << 4;
+ QTest::newRow("Fn locked") << 5;
+}
+
+void Ut_MHardwareKeyboard::testDelete()
+{
+ QFETCH(int, state);
+
+ setState(state);
+
+ // Native and Qt modifiers (except for Qt::ShiftModifier) in all of the
+ // following filterKey* calls don't match the reality.
+
+ filterKeyPress(Qt::Key_Shift, Qt::NoModifier, "", KeycodeNonCharacter, 0);
+
+ QVERIFY(filterKeyPress(Qt::Key_Delete, Qt::ShiftModifier, "\177", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(1));
+ QCOMPARE(inputContextConnection->lastKeyEvent().type(), QEvent::KeyPress);
+ QCOMPARE(inputContextConnection->lastKeyEvent().key(), static_cast<int>(Qt::Key_Delete));
+ QCOMPARE(inputContextConnection->lastKeyEvent().modifiers(), Qt::NoModifier);
+ QCOMPARE(inputContextConnection->lastKeyEvent().text(), QString("\177"));
+
+ QVERIFY(filterKeyRelease(Qt::Key_Delete, Qt::ShiftModifier, "\177", KeycodeCharacter, 0));
+ QCOMPARE(inputContextConnection->keyEventsSent(), static_cast<unsigned int>(2));
+ QCOMPARE(inputContextConnection->lastKeyEvent().type(), QEvent::KeyRelease);
+ QCOMPARE(inputContextConnection->lastKeyEvent().key(), static_cast<int>(Qt::Key_Delete));
+ QCOMPARE(inputContextConnection->lastKeyEvent().modifiers(), Qt::NoModifier);
+ QCOMPARE(inputContextConnection->lastKeyEvent().text(), QString("\177"));
+
+ filterKeyRelease(Qt::Key_Shift, Qt::NoModifier, "", KeycodeNonCharacter, 0);
+}
+
QTEST_APPLESS_MAIN(Ut_MHardwareKeyboard);
--- unit_test/ut_mhardwarekeyboard/ut_mhardwarekeyboard.h
+++ unit_test/ut_mhardwarekeyboard/ut_mhardwarekeyboard.h
@@ -56,6 +56,10 @@
void testSymPlusCharacterBasic();
void testSymPlusCharSwitchs();
+ void testReleaseEvents();
+ void testDelete_data();
+ void testDelete();
+
private:
bool checkLatchedState(unsigned int mask, unsigned int value) const;
bool checkLockedState(unsigned int mask, unsigned int value) const;
--- unit_test/ut_mimcorrectioncandidatewidget/ut_mimcorrectioncandidatewidget.cpp
+++ unit_test/ut_mimcorrectioncandidatewidget/ut_mimcorrectioncandidatewidget.cpp
@@ -37,8 +37,6 @@
MApplication::setLoadMInputContext(false);
app = new MApplication(dummyArgc, dummyArgv);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
-
// MImCorrectionCandidateWidget uses this internally
new MPlainWindow;
if (MPlainWindow::instance()->orientationAngle() != M::Angle0) {
@@ -96,13 +94,16 @@
// Goes over sceneHeight limit
QTest::newRow("positive3") <<QPoint(700, sceneHeight - 50) << -1
- << QPoint(700, (sceneHeight - testCandidateWidgetSize.height()));
+ << QPoint(700, ((sceneHeight - testCandidateWidgetSize.height()) > 0)?
+ (sceneHeight - testCandidateWidgetSize.height()):0);
// No room above so aligns to y=0.
QTest::newRow("bottom limit 1") << QPoint(10, 10) << 4 << QPoint(10, 0);
// There is room above so bottom limit holds (y+height=bottomlimit).
- QTest::newRow("bottom limit 2") << QPoint(10, 250) << 220 << QPoint(10, 220 - testCandidateWidgetSize.height());
+ QTest::newRow("bottom limit 2") << QPoint(10, 250) << 220
+ << QPoint(10, ((220 - testCandidateWidgetSize.height()) > 0)?
+ (220 - testCandidateWidgetSize.height()):0);
}
void Ut_MImCorrectionCandidateWidget::checkPositionByPoint()
--- unit_test/ut_mimtoolbar/testtoolbar.xml
+++ unit_test/ut_mimtoolbar/testtoolbar.xml
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE DUI_IM_TOOLBAR_WIDGET SYSTEM 'ImToolbarDTD.dtd'>
+
+<toolbar version="1">
+ <layout>
+ <row>
+ <button name="testbutton1" group="group1" priority="0" showon="always" alignment="left" text="testbutton1" toggle="true">
+ <actions>
+ <sendkeysequence keysequence="Ctrl+I"/>
+ <copy/>
+ <showgroup group="group3"/>
+ </actions>
+ </button>
+ <label name="testlabel1" group="group4" priority="1" showon="always" hideon="selectedtext" alignment="left" text="testlabel1"/>
+ <button name="testbutton2" group="group2" priority="0" showon="always" alignment="right" text="testbutton2">
+ <actions>
+ <sendstring string="test string"/>
+ <paste/>
+ <hidegroup group="group1"/>
+ </actions>
+ </button>
+ <!-- /row>
+ <row -->
+ <button name="testbutton3" group="group3" priority="1" showon="selectedtext" alignment="right" text="testbutton3">
+ </button>
+ </row>
+ </layout>
+</toolbar>
--- unit_test/ut_mimtoolbar/ut_mimtoolbar.cpp
+++ unit_test/ut_mimtoolbar/ut_mimtoolbar.cpp
@@ -18,25 +18,27 @@
#include "ut_mimtoolbar.h"
#include "mimtoolbar.h"
-#include "toolbarmanager.h"
-#include "toolbardata.h"
#include "mtoolbarbutton.h"
+#include "mtoolbarlabel.h"
#include "mapplication.h"
#include "mvirtualkeyboard.h"
#include "layoutsmanager.h"
#include "mvirtualkeyboardstyle.h"
#include <mplainwindow.h>
+#include <mtoolbardata.h>
#include <MTheme>
#include <MSceneWindow>
#include <MButton>
#include <MLabel>
#include <MInfoBanner>
+#include <MScene>
#include "mgconfitem_stub.h"
#include <QtTest/QTest>
#include <QObject>
#include <QDebug>
#include <QFile>
+#include <QDir>
#include <QStringList>
#include <QSignalSpy>
#include <QKeyEvent>
@@ -46,10 +48,7 @@
Q_DECLARE_METATYPE(CopyPasteState);
namespace
{
- // This file doesn't really exist in filesystem, its memory representation
- // is constructed in init().
- QString ToolbarFileName("/usr/share/meegotouch/imtoolbars/testtoolbar.xml");
- qlonglong ToolbarId(qrand());
+ QString ToolbarFileName = "/testtoolbar.xml";
int indexOf(const QGraphicsLayout *layout, const QGraphicsLayoutItem *item)
{
@@ -83,95 +82,24 @@
qRegisterMetaType<CopyPasteState>("CopyPasteState");
LayoutsManager::createInstance();
- QString cssFile("../../m-keyboard/theme/864x480.css");
- if (!QFile::exists(cssFile)) {
- cssFile = "/usr/share/meegotouch/virtual-keyboard/css/864x480.css";
- QVERIFY(QFile::exists(cssFile));
- }
- MTheme::instance()->loadCSS(cssFile);
-
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
- ToolbarManager::createInstance();
- //fill up toolbar with some data
- ToolbarData *toolbar = new ToolbarData;
- toolbar->toolbarFileName = ToolbarFileName;
- ToolbarWidget *b1 = new ToolbarWidget(ToolbarWidget::Button);
- b1->widgetName = "testbutton1";
- b1->group = "group1";
- b1->priority = 0;
- b1->orientation = M::Landscape;
- b1->showOn = ToolbarWidget::Always;
- b1->hideOn = ToolbarWidget::Undefined;
- b1->alignment = Qt::AlignLeft;
- b1->text = "testbutton1";
- b1->textId = "";
- b1->toggle = true;
- b1->pressed = false;
- ToolbarWidget::Action *action11 = new ToolbarWidget::Action(ToolbarWidget::SendKeySequence);
- action11->keys = "Ctrl+I";
- b1->actions.append(action11);
- ToolbarWidget::Action *action12 = new ToolbarWidget::Action(ToolbarWidget::Copy);
- b1->actions.append(action12);
- ToolbarWidget::Action *action13 = new ToolbarWidget::Action(ToolbarWidget::ShowGroup);
- action13->group = "group3";
- b1->actions.append(action13);
- toolbar->widgets.append(b1);
-
- ToolbarWidget *l1 = new ToolbarWidget(ToolbarWidget::Label);
- l1->widgetName = "testlabel1";
- l1->group = "group4";
- l1->priority = 1;
- l1->orientation = M::Landscape;
- l1->showOn = ToolbarWidget::Always;
- l1->hideOn = ToolbarWidget::WhenSelectingText;
- l1->alignment = Qt::AlignLeft;
- l1->text = "testlabel1";
- l1->textId = "";
- toolbar->widgets.append(l1);
-
- ToolbarWidget *b2 = new ToolbarWidget(ToolbarWidget::Button);
- b2->widgetName = "testbutton2";
- b2->group = "group2";
- b2->priority = 0;
- b2->orientation = M::Landscape;
- b2->showOn = ToolbarWidget::Always;
- b2->hideOn = ToolbarWidget::Undefined;
- b2->alignment = Qt::AlignRight;
- b2->text = "testbutton2";
- b2->textId = "";
- ToolbarWidget::Action *action21 = new ToolbarWidget::Action(ToolbarWidget::SendString);
- action21->text = "test string";
- b2->actions.append(action21);
- ToolbarWidget::Action *action22 = new ToolbarWidget::Action(ToolbarWidget::Paste);
- b2->actions.append(action22);
- ToolbarWidget::Action *action23 = new ToolbarWidget::Action(ToolbarWidget::HideGroup);
- action23->group = "group1";
- b2->actions.append(action23);
- toolbar->widgets.append(b2);
-
- ToolbarWidget *b3 = new ToolbarWidget(ToolbarWidget::Button);
- b3->widgetName = "testbutton3";
- b3->group = "group3";
- b3->priority = 1;
- b3->orientation = M::Landscape;
- b3->showOn = ToolbarWidget::WhenSelectingText;
- b3->hideOn = ToolbarWidget::Undefined;
- b3->alignment = Qt::AlignRight;
- b3->text = "testbutton3";
- b3->textId = "";
- toolbar->widgets.append(b3);
-
- ToolbarManager::instance().toolbars.insert(ToolbarId, ToolbarFileName);
- ToolbarManager::instance().cachedToolbars.insert(ToolbarId, toolbar);
- ToolbarManager::instance().cachedToolbarIds.prepend(ToolbarId);
-}
+ new MPlainWindow; // Create singleton
+ ToolbarFileName = QCoreApplication::applicationDirPath() + ToolbarFileName;
+ QVERIFY(QFile::exists(ToolbarFileName));
+}
void Ut_MImToolbar::init()
{
m_subject = new MImToolbar(*style);
+ MPlainWindow::instance()->scene()->addItem(m_subject);
+
+ //fill up toolbar with some data
+ toolbarData = QSharedPointer<MToolbarData>(new MToolbarData);
+ bool ok = toolbarData->loadNokiaToolbarXml(ToolbarFileName);
+ QVERIFY(ok);
}
@@ -182,8 +110,9 @@
void Ut_MImToolbar::cleanupTestCase()
{
- ToolbarManager::destroyInstance();
+ toolbarData.clear();
LayoutsManager::destroyInstance();
+ delete MPlainWindow::instance();
delete style;
style = 0;
delete app;
@@ -250,44 +179,44 @@
{
QSignalSpy spy(m_subject, SIGNAL(regionUpdated()));
QVERIFY(spy.isValid());
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//toolbar buttons depend on the its data
//including spacing widget and close button
- QCOMPARE(m_subject->leftBar.count(), 2);
- QCOMPARE(m_subject->rightBar.count(), 1);
+ QCOMPARE(m_subject->leftBar.layout()->count(), 2);
+ QCOMPARE(m_subject->rightBar.layout()->count(), 1);
QCOMPARE(spy.count(), 1);
spy.clear();
}
void Ut_MImToolbar::testShowGroup()
{
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//find button testbutton2, which click will show group test
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton1"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton1"));
QVERIFY(button != 0);
button->click();
- QCOMPARE(m_subject->leftBar.count(), 2);
- QCOMPARE(m_subject->rightBar.count(), 2);
+ QCOMPARE(m_subject->leftBar.layout()->count(), 2);
+ QCOMPARE(m_subject->rightBar.layout()->count(), 2);
}
void Ut_MImToolbar::testHideGroup()
{
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//find button testbutton2, which click will hide group test
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton2"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton2"));
QVERIFY(button != 0);
button->click();
- QCOMPARE(m_subject->leftBar.count(), 1);
- QCOMPARE(m_subject->rightBar.count(), 1);
+ QCOMPARE(m_subject->leftBar.layout()->count(), 1);
+ QCOMPARE(m_subject->rightBar.layout()->count(), 1);
}
void Ut_MImToolbar::testSendString()
{
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
QSignalSpy spy(m_subject, SIGNAL(sendStringRequest(const QString &)));
QVERIFY(spy.isValid());
//find button testbutton2, which click will send string
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton2"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton2"));
QVERIFY(button != 0);
button->click();
QVERIFY(spy.count() == 1);
@@ -296,13 +225,13 @@
void Ut_MImToolbar::testKeySequenceString()
{
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//find button testbutton1, which click will send key sequence (QKeyEvent)
//because QKeyEvent is not supported by MetaType, use its own slot to test it.
keyEvents = 0;
connect(m_subject, SIGNAL(sendKeyEventRequest(const QKeyEvent &)),
this, SLOT(receiveKeyEvent(const QKeyEvent &)));
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton1"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton1"));
QVERIFY(button != 0);
button->click();
QVERIFY(keyEvents > 0);
@@ -311,7 +240,7 @@
void Ut_MImToolbar::testHideToolbarWidget()
{
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
m_subject->hideToolbarWidget();
}
@@ -325,9 +254,9 @@
QSignalSpy spy(m_subject, SIGNAL(copyPasteRequest(CopyPasteState)));
QVERIFY(spy.isValid());
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//find button testbutton2, which click will copy
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton1"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton1"));
QVERIFY(button != 0);
button->click();
QVERIFY(spy.count() == 1);
@@ -342,9 +271,9 @@
QSignalSpy spy(m_subject, SIGNAL(copyPasteRequest(CopyPasteState)));
QVERIFY(spy.isValid());
- m_subject->showToolbarWidget(ToolbarId);
+ m_subject->showToolbarWidget(toolbarData);
//find button testbutton2, which click will paste
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton2"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton2"));
QVERIFY(button != 0);
button->click();
QVERIFY(spy.count() == 1);
@@ -359,9 +288,10 @@
{
QSignalSpy regionSignals(m_subject, SIGNAL(regionUpdated()));
- m_subject->showToolbarWidget(ToolbarId);
- QCOMPARE(m_subject->rightBar.count(), 1);
+ m_subject->showToolbarWidget(toolbarData);
QCOMPARE(regionSignals.count(), 1);
+ m_subject->updateVisibility();
+ QCOMPARE(regionSignals.count(), 2);
// Get region when there are two buttons on the right.
QRegion regionTwoButtons = m_subject->region();
@@ -372,13 +302,16 @@
// We need to add a new button, let's use groups.
// Clicking testbutton1 will add one button to the right.
- MButton *button = qobject_cast<MButton *>(m_subject->toolbarMgr.widget("testbutton1"));
+ MButton *button = qobject_cast<MButton *>(find("testbutton1"));
QVERIFY(button != 0);
button->click();
- QCOMPARE(m_subject->rightBar.count(), 2);
+
+ while (QCoreApplication::hasPendingEvents()) {
+ QCoreApplication::processEvents();
+ }
// Button added, check that regionUpdate() was emitted.
- QCOMPARE(regionSignals.count(), 2);
+ QCOMPARE(regionSignals.count(), 3);
// Get region when there are three buttons on the right.
QRegion regionThreeButtons = m_subject->region();
@@ -391,44 +324,29 @@
m_subject->hideToolbarWidget();
- QCOMPARE(regionSignals.count(), 3);
+ QCOMPARE(regionSignals.count(), 4);
m_subject->hide();
- QCOMPARE(regionSignals.count(), 4);
+ QCOMPARE(regionSignals.count(), 5);
QVERIFY(m_subject->region().isEmpty());
}
-void Ut_MImToolbar::testSetToolbarItemAttribute()
+MWidget* Ut_MImToolbar::find(const QString &name)
{
- m_subject->showToolbarWidget(ToolbarId);
- QString text("dummy_label");
-
- MToolbarButton *button = qobject_cast<MToolbarButton *>(m_subject->toolbarMgr.widget("testbutton1"));
- QVERIFY(button != 0);
- QCOMPARE(button->isCheckable(), true);
- QCOMPARE(button->isChecked(), false);
-
- MLabel *label = qobject_cast<MLabel *>(m_subject->toolbarMgr.widget("testlabel1"));
- QVERIFY(label != 0);
-
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testlabel1", "text", text);
- QCOMPARE(label->text(), text);
-
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testbutton1", "text", text);
- QCOMPARE(button->text(), text);
-
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testbutton1", "pressed", QVariant(true));
- QCOMPARE(button->isChecked(), true);
+ foreach (QPointer<MWidget> widget, m_subject->customWidgets) {
+ MToolbarButton *button = qobject_cast<MToolbarButton*>(widget);
+ if (button && button->item() && button->item()->name() == name) {
+ return button;
+ }
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testbutton1", "pressed", QVariant(false));
- QCOMPARE(button->isChecked(), false);
+ MToolbarLabel *label = qobject_cast<MToolbarLabel*>(widget);
+ if (label && label->item() && label->item()->name() == name) {
+ return label;
+ }
+ }
- QString icon("dummy_icon");
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testbutton1", "icon", icon);
- QCOMPARE(button->iconFile, icon);
- ToolbarManager::instance().setToolbarItemAttribute(ToolbarId, "testbutton1", "icon", QString(""));
- QCOMPARE(button->iconFile, QString(""));
+ return 0;
}
QTEST_APPLESS_MAIN(Ut_MImToolbar);
--- unit_test/ut_mimtoolbar/ut_mimtoolbar.h
+++ unit_test/ut_mimtoolbar/ut_mimtoolbar.h
@@ -21,10 +21,14 @@
#include <QtTest/QTest>
#include <QObject>
+#include <QSharedPointer>
+#include <mtoolbardata.h>
+
class MApplication;
class MImToolbar;
class QKeyEvent;
class MVirtualKeyboardStyleContainer;
+class MWidget;
class Ut_MImToolbar : public QObject
{
@@ -35,6 +39,7 @@
MImToolbar *m_subject;
int keyEvents;
MVirtualKeyboardStyleContainer *style;
+ QSharedPointer<MToolbarData> toolbarData;
private slots:
//! initialize application and class
@@ -53,9 +58,13 @@
void testCopy();
void testPaste();
void testRegion();
- void testSetToolbarItemAttribute();
void receiveKeyEvent(const QKeyEvent &);
+
+private:
+ // Find custom widget by given \a name
+ MWidget *find(const QString &name);
+
};
#endif
--- unit_test/ut_mimtoolbar/ut_mimtoolbar.pro
+++ unit_test/ut_mimtoolbar/ut_mimtoolbar.pro
@@ -20,4 +20,8 @@
SOURCES += ut_mimtoolbar.cpp \
../stubs/fakegconf.cpp
+target.files += \
+ $$TARGET \
+ testtoolbar.xml \
+
include(../common_check.pri)
--- unit_test/ut_mkeyboardhost/minputcontextstubconnection.cpp
+++ unit_test/ut_mkeyboardhost/minputcontextstubconnection.cpp
@@ -154,3 +154,7 @@
{
keyRedirectionEnabled = enabled;
}
+
+void MInputContextStubConnection::setDetectableAutoRepeat(bool /*enabled*/)
+{
+}
--- unit_test/ut_mkeyboardhost/minputcontextstubconnection.h
+++ unit_test/ut_mkeyboardhost/minputcontextstubconnection.h
@@ -50,6 +50,7 @@
virtual bool surroundingText(QString &text, int &cursorPosition);
virtual void setRedirectKeys(bool enabled);
+ virtual void setDetectableAutoRepeat(bool enabled);
QString preedit;
QString commit;
--- unit_test/ut_mkeyboardhost/ut_mkeyboardhost.cpp
+++ unit_test/ut_mkeyboardhost/ut_mkeyboardhost.cpp
@@ -21,10 +21,9 @@
#include <mhardwarekeyboard.h>
#include <mkeyboardhost.h>
#include <mvirtualkeyboardstyle.h>
-#include <layoutmenu.h>
#include <symbolview.h>
-#include "duiimenginewords.h"
+#include <mimenginewords.h>
#include "mgconfitem_stub.h"
#include "minputcontextstubconnection.h"
@@ -38,6 +37,7 @@
#include <MWidgetController>
#include <MDialog>
+#include <QGraphicsLayout>
#include <QDir>
#include <X11/X.h>
@@ -51,8 +51,10 @@
bool gAccurateMode = false;
int gSetKeyboardStateCallCount = 0;
MIMHandlerState gSetKeyboardStateParam = OnScreen;
- const int LayoutMenuShowTime = 300; // in ms
const int SceneRotationTime = 1400; // in ms
+
+ // This GConf item defines whether multitouch is enabled or disabled
+ const char * const MultitouchSettings = "/meegotouch/inputmethods/multitouch/enabled";
}
namespace QTest
@@ -71,7 +73,7 @@
Q_DECLARE_METATYPE(QSet<MIMHandlerState>)
Q_DECLARE_METATYPE(MIMHandlerState)
-
+Q_DECLARE_METATYPE(ModifierState)
static void waitForSignal(const QObject* object, const char* signal, int timeout = 500)
{
@@ -111,9 +113,10 @@
// Avoid waiting if im server is not responding
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
inputContext = new MInputContextStubConnection;
window = new MPlainWindow;
+
+ MGConfItem(MultitouchSettings).set(true);
}
void Ut_MKeyboardHost::cleanupTestCase()
@@ -131,6 +134,8 @@
// Uses dummy driver
MGConfItem engineConfig(InputMethodCorrectionEngine);
engineConfig.set(QVariant(QString("dummyimdriver")));
+ MGConfItem config(InputMethodCorrectionSetting);
+ config.set(QVariant(false));
subject = new MKeyboardHost(inputContext, 0);
inputContext->clear();
@@ -353,6 +358,7 @@
{
subject->show();
MGConfItem config(InputMethodCorrectionSetting);
+ config.set(QVariant(true));
QVERIFY(subject->imCorrectionEngine != 0);
//default error correction option is true;
@@ -382,19 +388,19 @@
inputContext->cursorPos = 0;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
inputContext->cursorPos = 1;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
inputContext->cursorPos = 12;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
inputContext->cursorPos = 13;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
subject->hide();
@@ -402,23 +408,23 @@
inputContext->cursorPos = 13;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
inputContext->cursorPos = 16;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
inputContext->cursorPos = 31;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
inputContext->cursorPos = 33;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
inputContext->cursorPos = 0;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
// When autoCaps is on and shift is latched, any key input except shift and backspace (in an sepcial case)
// will turn off shift.
KeyEvent press("a", QEvent::KeyPress);
@@ -426,18 +432,18 @@
subject->handleKeyPress(press);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
// If there are some preedit, capitalization should be off.
subject->preedit = "Test";
inputContext->cursorPos = 0;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
subject->preedit = "";
inputContext->cursorPos = 0;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
// The special case for backspace when autoCaps is on, that is cursor is at 0 position,
// should not change the shift state.
press = KeyEvent("", QEvent::KeyPress, Qt::Key_Backspace);
@@ -445,17 +451,17 @@
subject->handleKeyPress(press);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
// If cursor is not at 0 position, backspace should also change the shift state.
inputContext->cursorPos = 2;
subject->update();
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ subject->vkbWidget->setShiftState(ModifierLatchedState);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
subject->handleKeyPress(press);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
// Test holding backspace with preedit.
press = KeyEvent("", QEvent::KeyPress, Qt::Key_Backspace);
@@ -464,9 +470,9 @@
subject->preedit = "You can use";
// initial state: preedit("You can use"), shift state:latched, start holding backspace
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
+ subject->vkbWidget->setShiftState(ModifierLatchedState);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
// press and release backspace before timeout will only delete one character,
subject->handleKeyPress(press);
@@ -474,7 +480,7 @@
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
QCOMPARE(subject->preedit, QString("You can us"));
// but hold backspace longer than timeout, will delete the whole preedit.
@@ -483,17 +489,17 @@
QTest::qWait(interval / 2);
QVERIFY(subject->backSpaceTimer.isActive());
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
QTest::qWait((interval / 2) + 50);
// final state: preedit(""), shift state:on, after holding backspace enough time.
QVERIFY(subject->preedit.isEmpty());
QVERIFY(!subject->backSpaceTimer.isActive());
inputContext->cursorPos = 13;
subject->update();
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
subject->hide();
QTest::qWait(MVirtualKeyboard::ShowHideTime + 50);
@@ -504,28 +510,28 @@
subject->show();
subject->update();
QTest::qWait(MVirtualKeyboard::ShowHideTime + 50);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
// When shift is latched, any key input except shift will turn off shift.
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ subject->vkbWidget->setShiftState(ModifierLatchedState);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
press = KeyEvent("a", QEvent::KeyPress);
release = KeyEvent(press, QEvent::KeyRelease);
subject->handleKeyPress(press);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
// Backspace will also change the shift state when cursor is at 0 position.
inputContext->cursorPos = 0;
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOn);
+ subject->vkbWidget->setShiftState(ModifierLatchedState);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierLatchedState);
press = KeyEvent("", QEvent::KeyPress, Qt::Key_Backspace);
release = KeyEvent(press, QEvent::KeyRelease);
subject->handleKeyPress(press);
subject->handleKeyRelease(release);
subject->handleKeyClick(release);
- QVERIFY(subject->vkbWidget->shiftStatus() == MVirtualKeyboard::ShiftOff);
+ QVERIFY(subject->vkbWidget->shiftStatus() == ModifierClearState);
}
void Ut_MKeyboardHost::testApplicationOrientationChanged()
@@ -600,6 +606,7 @@
// is made visible right before the animation starts.
QCOMPARE(spy.count(), c1);
QCOMPARE(spy2.count(), c2);
+
QCOMPARE(region(spy, c1 - 1), region(spy2, 0));
QVERIFY(!region(spy, c1 - 1).isEmpty());
@@ -611,19 +618,39 @@
QCOMPARE(spy2.count(), c2);
qDebug() << "Passthrough region: " << region(spy, 1);
qDebug() << "libmeegotouch region: " << region(spy2, 1);
- QCOMPARE(region(spy, c1 - 1), region(spy2, 1));
+ QVERIFY((region(spy, c1 - 1) - region(spy2, 1)).isEmpty());
- // When layout menu is shown, input method area doesn't change...
- QTimer::singleShot(LayoutMenuShowTime, subject->layoutMenu->keyboardOptionDialog, SLOT(reject()));
- qDebug() << "Opening and closing layout menu...";
- subject->showLayoutMenu();
- waitForSignal(subject->layoutMenu, SIGNAL(regionUpdated(const QRegion&)));
- qDebug() << "...layout menu closed.";
- c1 += 2;
+ // In normal input method mode there is no invisible handle with non-zero area
+ const QRect zeroSizeInvisibleHandleRect(
+ dynamic_cast<QGraphicsWidget*>(subject->vkbWidget->layout()->itemAt(MVirtualKeyboard::SharedHandleAreaIndex))->layout()->itemAt(0)
+ ->geometry().toRect());
+ QVERIFY(zeroSizeInvisibleHandleRect.isEmpty());
+
+ // In direct mode an invisible handle is added on top of the keyboard
+ subject->vkbWidget->setInputMethodMode(M::InputMethodModeDirect);
+ ++c1;
+ ++c2;
+ QCOMPARE(spy.count(), c1);
+ QCOMPARE(spy2.count(), c2);
+
+ const QRect invisibleHandleRect(
+ dynamic_cast<QGraphicsWidget*>(subject->vkbWidget->layout()->itemAt(MVirtualKeyboard::SharedHandleAreaIndex))->layout()->itemAt(0)
+ ->geometry().toRect());
+ QVERIFY(!invisibleHandleRect.isEmpty());
+ const QRegion invisibleHandleRegion(
+ invisibleHandleRect.translated(0, (region(spy2, 0).boundingRect().top()
+ - invisibleHandleRect.height())));
+
+ QCOMPARE(region(spy, c1 - 1), region(spy2, c2 - 1) + invisibleHandleRegion);
+
+ subject->vkbWidget->setInputMethodMode(M::InputMethodModeNormal);
+ ++c1;
+ ++c2;
QCOMPARE(spy.count(), c1);
QCOMPARE(spy2.count(), c2);
- // ...and after closing the region is again the same as the input method area
+
QCOMPARE(region(spy, c1 - 1), region(spy2, c2 - 1));
+ QCOMPARE(region(spy, c1 - 1), region(spy2, c1 - 3));
// In opaque mode, candidate widget has its own window, so no regions are sent to kbhost.
#ifndef DUI_IM_DISABLE_TRANSLUCENCY
@@ -636,7 +663,7 @@
subject->correctionCandidateWidget->hide();
++c1;
QCOMPARE(spy.count(), c1);
- QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy2.count(), c2);
QCOMPARE(region(spy, c1 - 1), region(spy2, c2 - 1));
#endif
@@ -654,7 +681,8 @@
++c2;
QCOMPARE(spy.count(), c1);
QCOMPARE(spy2.count(), c2);
- QCOMPARE(region(spy, c1BeforeSymOpen - 1), region(spy, c1 - 1)); // the same as before opening it
+ // the same as before opening it
+ QCOMPARE(region(spy, c1BeforeSymOpen - 1), region(spy, c1 - 1));
// Hide the keyboard -> empty region and input method area
subject->hide();
@@ -674,7 +702,11 @@
rotateToAngle(M::Angle270);
subject->show();
QTest::qWait(MVirtualKeyboard::ShowHideTime + 50);
+
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy2.count(), 2);
QCOMPARE(region(spy, 1), region(spy2, 1));
+
QRegion region270(region(spy, 1));
subject->hide();
QTest::qWait(MVirtualKeyboard::ShowHideTime + 50);
@@ -800,18 +832,21 @@
void Ut_MKeyboardHost::testSymbolKeyClick()
{
QVERIFY(subject->symbolView);
+
+ // Symbol view is toggled by clicking the Sym button.
+
+ // Initially symbol view is closed.
QVERIFY(!subject->symbolView->isActive());
- //symbol key click will active symbol view and switch the pages
- int currentPageIndex;
- for (int i = 0; i < subject->symbolView->pageCount(); i++) {
+ bool symOpenExpected = false;
+
+ for (int clicks = 1; clicks <= 3; ++clicks) {
subject->handleSymbolKeyClick();
- QVERIFY(subject->symbolView->isActive());
- currentPageIndex = subject->symbolView->currentPage();
- QCOMPARE(currentPageIndex, i);
+
+ const bool symOpen = subject->symbolView->isActive();
+ symOpenExpected = !symOpenExpected;
+
+ QCOMPARE(symOpen, symOpenExpected);
}
- //if reach the last page, then symbol view will be closed
- subject->handleSymbolKeyClick();
- QVERIFY(!subject->symbolView->isActive());
}
void Ut_MKeyboardHost::testUpdateSymbolViewLevel()
@@ -861,32 +896,33 @@
//onscreen state
QVERIFY(subject->vkbWidget);
- QSignalSpy spy1(subject->vkbWidget, SIGNAL(shiftLevelChanged()));
-
subject->autoCapsEnabled = false; // disable auto caps
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOff);
+ subject->vkbWidget->setShiftState(ModifierClearState);
state.clear();
state << OnScreen;
subject->setState(state);
+ QSignalSpy spy1(subject->vkbWidget, SIGNAL(shiftLevelChanged()));
+
QVERIFY(!subject->symbolView->isActive());
subject->symbolView->showSymbolView();
QVERIFY(subject->symbolView->isActive());
QCOMPARE(subject->symbolView->currentLevel(), 0);
- QCOMPARE(subject->vkbWidget->shiftStatus(), MVirtualKeyboard::ShiftOff);
+ QCOMPARE(subject->vkbWidget->shiftStatus(), ModifierClearState);
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOn);
- QCOMPARE(subject->vkbWidget->shiftStatus(), MVirtualKeyboard::ShiftOn);
+ spy1.clear();
+ subject->vkbWidget->setShiftState(ModifierLatchedState);
+ QCOMPARE(subject->vkbWidget->shiftStatus(), ModifierLatchedState);
QCOMPARE(spy1.count(), 1);
QCOMPARE(subject->symbolView->currentLevel(), 1);
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftLock);
+ subject->vkbWidget->setShiftState(ModifierLockedState);
QCOMPARE(spy1.count(), 2);
- QCOMPARE(subject->vkbWidget->shiftStatus(), MVirtualKeyboard::ShiftLock);
+ QCOMPARE(subject->vkbWidget->shiftStatus(), ModifierLockedState);
QCOMPARE(subject->symbolView->currentLevel(), 1);
- subject->vkbWidget->setShiftState(MVirtualKeyboard::ShiftOff);
+ subject->vkbWidget->setShiftState(ModifierClearState);
QCOMPARE(spy1.count(), 3);
- QCOMPARE(subject->vkbWidget->shiftStatus(), MVirtualKeyboard::ShiftOff);
+ QCOMPARE(subject->vkbWidget->shiftStatus(), ModifierClearState);
QCOMPARE(subject->symbolView->currentLevel(), 0);
subject->hide();
@@ -951,4 +987,106 @@
QCOMPARE(inputContext->commit, QString(event2.text()[0]) + " ");
}
+void Ut_MKeyboardHost::testPressShift_data()
+{
+ QTest::addColumn<MIMHandlerState>("state");
+ QTest::addColumn<ModifierState>("initialShiftState");
+ QTest::addColumn<ModifierState>("expectedShiftState");
+ QTest::addColumn<bool>("enableMultiTouch");
+
+ QTest::newRow("screen lowercase") << OnScreen << ModifierClearState << ModifierLatchedState << true;
+ QTest::newRow("screen latched") << OnScreen << ModifierLatchedState << ModifierClearState << true;
+ QTest::newRow("screen locked") << OnScreen << ModifierLockedState << ModifierClearState << true;
+
+ QTest::newRow("hw lowercase") << Hardware << ModifierClearState << ModifierClearState << true;
+ QTest::newRow("hw latched") << Hardware << ModifierLatchedState << ModifierLatchedState << true;
+ QTest::newRow("hw locked") << Hardware << ModifierLockedState << ModifierLockedState << true;
+
+ QTest::newRow("single-touch lowercase") << OnScreen << ModifierClearState << ModifierClearState << false;
+ QTest::newRow("single-touch latched") << OnScreen << ModifierLatchedState << ModifierLatchedState << false;
+ QTest::newRow("single-touch locked") << OnScreen << ModifierLockedState << ModifierLockedState << false;
+}
+
+void Ut_MKeyboardHost::testPressShift()
+{
+ QFETCH(MIMHandlerState, state);
+ QFETCH(ModifierState, initialShiftState);
+ QFETCH(ModifierState, expectedShiftState);
+ QFETCH(bool, enableMultiTouch);
+
+ QSet<MIMHandlerState> set;
+ set << state;
+
+ KeyEvent pressShift(QString(), QEvent::KeyPress, Qt::Key_Shift, KeyEvent::NotSpecial, Qt::ShiftModifier);
+
+ subject->setState(set);
+ subject->vkbWidget->setShiftState(initialShiftState);
+ subject->enableMultiTouch = enableMultiTouch;
+
+ subject->handleKeyPress(pressShift);
+ QVERIFY(subject->vkbWidget->shiftStatus() == expectedShiftState);
+
+ subject->handleKeyPress(pressShift);
+ QVERIFY(subject->vkbWidget->shiftStatus() == expectedShiftState);
+}
+
+void Ut_MKeyboardHost::testReleaseShift_data()
+{
+ QTest::addColumn<MIMHandlerState>("state");
+ QTest::addColumn<ModifierState>("initialShiftState");
+ QTest::addColumn<ModifierState>("expectedShiftState");
+ QTest::addColumn<bool>("upperCase");
+ QTest::addColumn<bool>("upperCase2");
+
+ QTest::newRow("screen lowercase") << OnScreen << ModifierClearState << ModifierClearState << false << false;
+ QTest::newRow("screen latched") << OnScreen << ModifierLatchedState << ModifierLatchedState << false << false;
+ QTest::newRow("screen locked") << OnScreen << ModifierLockedState << ModifierLockedState << false << false;
+
+ QTest::newRow("screen lowercase 2") << OnScreen << ModifierClearState << ModifierLatchedState << false << true;
+ QTest::newRow("screen latched 2") << OnScreen << ModifierLatchedState << ModifierClearState << true << false;
+ QTest::newRow("screen locked 2") << OnScreen << ModifierLockedState << ModifierLatchedState << false << true;
+
+ QTest::newRow("hw lowercase") << Hardware << ModifierClearState << ModifierClearState << false << false;
+ QTest::newRow("hw latched") << Hardware << ModifierLatchedState << ModifierLatchedState << false << false;
+ QTest::newRow("hw locked") << Hardware << ModifierLockedState << ModifierLockedState << false << false;
+}
+
+void Ut_MKeyboardHost::testReleaseShift()
+{
+ QFETCH(MIMHandlerState, state);
+ QFETCH(ModifierState, initialShiftState);
+ QFETCH(ModifierState, expectedShiftState);
+ QFETCH(bool, upperCase);
+ QFETCH(bool, upperCase2);
+
+ QSet<MIMHandlerState> set;
+ set << state;
+
+ KeyEvent pressShift (QString(), QEvent::KeyPress, Qt::Key_Shift, KeyEvent::NotSpecial, Qt::ShiftModifier);
+ KeyEvent releaseShift(QString(), QEvent::KeyRelease, Qt::Key_Shift, KeyEvent::NotSpecial, Qt::ShiftModifier);
+
+ subject->setState(set);
+ subject->vkbWidget->setShiftState(initialShiftState);
+ subject->upperCase = upperCase;
+
+ subject->handleKeyPress(pressShift);
+ subject->upperCase = upperCase2;
+ subject->handleKeyRelease(releaseShift);
+ QVERIFY(subject->vkbWidget->shiftStatus() == expectedShiftState);
+
+ subject->handleKeyRelease(releaseShift);
+ QVERIFY(subject->vkbWidget->shiftStatus() == expectedShiftState);
+}
+
+void Ut_MKeyboardHost::testCommitPreeditOnStateChange()
+{
+ const QString text("fish");
+ subject->setPreedit(text);
+ QSet<MIMHandlerState> state;
+ state << Hardware;
+ subject->setState(state);
+ QCOMPARE(inputContext->commit, text);
+}
+
QTEST_APPLESS_MAIN(Ut_MKeyboardHost);
+
--- unit_test/ut_mkeyboardhost/ut_mkeyboardhost.h
+++ unit_test/ut_mkeyboardhost/ut_mkeyboardhost.h
@@ -70,6 +70,14 @@
void testKeyCycle_data();
void testKeyCycle();
+ void testPressShift_data();
+ void testPressShift();
+
+ void testReleaseShift_data();
+ void testReleaseShift();
+
+ void testCommitPreeditOnStateChange();
+
private:
void rotateToAngle(M::OrientationAngle);
};
--- unit_test/ut_mkeyboardhost/ut_mkeyboardhost.pro
+++ unit_test/ut_mkeyboardhost/ut_mkeyboardhost.pro
@@ -6,16 +6,17 @@
LIBS += -L/usr/lib -Wl,-rpath=/usr/lib/meego-im-plugins/ -lmeego-keyboard
-CONFIG += duiimengine duiimenginewords link_pkgconfig
+CONFIG += meegoimengine meegoimenginewords link_pkgconfig
PKGCONFIG += gconf-2.0
# Input
HEADERS += ut_mkeyboardhost.h \
minputcontextstubconnection.h \
../stubs/mgconfitem_stub.h \
- ../stubs/fakegconf.h
+ ../stubs/fakegconf.h \
+
SOURCES += ut_mkeyboardhost.cpp \
minputcontextstubconnection.cpp \
- ../stubs/fakegconf.cpp
+ ../stubs/fakegconf.cpp \
include(../common_check.pri)
--- unit_test/ut_mkeyboardplugin/ut_mkeyboardplugin.cpp
+++ unit_test/ut_mkeyboardplugin/ut_mkeyboardplugin.cpp
@@ -51,12 +51,6 @@
// some simple checks that the functions seems to work
// check name of plugin
QVERIFY(m_subject->name() == "MeegoKeyboard");
-
- // check possible languages
- QVERIFY(m_subject->languages().count() == 1);
-
- // only language at the moment is 'en' for this plugin
- QVERIFY(m_subject->languages().indexOf("en") != -1);
}
--- unit_test/ut_mvirtualkeyboard/ut_mvirtualkeyboard.cpp
+++ unit_test/ut_mvirtualkeyboard/ut_mvirtualkeyboard.cpp
@@ -19,10 +19,10 @@
#include "mapplication.h"
#include "mgconfitem_stub.h"
#include "mreactionmaptester.h"
+#include "mvirtualkeyboardstyle.h"
#include "mvirtualkeyboard.h"
#include "horizontalswitcher.h"
#include "layoutsmanager.h"
-#include "toolbarmanager.h"
#include "notification.h"
#include "ut_mvirtualkeyboard.h"
#include "vkbdatakey.h"
@@ -41,7 +41,6 @@
#include <QGraphicsLayout>
#include <mtexteditmodel.h>
#include <mtheme.h>
-#include <layoutmenu.h>
namespace
{
@@ -57,11 +56,6 @@
{
}
-LayoutMenu::~LayoutMenu()
-{
-//this stub allows to avoid crash in libmeegotouch
-}
-
void Notification::displayText(const QString &message)
{
Q_UNUSED(message);
@@ -84,28 +78,14 @@
MGConfItem item1(InputMethodSetting);
QStringList langlist;
- langlist << "en_GB" << "fi" << "ar_SA";
+ langlist << "en_GB" << "fi" << "ar";
item1.set(QVariant(langlist));
QString DefaultLanguageSetting("/meegotouch/inputmethods/languages/default");
MGConfItem item2(DefaultLanguageSetting);
- QString defaultlanguage = "en_GB";
+ QString defaultlanguage = "en_gb";
item2.set(QVariant(defaultlanguage));
- QString pixmapDirectory("../../m-keyboard/theme");
- if (!QFile::exists(pixmapDirectory)) {
- pixmapDirectory = "/usr/share/meegotouch/virtual-keyboard/images";
- QVERIFY(QFile::exists(pixmapDirectory));
- }
- MTheme::instance()->addPixmapDirectory(pixmapDirectory);
-
- QString cssFile("../../m-keyboard/theme/864x480.css");
- if (!QFile::exists(cssFile)) {
- cssFile = "/usr/share/meegotouch/virtual-keyboard/css/864x480.css";
- QVERIFY(QFile::exists(cssFile));
- }
- MTheme::instance()->loadCSS(cssFile);
-
// MVirtualkeyboard uses MPlainWindow internally so we need to instantiate it.
new MPlainWindow; // creates a static instance
@@ -115,14 +95,17 @@
MPlainWindow::instance()->sceneManager()->appearSceneWindowNow(vkbParent);
LayoutsManager::createInstance();
- ToolbarManager::createInstance();
+
+ vkbStyleContainer = new MVirtualKeyboardStyleContainer;
+ vkbStyleContainer->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
}
void Ut_MVirtualKeyboard::cleanupTestCase()
{
- ToolbarManager::destroyInstance();
LayoutsManager::destroyInstance();
delete vkbParent;
+ delete vkbStyleContainer;
+ vkbStyleContainer = 0;
delete MPlainWindow::instance();
delete app;
app = 0;
@@ -130,7 +113,7 @@
void Ut_MVirtualKeyboard::init()
{
- m_vkb = new MVirtualKeyboard(LayoutsManager::instance(), vkbParent);
+ m_vkb = new MVirtualKeyboard(LayoutsManager::instance(), vkbStyleContainer, vkbParent);
connect(m_vkb, SIGNAL(regionUpdated(const QRegion &)), m_vkb, SLOT(redrawReactionMaps()));
@@ -143,6 +126,7 @@
// Stub might have been set to a local instance.
gMReactionMapStub = &gDefaultMReactionMapStub;
delete m_vkb;
+ m_vkb = 0;
}
void Ut_MVirtualKeyboard::clickBackspaceTest()
@@ -211,10 +195,10 @@
void Ut_MVirtualKeyboard::setShiftStateTest()
{
- QList<MVirtualKeyboard::ShiftLevel> levels;
- levels << MVirtualKeyboard::ShiftOn << MVirtualKeyboard::ShiftOff
- << MVirtualKeyboard::ShiftLock;
- foreach(MVirtualKeyboard::ShiftLevel level, levels) {
+ QList<ModifierState> levels;
+ levels << ModifierLatchedState << ModifierClearState
+ << ModifierLockedState;
+ foreach(ModifierState level, levels) {
m_vkb->setShiftState(level);
QCOMPARE(m_vkb->shiftStatus(), level);
}
@@ -366,7 +350,7 @@
QCOMPARE(m_vkb->activity, MVirtualKeyboard::Active);
// Set states that should be changed next time opening vkb.
- m_vkb->setShiftState(MVirtualKeyboard::ShiftOn); // Shift on
+ m_vkb->setShiftState(ModifierLatchedState); // Shift on
// Test after reopening the keyboard, rather than after closing.
m_vkb->hideKeyboard();
@@ -374,12 +358,12 @@
m_vkb->showKeyboard();
QTest::qWait(MVirtualKeyboard::ShowHideTime + 50);
- QCOMPARE(m_vkb->shiftStatus(), MVirtualKeyboard::ShiftOff); // Shift should be off
+ QCOMPARE(m_vkb->shiftStatus(), ModifierClearState); // Shift should be off
}
void Ut_MVirtualKeyboard::switchLevelTest()
{
- m_vkb->shiftLevel = MVirtualKeyboard::ShiftLock;
+ m_vkb->shiftLevel = ModifierLockedState;
m_vkb->switchLevel();
QCOMPARE(m_vkb->currentLevel, 1);
}
@@ -796,16 +780,17 @@
m_vkb->setCopyPasteButton(true, false);
QVERIFY(top >= m_vkb->geometry().top());
top = m_vkb->geometry().top();
+ const int topInHardwareState(top);
//show whole keyboard
m_vkb->setKeyboardState(OnScreen);
- top -= m_vkb->layout()->itemAt(1)->geometry().height();
+ top -= m_vkb->layout()->itemAt(MVirtualKeyboard::KeyboardIndex)->geometry().height()
+ + m_vkb->layout()->itemAt(MVirtualKeyboard::KeyboardHandleIndex)->geometry().height();
QCOMPARE(top, int(m_vkb->geometry().top()));
//show toolbar only
m_vkb->setKeyboardState(Hardware);
- top += m_vkb->layout()->itemAt(1)->geometry().height();
- QCOMPARE(top, int(m_vkb->geometry().top()));
+ QCOMPARE(topInHardwareState, int(m_vkb->geometry().top()));
}
void Ut_MVirtualKeyboard::testReactionMaps()
@@ -871,10 +856,10 @@
QSignalSpy spy(m_vkb, SIGNAL(showSymbolViewRequested()));
QVERIFY(spy.isValid());
- m_vkb->flickUpHandler(0);
+ m_vkb->flickUpHandler(KeyBinding());
QCOMPARE(spy.count(), 0);
- m_vkb->flickUpHandler(&binding);
+ m_vkb->flickUpHandler(binding);
QCOMPARE(spy.count(), expected);
}
--- unit_test/ut_mvirtualkeyboard/ut_mvirtualkeyboard.h
+++ unit_test/ut_mvirtualkeyboard/ut_mvirtualkeyboard.h
@@ -26,6 +26,7 @@
class MApplication;
class MVirtualKeyboard;
+class MVirtualKeyboardStyleContainer;
class QGraphicsScene;
class LayoutSection;
class MSceneWindow;
@@ -37,6 +38,7 @@
MApplication *app;
MVirtualKeyboard *m_vkb;
MSceneWindow *vkbParent;
+ MVirtualKeyboardStyleContainer *vkbStyleContainer;
QSharedPointer<const LayoutSection> functionkeySection;
int numFunctionKeys;
--- unit_test/ut_symbolview/ut_symbolview.cpp
+++ unit_test/ut_symbolview/ut_symbolview.cpp
@@ -44,7 +44,7 @@
{
const QString InputMethodSettingName("/meegotouch/inputmethods/languages");
const QString DefaultLanguageSettingName("/meegotouch/inputmethods/languages/default");
- const QString DefaultLanguage("en");
+ const QString DefaultLanguage("en_us");
const int SceneRotationTime = 1400;
} // namespace
@@ -59,14 +59,13 @@
// Avoid waiting if im server is not responding
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
style = new MVirtualKeyboardStyleContainer;
style->initialize("MVirtualKeyboard", "MVirtualKeyboardView", 0);
MGConfItem inputMethodSetting(InputMethodSettingName);
QStringList langlist;
- langlist << "en";
+ langlist << "en_us";
inputMethodSetting.set(QVariant(langlist));
MGConfItem defaultLanguageSetting(DefaultLanguageSettingName);
@@ -304,4 +303,14 @@
subject->finalizeOrientationChange();
}
+void Ut_SymbolView::testSetLanguage()
+{
+ // set an invalid language, at least it won't crash
+ // and still has the laste valid language.
+ QString oldLanguage = subject->currentLanguage;
+ subject->setLanguage("ThisLanguageLayoutShouldNotExist");
+ QVERIFY(subject->currentLanguage != "ThisLanguageLayoutShouldNotExist");
+ QCOMPARE(subject->currentLanguage, oldLanguage);
+}
+
QTEST_APPLESS_MAIN(Ut_SymbolView);
--- unit_test/ut_symbolview/ut_symbolview.h
+++ unit_test/ut_symbolview/ut_symbolview.h
@@ -56,6 +56,7 @@
void testChangeTab();
void testHideWithFlick_data();
void testHideWithFlick();
+ void testSetLanguage();
private:
void rotateToAngle(M::OrientationAngle angle);
--- unit_test/ut_toolbarmanager/ut_toolbarmanager.cpp
+++ unit_test/ut_toolbarmanager/ut_toolbarmanager.cpp
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#include "ut_toolbarmanager.h"
-#include <toolbarmanager.h>
-#include <toolbardata.h>
-#include <MApplication>
-#include <QDebug>
-
-
-namespace {
- const int MaximumToolbarCount = 10;
-}
-
-// overwrite ToolbarData::loadNokiaToolbarXml to avoid loading actual xml file.
-bool ToolbarData::loadNokiaToolbarXml(const QString &fileName)
-{
- Q_UNUSED(fileName);
- toolbarFileName = fileName;
- return true;
-}
-
-void Ut_ToolbarManager::initTestCase()
-{
- // Avoid waiting if im server is not responding
- MApplication::setLoadMInputContext(false);
-
- static char *argv[1] = {(char *) "ut_toolbarmanager"};
- static int argc = 1;
- app = new MApplication(argc, argv);
-}
-
-void Ut_ToolbarManager::cleanupTestCase()
-{
- delete app;
- app = 0;
-}
-
-void Ut_ToolbarManager::init()
-{
-}
-
-void Ut_ToolbarManager::cleanup()
-{
-}
-
-void Ut_ToolbarManager::testLoadToolbar()
-{
- std::auto_ptr<ToolbarManager> subject(new ToolbarManager);
- QList<qlonglong> toolbarIds;
- for (qlonglong i = 1; i <= 14; i ++)
- toolbarIds << i;
- QStringList toolbars;
- toolbars << "testToolbar1"
- << "testToolbar2"
- << "testToolbar3"
- << "testToolbar4"
- << "testToolbar5"
- << "testToolbar6"
- << "testToolbar7"
- << "testToolbar8"
- << "testToolbar9"
- << "testToolbar10"
- << "testToolbar11"
- << "testToolbar12"
- << "testToolbar13"
- << "testToolbar14";
-
- int toolbarCount = 0;
- // register all toolbars
- for (int i = 0; i < toolbarIds.count(); i++) {
- subject->registerToolbar(toolbarIds.at(i), toolbars.at(i));
- toolbarCount ++;
- QTest::qWait(50);
- //toolbar loop can only cache no more than MaximumToolbarCount toolbars
- if (toolbarCount < MaximumToolbarCount)
- QCOMPARE(subject->toolbarList().count(), toolbarCount);
- else
- QCOMPARE(subject->toolbarList().count(), MaximumToolbarCount);
- }
-
- for (int i = 0; i < toolbarIds.count(); i++) {
- QVERIFY(subject->loadToolbar(toolbarIds.at(i)));
- QTest::qWait(50);
- // the loaded toolbar is the current toolbar
- QCOMPARE(subject->currentToolbar(), toolbarIds.at(i));
- QVERIFY(subject->toolbarList().contains(toolbarIds.at(i)));
- if (i > MaximumToolbarCount) {
- // the rarely used toolbar will be removed from cached toolbars
- QVERIFY(!subject->toolbarList().contains(toolbarIds.at(i - MaximumToolbarCount)));
- }
- }
-
- toolbarCount = toolbarIds.count();
- foreach (qlonglong id, toolbarIds) {
- QVERIFY(subject->toolbars.contains(id));
- subject->unregisterToolbar(id);
- toolbarCount --;
- QCOMPARE(subject->toolbars.count(), toolbarCount);
- QVERIFY(!subject->toolbars.contains(id));
- }
-}
-
-QTEST_APPLESS_MAIN(Ut_ToolbarManager);
-
--- unit_test/ut_toolbarmanager/ut_toolbarmanager.h
+++ unit_test/ut_toolbarmanager/ut_toolbarmanager.h
-/* * This file is part of meego-keyboard *
- *
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * Contact: Nokia Corporation (directui at nokia.com)
- *
- * If you have questions regarding the use of this file, please contact
- * Nokia at directui at nokia.com.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * and appearing in the file LICENSE.LGPL included in the packaging
- * of this file.
- */
-
-
-
-#ifndef UT_TOOLBARMANAGER_H
-#define UT_TOOLBARMANAGER_H
-
-#include <QObject>
-#include <QtTest/QTest>
-
-class MApplication;
-
-class Ut_ToolbarManager : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void init();
- void cleanup();
- void testLoadToolbar();
-
-private:
- MApplication *app;
-};
-
-#endif
-
--- unit_test/ut_toolbarmanager/ut_toolbarmanager.pro
+++ unit_test/ut_toolbarmanager/ut_toolbarmanager.pro
-TEMPLATE = app
-CONFIG += QtTest meegotouch
-DEPENDPATH += .
-INCLUDEPATH += . \
- ../../m-keyboard/ \
- ../stubs/
-
-LIBS += -Wl,-rpath=/usr/lib/meego-im-plugins/ -L../../m-keyboard -lmeego-keyboard
-
-# Input
-HEADERS += ut_toolbarmanager.h \
-
-SOURCES += ut_toolbarmanager.cpp \
-
-include(../common_check.pri)
--- unit_test/ut_vkbdatakey/ut_vkbdatakey.cpp
+++ unit_test/ut_vkbdatakey/ut_vkbdatakey.cpp
@@ -37,7 +37,6 @@
// Avoid waiting if im server is not responding
MApplication::setLoadMInputContext(false);
app = new MApplication(argc, app_name);
- MTheme::instance()->loadCSS("/usr/share/meegotouch/virtual-keyboard/css/864x480.css");
}
void Ut_VKBDataKey::cleanupTestCase()
--- unit_test/ut_widgetbar/ut_widgetbar.cpp
+++ unit_test/ut_widgetbar/ut_widgetbar.cpp
@@ -16,12 +16,15 @@
#include "ut_widgetbar.h"
#include "widgetbar.h"
+#include "mtoolbarbutton.h"
+#include "mtoolbarlabel.h"
#include <MApplication>
#include <MButton>
#include <MLabel>
#include <QGraphicsLayout>
+#include <mtoolbaritem.h>
void Ut_WidgetBar::initTestCase()
{
@@ -208,5 +211,44 @@
QCOMPARE(index, -1);
}
+void Ut_WidgetBar::testLayoutUpdates()
+{
+ QSharedPointer<MToolbarItem> buttonItem1(new MToolbarItem("buttonItem1", MInputMethod::ItemButton));
+ QSharedPointer<MToolbarItem> buttonItem2(new MToolbarItem("buttonItem2", MInputMethod::ItemButton));
+ QSharedPointer<MToolbarItem> buttonItem3(new MToolbarItem("buttonItem3", MInputMethod::ItemButton));
+ QSharedPointer<MToolbarItem> labelItem(new MToolbarItem("labelItem", MInputMethod::ItemLabel));
+
+ MToolbarButton *button1 = new MToolbarButton(buttonItem1);
+ MToolbarButton *button2 = new MToolbarButton(buttonItem2);
+ MToolbarButton *button3 = new MToolbarButton(buttonItem3);
+ MToolbarLabel *label1 = new MToolbarLabel(labelItem);
+
+ subject->insert(0, button1);
+ subject->insert(1, button2);
+ subject->insert(2, label1);
+ subject->insert(3, button3);
+
+ QCOMPARE(subject->layout()->count(), 4);
+
+ labelItem->setVisible(false);
+ buttonItem2->setVisible(false);
+ buttonItem1->setVisible(false);
+
+ QCOMPARE(subject->layout()->count(), 1);
+ QCOMPARE(subject->layoutIndexOf(button3), 0);
+
+ buttonItem2->setVisible(true);
+ QCOMPARE(subject->layoutIndexOf(button2), 0);
+
+ labelItem->setVisible(true);
+ QCOMPARE(subject->layoutIndexOf(button2), 0);
+ QCOMPARE(subject->layoutIndexOf(label1), 1);
+
+ buttonItem1->setVisible(true);
+ QCOMPARE(subject->layoutIndexOf(button1), 0);
+ QCOMPARE(subject->layoutIndexOf(button2), 1);
+ QCOMPARE(subject->layoutIndexOf(label1), 2);
+ QCOMPARE(subject->layoutIndexOf(button3), 3);
+}
QTEST_APPLESS_MAIN(Ut_WidgetBar);
--- unit_test/ut_widgetbar/ut_widgetbar.h
+++ unit_test/ut_widgetbar/ut_widgetbar.h
@@ -47,6 +47,8 @@
void testLayoutContent();
void testIndexOf();
+
+ void testLayoutUpdates();
};
#endif // UT_WIDGETBAR_H
--- unit_test/ut_widgetbar/ut_widgetbar.pro
+++ unit_test/ut_widgetbar/ut_widgetbar.pro
@@ -1,14 +1,21 @@
TEMPLATE = app
-CONFIG += QtTest meegotouch
+CONFIG += QtTest meegotouch meegoimframework
include(../common_check.pri)
-STYLE_HEADERS += $$WIDGETS_DIR/widgetbarstyle.h
+STYLE_HEADERS += $$WIDGETS_DIR/widgetbarstyle.h \
+ $$WIDGETS_DIR/mtoolbarbuttonstyle.h \
SOURCES += ut_widgetbar.cpp \
- $$WIDGETS_DIR/widgetbar.cpp
+ $$WIDGETS_DIR/widgetbar.cpp \
+ $$WIDGETS_DIR/mtoolbarbutton.cpp \
+ $$WIDGETS_DIR/mtoolbarlabel.cpp \
+ $$WIDGETS_DIR/mtoolbarbuttonview.cpp \
HEADERS += ut_widgetbar.h \
$$WIDGETS_DIR/widgetbar.h \
+ $$WIDGETS_DIR/mtoolbarbutton.h \
+ $$WIDGETS_DIR/mtoolbarlabel.h \
+ $$WIDGETS_DIR/mtoolbarbuttonview.h \
$$STYLE_HEADERS \
++++++ meegotouch-inputmethodkeyboard.yaml
--- meegotouch-inputmethodkeyboard.yaml
+++ meegotouch-inputmethodkeyboard.yaml
@@ -1,6 +1,6 @@
Name: meegotouch-inputmethodkeyboard
Summary: MeeGo Virtual Keyboard
-Version: 0.4.2.1
+Version: 0.4.8
Release: 1
Group: System/GUI/Other
License: LGPL v2.1
@@ -9,14 +9,6 @@
- "%{name}-%{version}.tar.bz2"
Description: MeeGo Virtual Keyboard
-# Remove this once duiimengine, meegoimframework, meegotouchfeedback
-# and meegotouchfeedbackreactionmaps have been removed
-# Then uncomment lines in PkgConfigBR
-PkgBR:
- - meegotouch-inputmethodframework-devel
- - meegotouch-inputmethodengine-devel
- - meegotouch-feedback-devel
- - meegotouch-feedbackreactionmaps-devel
PkgConfigBR:
- QtCore >= 4.6.0
- QtDBus
@@ -25,10 +17,9 @@
- QtNetwork
- QtGui
- meegotouch
-# - MeegoImFramework
-# - DuiImEngine
-# - DuiImEngineWords
-# - meegotouchfeedbackreactionmaps
+ - MeegoImFramework
+ - MeegoImEngine
+ - meegotouch-feedbackreactionmaps
Provides:
- duikeyboard >= 0.4.0
More information about the MeeGo-commits
mailing list