From a9cb2be8c14317001c0945da84f1a19e1d6ee6c6 Mon Sep 17 00:00:00 2001 From: mread Date: Fri, 18 Mar 2011 10:42:45 +0000 Subject: Making Symbian helper threads exit cleanly at app exit The idle detector thread and the adopted thread monitor thread could keep an app alive unnecessarily after main had exited, if the app's main thread was no longer set "process permanent". The idle detector thread now exits when the QCoreApplication is destroyed. The adopted thread monitor thread now exits when there are no more adopted threads to monitor. Task-number: QTBUG-18073 Reviewed-by: Shane Kearns --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 50 ++++++++++++++++++++----- src/corelib/thread/qthread_symbian.cpp | 36 +++++++++++++----- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 53796be..4c01bde 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -654,34 +655,54 @@ class QIdleDetectorThread { public: QIdleDetectorThread() - : m_state(STATE_RUN), m_stop(false) + : m_state(STATE_RUN), m_stop(false), m_running(false) { - qt_symbian_throwIfError(m_lock.CreateLocal(0)); + start(); + } + + ~QIdleDetectorThread() + { + stop(); + } + + void start() + { + QMutexLocker lock(&m_mutex); + if (m_running) + return; + m_stop = false; + m_state = STATE_RUN; TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this); if (err != KErrNone) - m_lock.Close(); - qt_symbian_throwIfError(err); + return; // Fail silently on error. Next kick will try again. Exception might stop the event being processed m_idleDetectorThread.SetPriority(EPriorityAbsoluteBackgroundNormal); m_idleDetectorThread.Resume(); + m_running = true; + // get a callback from QCoreApplication destruction to stop this thread + qAddPostRoutine(StopIdleDetectorThread); } - ~QIdleDetectorThread() + void stop() { + QMutexLocker lock(&m_mutex); + if (!m_running) + return; // close down the idle thread because if corelib is loaded temporarily, this would leak threads into the host process m_stop = true; - m_lock.Signal(); + m_kick.release(); m_idleDetectorThread.SetPriority(EPriorityNormal); TRequestStatus s; m_idleDetectorThread.Logon(s); User::WaitForRequest(s); m_idleDetectorThread.Close(); - m_lock.Close(); + m_running = false; } void kick() { + start(); m_state = STATE_KICKED; - m_lock.Signal(); + m_kick.release(); } bool hasRun() @@ -700,20 +721,29 @@ private: void IdleLoop() { while (!m_stop) { - m_lock.Wait(); + m_kick.acquire(); m_state = STATE_RUN; } } + static void StopIdleDetectorThread(); + private: enum IdleStates {STATE_KICKED, STATE_RUN} m_state; bool m_stop; + bool m_running; RThread m_idleDetectorThread; - RSemaphore m_lock; + QSemaphore m_kick; + QMutex m_mutex; }; Q_GLOBAL_STATIC(QIdleDetectorThread, idleDetectorThread); +void QIdleDetectorThread::StopIdleDetectorThread() +{ + idleDetectorThread()->stop(); +} + const int maxBusyTime = 2000; // maximum time we allow idle detector to be blocked before worrying, in milliseconds const int baseDelay = 1000; // minimum delay time used when backing off to allow idling, in microseconds #endif diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 128124f..75cb5eb 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -131,11 +131,7 @@ public: { data->symbian_thread_handle.LogonCancel(iStatus); } - void RunL() - { - data->deref(); - delete this; - } + void RunL(); private: QThreadData* data; }; @@ -177,6 +173,7 @@ public: for (int i=threadsToAdd.size()-1; i>=0; i--) { // Create an active object to monitor the thread new (ELeave) QCAdoptedThreadMonitor(threadsToAdd[i]); + count++; threadsToAdd.pop_back(); } start(); @@ -193,6 +190,8 @@ public: User::WaitForRequest(started); monitorThread.Close(); } + if (RThread().Id() == adoptedThreadAdder->monitorThread.Id()) + return; adoptedThreadAdder->threadsToAdd.push_back(thread); if (adoptedThreadAdder->stat) { adoptedThreadAdder->monitorThread.RequestComplete(adoptedThreadAdder->stat, KErrNone); @@ -204,15 +203,15 @@ public: CleanupStack::PushL(scheduler); CActiveScheduler::Install(scheduler); - adoptedThreadAdder = new(ELeave) QCAddAdoptedThread(); + adoptedThreadAdder = new(ELeave) QCAddAdoptedThread(); CleanupStack::PushL(adoptedThreadAdder); adoptedThreadAdder->ConstructL(); + QCAddAdoptedThread *adder = adoptedThreadAdder; RThread::Rendezvous(KErrNone); CActiveScheduler::Start(); - CleanupStack::PopAndDestroy(adoptedThreadAdder); - adoptedThreadAdder = 0; + CleanupStack::PopAndDestroy(adder); CleanupStack::PopAndDestroy(scheduler); } static int monitorThreadFunc(void *) @@ -224,18 +223,37 @@ public: delete cleanup; return ret; } + static void threadDied() + { + QMutexLocker adoptedThreadMonitorMutexlock(&adoptedThreadMonitorMutex); + if (adoptedThreadAdder) { + adoptedThreadAdder->count--; + if (adoptedThreadAdder->count <= 0 && adoptedThreadAdder->threadsToAdd.size() == 0) { + CActiveScheduler::Stop(); + adoptedThreadAdder = 0; + } + } + } private: QVector threadsToAdd; RThread monitorThread; static QMutex adoptedThreadMonitorMutex; - static QCAddAdoptedThread* adoptedThreadAdder; + static QCAddAdoptedThread *adoptedThreadAdder; + int count; TRequestStatus *stat; }; QMutex QCAddAdoptedThread::adoptedThreadMonitorMutex; QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0; +void QCAdoptedThreadMonitor::RunL() +{ + data->deref(); + QCAddAdoptedThread::threadDied(); + delete this; +} + void QAdoptedThread::init() { Q_D(QThread); -- cgit v0.12 From 89660713717dcbd6126d6a38f911b7a90dff7ba7 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 18 Mar 2011 16:04:20 +0200 Subject: QComboBox fix for QTBUG-16985 --- src/gui/widgets/qcombobox.cpp | 83 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index b5dda5a..0bfc03d 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -7,11 +7,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -25,16 +25,16 @@ ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu")); QVariant value = index.data(Qt::ForegroundRole); - if (value.canConvert()) { + if (qVariantCanConvert(value)) { resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast(value)); resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast(value)); resolvedpalette.setBrush(QPalette::Text, qvariant_cast(value)); @@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.icon = qvariant_cast(variant); break; } - if (index.data(Qt::BackgroundRole).canConvert()) { + if (qVariantCanConvert(index.data(Qt::BackgroundRole))) { menuOption.palette.setBrush(QPalette::All, QPalette::Background, qvariant_cast(index.data(Qt::BackgroundRole))); } @@ -369,7 +369,6 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent) if (timerEvent->timerId() == adjustSizeTimer.timerId()) { adjustSizeTimer.stop(); if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) { - combo->updateGeometry(); combo->adjustSize(); combo->update(); } @@ -1089,8 +1088,6 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity() container->setPalette(q->palette()); container->setWindowOpacity(1.0); } - if (lineEdit) - lineEdit->setPalette(q->palette()); } /*! @@ -1301,7 +1298,7 @@ QComboBox::~QComboBox() By default, this property has a value of 10. \note This property is ignored for non-editable comboboxes in styles that returns - true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. + false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. */ int QComboBox::maxVisibleItems() const { @@ -2011,18 +2008,11 @@ void QComboBox::setCurrentIndex(int index) void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) { Q_Q(QComboBox); - - QModelIndex normalized; - if (mi.column() != modelColumn) - normalized = model->index(mi.row(), modelColumn, mi.parent()); - if (!normalized.isValid()) - normalized = mi; // Fallback to passed index. - - bool indexChanged = (normalized != currentIndex); + bool indexChanged = (mi != currentIndex); if (indexChanged) - currentIndex = QPersistentModelIndex(normalized); + currentIndex = QPersistentModelIndex(mi); if (lineEdit) { - QString newText = q->itemText(normalized.row()); + QString newText = q->itemText(currentIndex.row()); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); @@ -2358,7 +2348,9 @@ void QComboBox::showPopup() initStyleOption(&opt); QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); - QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + //QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); + QPoint below = mapToGlobal(listRect.bottomLeft()); int belowHeight = screen.bottom() - below.y(); QPoint above = mapToGlobal(listRect.topLeft()); @@ -2486,18 +2478,10 @@ void QComboBox::showPopup() listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty()) { - TRect cbaRect = TRect(); - AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); - AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); - switch (cbaLocation) { - case AknLayoutUtils::EAknCbaLocationRight: - listRect.setRight(screen.right()); - break; - case AknLayoutUtils::EAknCbaLocationLeft: - listRect.setLeft(screen.left()); - break; - } + if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { + // landscape without stacon, menu should be at the right + (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : + listRect.setLeft(screen.left()); } } #endif @@ -2716,8 +2700,9 @@ void QComboBox::changeEvent(QEvent *e) initStyleOption(&opt); if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) { - const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); - + //const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); + QRect listRect(style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); listRect.setHeight(qMin(screen.height(), screen.width())); @@ -2731,13 +2716,15 @@ void QComboBox::changeEvent(QEvent *e) listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty()) { + if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { // landscape without stacon, menu should be at the right (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : listRect.setLeft(screen.left()); } - d->container->setGeometry(listRect); + //d->container->setGeometry(listRect); } + + d->container->setGeometry(listRect); } } #endif @@ -2770,6 +2757,10 @@ void QComboBox::changeEvent(QEvent *e) void QComboBox::resizeEvent(QResizeEvent *) { Q_D(QComboBox); +#ifdef Q_WS_S60 + if (d->viewContainer() && d->viewContainer()->isVisible()) + showPopup(); +#endif d->updateLineEditGeometry(); } -- cgit v0.12 From e37d500cb1da388fbd53ae9e58548a59df29f598 Mon Sep 17 00:00:00 2001 From: mread Date: Fri, 18 Mar 2011 15:51:36 +0000 Subject: Moving Symbian CPU core detection to qthread_symbian.cpp This is resolving a merge issue where Symbian CPU core detection was added in one branch, but all the Symbian thread support was moved to a new file in another branch. Reviewed-by: Shane Kearns --- src/corelib/thread/qthread_symbian.cpp | 21 +++++++++++++++++---- src/corelib/thread/qthread_unix.cpp | 26 -------------------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 75cb5eb..1474b36 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -48,7 +48,14 @@ #include #include +#include +#include +// You only find these enumerations on Symbian^3 onwards, so we need to provide our own +// to remain compatible with older releases. They won't be called by pre-Sym^3 SDKs. + +// HALData::ENumCpus +#define QT_HALData_ENumCpus 119 QT_BEGIN_NAMESPACE @@ -376,10 +383,16 @@ Qt::HANDLE QThread::currentThreadId() int QThread::idealThreadCount() { - int cores = -1; - - // ### TODO - Get the number of cores from HAL? when multicore architectures (SMP) are supported - cores = 1; + int cores = 1; + + if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) { + TInt inumcpus; + TInt err; + err = HAL::Get((HALData::TAttribute)QT_HALData_ENumCpus, inumcpus); + if (err == KErrNone) { + cores = qMax(inumcpus, 1); + } + } return cores; } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index a1c6458..835378a 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -50,11 +50,6 @@ #include -#ifdef Q_OS_SYMBIAN -#include -#include -#endif - #include "qthreadstorage.h" #include "qthread_p.h" @@ -64,12 +59,6 @@ #include #include -// You only find these enumerations on Symbian^3 onwards, so we need to provide our own -// to remain compatible with older releases. They won't be called by pre-Sym^3 SDKs. - -// HALData::ENumCpus -#define QT_HALData_ENumCpus 119 - #ifdef Q_OS_BSD4 #include #endif @@ -378,21 +367,6 @@ int QThread::idealThreadCount() #elif defined(Q_OS_INTEGRITY) // as of aug 2008 Integrity only supports one single core CPU cores = 1; -#elif defined(Q_OS_SYMBIAN) - if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) { - TInt inumcpus; - TInt err; - err = HAL::Get((HALData::TAttribute)QT_HALData_ENumCpus, inumcpus); - if (err != KErrNone) { - cores = 1; - } else if ( inumcpus <= 0 ) { - cores = 1; - } else { - cores = inumcpus; - } - } else { - cores = 1; - } #elif defined(Q_OS_VXWORKS) // VxWorks # if defined(QT_VXWORKS_HAS_CPUSET) -- cgit v0.12 From 7e26a493ecd1d77b1637a4c86b6f47fcce67a92c Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 22 Mar 2011 13:05:25 +0200 Subject: Revert "QComboBox fix for QTBUG-16985" The commit has to be reverted due to introduced build break for non-Symbian platforms. This reverts commit 89660713717dcbd6126d6a38f911b7a90dff7ba7. --- src/gui/widgets/qcombobox.cpp | 83 ++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 0bfc03d..b5dda5a 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -7,11 +7,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -25,16 +25,16 @@ ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu")); QVariant value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert(value)) { + if (value.canConvert()) { resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast(value)); resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast(value)); resolvedpalette.setBrush(QPalette::Text, qvariant_cast(value)); @@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.icon = qvariant_cast(variant); break; } - if (qVariantCanConvert(index.data(Qt::BackgroundRole))) { + if (index.data(Qt::BackgroundRole).canConvert()) { menuOption.palette.setBrush(QPalette::All, QPalette::Background, qvariant_cast(index.data(Qt::BackgroundRole))); } @@ -369,6 +369,7 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent) if (timerEvent->timerId() == adjustSizeTimer.timerId()) { adjustSizeTimer.stop(); if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) { + combo->updateGeometry(); combo->adjustSize(); combo->update(); } @@ -1088,6 +1089,8 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity() container->setPalette(q->palette()); container->setWindowOpacity(1.0); } + if (lineEdit) + lineEdit->setPalette(q->palette()); } /*! @@ -1298,7 +1301,7 @@ QComboBox::~QComboBox() By default, this property has a value of 10. \note This property is ignored for non-editable comboboxes in styles that returns - false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. + true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. */ int QComboBox::maxVisibleItems() const { @@ -2008,11 +2011,18 @@ void QComboBox::setCurrentIndex(int index) void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) { Q_Q(QComboBox); - bool indexChanged = (mi != currentIndex); + + QModelIndex normalized; + if (mi.column() != modelColumn) + normalized = model->index(mi.row(), modelColumn, mi.parent()); + if (!normalized.isValid()) + normalized = mi; // Fallback to passed index. + + bool indexChanged = (normalized != currentIndex); if (indexChanged) - currentIndex = QPersistentModelIndex(mi); + currentIndex = QPersistentModelIndex(normalized); if (lineEdit) { - QString newText = q->itemText(currentIndex.row()); + QString newText = q->itemText(normalized.row()); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); @@ -2348,9 +2358,7 @@ void QComboBox::showPopup() initStyleOption(&opt); QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); - //QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); - QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); - + QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); QPoint below = mapToGlobal(listRect.bottomLeft()); int belowHeight = screen.bottom() - below.y(); QPoint above = mapToGlobal(listRect.topLeft()); @@ -2478,10 +2486,18 @@ void QComboBox::showPopup() listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { - // landscape without stacon, menu should be at the right - (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : - listRect.setLeft(screen.left()); + if (staConTopRect.IsEmpty()) { + TRect cbaRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); + AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); + switch (cbaLocation) { + case AknLayoutUtils::EAknCbaLocationRight: + listRect.setRight(screen.right()); + break; + case AknLayoutUtils::EAknCbaLocationLeft: + listRect.setLeft(screen.left()); + break; + } } } #endif @@ -2700,9 +2716,8 @@ void QComboBox::changeEvent(QEvent *e) initStyleOption(&opt); if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) { - //const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); - QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); - + const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + QRect listRect(style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); listRect.setHeight(qMin(screen.height(), screen.width())); @@ -2716,15 +2731,13 @@ void QComboBox::changeEvent(QEvent *e) listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { + if (staConTopRect.IsEmpty()) { // landscape without stacon, menu should be at the right (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : listRect.setLeft(screen.left()); } - //d->container->setGeometry(listRect); + d->container->setGeometry(listRect); } - - d->container->setGeometry(listRect); } } #endif @@ -2757,10 +2770,6 @@ void QComboBox::changeEvent(QEvent *e) void QComboBox::resizeEvent(QResizeEvent *) { Q_D(QComboBox); -#ifdef Q_WS_S60 - if (d->viewContainer() && d->viewContainer()->isVisible()) - showPopup(); -#endif d->updateLineEditGeometry(); } -- cgit v0.12 From e28d33a6924d14afc5851a9a3587891f8507ee16 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 22 Mar 2011 13:49:22 +0200 Subject: Fix for QTBUG-16985. QComboBox popup is resized/positioned correctly when device orientation changes. Task-number: QTBUG-16985 Reviewed-by: Sami Merila --- src/gui/widgets/qcombobox.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index b5dda5a..34e3672 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -2358,7 +2358,12 @@ void QComboBox::showPopup() initStyleOption(&opt); QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); +#ifndef Q_WS_S60 QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); +#else + QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); +#endif + QPoint below = mapToGlobal(listRect.bottomLeft()); int belowHeight = screen.bottom() - below.y(); QPoint above = mapToGlobal(listRect.topLeft()); @@ -2486,18 +2491,10 @@ void QComboBox::showPopup() listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty()) { - TRect cbaRect = TRect(); - AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); - AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); - switch (cbaLocation) { - case AknLayoutUtils::EAknCbaLocationRight: - listRect.setRight(screen.right()); - break; - case AknLayoutUtils::EAknCbaLocationLeft: - listRect.setLeft(screen.left()); - break; - } + if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { + // landscape without stacon, menu should be at the right + (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : + listRect.setLeft(screen.left()); } } #endif @@ -2716,7 +2713,7 @@ void QComboBox::changeEvent(QEvent *e) initStyleOption(&opt); if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) { - const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + QRect screen = qt_TRect2QRect(static_cast(S60->appUi())->ClientRect()); QRect listRect(style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); @@ -2731,13 +2728,14 @@ void QComboBox::changeEvent(QEvent *e) listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty()) { + if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { // landscape without stacon, menu should be at the right (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : listRect.setLeft(screen.left()); } - d->container->setGeometry(listRect); } + + d->container->setGeometry(listRect); } } #endif @@ -2770,6 +2768,10 @@ void QComboBox::changeEvent(QEvent *e) void QComboBox::resizeEvent(QResizeEvent *) { Q_D(QComboBox); +#ifdef Q_WS_S60 + if (d->viewContainer() && d->viewContainer()->isVisible()) + showPopup(); +#endif d->updateLineEditGeometry(); } -- cgit v0.12 From 7cce8ce5af4087c662db657887b7971a2931e849 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 22 Mar 2011 16:27:23 +0200 Subject: Make createpackage and patch_capabilties scripts use tmp dir Temporary files created by these two scripts will now be created under a separate directory, contents of which is also added to cleanup. Task-number: QTBUG-11394 Reviewed-by: axis --- bin/createpackage.pl | 41 ++++++++++++++------------ bin/patch_capabilities.pl | 50 +++++++++++++++++++++++--------- mkspecs/common/symbian/symbian.conf | 2 +- mkspecs/features/symbian/sis_targets.prf | 21 ++++++++------ 4 files changed, 73 insertions(+), 41 deletions(-) diff --git a/bin/createpackage.pl b/bin/createpackage.pl index df91876..b7457e1 100755 --- a/bin/createpackage.pl +++ b/bin/createpackage.pl @@ -58,7 +58,7 @@ use File::Spec; use File::Path; # use CWD abs_bath, which is exported only on request use Cwd 'abs_path'; - +use File::Copy; sub Usage() { print <] = Specifies temporary directory to be used for package creation. + Defaults to 'createpackage_tmp' under same directory as templatepkg. Where parameters are as follows: templatepkg = Name of .pkg file template target = Either debug or release @@ -130,6 +132,7 @@ my $signed_sis_name = ""; my $onlyUnsigned = ""; my $convertGcce = ""; my $dontPatchCaps = ""; +my $tempPackageDir = ""; unless (GetOptions('i|install' => \$install, 'p|preprocess' => \$preprocessonly, @@ -139,7 +142,8 @@ unless (GetOptions('i|install' => \$install, 's|stub' => \$stub, 'n|sisname=s' => \$signed_sis_name, 'g|gcce-is-armv5' => \$convertGcce, - 'd|dont-patch' => \$dontPatchCaps,)) { + 'd|dont-patch' => \$dontPatchCaps, + 't|tmp-dir=s' => \$tempPackageDir,)) { Usage(); } @@ -190,18 +194,22 @@ $key = $ARGV[3] or $key = ""; my $passphrase; $passphrase = $ARGV[4] or $passphrase = ""; +if ($tempPackageDir eq "") { + my ($templateVolume, $templatePath, $templateFileName) = File::Spec->splitpath($templatepkg); + $tempPackageDir = File::Spec->catpath($templateVolume, $templatePath."createpackage_tmp", ""); +} + +mkpath($tempPackageDir); + # Generate output pkg basename (i.e. file name without extension) my $pkgoutputbasename = $templatepkg; -my $preservePkgOutput = ""; $pkgoutputbasename =~ s/_template/_$targetplatform/g; $pkgoutputbasename =~ s/_installer\.pkg/_installer___temp\.pkg/g; -if ($pkgoutputbasename eq $templatepkg) { - $preservePkgOutput = "1"; -} $pkgoutputbasename =~ s/\.pkg//g; # Store output file names to variables -my $pkgoutput = $pkgoutputbasename.".pkg"; +my ($dummy1, $dummy2, $pkgoutput) = File::Spec->splitpath($pkgoutputbasename.".pkg"); +$pkgoutput = $tempPackageDir."/".$pkgoutput; my $sisoutputbasename; if ($signed_sis_name eq "") { $sisoutputbasename = $pkgoutputbasename; @@ -300,9 +308,7 @@ unlink $unsigned_sis_name; if (!$onlyUnsigned) { unlink $signed_sis_name; } -if (!$preservePkgOutput) { - unlink $pkgoutput; -} +unlink $pkgoutput; # Preprocess PKG @@ -334,6 +340,11 @@ print OUTPUT $_; close OUTPUT; if ($preprocessonly) { + # Copy preprocessed file from tmp dir to pkg file dir + my ($templateVolume, $templatePath, $templateFileName) = File::Spec->splitpath($templatepkg); + my ($dummy1, $dummy2, $copyFileName) = File::Spec->splitpath($pkgoutput); + my $copyTarget = File::Spec->catpath($templateVolume, $templatePath, $copyFileName); + copy($pkgoutput, $copyTarget) or die "Preprocessed pkg file '$pkgoutput' cannot be copied."; exit; } @@ -354,7 +365,7 @@ if($stub) { system ("$patch_capabilities -c $pkgoutput") and print ("Warning: Package check for self-signing viability failed. Installing the package on a device will most likely fail!\n\n"); } else { print("Auto-patching self-signed package.\n"); - system ("$patch_capabilities $pkgoutput") and die ("ERROR: Automatic patching failed"); + system ("$patch_capabilities -t $tempPackageDir $pkgoutput") and die ("ERROR: Automatic patching failed"); } } @@ -377,9 +388,6 @@ if($stub) { print ("\nUnsigned package creation failed!\n"); } - if (!$preservePkgOutput) { - unlink $pkgoutput; - } print ("\n"); exit; } @@ -405,10 +413,7 @@ if($stub) { print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n"); } - # remove temporary pkg and unsigned sis - if (!$preservePkgOutput) { - unlink $pkgoutput; - } + # remove temporary unsigned sis if (!$preserveUnsigned) { unlink $unsigned_sis_name; } diff --git a/bin/patch_capabilities.pl b/bin/patch_capabilities.pl index 91ab4b8..40b6a17 100755 --- a/bin/patch_capabilities.pl +++ b/bin/patch_capabilities.pl @@ -53,6 +53,7 @@ use File::Copy; use File::Spec; +use File::Path; sub Usage() { print("This script can be used to set capabilities of all binaries\n"); @@ -63,11 +64,13 @@ sub Usage() { print(" symbian-sbsv2 platform, 'target-platform' is REQUIRED. ***\n\n"); print(" *** NOTE2: When patching gcce binaries built with symbian-sbsv2 toolchain,\n"); print(" armv5 must be specified as platform.\n"); - print("\nUsage: patch_capabilities.pl [-c] pkg_filename [target-platform [capability list]]\n"); + print("\nUsage: patch_capabilities.pl [-c|-t tmp_path] pkg_filename [target-platform [capability list]]\n"); print("\nE.g. patch_capabilities.pl myapp_template.pkg release-armv5 \"All -TCB\"\n"); print("\nThe parameter -c can be used to just check if package is compatible with self-signing\n"); print("without actually doing any patching.\n"); print("Explicit capability list cannot be used with -c parameter.\n"); + print("\nThe parameter -t can be used to specify a dir under which the temporary files are created.\n"); + print("Defaults to 'patch_capabilities_tmp' under the path to pkg file.\n"); exit(); } @@ -101,6 +104,7 @@ if (@ARGV) my $pkgFileName = shift(@ARGV); my $justCheck = ""; my $msgPrefix = "Patching:"; + my $tempPatchPath = ""; if ($pkgFileName eq "-c") { $pkgFileName = shift(@ARGV); @@ -108,6 +112,18 @@ if (@ARGV) $msgPrefix = "Warning:"; } + if ($pkgFileName eq "-t") { + $tempPatchPath = shift(@ARGV); + $pkgFileName = shift(@ARGV); + } + + my ($pkgVolume, $pkgPath, $pkgPlainFileName) = File::Spec->splitpath($pkgFileName); + if ($tempPatchPath eq "") { + $tempPatchPath = File::Spec->catpath($pkgVolume, $pkgPath."patch_capabilities_tmp", ""); + } + + mkpath($tempPatchPath); + # These variables will only be set for template .pkg files. my $target; my $platform; @@ -165,8 +181,9 @@ if (@ARGV) # Start with no binaries listed. my @binaries = (); + my $binariesDelimeter = "///"; - my $tempPkgFileName = $pkgFileName."_@@TEMP@@"; + my $tempPkgFileName = $tempPatchPath."/__TEMP__".$pkgPlainFileName; if (!$justCheck) { unlink($tempPkgFileName); @@ -216,19 +233,23 @@ if (@ARGV) $sourcePath =~ s/\$\(TARGET\)/$target/gm; } + my ($dummy1, $dummy2, $binaryBaseName) = File::Spec->splitpath($sourcePath); + if ($justCheck) { - push (@binaries, $sourcePath); + push (@binaries, $binaryBaseName.$binariesDelimeter.$sourcePath); } else { - # Change the source file name (but only if not already patched) + # Copy original files over to patching dir + # Patching dir will be flat to make it cleanable with QMAKE_CLEAN, so path + # will be collapsed into the file name to avoid name collisions in the rare + # case where custom pkg rules are used to install files with same names from + # different directories (probably using platform checks to choose only one of them.) my $patchedSourcePath = $sourcePath; - if ($patchedSourcePath !~ m/_patched_caps/) - { - $newLine =~ s/(^.*)(\.dll|\.exe)(.*)(\.dll|\.exe)/$1_patched_caps$2$3$4/i; - $patchedSourcePath =~ s/(^.*)(\.dll|\.exe)/$1_patched_caps$2/i; + $patchedSourcePath =~ s/[\/\\:]/_/g; + $patchedSourcePath = "$tempPatchPath/$patchedSourcePath"; + $newLine =~ s/^.*(\.dll|\.exe)(.*)(\.dll|\.exe)/\"$patchedSourcePath$2$3/i; - copy($sourcePath, $patchedSourcePath) or die "$sourcePath cannot be copied for patching."; - } - push (@binaries, $patchedSourcePath); + copy($sourcePath, $patchedSourcePath) or die "$sourcePath cannot be copied for patching."; + push (@binaries, $binaryBaseName.$binariesDelimeter.$patchedSourcePath); } } } @@ -250,10 +271,13 @@ if (@ARGV) my $baseCommandToExecute = "${epocToolsDir}elftran -vid 0x0 -capability \"%s\" "; # Actually set the capabilities of the listed binaries. - foreach my $binaryPath(@binaries) + foreach my $binariesItem(@binaries) { + $binariesItem =~ m|^(.*)$binariesDelimeter(.*)$|; + my $binaryBaseName = $1; + my $binaryPath = $2; + # Create the command line for setting the capabilities. - my ($binaryVolume, $binaryDirs, $binaryBaseName) = File::Spec->splitpath($binaryPath); my $commandToExecute = $baseCommandToExecute; my $executeNeeded = ""; if (@capabilitiesSpecified) diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index d9f6279..74acc64 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -93,7 +93,7 @@ contains(QMAKE_HOST.os,Windows) { QMAKE_COPY = copy /y QMAKE_COPY_DIR = xcopy /s /q /y /i QMAKE_MOVE = move - QMAKE_DEL_FILE = del 2> NUL + QMAKE_DEL_FILE = del /q 2> NUL QMAKE_MKDIR = mkdir QMAKE_DEL_DIR = rmdir QMAKE_DEL_TREE = rmdir /s /q diff --git a/mkspecs/features/symbian/sis_targets.prf b/mkspecs/features/symbian/sis_targets.prf index 9963b30..d0fe881 100644 --- a/mkspecs/features/symbian/sis_targets.prf +++ b/mkspecs/features/symbian/sis_targets.prf @@ -26,6 +26,9 @@ equals(GENERATE_SIS_TARGETS, true) { qtPrepareTool(QMAKE_CREATEPACKAGE, createpackage) + CREATEPACKAGE_DIR = $$OBJECTS_DIR/createpackage_tmp + QMAKE_CLEAN += $$CREATEPACKAGE_DIR/* + symbian-abld|symbian-sbsv2 { symbian-sbsv2 { CONVERT_GCCE_PARAM = -g @@ -48,7 +51,7 @@ equals(GENERATE_SIS_TARGETS, true) { sis_target.depends += $${baseTarget}_template.pkg ok_sis_target.target = ok_sis - ok_sis_target.commands = $$QMAKE_CREATEPACKAGE $$CONVERT_GCCE_PARAM $(QT_SIS_OPTIONS) $${baseTarget}_template.pkg \ + ok_sis_target.commands = $$QMAKE_CREATEPACKAGE $$CONVERT_GCCE_PARAM -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) $${baseTarget}_template.pkg \ $(QT_SIS_TARGET) $(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE) unsigned_sis_target.target = unsigned_sis @@ -65,7 +68,7 @@ equals(GENERATE_SIS_TARGETS, true) { unsigned_sis_target.depends += $${baseTarget}_template.pkg ok_unsigned_sis_target.target = ok_unsigned_sis - ok_unsigned_sis_target.commands = $$QMAKE_CREATEPACKAGE $$CONVERT_GCCE_PARAM $(QT_SIS_OPTIONS) -o $${baseTarget}_template.pkg $(QT_SIS_TARGET) + ok_unsigned_sis_target.commands = $$QMAKE_CREATEPACKAGE $$CONVERT_GCCE_PARAM -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) -o $${baseTarget}_template.pkg $(QT_SIS_TARGET) target_sis_target.target = $${baseTarget}.sis target_sis_target.commands = $(MAKE) -f $(MAKEFILE) sis @@ -77,7 +80,7 @@ equals(GENERATE_SIS_TARGETS, true) { installer_sis_target.depends = $${baseTarget}_installer.pkg sis ok_installer_sis_target.target = ok_installer_sis - ok_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) $${baseTarget}_installer.pkg - \ + ok_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) $${baseTarget}_installer.pkg - \ $(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE) ok_installer_sis_target.depends = $${baseTarget}_installer.pkg @@ -86,7 +89,7 @@ equals(GENERATE_SIS_TARGETS, true) { unsigned_installer_sis_target.depends = $${baseTarget}_installer.pkg unsigned_sis ok_unsigned_installer_sis_target.target = ok_unsigned_installer_sis - ok_unsigned_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) -o $${baseTarget}_installer.pkg + ok_unsigned_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) -o $${baseTarget}_installer.pkg ok_unsigned_installer_sis_target.depends = $${baseTarget}_installer.pkg fail_sis_nocache_target.target = fail_sis_nocache @@ -106,7 +109,7 @@ equals(GENERATE_SIS_TARGETS, true) { stub_sis_target.depends += $${baseTarget}_stub.pkg ok_stub_sis_target.target = ok_stub_sis - ok_stub_sis_target.commands = $$QMAKE_CREATEPACKAGE -s $(QT_SIS_OPTIONS) $${baseTarget}_stub.pkg \ + ok_stub_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR -s $(QT_SIS_OPTIONS) $${baseTarget}_stub.pkg \ $(QT_SIS_TARGET) $(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE) QMAKE_EXTRA_TARGETS += sis_target \ @@ -150,12 +153,12 @@ equals(GENERATE_SIS_TARGETS, true) { !equals(TARGET, "$$baseTarget"):sis_destdir = $$sis_destdir/$$dirname(TARGET) sis_target.target = sis - sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) $${baseTarget}_template.pkg \ + sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) $${baseTarget}_template.pkg \ - $(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE) sis_target.depends = first $${baseTarget}_template.pkg unsigned_sis_target.target = unsigned_sis - unsigned_sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) -o $${baseTarget}_template.pkg + unsigned_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) -o $${baseTarget}_template.pkg unsigned_sis_target.depends = first $${baseTarget}_template.pkg target_sis_target.target = $${sis_destdir}/$${baseTarget}.sis @@ -166,12 +169,12 @@ equals(GENERATE_SIS_TARGETS, true) { installer_sis_target.depends = $${baseTarget}_installer.pkg sis ok_installer_sis_target.target = ok_installer_sis - ok_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) $${baseTarget}_installer.pkg - \ + ok_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) $${baseTarget}_installer.pkg - \ $(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE) ok_installer_sis_target.depends = $${baseTarget}_installer.pkg unsigned_installer_sis_target.target = unsigned_installer_sis - unsigned_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE $(QT_SIS_OPTIONS) -o $${baseTarget}_installer.pkg + unsigned_installer_sis_target.commands = $$QMAKE_CREATEPACKAGE -t $$CREATEPACKAGE_DIR $(QT_SIS_OPTIONS) -o $${baseTarget}_installer.pkg unsigned_installer_sis_target.depends = $${baseTarget}_installer.pkg unsigned_sis !isEmpty(sis_destdir):!equals(sis_destdir, "."):!equals(sis_destdir, "./") { -- cgit v0.12