diff options
-rw-r--r-- | src/corelib/io/qfile.cpp | 7 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_symbian.cpp | 10 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_symbian_p.h | 18 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 75 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 3 | ||||
-rw-r--r-- | src/corelib/plugin/qfactoryloader.cpp | 239 | ||||
-rw-r--r-- | src/corelib/plugin/qfactoryloader_p.h | 1 | ||||
-rw-r--r-- | src/gui/inputmethod/qcoefepinputcontext_p.h | 2 | ||||
-rw-r--r-- | src/gui/inputmethod/qcoefepinputcontext_s60.cpp | 77 | ||||
-rw-r--r-- | src/s60installs/bwins/QtCoreu.def | 5 | ||||
-rw-r--r-- | src/s60installs/eabi/QtCoreu.def | 2 |
11 files changed, 311 insertions, 128 deletions
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 06c403a..d08574d 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1332,6 +1332,13 @@ bool QFile::open(const RFile &f, OpenMode mode, FileHandleFlags handleFlags) This function is not supported on Windows CE. + On Symbian, this function returns -1 if the file was opened normally, + as Symbian OS native file handles do not fit in an int, and are + incompatible with C library functions that the handle would be used for. + If the file was opened using the overloads that take an open C library + file handle / file descriptor, then this function returns that same + handle. + \sa QSocketNotifier */ diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp index 63cc4f1..fa857c6 100644 --- a/src/corelib/io/qfilesystemwatcher_symbian.cpp +++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QNotifyChangeEvent::QNotifyChangeEvent(RFs &fs, const TDesC &file, - QSymbianFileSystemWatcherEngine *e, bool aIsDir, + QSymbianFileSystemWatcherInterface *e, bool aIsDir, TInt aPriority) : CActive(aPriority), isDir(aIsDir), @@ -96,9 +96,9 @@ void QNotifyChangeEvent::RunL() if (!failureCount) { int err; - QT_TRYCATCH_ERROR(err, engine->emitPathChanged(this)); + QT_TRYCATCH_ERROR(err, engine->handlePathChanged(this)); if (err != KErrNone) - qWarning("QNotifyChangeEvent::RunL() - emitPathChanged threw exception (Converted error code: %d)", err); + qWarning("QNotifyChangeEvent::RunL() - handlePathChanged threw exception (Converted error code: %d)", err); } } } @@ -203,7 +203,7 @@ QStringList QSymbianFileSystemWatcherEngine::removePaths(const QStringList &path return p; } -void QSymbianFileSystemWatcherEngine::emitPathChanged(QNotifyChangeEvent *e) +void QSymbianFileSystemWatcherEngine::handlePathChanged(QNotifyChangeEvent *e) { QMutexLocker locker(&mutex); @@ -255,7 +255,7 @@ void QSymbianFileSystemWatcherEngine::addNativeListener(const QString &directory QMutexLocker locker(&mutex); QString nativeDir(QDir::toNativeSeparators(directoryPath)); TPtrC ptr(qt_QString2TPtrC(nativeDir)); - currentAddEvent = new QNotifyChangeEvent(qt_s60GetRFs(), ptr, this, directoryPath.endsWith(QChar(L'/'), Qt::CaseSensitive)); + currentAddEvent = q_check_ptr(new QNotifyChangeEvent(qt_s60GetRFs(), ptr, this, directoryPath.endsWith(QChar(L'/')))); syncCondition.wakeOne(); } diff --git a/src/corelib/io/qfilesystemwatcher_symbian_p.h b/src/corelib/io/qfilesystemwatcher_symbian_p.h index 0b317a0..842df80 100644 --- a/src/corelib/io/qfilesystemwatcher_symbian_p.h +++ b/src/corelib/io/qfilesystemwatcher_symbian_p.h @@ -66,29 +66,35 @@ QT_BEGIN_NAMESPACE -class QSymbianFileSystemWatcherEngine; +class QSymbianFileSystemWatcherInterface; class QNotifyChangeEvent : public CActive { public: - QNotifyChangeEvent(RFs &fsSession, const TDesC &file, QSymbianFileSystemWatcherEngine *engine, + QNotifyChangeEvent(RFs &fsSession, const TDesC &file, QSymbianFileSystemWatcherInterface *engine, bool aIsDir, TInt aPriority = EPriorityStandard); ~QNotifyChangeEvent(); bool isDir; + TPath watchedPath; private: void RunL(); void DoCancel(); RFs &fsSession; - TPath watchedPath; - QSymbianFileSystemWatcherEngine *engine; + QSymbianFileSystemWatcherInterface *engine; int failureCount; }; -class QSymbianFileSystemWatcherEngine : public QFileSystemWatcherEngine +class QSymbianFileSystemWatcherInterface +{ +public: + virtual void handlePathChanged(QNotifyChangeEvent *e) = 0; +}; + +class QSymbianFileSystemWatcherEngine : public QFileSystemWatcherEngine, public QSymbianFileSystemWatcherInterface { Q_OBJECT @@ -111,7 +117,7 @@ public Q_SLOTS: private: friend class QNotifyChangeEvent; - void emitPathChanged(QNotifyChangeEvent *e); + void handlePathChanged(QNotifyChangeEvent *e); void startWatcher(); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c4a9e40..2eb68f7 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2329,6 +2329,33 @@ QString QCoreApplication::applicationVersion() #ifndef QT_NO_LIBRARY +#if defined(Q_OS_SYMBIAN) +void qt_symbian_installLibraryPaths(QString installPathPlugins, QStringList& libPaths) +{ + // Add existing path on all drives for relative PluginsPath in Symbian + QString tempPath = installPathPlugins; + if (tempPath.at(tempPath.length() - 1) != QDir::separator()) { + tempPath += QDir::separator(); + } + RFs& fs = qt_s60GetRFs(); + TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData())); + // Symbian searches should start from Y:. Fix start drive otherwise TFindFile starts from the session drive + _LIT(KStartDir, "Y:"); + TFileName dirPath(KStartDir); + dirPath.Append(tempPathPtr); + TFindFile finder(fs); + TInt err = finder.FindByDir(tempPathPtr, dirPath); + while (err == KErrNone) { + QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()), + finder.File().Length()); + foundDir = QDir(foundDir).canonicalPath(); + if (!libPaths.contains(foundDir)) + libPaths.append(foundDir); + err = finder.Find(); + } +} +#endif + Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive)) /*! @@ -2361,24 +2388,8 @@ QStringList QCoreApplication::libraryPaths() QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList; QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); #if defined(Q_OS_SYMBIAN) - // Add existing path on all drives for relative PluginsPath in Symbian if (installPathPlugins.at(1) != QChar(QLatin1Char(':'))) { - QString tempPath = installPathPlugins; - if (tempPath.at(tempPath.length() - 1) != QDir::separator()) { - tempPath += QDir::separator(); - } - RFs& fs = qt_s60GetRFs(); - TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData())); - TFindFile finder(fs); - TInt err = finder.FindByDir(tempPathPtr, tempPathPtr); - while (err == KErrNone) { - QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()), - finder.File().Length()); - foundDir = QDir(foundDir).canonicalPath(); - if (!app_libpaths->contains(foundDir)) - app_libpaths->append(foundDir); - err = finder.Find(); - } + qt_symbian_installLibraryPaths(installPathPlugins, *app_libpaths); } #else if (QFile::exists(installPathPlugins)) { @@ -2493,6 +2504,36 @@ void QCoreApplication::removeLibraryPath(const QString &path) QFactoryLoader::refreshAll(); } +#if defined(Q_OS_SYMBIAN) +void QCoreApplicationPrivate::rebuildInstallLibraryPaths() +{ + // check there is not a single fixed install path + QString nativeInstallPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); + if (nativeInstallPathPlugins.at(1) == QChar(QLatin1Char(':'))) + return; + QString installPathPlugins = QDir::cleanPath(nativeInstallPathPlugins); + // look for the install path at the drive roots + installPathPlugins.prepend(QChar(QLatin1Char(':'))); + + QMutexLocker locker(libraryPathMutex()); + QStringList &app_libpaths = *coreappdata()->app_libpaths; + // Build a new library path, copying non-installPath components, and replacing existing install path with new + QStringList newPaths; + bool installPathFound = false; + foreach (QString path, app_libpaths) { + if (path.mid(1).compare(installPathPlugins, Qt::CaseInsensitive) == 0) { + // skip existing install paths, insert new install path when we find the first + if (!installPathFound) + qt_symbian_installLibraryPaths(nativeInstallPathPlugins, newPaths); + installPathFound = true; + } else { + newPaths.append(path); + } + } + app_libpaths = newPaths; +} +#endif + #endif //QT_NO_LIBRARY /*! diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index c6c6489..6f75da3 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -126,6 +126,9 @@ public: void symbianInit(); # endif static CApaCommandLine* symbianCommandLine(); +#ifndef QT_NO_LIBRARY + static void rebuildInstallLibraryPaths(); +#endif #endif static bool isTranslatorInstalled(QTranslator *translator); diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index c8831e5..24b4be0 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -50,8 +50,13 @@ #include "qmutex.h" #include "qplugin.h" #include "qpluginloader.h" +#include "qlibraryinfo.h" #include "private/qobject_p.h" #include "private/qcoreapplication_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qcore_symbian_p.h" +#include "private/qfilesystemwatcher_symbian_p.h" +#endif QT_BEGIN_NAMESPACE @@ -59,6 +64,23 @@ Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders) Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive)) +#ifdef Q_OS_SYMBIAN +class QSymbianSystemPluginWatcher : public QSymbianFileSystemWatcherInterface +{ +public: + QSymbianSystemPluginWatcher(); + ~QSymbianSystemPluginWatcher(); + + void watchForUpdates(); + void handlePathChanged(QNotifyChangeEvent *e); + + QList<QNotifyChangeEvent*> watchers; + TDriveList drives; +}; + +Q_GLOBAL_STATIC(QSymbianSystemPluginWatcher, qt_symbian_system_plugin_watcher) +#endif + class QFactoryLoaderPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QFactoryLoader) @@ -98,102 +120,117 @@ QFactoryLoader::QFactoryLoader(const char *iid, QMutexLocker locker(qt_factoryloader_mutex()); update(); qt_factory_loaders()->append(this); +#ifdef Q_OS_SYMBIAN + // kick off Symbian plugin watcher for updates + qt_symbian_system_plugin_watcher(); +#endif } - -void QFactoryLoader::update() +void QFactoryLoader::updateDir(const QString &pluginDir, QSettings& settings) { -#ifdef QT_SHARED Q_D(QFactoryLoader); - QStringList paths = QCoreApplication::libraryPaths(); - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - for (int i = 0; i < paths.count(); ++i) { - const QString &pluginDir = paths.at(i); - // Already loaded, skip it... - if (d->loadedPaths.contains(pluginDir)) - continue; - d->loadedPaths << pluginDir; + QString path = pluginDir + d->suffix; + if (!QDir(path).exists(QLatin1String("."))) + return; - QString path = pluginDir + d->suffix; - if (!QDir(path).exists(QLatin1String("."))) - continue; + QStringList plugins = QDir(path).entryList(QDir::Files); + QLibraryPrivate *library = 0; + for (int j = 0; j < plugins.count(); ++j) { + QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j)); - QStringList plugins = QDir(path).entryList(QDir::Files); - QLibraryPrivate *library = 0; - for (int j = 0; j < plugins.count(); ++j) { - QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j)); + if (qt_debug_component()) { + qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; + } + library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); + if (!library->isPlugin(&settings)) { if (qt_debug_component()) { - qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; + qDebug() << library->errorString; + qDebug() << " not a plugin"; } - library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); - if (!library->isPlugin(&settings)) { + library->release(); + continue; + } + QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4") + .arg((QT_VERSION & 0xff0000) >> 16) + .arg((QT_VERSION & 0xff00) >> 8) + .arg(QLatin1String(d->iid)) + .arg(fileName); + QStringList reg, keys; + reg = settings.value(regkey).toStringList(); + if (reg.count() && library->lastModified == reg[0]) { + keys = reg; + keys.removeFirst(); + } else { + if (!library->loadPlugin()) { if (qt_debug_component()) { qDebug() << library->errorString; - qDebug() << " not a plugin"; + qDebug() << " could not load"; } library->release(); continue; } - QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4") - .arg((QT_VERSION & 0xff0000) >> 16) - .arg((QT_VERSION & 0xff00) >> 8) - .arg(QLatin1String(d->iid)) - .arg(fileName); - QStringList reg, keys; - reg = settings.value(regkey).toStringList(); - if (reg.count() && library->lastModified == reg[0]) { - keys = reg; - keys.removeFirst(); - } else { - if (!library->loadPlugin()) { - if (qt_debug_component()) { - qDebug() << library->errorString; - qDebug() << " could not load"; - } - library->release(); - continue; - } - QObject *instance = library->instance(); - if (!instance) { - library->release(); - // ignore plugins that have a valid signature but cannot be loaded. - continue; - } - QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); - if (instance && factory && instance->qt_metacast(d->iid)) - keys = factory->keys(); - if (keys.isEmpty()) - library->unload(); - reg.clear(); - reg << library->lastModified; - reg += keys; - settings.setValue(regkey, reg); - } - if (qt_debug_component()) { - qDebug() << "keys" << keys; - } - - if (keys.isEmpty()) { + QObject *instance = library->instance(); + if (!instance) { library->release(); + // ignore plugins that have a valid signature but cannot be loaded. continue; } - d->libraryList += library; - for (int k = 0; k < keys.count(); ++k) { - // first come first serve, unless the first - // library was built with a future Qt version, - // whereas the new one has a Qt version that fits - // better - QString key = keys.at(k); - if (!d->cs) - key = key.toLower(); - QLibraryPrivate *previous = d->keyMap.value(key); - if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) { - d->keyMap[key] = library; - d->keyList += keys.at(k); - } + QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); + if (instance && factory && instance->qt_metacast(d->iid)) + keys = factory->keys(); + if (keys.isEmpty()) + library->unload(); + reg.clear(); + reg << library->lastModified; + reg += keys; + settings.setValue(regkey, reg); + } + if (qt_debug_component()) { + qDebug() << "keys" << keys; + } + + if (keys.isEmpty()) { + library->release(); + continue; + } + + int keysUsed = 0; + for (int k = 0; k < keys.count(); ++k) { + // first come first serve, unless the first + // library was built with a future Qt version, + // whereas the new one has a Qt version that fits + // better + QString key = keys.at(k); + if (!d->cs) + key = key.toLower(); + QLibraryPrivate *previous = d->keyMap.value(key); + if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) { + d->keyMap[key] = library; + d->keyList += keys.at(k); + keysUsed++; } } + if (keysUsed) + d->libraryList += library; + else + library->release(); + } +} + +void QFactoryLoader::update() +{ +#ifdef QT_SHARED + Q_D(QFactoryLoader); + QStringList paths = QCoreApplication::libraryPaths(); + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + for (int i = 0; i < paths.count(); ++i) { + const QString &pluginDir = paths.at(i); + // Already loaded, skip it... + if (d->loadedPaths.contains(pluginDir)) + continue; + d->loadedPaths << pluginDir; + updateDir(pluginDir, settings); } #else Q_D(QFactoryLoader); @@ -264,6 +301,56 @@ void QFactoryLoader::refreshAll() } } +#ifdef Q_OS_SYMBIAN +QSymbianSystemPluginWatcher::QSymbianSystemPluginWatcher() +{ + qt_s60GetRFs().DriveList(drives); + watchForUpdates(); +} + +QSymbianSystemPluginWatcher::~QSymbianSystemPluginWatcher() +{ + qDeleteAll(watchers); +} + +void QSymbianSystemPluginWatcher::watchForUpdates() +{ + QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); + if (installPathPlugins.at(1) == QChar(QLatin1Char(':'))) + return; + + installPathPlugins.prepend(QLatin1String("?:")); + installPathPlugins = QDir::toNativeSeparators(installPathPlugins); + RFs& fs = qt_s60GetRFs(); + for (int i=0; i<KMaxDrives; i++) { + int attr = drives[i]; + if ((attr & KDriveAttLocal) && !(attr & KDriveAttRom)) { + // start new watcher + TChar driveLetter; + fs.DriveToChar(i, driveLetter); + installPathPlugins[0] = driveLetter; + TPtrC ptr(qt_QString2TPtrC(installPathPlugins)); + QNotifyChangeEvent *event = q_check_ptr(new QNotifyChangeEvent(fs, ptr, this, true)); + watchers.push_back(event); + } + } +} + +void QSymbianSystemPluginWatcher::handlePathChanged(QNotifyChangeEvent *e) +{ + QCoreApplicationPrivate::rebuildInstallLibraryPaths(); + QMutexLocker locker(qt_factoryloader_mutex()); + QString dirName(QDir::cleanPath(qt_TDesC2QString(e->watchedPath))); + QList<QFactoryLoader *> *loaders = qt_factory_loaders(); + for (QList<QFactoryLoader *>::const_iterator it = loaders->constBegin(); + it != loaders->constEnd(); ++it) { + QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); + (*it)->updateDir(dirName, settings); + } +} + +#endif + QT_END_NAMESPACE #endif // QT_NO_LIBRARY diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h index e90ebf6..8548ab2 100644 --- a/src/corelib/plugin/qfactoryloader_p.h +++ b/src/corelib/plugin/qfactoryloader_p.h @@ -82,6 +82,7 @@ public: #endif void update(); + void updateDir(const QString &pluginDir, QSettings& settings); static void refreshAll(); }; diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 8ef9726..ad51b4b 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -136,6 +136,7 @@ private: private Q_SLOTS: void ensureInputCapabilitiesChanged(); void translateInputWidget(); + void ensureWidgetVisibility(); // From MCoeFepAwareTextEditor public: @@ -208,6 +209,7 @@ private: int m_splitViewResizeBy; Qt::WindowStates m_splitViewPreviousWindowStates; QRectF m_transformation; + QGraphicsItem *m_splitViewPreviousFocusItem; //can't use QPointer<> since QGraphicsItem is not a QObject. CAknCcpuSupport *m_ccpu; QAction *m_copyAction; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 3546079..bacf07a 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -382,6 +382,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_hasTempPreeditString(false), m_splitViewResizeBy(0), m_splitViewPreviousWindowStates(Qt::WindowNoState), + m_splitViewPreviousFocusItem(0), m_ccpu(0) { m_fepState->SetObjectProvider(this); @@ -451,6 +452,11 @@ void QCoeFepInputContext::reset() if (m_cachedPreeditString.isEmpty() && !(currentHints & Qt::ImhNoPredictiveText)) m_cachedPreeditString = m_preeditString; commitCurrentString(true); + + // QGraphicsScene calls reset() when changing focus item. Unfortunately, the new focus item is + // set right after resetting the input context. Therefore, asynchronously call ensureWidgetVisibility(). + if (S60->splitViewLastWidget) + QMetaObject::invokeMethod(this,"ensureWidgetVisibility", Qt::QueuedConnection); } void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType) @@ -793,9 +799,8 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) { QGraphicsView *gv = qobject_cast<QGraphicsView*>(S60->splitViewLastWidget); - if (!gv) { + if (!gv) return; - } QSymbianControl *symControl = static_cast<QSymbianControl*>(gv->effectiveWinId()); symControl->CancelLongTapTimer(); @@ -810,11 +815,13 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) if (!alwaysResize) { if (gv->scene() && S60->partial_keyboardAutoTranslation) { if (gv->scene()->focusItem()) { + QGraphicsItem *focusItem = + m_splitViewPreviousFocusItem ? m_splitViewPreviousFocusItem : gv->scene()->focusItem(); // Check if the widget contains cursorPositionChanged signal and disconnect from it. QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); - int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); + int index = focusItem->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); if (index != -1) - disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + disconnect(focusItem->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); } QGraphicsItem *rootItem = 0; @@ -882,6 +889,11 @@ bool QCoeFepInputContext::isPartialKeyboardSupported() return (S60->partial_keyboard || !QApplication::testAttribute(Qt::AA_S60DisablePartialScreenInputMode)); } +void QCoeFepInputContext::ensureWidgetVisibility() +{ + ensureFocusWidgetVisible(S60->splitViewLastWidget); +} + // Ensure that the input widget is visible in the splitview rect. void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) @@ -913,17 +925,22 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) // states getting changed. if (!moveWithinVisibleArea) { - // Check if the widget contains cursorPositionChanged signal and connect to it. - QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); - if (gv->scene() && gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) { - int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); - if (index != -1) - connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); - } S60->splitViewLastWidget = widget; m_splitViewPreviousWindowStates = windowToMove->windowState(); } + // Check if the widget contains cursorPositionChanged signal and connect to it. + if (gv->scene() && gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) { + QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); + if (m_splitViewPreviousFocusItem && m_splitViewPreviousFocusItem != gv->scene()->focusItem()) + disconnect(m_splitViewPreviousFocusItem->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); + if (index != -1) { + connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); + m_splitViewPreviousFocusItem = gv->scene()->focusItem(); + } + } + int windowTop = widget->window()->pos().y(); const bool userResize = widget->testAttribute(Qt::WA_Resized); @@ -1266,10 +1283,15 @@ void QCoeFepInputContext::translateInputWidget() m_transformation = (rootItem->transform().isTranslating()) ? QRectF(0,0, gv->width(), rootItem->transform().dy()) : QRectF(); - // Adjust cursor bounding rect to be lower, so that view translates if the cursor gets near - // the splitview border. - QRect cursorRect = cursorP.boundingRect().adjusted(0, cursor.height(), 0, cursor.height()); - if (splitViewRect.contains(cursorRect)) + // Adjust cursor bounding rect towards navigation direction, + // so that view translates if the cursor gets near the splitview border. + QRect cursorRect = (cursorP.boundingRect().top() < 0) ? + cursorP.boundingRect().adjusted(0, -cursor.height(), 0, -cursor.height()) : + cursorP.boundingRect().adjusted(0, cursor.height(), 0, cursor.height()); + + // If the current cursor position and upcoming cursor positions are visible in the splitview + // area, do not move the view. + if (splitViewRect.contains(cursorRect) && splitViewRect.contains(cursorP.boundingRect())) return; // New Y position should be ideally just above the keyboard. @@ -1281,22 +1303,29 @@ void QCoeFepInputContext::translateInputWidget() const qreal itemHeight = path.boundingRect().height(); // Limit the maximum translation so that underlaying window content is not exposed. - qreal maxY = gv->sceneRect().bottom() - splitViewRect.bottom(); - maxY = m_transformation.height() ? (qMin(itemHeight, maxY) + m_transformation.height()) : maxY; - if (maxY < 0) - maxY = 0; + qreal availableSpace = gv->sceneRect().bottom() - splitViewRect.bottom(); + availableSpace = m_transformation.height() ? + (qMin(itemHeight, availableSpace) + m_transformation.height()) : + availableSpace; // Translation should happen row-by-row, but initially it needs to ensure that cursor is visible. const qreal translation = m_transformation.height() ? cursor.height() : (cursorRect.bottom() - vkbRect.top()); - qreal dy = -(qMin(maxY, translation)); + qreal dy = 0.0; + if (availableSpace > 0) + dy = -(qMin(availableSpace, translation)); + else + dy = -(translation); - // Correct the translation direction, if the cursor rect would be moved outside of application area. - if ((cursorRect.bottom() + dy) < 0) + // Correct the translation direction, if the cursor rect would be moved above application area. + if ((cursorP.boundingRect().bottom() + dy) < 0) dy *= -1; - // Do not allow transform above screen top, nor beyond scenerect - if (m_transformation.height() + dy > 0 || gv->sceneRect().bottom() + m_transformation.height() < 0) { + // Do not allow transform above screen top, nor beyond scenerect. Also, if there is no available + // space anymore, skip translation. + if ((m_transformation.height() + dy) > 0 + || (gv->sceneRect().bottom() + m_transformation.height()) < 0 + || !availableSpace) { // If we already have some transformation, remove it. if (m_transformation.height() < 0 || gv->sceneRect().bottom() + m_transformation.height() < 0) { rootItem->resetTransform(); diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index be09295..3437502 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4879,4 +4879,9 @@ EXPORTS ?languageId@QLocalePrivate@@QBEGXZ @ 4878 NONAME ; unsigned short QLocalePrivate::languageId(void) const ?started@QFutureWatcherBase@@IAEXXZ @ 4879 NONAME ; void QFutureWatcherBase::started(void) ?staticMetaObjectExtraData@QAbstractState@@0UQMetaObjectExtraData@@B @ 4880 NONAME ; struct QMetaObjectExtraData const QAbstractState::staticMetaObjectExtraData + ?rebuildInstallLibraryPaths@QCoreApplicationPrivate@@SAXXZ @ 4881 NONAME ; void QCoreApplicationPrivate::rebuildInstallLibraryPaths(void) + ?connectNotify@QFutureWatcherBase@@MAEXPBD@Z @ 4882 NONAME ; void QFutureWatcherBase::connectNotify(char const *) + ?event@QFutureWatcherBase@@UAE_NPAVQEvent@@@Z @ 4883 NONAME ; bool QFutureWatcherBase::event(class QEvent *) + ?updateDir@QFactoryLoader@@QAEXABVQString@@AAVQSettings@@@Z @ 4884 NONAME ; void QFactoryLoader::updateDir(class QString const &, class QSettings &) + ?disconnectNotify@QFutureWatcherBase@@MAEXPBD@Z @ 4885 NONAME ; void QFutureWatcherBase::disconnectNotify(char const *) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index cf42b67..1fabdb2 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -4162,4 +4162,6 @@ EXPORTS inflateReset2 @ 4161 NONAME inflateUndermine @ 4162 NONAME zlibCompileFlags @ 4163 NONAME + _ZN14QFactoryLoader9updateDirERK7QStringR9QSettings @ 4164 NONAME + _ZN23QCoreApplicationPrivate26rebuildInstallLibraryPathsEv @ 4165 NONAME |