From 702b4cb5d464ac5abb97a3e75601b6a946673ee4 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 21 Jun 2011 14:50:08 +0100 Subject: Workaround webkit deadlock on macos x The webkit AtomicallyInitializedStatic and Qt's Q_GLOBAL_STATIC can deadlock on the Mac, as the mac compiler inserts calls to __cxa_guard_acquire and __cxa_guard_release around initialisation of local statics. In Q_GLOBAL_STATIC case, this is the QGlobalStaticDeleter local static Whereas webkit AtomicallyInitializedStatic is a local static variable in any case. Problem is triggered because webkit constructs QNetworkConfigurationManager inside the constructor of a local static - networkStateNotifier And the generic bearer plugin calls QNetworkInterface::allInterfaces in the bearer thread, which needs an initialised Q_GLOBAL_STATIC. Reviewed-by: Laszlo Agocs (cherry picked from commit 38db40d9a2db44e47b0aabd9487284cd1106b353) Task-number: QTBUG-24554 Change-Id: Id2c7818faefb46e66b0bbc30ce30595d46d53016 Reviewed-by: Zeno Albisser --- src/plugins/bearer/generic/qgenericengine.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp index 7b30b5d64c..5682d113ef 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -147,6 +147,9 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf QGenericEngine::QGenericEngine(QObject *parent) : QBearerEngineImpl(parent) { + //workaround for deadlock in __cxa_guard_acquire with webkit on macos x + //initialise the Q_GLOBAL_STATIC in same thread as the AtomicallyInitializedStatic + (void)QNetworkInterface::interfaceFromIndex(0); } QGenericEngine::~QGenericEngine() -- cgit v1.2.3 From df19bffbd9a3a8bd69acf1ff6f3ba9c4649d13be Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Fri, 9 Mar 2012 18:28:12 -0800 Subject: Move tst_qshortcut.cpp to QtWidgets QShortcut belongs to QtWidgets instead of QtGui. Change-Id: I9715399bb372a6ea4bd76109f87ba31a1e30a7e6 Reviewed-by: Gunnar Sletta Reviewed-by: Friedemann Kleint --- tests/auto/gui/kernel/kernel.pro | 1 - tests/auto/gui/kernel/qshortcut/.gitignore | 1 - tests/auto/gui/kernel/qshortcut/qshortcut.pro | 12 - tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp | 1259 -------------------- tests/auto/widgets/kernel/kernel.pro | 1 + tests/auto/widgets/kernel/qshortcut/.gitignore | 1 + tests/auto/widgets/kernel/qshortcut/qshortcut.pro | 12 + .../widgets/kernel/qshortcut/tst_qshortcut.cpp | 1259 ++++++++++++++++++++ 8 files changed, 1273 insertions(+), 1273 deletions(-) delete mode 100644 tests/auto/gui/kernel/qshortcut/.gitignore delete mode 100644 tests/auto/gui/kernel/qshortcut/qshortcut.pro delete mode 100644 tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp create mode 100644 tests/auto/widgets/kernel/qshortcut/.gitignore create mode 100644 tests/auto/widgets/kernel/qshortcut/qshortcut.pro create mode 100644 tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro index 116e9dd1f1..48d94b9bf8 100644 --- a/tests/auto/gui/kernel/kernel.pro +++ b/tests/auto/gui/kernel/kernel.pro @@ -13,7 +13,6 @@ SUBDIRS=\ qmouseevent_modal \ qpalette \ qscreen \ - qshortcut \ qtouchevent \ qwindow \ qguiapplication \ diff --git a/tests/auto/gui/kernel/qshortcut/.gitignore b/tests/auto/gui/kernel/qshortcut/.gitignore deleted file mode 100644 index 3a17eb18e3..0000000000 --- a/tests/auto/gui/kernel/qshortcut/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qshortcut diff --git a/tests/auto/gui/kernel/qshortcut/qshortcut.pro b/tests/auto/gui/kernel/qshortcut/qshortcut.pro deleted file mode 100644 index 7ac1dd2c9d..0000000000 --- a/tests/auto/gui/kernel/qshortcut/qshortcut.pro +++ /dev/null @@ -1,12 +0,0 @@ -CONFIG += testcase -TARGET = tst_qshortcut - -# Project Configuration ---------------------------------------------- -INCLUDEPATH += ../ - -# Normal Test Files -------------------------------------------------- -QT += widgets testlib -HEADERS += -SOURCES += tst_qshortcut.cpp - - diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp deleted file mode 100644 index 61efb6e3f3..0000000000 --- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp +++ /dev/null @@ -1,1259 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used 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. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class AccelForm; -QT_BEGIN_NAMESPACE -class QMainWindow; -class QTextEdit; -QT_END_NAMESPACE - -class tst_QShortcut : public QObject -{ - Q_OBJECT -public: - tst_QShortcut(); - virtual ~tst_QShortcut(); - - - enum Action { - SetupAccel, - TestAccel, - ClearAll - } currentAction; - - enum Widget { - NoWidget, - TriggerSlot1, - TriggerSlot2, - TriggerSlot3, - TriggerSlot4, - TriggerSlot5, - TriggerSlot6, - TriggerSlot7 - }; - - enum Result { - NoResult, - Slot1Triggered, - Slot2Triggered, - Slot3Triggered, - Slot4Triggered, - Slot5Triggered, - Slot6Triggered, - Slot7Triggered, - Ambiguous - } currentResult; - -public slots: - void slotTrig1() { currentResult = Slot1Triggered; } - void slotTrig2() { currentResult = Slot2Triggered; } - void slotTrig3() { currentResult = Slot3Triggered; } - void slotTrig4() { currentResult = Slot4Triggered; } - void slotTrig5() { currentResult = Slot5Triggered; } - void slotTrig6() { currentResult = Slot6Triggered; } - void slotTrig7() { currentResult = Slot7Triggered; } - void ambigSlot1() { currentResult = Ambiguous; ambigResult = Slot1Triggered; } - void ambigSlot2() { currentResult = Ambiguous; ambigResult = Slot2Triggered; } - void ambigSlot3() { currentResult = Ambiguous; ambigResult = Slot3Triggered; } - void ambigSlot4() { currentResult = Ambiguous; ambigResult = Slot4Triggered; } - void ambigSlot5() { currentResult = Ambiguous; ambigResult = Slot5Triggered; } - void ambigSlot6() { currentResult = Ambiguous; ambigResult = Slot6Triggered; } - void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; } - void statusMessage( const QString& message ) { sbText = message; } - void shortcutDestroyed(QObject* obj); - -public slots: - void initTestCase(); - void cleanupTestCase(); - -private slots: - void number_data(); - void number(); - void text_data(); - void text(); - void disabledItems(); - void ambiguousItems(); - void ambiguousRotation(); - void keypressConsumption(); - void unicodeCompare(); - void context(); - -protected: - static Qt::KeyboardModifiers toButtons( int key ); - void defElements(); - - void clearAllShortcuts(); - QShortcut *setupShortcut(int testWidget, const QKeySequence &ks); - QShortcut *setupShortcut(int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0); - - QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0); - QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut); - - void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0); - void sendKeyEvents(int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0); - - void testElement(); - - QMainWindow *mainW; - QList shortcuts; - QTextEdit *edit; - QString sbText; - Result ambigResult; -}; - -Q_DECLARE_METATYPE(tst_QShortcut::Widget); -Q_DECLARE_METATYPE(tst_QShortcut::Result); -Q_DECLARE_METATYPE(tst_QShortcut::Action); - -class TestEdit : public QTextEdit -{ - Q_OBJECT -public: - TestEdit(QWidget *parent, const char *name) - : QTextEdit(parent) - { - setObjectName(name); - } - -protected: - bool event(QEvent *e) { - // Make testedit allow any Ctrl+Key as shortcut - if (e->type() == QEvent::ShortcutOverride) { - QKeyEvent *ke = static_cast(e); - if (ke->modifiers() == Qt::ControlModifier - && ke->key() > Qt::Key_Any - && ke->key() < Qt::Key_ydiaeresis) { - ke->ignore(); - return true; - } - } - - // If keypress not processed as normal, check for - // Ctrl+Key event, and input custom string for - // result comparison. - if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = static_cast(e); - if (ke->modifiers() && ke->key() > Qt::Key_Any - && ke->key() < Qt::Key_ydiaeresis) { - if (ke->modifiers() == Qt::ControlModifier) - insertPlainText(QString("").arg(char(ke->key()))); - else if (ke->modifiers() == Qt::AltModifier) - insertPlainText(QString("").arg(char(ke->key()))); - else if (ke->modifiers() == Qt::ShiftModifier) - insertPlainText(QString("").arg(char(ke->key()))); - return true; - } - } - return QTextEdit::event(e); - } -}; - -tst_QShortcut::tst_QShortcut(): mainW( 0 ) -{ -} - -tst_QShortcut::~tst_QShortcut() -{ - clearAllShortcuts(); -} - -void tst_QShortcut::initTestCase() -{ - currentResult = NoResult; - mainW = new QMainWindow(0); - mainW->setWindowFlags(Qt::X11BypassWindowManagerHint); - edit = new TestEdit(mainW, "test_edit"); - mainW->setFixedSize( 100, 100 ); - mainW->setCentralWidget( edit ); - mainW->show(); - QTest::qWaitForWindowShown(mainW); - mainW->activateWindow(); - QTest::qWait(100); - connect( mainW->statusBar(), SIGNAL(messageChanged(const QString&)), - this, SLOT(statusMessage(const QString&)) ); -} - -void tst_QShortcut::cleanupTestCase() -{ - delete mainW; -} - -Qt::KeyboardModifiers tst_QShortcut::toButtons( int key ) -{ - Qt::KeyboardModifiers result = Qt::NoModifier; - if ( key & Qt::SHIFT ) - result |= Qt::ShiftModifier; - if ( key & Qt::CTRL ) - result |= Qt::ControlModifier; - if ( key & Qt::META ) - result |= Qt::MetaModifier; - if ( key & Qt::ALT ) - result |= Qt::AltModifier; - return result; -} - -void tst_QShortcut::defElements() -{ - QTest::addColumn("action"); - QTest::addColumn("testWidget"); - QTest::addColumn("txt"); - QTest::addColumn("k1"); - QTest::addColumn("c1"); - QTest::addColumn("k2"); - QTest::addColumn("c2"); - QTest::addColumn("k3"); - QTest::addColumn("c3"); - QTest::addColumn("k4"); - QTest::addColumn("c4"); - QTest::addColumn("result"); -} - -void tst_QShortcut::number() -{ - // We expect a failure on these tests, until QtTestKeyboard is - // fixed to do real platform dependent keyboard simulations - if (QTest::currentDataTag() == QString("N006a:Shift+Tab - [BackTab]") - || QTest::currentDataTag() == QString("N006b:Shift+Tab - [Shift+BackTab]")) - QEXPECT_FAIL("", "FLAW IN QTESTKEYBOARD: Keyboard events not passed through " - "platform dependent key handling code", Continue); - testElement(); -} -void tst_QShortcut::text() -{ - testElement(); -} -// ------------------------------------------------------------------ -// Number Elements -------------------------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::number_data() -{ - defElements(); - - // Clear all - QTest::newRow("N00 - clear") << ClearAll << NoWidget <activateWindow(); - qApp->syncX(); - QTest::qWait(100); - - /* Testing Disabled Shortcuts - Qt::Key_M on slot1 - Shift + Qt::Key_M on slot1 - Qt::Key_M on slot2 (disabled) - Shift + Qt::Key_M on slot2 (disabled) - */ - - // Setup two identical shortcuts on different pushbuttons - QPushButton pb1(mainW); - QPushButton pb2(mainW); - pb1.setObjectName("pushbutton-1"); - pb2.setObjectName("pushbutton-2"); - pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger - pb2.show(); - - QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M"); - QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb1", TriggerSlot1, "Shift+M"); - QShortcut *cut3 = setupShortcut(&pb2, "shortcut3-pb2", TriggerSlot2, "M"); - QShortcut *cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+M"); - - cut3->setEnabled(false); - cut4->setEnabled(false); - - currentResult = NoResult; - sendKeyEvents(Qt::Key_M, 'm'); - QCOMPARE(currentResult, Slot1Triggered); - - currentResult = NoResult; - sendKeyEvents(Qt::SHIFT+Qt::Key_M, 'M'); - QCOMPARE(currentResult, Slot1Triggered); - - cut2->setEnabled(false); - cut4->setEnabled(true); - - /* Testing Disabled Shortcuts - Qt::Key_M on slot1 - Shift + Qt::Key_M on slot1 (disabled) - Qt::Key_M on slot2 (disabled) - Shift + Qt::Key_M on slot2 - */ - currentResult = NoResult; - sendKeyEvents( Qt::Key_M, 'm' ); - QCOMPARE( currentResult, Slot1Triggered ); - - currentResult = NoResult; - sendKeyEvents( Qt::SHIFT+Qt::Key_M, 'M' ); - QCOMPARE( currentResult, Slot2Triggered ); - - - /* Testing Disabled Accel - Qt::Key_F5 on slot1 - Shift + Qt::Key_F5 on slot2 (disabled) - */ - clearAllShortcuts(); - cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "F5"); - cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+F5"); - - cut1->setKey(QKeySequence("F5")); - cut4->setKey(QKeySequence("Shift+F5")); - - cut1->setEnabled(true); - cut4->setEnabled(false); - - currentResult = NoResult; - sendKeyEvents( Qt::Key_F5, 0 ); - QCOMPARE( currentResult, Slot1Triggered ); - - currentResult = NoResult; - sendKeyEvents( Qt::SHIFT+Qt::Key_F5, 0 ); - QCOMPARE( currentResult, NoResult ); - -#if 0 - qFatal("Not testing statusbar text feedback yet, since not implemented"); - /* Testing Disabled Accel, and the corresponding statusbar feedback - Ctrl + Qt::Key_K, Ctrl + Qt::Key_L on slot1 - Ctrl + Qt::Key_K, Ctrl + Qt::Key_M on slot2 (disabled) - */ - cut1->setKey(QKeySequence("Ctrl+K, Ctrl+L")); - cut4->setKey(QKeySequence("Ctrl+K, Ctrl+M")); - - cut1->setEnabled(true); - cut4->setEnabled(false); - - currentResult = NoResult; - sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); - sendKeyEvents( Qt::CTRL+Qt::Key_Q, 0 ); - QCOMPARE( currentResult, NoResult ); - if (over_330) - QCOMPARE( sbText, QString("Ctrl+K, Ctrl+Q not defined") ); - - currentResult = NoResult; - sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); - sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 ); - QCOMPARE( currentResult, NoResult ); - if (over_330) - QCOMPARE( sbText, QString::null ); - - currentResult = NoResult; - sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); - sendKeyEvents( Qt::CTRL+Qt::Key_L, 0 ); - QCOMPARE( currentResult, Slot1Triggered ); - if (over_330) - QCOMPARE( sbText, QString::null ); -#endif - clearAllShortcuts(); - cut1 = 0; - cut4 = 0; -} -// ------------------------------------------------------------------ -// Ambiguous Elements ----------------------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::ambiguousRotation() -{ - clearAllShortcuts(); - /* Testing Shortcut rotation scheme - Ctrl + Qt::Key_A on slot1 (disabled) - Ctrl + Qt::Key_A on slot2 (disabled) - Ctrl + Qt::Key_A on slot3 - Ctrl + Qt::Key_A on slot4 - Ctrl + Qt::Key_A on slot5 (disabled) - Ctrl + Qt::Key_A on slot6 - Ctrl + Qt::Key_A on slot7 (disabled) - */ - QShortcut *cut1 = setupShortcut(TriggerSlot1, "Ctrl+A"); - QShortcut *cut2 = setupShortcut(TriggerSlot2, "Ctrl+A"); - QShortcut *cut3 = setupShortcut(TriggerSlot3, "Ctrl+A"); - QShortcut *cut4 = setupShortcut(TriggerSlot4, "Ctrl+A"); - QShortcut *cut5 = setupShortcut(TriggerSlot5, "Ctrl+A"); - QShortcut *cut6 = setupShortcut(TriggerSlot6, "Ctrl+A"); - QShortcut *cut7 = setupShortcut(TriggerSlot7, "Ctrl+A"); - - cut1->setEnabled(false); - cut2->setEnabled(false); - cut5->setEnabled(false); - cut7->setEnabled(false); - - // Test proper rotation - // Start on first - // Go to last - // Go back to first - // Continue... - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot3Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot4Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot6Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot3Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot4Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot6Triggered); - - /* Testing Shortcut rotation scheme - Ctrl + Qt::Key_A on slot1 - Ctrl + Qt::Key_A on slot2 - Ctrl + Qt::Key_A on slot3 (disabled) - Ctrl + Qt::Key_A on slot4 (disabled) - Ctrl + Qt::Key_A on slot5 - Ctrl + Qt::Key_A on slot6 (disabled) - Ctrl + Qt::Key_A on slot7 - */ - - cut1->setEnabled(true); - cut2->setEnabled(true); - cut5->setEnabled(true); - cut7->setEnabled(true); - - cut3->setEnabled(false); - cut4->setEnabled(false); - cut6->setEnabled(false); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot1Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot2Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot5Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot7Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot1Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot2Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot5Triggered); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(Qt::CTRL+Qt::Key_A); - QCOMPARE(currentResult, Ambiguous); - QCOMPARE(ambigResult, Slot7Triggered); - - clearAllShortcuts(); - cut1 = 0; cut2 = 0; - cut3 = 0; cut4 = 0; - cut5 = 0; cut6 = 0; - cut7 = 0; -} - -void tst_QShortcut::ambiguousItems() -{ - clearAllShortcuts(); - /* Testing Ambiguous Shortcuts - Qt::Key_M on Pushbutton 1 - Qt::Key_M on Pushbutton 2 - */ - - // Setup two identical shortcuts on different pushbuttons - QPushButton pb1(mainW); - QPushButton pb2(mainW); - pb1.setObjectName("pushbutton-1"); - pb2.setObjectName("pushbutton-2"); - pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger - pb2.show(); - - setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M"); - setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, "M"); - - currentResult = NoResult; - sendKeyEvents( Qt::Key_M, 'm' ); - QCOMPARE( currentResult, Ambiguous ); - QCOMPARE( ambigResult, Slot1Triggered ); - - currentResult = NoResult; - sendKeyEvents( Qt::Key_M, 'm' ); - QCOMPARE( currentResult, Ambiguous ); - QCOMPARE( ambigResult, Slot2Triggered ); - - currentResult = NoResult; - sendKeyEvents( Qt::Key_M, 'm' ); - QCOMPARE( currentResult, Ambiguous ); - QCOMPARE( ambigResult, Slot1Triggered ); - - clearAllShortcuts(); -} - - -// ------------------------------------------------------------------ -// Unicode and non-unicode Elements --------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::unicodeCompare() -{ - clearAllShortcuts(); - /* Testing Unicode/non-Unicode Shortcuts - Qt::Key_M on Pushbutton 1 - Qt::Key_M on Pushbutton 2 - */ - QPushButton pb1(mainW); - QPushButton pb2(mainW); - pb1.setObjectName("pushbutton-1"); - pb2.setObjectName("pushbutton-2"); - pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger - pb2.show(); - - QKeySequence ks1("Ctrl+M"); // Unicode - QKeySequence ks2(Qt::CTRL+Qt::Key_M); // non-Unicode - setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, ks1); - setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, ks2); - - currentResult = NoResult; - sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 ); - QCOMPARE( currentResult, Ambiguous ); - // They _are_ ambiguous, so the QKeySequence operator== - // should indicate the same - QVERIFY( ks1 == ks2 ); - QVERIFY( !(ks1 != ks2) ); - - clearAllShortcuts(); -} - -// ------------------------------------------------------------------ -// Keypress consumption verification -------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::keypressConsumption() -{ - clearAllShortcuts(); - edit->clear(); - QCOMPARE(edit->toPlainText().size(), 0); - - QShortcut *cut1 = setupShortcut(edit, "shortcut1-line", TriggerSlot1, "Ctrl+I, A"); - QShortcut *cut2 = setupShortcut(edit, "shortcut1-line", TriggerSlot2, "Ctrl+I, B"); - - currentResult = NoResult; - ambigResult = NoResult; - sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QCOMPARE(edit->toPlainText(), QString("")); - - // Make sure next keypress is eaten (failing multiple keysequence) - sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QCOMPARE(edit->toPlainText(), QString("")); - - // Next keypress should be normal - sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QCOMPARE(edit->toPlainText(), QString("c")); - - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - QCOMPARE(edit->toPlainText().size(), 0); - - cut1->setEnabled(false); - cut2->setEnabled(false); - - // Make sure keypresses is passed on, since all multiple keysequences - // with Ctrl+I are disabled - sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QVERIFY(edit->toPlainText().endsWith("")); - - sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit - QCOMPARE( currentResult, NoResult ); - QCOMPARE( ambigResult, NoResult ); - QVERIFY(edit->toPlainText().endsWith("a")); - - clearAllShortcuts(); -} - -// ------------------------------------------------------------------ -// Context Validation ----------------------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::context() -{ - clearAllShortcuts(); - - QWidget myBox; - TestEdit *other1 = new TestEdit(&myBox, "test_edit_other1"); - TestEdit *other2 = new TestEdit(&myBox, "test_edit_other2"); - QHBoxLayout *layout = new QHBoxLayout(&myBox); - layout->addWidget(other1); - layout->addWidget(other2); - myBox.show(); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(&myBox); -#endif - - setupShortcut(other1, "ActiveWindow", TriggerSlot1, QKeySequence("Alt+1"), Qt::WindowShortcut); - setupShortcut(other2, "Focus", TriggerSlot2, QKeySequence("Alt+2"), Qt::WidgetShortcut); - setupShortcut(edit, "Application", TriggerSlot3, QKeySequence("Alt+3"), Qt::ApplicationShortcut); - - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - other1->clear(); - other2->clear(); - - // edit doesn't have focus, so ActiveWindow context should work - // ..but Focus context shouldn't.. - // Changing focus to edit should make focus context work - // Application context should always work - - - // Focus on 'other1' edit, so Active Window context should trigger - other1->activateWindow(); // <--- - QApplication::setActiveWindow(other1); - QCOMPARE(qApp->activeWindow(), other1->window()); - QCOMPARE(qApp->focusWidget(), (QWidget *)other1); - - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - other1->clear(); - other2->clear(); - - QCOMPARE(qApp->focusWidget(), (QWidget *)other1); - sendKeyEvents(other1, Qt::ALT+Qt::Key_1); - QCOMPARE(currentResult, Slot1Triggered); - QCOMPARE(ambigResult, NoResult); - QCOMPARE(edit->toPlainText(), QString("")); - QCOMPARE(other1->toPlainText(), QString("")); - QCOMPARE(other2->toPlainText(), QString("")); - - // ..but not Focus context on 'other2'.. - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - other1->clear(); - other2->clear(); - - sendKeyEvents(other1, Qt::ALT+Qt::Key_2); - QCOMPARE(currentResult, NoResult); - QCOMPARE(ambigResult, NoResult); - QCOMPARE(edit->toPlainText(), QString("")); - QCOMPARE(other1->toPlainText(), QString("")); - QCOMPARE(other2->toPlainText(), QString("")); - - // ..however, application global context on 'edit' should.. - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - other1->clear(); - other2->clear(); - - sendKeyEvents(other1, Qt::ALT+Qt::Key_3); - QCOMPARE(currentResult, Slot3Triggered); - QCOMPARE(ambigResult, NoResult); - QCOMPARE(edit->toPlainText(), QString("")); - QCOMPARE(other1->toPlainText(), QString("")); - QCOMPARE(other2->toPlainText(), QString("")); - - // Changing focus to 'other2' should make the Focus context there work - other2->activateWindow(); - other2->setFocus(); // ### - qApp->syncX(); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(other2); -#endif - QTest::qWait(100); - QCOMPARE(qApp->activeWindow(), other2->window()); - QCOMPARE(qApp->focusWidget(), (QWidget *)other2); - - currentResult = NoResult; - ambigResult = NoResult; - edit->clear(); - other1->clear(); - other2->clear(); - - sendKeyEvents(other2, Qt::ALT+Qt::Key_2); - QCOMPARE(currentResult, Slot2Triggered); - QCOMPARE(ambigResult, NoResult); - QCOMPARE(edit->toPlainText(), QString("")); - QCOMPARE(other1->toPlainText(), QString("")); - QCOMPARE(other2->toPlainText(), QString("")); - - clearAllShortcuts(); - delete other1; - delete other2; - edit->activateWindow(); - qApp->syncX(); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(edit); -#endif - QTest::qWait(100); -} - -// ------------------------------------------------------------------ -// Element Testing helper functions --------------------------------- -// ------------------------------------------------------------------ -void tst_QShortcut::clearAllShortcuts() -{ - QList shortcutsCpy = shortcuts; - qDeleteAll(shortcutsCpy); - shortcuts.clear(); -} - -QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QKeySequence &ks) -{ - return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, ks); -} - -QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QString &txt, int k1, int k2, int k3, int k4) -{ - return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, - (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt))); -} - -QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1, int k2, int k3, int k4) -{ - return setupShortcut(parent, name, testWidget, - (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt))); -} - -QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, - const QKeySequence &ks, Qt::ShortcutContext context) -{ - // Set up shortcut for next test - QShortcut *cut = new QShortcut(QKeySequence(), parent, 0, 0, context); - cut->setObjectName(name); - cut->setKey(ks); - - const char *normal = 0; - const char *ambig = 0; - switch(testWidget) - { - case TriggerSlot1: - normal = SLOT(slotTrig1()); - ambig = SLOT(ambigSlot1()); - break; - case TriggerSlot2: - normal = SLOT(slotTrig2()); - ambig = SLOT(ambigSlot2()); - break; - case TriggerSlot3: - normal = SLOT(slotTrig3()); - ambig = SLOT(ambigSlot3()); - break; - case TriggerSlot4: - normal = SLOT(slotTrig4()); - ambig = SLOT(ambigSlot4()); - break; - case TriggerSlot5: - normal = SLOT(slotTrig5()); - ambig = SLOT(ambigSlot5()); - break; - case TriggerSlot6: - normal = SLOT(slotTrig6()); - ambig = SLOT(ambigSlot6()); - break; - case TriggerSlot7: - normal = SLOT(slotTrig7()); - ambig = SLOT(ambigSlot7()); - break; - } - connect(cut, SIGNAL(activated()), this, normal); - connect(cut, SIGNAL(activatedAmbiguously()), this, ambig); - connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*))); - shortcuts.append(cut); - return cut; -} - -void tst_QShortcut::shortcutDestroyed(QObject* obj) -{ - shortcuts.removeAll(static_cast(obj)); -} - -void tst_QShortcut::sendKeyEvents(int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4) -{ - sendKeyEvents(mainW, k1, c1, k2, c2, k3, c3, k4, c4); -} - -void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4) -{ - Qt::KeyboardModifiers b1 = toButtons( k1 ); - Qt::KeyboardModifiers b2 = toButtons( k2 ); - Qt::KeyboardModifiers b3 = toButtons( k3 ); - Qt::KeyboardModifiers b4 = toButtons( k4 ); - k1 &= ~Qt::MODIFIER_MASK; - k2 &= ~Qt::MODIFIER_MASK; - k3 &= ~Qt::MODIFIER_MASK; - k4 &= ~Qt::MODIFIER_MASK; - - - if (k1 || c1.toAscii()) { - QString c(c1.unicode() == QChar::Null ? QString() : QString(c1)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k1), c, b1); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k1), c, b1); - } - - if (k2 || c2.toAscii()) { - QString c(c2.unicode() == QChar::Null ? QString() : QString(c2)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k2), c, b2); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k2), c, b2); - } - - if (k3 || c3.toAscii()) { - QString c(c3.unicode() == QChar::Null ? QString() : QString(c3)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k3), c, b3); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k3), c, b3); - } - - if (k4 || c4.toAscii()) { - QString c(c4.unicode() == QChar::Null ? QString() : QString(c4)); - QTest::sendKeyEvent(QTest::Press, w, static_cast(k4), c, b4); - QTest::sendKeyEvent(QTest::Release, w, static_cast(k4), c, b4); - } -} - -void tst_QShortcut::testElement() -{ - currentResult = NoResult; - QFETCH(tst_QShortcut::Action, action); - QFETCH(tst_QShortcut::Widget, testWidget); - QFETCH(QString, txt); - QFETCH(int, k1); - QFETCH(int, c1); - QFETCH(int, k2); - QFETCH(int, c2); - QFETCH(int, k3); - QFETCH(int, c3); - QFETCH(int, k4); - QFETCH(int, c4); - QFETCH(tst_QShortcut::Result, result); - - if (action == ClearAll) { - clearAllShortcuts(); - } else if (action == SetupAccel) { - setupShortcut(testWidget, txt, k1, k2, k3, k4); - } else { - sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4); - QCOMPARE(currentResult, result); - } -} - -QTEST_MAIN(tst_QShortcut) -#include "tst_qshortcut.moc" diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro index 3a00300ac3..cf909b7e87 100644 --- a/tests/auto/widgets/kernel/kernel.pro +++ b/tests/auto/widgets/kernel/kernel.pro @@ -14,6 +14,7 @@ SUBDIRS=\ qwidget_window \ qwidgetaction \ qicon \ + qshortcut \ SUBDIRS -= qsound diff --git a/tests/auto/widgets/kernel/qshortcut/.gitignore b/tests/auto/widgets/kernel/qshortcut/.gitignore new file mode 100644 index 0000000000..3a17eb18e3 --- /dev/null +++ b/tests/auto/widgets/kernel/qshortcut/.gitignore @@ -0,0 +1 @@ +tst_qshortcut diff --git a/tests/auto/widgets/kernel/qshortcut/qshortcut.pro b/tests/auto/widgets/kernel/qshortcut/qshortcut.pro new file mode 100644 index 0000000000..7ac1dd2c9d --- /dev/null +++ b/tests/auto/widgets/kernel/qshortcut/qshortcut.pro @@ -0,0 +1,12 @@ +CONFIG += testcase +TARGET = tst_qshortcut + +# Project Configuration ---------------------------------------------- +INCLUDEPATH += ../ + +# Normal Test Files -------------------------------------------------- +QT += widgets testlib +HEADERS += +SOURCES += tst_qshortcut.cpp + + diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp new file mode 100644 index 0000000000..61efb6e3f3 --- /dev/null +++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp @@ -0,0 +1,1259 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used 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. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class AccelForm; +QT_BEGIN_NAMESPACE +class QMainWindow; +class QTextEdit; +QT_END_NAMESPACE + +class tst_QShortcut : public QObject +{ + Q_OBJECT +public: + tst_QShortcut(); + virtual ~tst_QShortcut(); + + + enum Action { + SetupAccel, + TestAccel, + ClearAll + } currentAction; + + enum Widget { + NoWidget, + TriggerSlot1, + TriggerSlot2, + TriggerSlot3, + TriggerSlot4, + TriggerSlot5, + TriggerSlot6, + TriggerSlot7 + }; + + enum Result { + NoResult, + Slot1Triggered, + Slot2Triggered, + Slot3Triggered, + Slot4Triggered, + Slot5Triggered, + Slot6Triggered, + Slot7Triggered, + Ambiguous + } currentResult; + +public slots: + void slotTrig1() { currentResult = Slot1Triggered; } + void slotTrig2() { currentResult = Slot2Triggered; } + void slotTrig3() { currentResult = Slot3Triggered; } + void slotTrig4() { currentResult = Slot4Triggered; } + void slotTrig5() { currentResult = Slot5Triggered; } + void slotTrig6() { currentResult = Slot6Triggered; } + void slotTrig7() { currentResult = Slot7Triggered; } + void ambigSlot1() { currentResult = Ambiguous; ambigResult = Slot1Triggered; } + void ambigSlot2() { currentResult = Ambiguous; ambigResult = Slot2Triggered; } + void ambigSlot3() { currentResult = Ambiguous; ambigResult = Slot3Triggered; } + void ambigSlot4() { currentResult = Ambiguous; ambigResult = Slot4Triggered; } + void ambigSlot5() { currentResult = Ambiguous; ambigResult = Slot5Triggered; } + void ambigSlot6() { currentResult = Ambiguous; ambigResult = Slot6Triggered; } + void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; } + void statusMessage( const QString& message ) { sbText = message; } + void shortcutDestroyed(QObject* obj); + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void number_data(); + void number(); + void text_data(); + void text(); + void disabledItems(); + void ambiguousItems(); + void ambiguousRotation(); + void keypressConsumption(); + void unicodeCompare(); + void context(); + +protected: + static Qt::KeyboardModifiers toButtons( int key ); + void defElements(); + + void clearAllShortcuts(); + QShortcut *setupShortcut(int testWidget, const QKeySequence &ks); + QShortcut *setupShortcut(int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0); + + QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0); + QShortcut *setupShortcut(QWidget *parent, const char *name, int testWidget, const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut); + + void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0); + void sendKeyEvents(int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0); + + void testElement(); + + QMainWindow *mainW; + QList shortcuts; + QTextEdit *edit; + QString sbText; + Result ambigResult; +}; + +Q_DECLARE_METATYPE(tst_QShortcut::Widget); +Q_DECLARE_METATYPE(tst_QShortcut::Result); +Q_DECLARE_METATYPE(tst_QShortcut::Action); + +class TestEdit : public QTextEdit +{ + Q_OBJECT +public: + TestEdit(QWidget *parent, const char *name) + : QTextEdit(parent) + { + setObjectName(name); + } + +protected: + bool event(QEvent *e) { + // Make testedit allow any Ctrl+Key as shortcut + if (e->type() == QEvent::ShortcutOverride) { + QKeyEvent *ke = static_cast(e); + if (ke->modifiers() == Qt::ControlModifier + && ke->key() > Qt::Key_Any + && ke->key() < Qt::Key_ydiaeresis) { + ke->ignore(); + return true; + } + } + + // If keypress not processed as normal, check for + // Ctrl+Key event, and input custom string for + // result comparison. + if (e->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(e); + if (ke->modifiers() && ke->key() > Qt::Key_Any + && ke->key() < Qt::Key_ydiaeresis) { + if (ke->modifiers() == Qt::ControlModifier) + insertPlainText(QString("").arg(char(ke->key()))); + else if (ke->modifiers() == Qt::AltModifier) + insertPlainText(QString("").arg(char(ke->key()))); + else if (ke->modifiers() == Qt::ShiftModifier) + insertPlainText(QString("").arg(char(ke->key()))); + return true; + } + } + return QTextEdit::event(e); + } +}; + +tst_QShortcut::tst_QShortcut(): mainW( 0 ) +{ +} + +tst_QShortcut::~tst_QShortcut() +{ + clearAllShortcuts(); +} + +void tst_QShortcut::initTestCase() +{ + currentResult = NoResult; + mainW = new QMainWindow(0); + mainW->setWindowFlags(Qt::X11BypassWindowManagerHint); + edit = new TestEdit(mainW, "test_edit"); + mainW->setFixedSize( 100, 100 ); + mainW->setCentralWidget( edit ); + mainW->show(); + QTest::qWaitForWindowShown(mainW); + mainW->activateWindow(); + QTest::qWait(100); + connect( mainW->statusBar(), SIGNAL(messageChanged(const QString&)), + this, SLOT(statusMessage(const QString&)) ); +} + +void tst_QShortcut::cleanupTestCase() +{ + delete mainW; +} + +Qt::KeyboardModifiers tst_QShortcut::toButtons( int key ) +{ + Qt::KeyboardModifiers result = Qt::NoModifier; + if ( key & Qt::SHIFT ) + result |= Qt::ShiftModifier; + if ( key & Qt::CTRL ) + result |= Qt::ControlModifier; + if ( key & Qt::META ) + result |= Qt::MetaModifier; + if ( key & Qt::ALT ) + result |= Qt::AltModifier; + return result; +} + +void tst_QShortcut::defElements() +{ + QTest::addColumn("action"); + QTest::addColumn("testWidget"); + QTest::addColumn("txt"); + QTest::addColumn("k1"); + QTest::addColumn("c1"); + QTest::addColumn("k2"); + QTest::addColumn("c2"); + QTest::addColumn("k3"); + QTest::addColumn("c3"); + QTest::addColumn("k4"); + QTest::addColumn("c4"); + QTest::addColumn("result"); +} + +void tst_QShortcut::number() +{ + // We expect a failure on these tests, until QtTestKeyboard is + // fixed to do real platform dependent keyboard simulations + if (QTest::currentDataTag() == QString("N006a:Shift+Tab - [BackTab]") + || QTest::currentDataTag() == QString("N006b:Shift+Tab - [Shift+BackTab]")) + QEXPECT_FAIL("", "FLAW IN QTESTKEYBOARD: Keyboard events not passed through " + "platform dependent key handling code", Continue); + testElement(); +} +void tst_QShortcut::text() +{ + testElement(); +} +// ------------------------------------------------------------------ +// Number Elements -------------------------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::number_data() +{ + defElements(); + + // Clear all + QTest::newRow("N00 - clear") << ClearAll << NoWidget <activateWindow(); + qApp->syncX(); + QTest::qWait(100); + + /* Testing Disabled Shortcuts + Qt::Key_M on slot1 + Shift + Qt::Key_M on slot1 + Qt::Key_M on slot2 (disabled) + Shift + Qt::Key_M on slot2 (disabled) + */ + + // Setup two identical shortcuts on different pushbuttons + QPushButton pb1(mainW); + QPushButton pb2(mainW); + pb1.setObjectName("pushbutton-1"); + pb2.setObjectName("pushbutton-2"); + pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger + pb2.show(); + + QShortcut *cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M"); + QShortcut *cut2 = setupShortcut(&pb1, "shortcut2-pb1", TriggerSlot1, "Shift+M"); + QShortcut *cut3 = setupShortcut(&pb2, "shortcut3-pb2", TriggerSlot2, "M"); + QShortcut *cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+M"); + + cut3->setEnabled(false); + cut4->setEnabled(false); + + currentResult = NoResult; + sendKeyEvents(Qt::Key_M, 'm'); + QCOMPARE(currentResult, Slot1Triggered); + + currentResult = NoResult; + sendKeyEvents(Qt::SHIFT+Qt::Key_M, 'M'); + QCOMPARE(currentResult, Slot1Triggered); + + cut2->setEnabled(false); + cut4->setEnabled(true); + + /* Testing Disabled Shortcuts + Qt::Key_M on slot1 + Shift + Qt::Key_M on slot1 (disabled) + Qt::Key_M on slot2 (disabled) + Shift + Qt::Key_M on slot2 + */ + currentResult = NoResult; + sendKeyEvents( Qt::Key_M, 'm' ); + QCOMPARE( currentResult, Slot1Triggered ); + + currentResult = NoResult; + sendKeyEvents( Qt::SHIFT+Qt::Key_M, 'M' ); + QCOMPARE( currentResult, Slot2Triggered ); + + + /* Testing Disabled Accel + Qt::Key_F5 on slot1 + Shift + Qt::Key_F5 on slot2 (disabled) + */ + clearAllShortcuts(); + cut1 = setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "F5"); + cut4 = setupShortcut(&pb2, "shortcut4-pb2", TriggerSlot2, "Shift+F5"); + + cut1->setKey(QKeySequence("F5")); + cut4->setKey(QKeySequence("Shift+F5")); + + cut1->setEnabled(true); + cut4->setEnabled(false); + + currentResult = NoResult; + sendKeyEvents( Qt::Key_F5, 0 ); + QCOMPARE( currentResult, Slot1Triggered ); + + currentResult = NoResult; + sendKeyEvents( Qt::SHIFT+Qt::Key_F5, 0 ); + QCOMPARE( currentResult, NoResult ); + +#if 0 + qFatal("Not testing statusbar text feedback yet, since not implemented"); + /* Testing Disabled Accel, and the corresponding statusbar feedback + Ctrl + Qt::Key_K, Ctrl + Qt::Key_L on slot1 + Ctrl + Qt::Key_K, Ctrl + Qt::Key_M on slot2 (disabled) + */ + cut1->setKey(QKeySequence("Ctrl+K, Ctrl+L")); + cut4->setKey(QKeySequence("Ctrl+K, Ctrl+M")); + + cut1->setEnabled(true); + cut4->setEnabled(false); + + currentResult = NoResult; + sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); + sendKeyEvents( Qt::CTRL+Qt::Key_Q, 0 ); + QCOMPARE( currentResult, NoResult ); + if (over_330) + QCOMPARE( sbText, QString("Ctrl+K, Ctrl+Q not defined") ); + + currentResult = NoResult; + sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); + sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 ); + QCOMPARE( currentResult, NoResult ); + if (over_330) + QCOMPARE( sbText, QString::null ); + + currentResult = NoResult; + sendKeyEvents( Qt::CTRL+Qt::Key_K, 0 ); + sendKeyEvents( Qt::CTRL+Qt::Key_L, 0 ); + QCOMPARE( currentResult, Slot1Triggered ); + if (over_330) + QCOMPARE( sbText, QString::null ); +#endif + clearAllShortcuts(); + cut1 = 0; + cut4 = 0; +} +// ------------------------------------------------------------------ +// Ambiguous Elements ----------------------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::ambiguousRotation() +{ + clearAllShortcuts(); + /* Testing Shortcut rotation scheme + Ctrl + Qt::Key_A on slot1 (disabled) + Ctrl + Qt::Key_A on slot2 (disabled) + Ctrl + Qt::Key_A on slot3 + Ctrl + Qt::Key_A on slot4 + Ctrl + Qt::Key_A on slot5 (disabled) + Ctrl + Qt::Key_A on slot6 + Ctrl + Qt::Key_A on slot7 (disabled) + */ + QShortcut *cut1 = setupShortcut(TriggerSlot1, "Ctrl+A"); + QShortcut *cut2 = setupShortcut(TriggerSlot2, "Ctrl+A"); + QShortcut *cut3 = setupShortcut(TriggerSlot3, "Ctrl+A"); + QShortcut *cut4 = setupShortcut(TriggerSlot4, "Ctrl+A"); + QShortcut *cut5 = setupShortcut(TriggerSlot5, "Ctrl+A"); + QShortcut *cut6 = setupShortcut(TriggerSlot6, "Ctrl+A"); + QShortcut *cut7 = setupShortcut(TriggerSlot7, "Ctrl+A"); + + cut1->setEnabled(false); + cut2->setEnabled(false); + cut5->setEnabled(false); + cut7->setEnabled(false); + + // Test proper rotation + // Start on first + // Go to last + // Go back to first + // Continue... + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot3Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot4Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot6Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot3Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot4Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot6Triggered); + + /* Testing Shortcut rotation scheme + Ctrl + Qt::Key_A on slot1 + Ctrl + Qt::Key_A on slot2 + Ctrl + Qt::Key_A on slot3 (disabled) + Ctrl + Qt::Key_A on slot4 (disabled) + Ctrl + Qt::Key_A on slot5 + Ctrl + Qt::Key_A on slot6 (disabled) + Ctrl + Qt::Key_A on slot7 + */ + + cut1->setEnabled(true); + cut2->setEnabled(true); + cut5->setEnabled(true); + cut7->setEnabled(true); + + cut3->setEnabled(false); + cut4->setEnabled(false); + cut6->setEnabled(false); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot1Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot2Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot5Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot7Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot1Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot2Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot5Triggered); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(Qt::CTRL+Qt::Key_A); + QCOMPARE(currentResult, Ambiguous); + QCOMPARE(ambigResult, Slot7Triggered); + + clearAllShortcuts(); + cut1 = 0; cut2 = 0; + cut3 = 0; cut4 = 0; + cut5 = 0; cut6 = 0; + cut7 = 0; +} + +void tst_QShortcut::ambiguousItems() +{ + clearAllShortcuts(); + /* Testing Ambiguous Shortcuts + Qt::Key_M on Pushbutton 1 + Qt::Key_M on Pushbutton 2 + */ + + // Setup two identical shortcuts on different pushbuttons + QPushButton pb1(mainW); + QPushButton pb2(mainW); + pb1.setObjectName("pushbutton-1"); + pb2.setObjectName("pushbutton-2"); + pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger + pb2.show(); + + setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, "M"); + setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, "M"); + + currentResult = NoResult; + sendKeyEvents( Qt::Key_M, 'm' ); + QCOMPARE( currentResult, Ambiguous ); + QCOMPARE( ambigResult, Slot1Triggered ); + + currentResult = NoResult; + sendKeyEvents( Qt::Key_M, 'm' ); + QCOMPARE( currentResult, Ambiguous ); + QCOMPARE( ambigResult, Slot2Triggered ); + + currentResult = NoResult; + sendKeyEvents( Qt::Key_M, 'm' ); + QCOMPARE( currentResult, Ambiguous ); + QCOMPARE( ambigResult, Slot1Triggered ); + + clearAllShortcuts(); +} + + +// ------------------------------------------------------------------ +// Unicode and non-unicode Elements --------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::unicodeCompare() +{ + clearAllShortcuts(); + /* Testing Unicode/non-Unicode Shortcuts + Qt::Key_M on Pushbutton 1 + Qt::Key_M on Pushbutton 2 + */ + QPushButton pb1(mainW); + QPushButton pb2(mainW); + pb1.setObjectName("pushbutton-1"); + pb2.setObjectName("pushbutton-2"); + pb1.show(); // Must be show for QShortcutMap::correctSubWindow to trigger + pb2.show(); + + QKeySequence ks1("Ctrl+M"); // Unicode + QKeySequence ks2(Qt::CTRL+Qt::Key_M); // non-Unicode + setupShortcut(&pb1, "shortcut1-pb1", TriggerSlot1, ks1); + setupShortcut(&pb1, "shortcut2-pb2", TriggerSlot2, ks2); + + currentResult = NoResult; + sendKeyEvents( Qt::CTRL+Qt::Key_M, 0 ); + QCOMPARE( currentResult, Ambiguous ); + // They _are_ ambiguous, so the QKeySequence operator== + // should indicate the same + QVERIFY( ks1 == ks2 ); + QVERIFY( !(ks1 != ks2) ); + + clearAllShortcuts(); +} + +// ------------------------------------------------------------------ +// Keypress consumption verification -------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::keypressConsumption() +{ + clearAllShortcuts(); + edit->clear(); + QCOMPARE(edit->toPlainText().size(), 0); + + QShortcut *cut1 = setupShortcut(edit, "shortcut1-line", TriggerSlot1, "Ctrl+I, A"); + QShortcut *cut2 = setupShortcut(edit, "shortcut1-line", TriggerSlot2, "Ctrl+I, B"); + + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QCOMPARE(edit->toPlainText(), QString("")); + + // Make sure next keypress is eaten (failing multiple keysequence) + sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QCOMPARE(edit->toPlainText(), QString("")); + + // Next keypress should be normal + sendKeyEvents(edit, Qt::Key_C, 'c'); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QCOMPARE(edit->toPlainText(), QString("c")); + + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + QCOMPARE(edit->toPlainText().size(), 0); + + cut1->setEnabled(false); + cut2->setEnabled(false); + + // Make sure keypresses is passed on, since all multiple keysequences + // with Ctrl+I are disabled + sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QVERIFY(edit->toPlainText().endsWith("")); + + sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit + QCOMPARE( currentResult, NoResult ); + QCOMPARE( ambigResult, NoResult ); + QVERIFY(edit->toPlainText().endsWith("a")); + + clearAllShortcuts(); +} + +// ------------------------------------------------------------------ +// Context Validation ----------------------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::context() +{ + clearAllShortcuts(); + + QWidget myBox; + TestEdit *other1 = new TestEdit(&myBox, "test_edit_other1"); + TestEdit *other2 = new TestEdit(&myBox, "test_edit_other2"); + QHBoxLayout *layout = new QHBoxLayout(&myBox); + layout->addWidget(other1); + layout->addWidget(other2); + myBox.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&myBox); +#endif + + setupShortcut(other1, "ActiveWindow", TriggerSlot1, QKeySequence("Alt+1"), Qt::WindowShortcut); + setupShortcut(other2, "Focus", TriggerSlot2, QKeySequence("Alt+2"), Qt::WidgetShortcut); + setupShortcut(edit, "Application", TriggerSlot3, QKeySequence("Alt+3"), Qt::ApplicationShortcut); + + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + other1->clear(); + other2->clear(); + + // edit doesn't have focus, so ActiveWindow context should work + // ..but Focus context shouldn't.. + // Changing focus to edit should make focus context work + // Application context should always work + + + // Focus on 'other1' edit, so Active Window context should trigger + other1->activateWindow(); // <--- + QApplication::setActiveWindow(other1); + QCOMPARE(qApp->activeWindow(), other1->window()); + QCOMPARE(qApp->focusWidget(), (QWidget *)other1); + + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + other1->clear(); + other2->clear(); + + QCOMPARE(qApp->focusWidget(), (QWidget *)other1); + sendKeyEvents(other1, Qt::ALT+Qt::Key_1); + QCOMPARE(currentResult, Slot1Triggered); + QCOMPARE(ambigResult, NoResult); + QCOMPARE(edit->toPlainText(), QString("")); + QCOMPARE(other1->toPlainText(), QString("")); + QCOMPARE(other2->toPlainText(), QString("")); + + // ..but not Focus context on 'other2'.. + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + other1->clear(); + other2->clear(); + + sendKeyEvents(other1, Qt::ALT+Qt::Key_2); + QCOMPARE(currentResult, NoResult); + QCOMPARE(ambigResult, NoResult); + QCOMPARE(edit->toPlainText(), QString("")); + QCOMPARE(other1->toPlainText(), QString("")); + QCOMPARE(other2->toPlainText(), QString("")); + + // ..however, application global context on 'edit' should.. + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + other1->clear(); + other2->clear(); + + sendKeyEvents(other1, Qt::ALT+Qt::Key_3); + QCOMPARE(currentResult, Slot3Triggered); + QCOMPARE(ambigResult, NoResult); + QCOMPARE(edit->toPlainText(), QString("")); + QCOMPARE(other1->toPlainText(), QString("")); + QCOMPARE(other2->toPlainText(), QString("")); + + // Changing focus to 'other2' should make the Focus context there work + other2->activateWindow(); + other2->setFocus(); // ### + qApp->syncX(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(other2); +#endif + QTest::qWait(100); + QCOMPARE(qApp->activeWindow(), other2->window()); + QCOMPARE(qApp->focusWidget(), (QWidget *)other2); + + currentResult = NoResult; + ambigResult = NoResult; + edit->clear(); + other1->clear(); + other2->clear(); + + sendKeyEvents(other2, Qt::ALT+Qt::Key_2); + QCOMPARE(currentResult, Slot2Triggered); + QCOMPARE(ambigResult, NoResult); + QCOMPARE(edit->toPlainText(), QString("")); + QCOMPARE(other1->toPlainText(), QString("")); + QCOMPARE(other2->toPlainText(), QString("")); + + clearAllShortcuts(); + delete other1; + delete other2; + edit->activateWindow(); + qApp->syncX(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(edit); +#endif + QTest::qWait(100); +} + +// ------------------------------------------------------------------ +// Element Testing helper functions --------------------------------- +// ------------------------------------------------------------------ +void tst_QShortcut::clearAllShortcuts() +{ + QList shortcutsCpy = shortcuts; + qDeleteAll(shortcutsCpy); + shortcuts.clear(); +} + +QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QKeySequence &ks) +{ + return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, ks); +} + +QShortcut *tst_QShortcut::setupShortcut(int testWidget, const QString &txt, int k1, int k2, int k3, int k4) +{ + return setupShortcut(mainW, QTest::currentDataTag() ? QTest::currentDataTag() : "", testWidget, + (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt))); +} + +QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, const QString &txt, int k1, int k2, int k3, int k4) +{ + return setupShortcut(parent, name, testWidget, + (txt.isEmpty() ? QKeySequence(k1, k2, k3, k4) : QKeySequence(txt))); +} + +QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int testWidget, + const QKeySequence &ks, Qt::ShortcutContext context) +{ + // Set up shortcut for next test + QShortcut *cut = new QShortcut(QKeySequence(), parent, 0, 0, context); + cut->setObjectName(name); + cut->setKey(ks); + + const char *normal = 0; + const char *ambig = 0; + switch(testWidget) + { + case TriggerSlot1: + normal = SLOT(slotTrig1()); + ambig = SLOT(ambigSlot1()); + break; + case TriggerSlot2: + normal = SLOT(slotTrig2()); + ambig = SLOT(ambigSlot2()); + break; + case TriggerSlot3: + normal = SLOT(slotTrig3()); + ambig = SLOT(ambigSlot3()); + break; + case TriggerSlot4: + normal = SLOT(slotTrig4()); + ambig = SLOT(ambigSlot4()); + break; + case TriggerSlot5: + normal = SLOT(slotTrig5()); + ambig = SLOT(ambigSlot5()); + break; + case TriggerSlot6: + normal = SLOT(slotTrig6()); + ambig = SLOT(ambigSlot6()); + break; + case TriggerSlot7: + normal = SLOT(slotTrig7()); + ambig = SLOT(ambigSlot7()); + break; + } + connect(cut, SIGNAL(activated()), this, normal); + connect(cut, SIGNAL(activatedAmbiguously()), this, ambig); + connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*))); + shortcuts.append(cut); + return cut; +} + +void tst_QShortcut::shortcutDestroyed(QObject* obj) +{ + shortcuts.removeAll(static_cast(obj)); +} + +void tst_QShortcut::sendKeyEvents(int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4) +{ + sendKeyEvents(mainW, k1, c1, k2, c2, k3, c3, k4, c4); +} + +void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4) +{ + Qt::KeyboardModifiers b1 = toButtons( k1 ); + Qt::KeyboardModifiers b2 = toButtons( k2 ); + Qt::KeyboardModifiers b3 = toButtons( k3 ); + Qt::KeyboardModifiers b4 = toButtons( k4 ); + k1 &= ~Qt::MODIFIER_MASK; + k2 &= ~Qt::MODIFIER_MASK; + k3 &= ~Qt::MODIFIER_MASK; + k4 &= ~Qt::MODIFIER_MASK; + + + if (k1 || c1.toAscii()) { + QString c(c1.unicode() == QChar::Null ? QString() : QString(c1)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k1), c, b1); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k1), c, b1); + } + + if (k2 || c2.toAscii()) { + QString c(c2.unicode() == QChar::Null ? QString() : QString(c2)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k2), c, b2); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k2), c, b2); + } + + if (k3 || c3.toAscii()) { + QString c(c3.unicode() == QChar::Null ? QString() : QString(c3)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k3), c, b3); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k3), c, b3); + } + + if (k4 || c4.toAscii()) { + QString c(c4.unicode() == QChar::Null ? QString() : QString(c4)); + QTest::sendKeyEvent(QTest::Press, w, static_cast(k4), c, b4); + QTest::sendKeyEvent(QTest::Release, w, static_cast(k4), c, b4); + } +} + +void tst_QShortcut::testElement() +{ + currentResult = NoResult; + QFETCH(tst_QShortcut::Action, action); + QFETCH(tst_QShortcut::Widget, testWidget); + QFETCH(QString, txt); + QFETCH(int, k1); + QFETCH(int, c1); + QFETCH(int, k2); + QFETCH(int, c2); + QFETCH(int, k3); + QFETCH(int, c3); + QFETCH(int, k4); + QFETCH(int, c4); + QFETCH(tst_QShortcut::Result, result); + + if (action == ClearAll) { + clearAllShortcuts(); + } else if (action == SetupAccel) { + setupShortcut(testWidget, txt, k1, k2, k3, k4); + } else { + sendKeyEvents(k1, c1, k2, c2, k3, c3, k4, c4); + QCOMPARE(currentResult, result); + } +} + +QTEST_MAIN(tst_QShortcut) +#include "tst_qshortcut.moc" -- cgit v1.2.3 From 01e8e9136dfa5d3260de0d318da6aece7214f85a Mon Sep 17 00:00:00 2001 From: Girish Ramakrishnan Date: Fri, 9 Mar 2012 14:39:14 -0800 Subject: Check for PKG_CONFIG_LIBDIR when cross compiling. When cross-compiling, check for PKG_CONFIG_LIBDIR instead of PKG_CONFIG_PATH. pkg-config searches for pc files in PKG_CONFIG_PATH *and* the compiled in defaults (/usr/lib/pkgconfig). This means that pc files from the host get found when cross-compiling. Setting PKG_CONFIG_LIBDIR makes pkg-config search only in the path set in PKG_CONFIG_LIBDIR. Documented in the url below: http://www.freedesktop.org/wiki/Software/pkg-config/CrossCompileProposal Change-Id: I22dbf29c5691572b7cb8a5fce712ae7ba811670e Reviewed-by: Oswald Buddenhagen --- configure | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 66c5f1a06d..e2df6028fd 100755 --- a/configure +++ b/configure @@ -2625,11 +2625,11 @@ if [ "$QT_CROSS_COMPILE" = "yes" ]; then echo >&2 "Please make sure you have a correctly set-up pkg-config" echo >&2 "environment!" echo >&2 "" - if [ -z "$PKG_CONFIG_PATH" ]; then + if [ -z "$PKG_CONFIG_LIBDIR" ]; then echo >&2 "" - echo >&2 "Warning: PKG_CONFIG_PATH has not been set. This could mean" - echo >&2 "the host compiler's .pc files will be used. This is probably" - echo >&2 "not what you want." + echo >&2 "Warning: PKG_CONFIG_LIBDIR has not been set. This could mean" + echo >&2 "the host's .pc files will be used (even if you set PKG_CONFIG_PATH)." + echo >&2 "This is probably not what you want." echo >&2 "" elif [ -z "$PKG_CONFIG_SYSROOT" ] && [ -z "$PKG_CONFIG_SYSROOT_DIR" ]; then echo >&2 "" -- cgit v1.2.3 From 412dbdf410c765e75c60d1f48143dd6c02a69493 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Wed, 29 Feb 2012 13:32:20 +0900 Subject: Input method on Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore input method implimentation in Qt4 Task-number: QTBUG-23867 Change-Id: I5d405ccc8b0a73c399d992f6474a0cc38d191157 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/cocoa.pro | 2 + src/plugins/platforms/cocoa/qcocoahelpers.h | 2 + src/plugins/platforms/cocoa/qcocoahelpers.mm | 19 ++ src/plugins/platforms/cocoa/qcocoainputcontext.h | 70 +++++++ src/plugins/platforms/cocoa/qcocoainputcontext.mm | 122 +++++++++++ src/plugins/platforms/cocoa/qcocoaintegration.h | 2 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 7 + .../platforms/cocoa/qcocoanativeinterface.h | 1 + src/plugins/platforms/cocoa/qnsview.h | 4 +- src/plugins/platforms/cocoa/qnsview.mm | 233 ++++++++++++++++++++- 10 files changed, 457 insertions(+), 5 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoainputcontext.h create mode 100644 src/plugins/platforms/cocoa/qcocoainputcontext.mm diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index b953210720..bd70a415d0 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -31,6 +31,7 @@ OBJECTIVE_SOURCES += main.mm \ qmacclipboard.mm \ qmacmime.mm \ qcocoasystemsettings.mm \ + qcocoainputcontext.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -59,6 +60,7 @@ HEADERS += qcocoaintegration.h \ qmacclipboard.h \ qmacmime.h \ qcocoasystemsettings.h \ + qcocoainputcontext.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 3e3e8fa507..e5fe664731 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -74,6 +74,8 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSSize qt_mac_toNSSize(const QSize &qtSize); +QColor qt_mac_toQColor(const NSColor *color); + QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index ec4399b66c..e41ddf4a9f 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -137,6 +137,25 @@ NSSize qt_mac_toNSSize(const QSize &qtSize) return NSMakeSize(qtSize.width(), qtSize.height()); } +QColor qt_mac_toQColor(const NSColor *color) +{ + QColor qtColor; + NSString *colorSpace = [color colorSpaceName]; + if (colorSpace == NSDeviceCMYKColorSpace) { + CGFloat cyan, magenta, yellow, black, alpha; + [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; + qtColor.setCmykF(cyan, magenta, yellow, black, alpha); + } else { + NSColor *tmpColor; + tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; + CGFloat red, green, blue, alpha; + [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; + qtColor.setRgbF(red, green, blue, alpha); + } + return qtColor; +} + + // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. struct KeyPair diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h new file mode 100644 index 0000000000..172c87e2dc --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used 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. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOAINPUTCONTEXT_H +#define QCOCOAINPUTCONTEXT_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QCocoaInputContext : public QPlatformInputContext +{ + Q_OBJECT +public: + explicit QCocoaInputContext(); + ~QCocoaInputContext(); + + virtual bool isValid() const { return true; } + + virtual void reset(); + +private Q_SLOTS: + void inputItemChanged(); + +private: + QPointer mWindow; +}; + +QT_END_NAMESPACE + +#endif // QCOCOAINPUTCONTEXT_H diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm new file mode 100644 index 0000000000..db3488a0f5 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used 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. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnsview.h" +#include "qcocoainputcontext.h" +#include "qcocoanativeinterface.h" +#include "qcocoaautoreleasepool.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QCocoaInputContext + \brief Cocoa Input context implementation + + Handles input of foreign characters (particularly East Asian) + languages. + + \section1 Testing + + \list + \o Select input sources like 'Kotoeri' in Language & Text Preferences + \o Compile the \a mainwindows/mdi example and open a text window. + \o In the language bar, switch to 'Hiragana'. + \o In a text editor control, type the syllable \a 'la'. + Underlined characters show up, indicating that there is completion + available. Press the Space key two times. A completion popup occurs + which shows the options. + \endlist + + \section1 Interaction + + Input method support in Cocoa uses NSTextInput protorol. Therefore + almost all functionality is implemented in QNSView. + + \ingroup qt-lighthouse-cocoa +*/ + + + +QCocoaInputContext::QCocoaInputContext() + : QPlatformInputContext() + , mWindow(QGuiApplication::focusWindow()) +{ + connect(qApp->inputMethod(), SIGNAL(inputItemChanged()), this, SLOT(inputItemChanged())); +} + +QCocoaInputContext::~QCocoaInputContext() +{ +} + +/*! + \brief Cancels a composition. +*/ + +void QCocoaInputContext::reset() +{ + QPlatformInputContext::reset(); + + if (!mWindow) return; + + QCocoaNativeInterface *nativeInterface = qobject_cast(QGuiApplication::platformNativeInterface()); + if (!nativeInterface) return; + + QNSView *view = static_cast(nativeInterface->nativeResourceForWindow("nsview", mWindow)); + if (!view) return; + + QCocoaAutoReleasePool pool; + NSInputManager *currentIManager = [NSInputManager currentInputManager]; + if (currentIManager) { + [currentIManager markedTextAbandoned:view]; + [view unmarkText]; + } +} + +void QCocoaInputContext::inputItemChanged() +{ + mWindow = QGuiApplication::focusWindow(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index bf54915365..2389fc2a55 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -89,6 +89,7 @@ public: QPlatformFontDatabase *fontDatabase() const; QPlatformNativeInterface *nativeInterface() const; + QPlatformInputContext *inputContext() const; QPlatformAccessibility *accessibility() const; QPlatformDrag *drag() const; @@ -98,6 +99,7 @@ private: QScopedPointer mFontDb; QAbstractEventDispatcher *mEventDispatcher; + QScopedPointer mInputContext; QScopedPointer mAccessibility; QScopedPointer mPlatformTheme; QList mScreens; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8411a795c1..d490495be4 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,7 @@ #include "qmenu_mac.h" #include "qcocoafiledialoghelper.h" #include "qcocoatheme.h" +#include "qcocoainputcontext.h" #include "qmacmime.h" #include @@ -90,6 +91,7 @@ QCocoaScreen::~QCocoaScreen() QCocoaIntegration::QCocoaIntegration() : mFontDb(new QCoreTextFontDatabase()) , mEventDispatcher(new QCocoaEventDispatcher()) + , mInputContext(new QCocoaInputContext) , mAccessibility(new QPlatformAccessibility) , mPlatformTheme(new QCocoaTheme) , mCocoaDrag(new QCocoaDrag) @@ -195,6 +197,11 @@ QPlatformNativeInterface *QCocoaIntegration::nativeInterface() const return new QCocoaNativeInterface(); } +QPlatformInputContext *QCocoaIntegration::inputContext() const +{ + return mInputContext.data(); +} + QPlatformAccessibility *QCocoaIntegration::accessibility() const { return mAccessibility.data(); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 7c6fb38577..d277cb2964 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -48,6 +48,7 @@ class QWidget; class QCocoaNativeInterface : public QPlatformNativeInterface { + Q_OBJECT public: void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); }; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 1a1a1cd3b9..b21e9e342f 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE class QCocoaWindow; QT_END_NAMESPACE -@interface QNSView : NSView { +@interface QNSView : NSView { CGImageRef m_cgImage; QWindow *m_window; QCocoaWindow *m_platformWindow; Qt::MouseButtons m_buttons; QAccessibleInterface *m_accessibleRoot; + QString m_composingText; + bool m_keyEventsAccepted; QStringList *currentCustomDragTypes; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9ed3332ba5..6206d53423 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -51,6 +51,7 @@ #include "qcocoadrag.h" #include +#include #include #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR @@ -94,6 +95,7 @@ static QTouchDevice *touchDevice = 0; m_window = window; m_platformWindow = platformWindow; m_accessibleRoot = 0; + m_keyEventsAccepted = false; #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR // prevent rift in space-time continuum, disable @@ -272,8 +274,15 @@ static QTouchDevice *touchDevice = 0; - (void)mouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::LeftButton; - [self handleMouseEvent:theEvent]; + if ([self hasMarkedText]) { + NSInputManager* inputManager = [NSInputManager currentInputManager]; + if ([inputManager wantsToHandleMouseEvents]) { + [inputManager handleMouseEvent:theEvent]; + } + } else { + m_buttons |= Qt::LeftButton; + [self handleMouseEvent:theEvent]; + } } - (void)mouseDragged:(NSEvent *)theEvent @@ -467,12 +476,228 @@ static QTouchDevice *touchDevice = 0; - (void)keyDown:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + QObject *fo = QGuiApplication::focusObject(); + m_keyEventsAccepted = false; + if (fo) { + QInputMethodQueryEvent queryEvent(Qt::ImHints); + if (QCoreApplication::sendEvent(fo, &queryEvent)) { + Qt::InputMethodHints hints = static_cast(queryEvent.value(Qt::ImHints).toUInt()); + if (!(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { + [self interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + } + } + } + + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + } } - (void)keyUp:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + } +} + +- (void) doCommandBySelector:(SEL)aSelector +{ + [self tryToPerform:aSelector with:self]; +} + +- (void) insertText:(id)aString +{ + QString commitString; + if ([aString length]) { + if ([aString isKindOfClass:[NSAttributedString class]]) { + commitString = QCFString::toQString(reinterpret_cast([aString string])); + } else { + commitString = QCFString::toQString(reinterpret_cast(aString)); + }; + } + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e; + e.setCommitString(commitString); + QCoreApplication::sendEvent(fo, &e); + m_keyEventsAccepted = true; + } + + m_composingText.clear(); + } + +- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange +{ + QString preeditString; + + QList attrs; + attrs<([aString string])); + int composingLength = preeditString.length(); + int index = 0; + // Create attributes for individual sections of preedit text + while (index < composingLength) { + NSRange effectiveRange; + NSRange range = NSMakeRange(index, composingLength-index); + NSDictionary *attributes = [aString attributesAtIndex:index + longestEffectiveRange:&effectiveRange + inRange:range]; + NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; + if (underlineStyle) { + QColor clr (Qt::black); + NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; + if (color) { + clr = qt_mac_toQColor(color); + } + QTextCharFormat format; + format.setFontUnderline(true); + format.setUnderlineColor(clr); + attrs<(aString)); + } + + if (attrs.isEmpty()) { + QTextCharFormat format; + format.setFontUnderline(true); + attrs<((CFStringRef)string); + return [[[NSAttributedString alloc] initWithString:const_cast(tmpString)] autorelease]; +} + +- (NSRange) markedRange +{ + NSRange range; + if (!m_composingText.isEmpty()) { + range.location = 0; + range.length = m_composingText.length(); + } else { + range.location = NSNotFound; + range.length = 0; + } + return range; +} + + +- (NSRange) selectedRange +{ + NSRange selRange = {NSNotFound, 0}; + selRange.location = NSNotFound; + selRange.length = 0; + + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return selRange; + QInputMethodQueryEvent queryEvent(Qt::ImCurrentSelection); + if (!QCoreApplication::sendEvent(fo, &queryEvent)) + return selRange; + QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); + + if (!selectedText.isEmpty()) { + selRange.location = 0; + selRange.length = selectedText.length(); + } + return selRange; +} + +- (NSRect) firstRectForCharacterRange:(NSRange)theRange +{ + Q_UNUSED(theRange); + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return NSZeroRect; + + if (!m_window) + return NSZeroRect; + + // The returned rect is always based on the internal cursor. + QRect mr = qApp->inputMethod()->cursorRectangle().toRect(); + QPoint mp = m_window->mapToGlobal(mr.bottomLeft()); + + NSRect rect; + rect.origin.x = mp.x(); + rect.origin.y = qt_mac_flipYCoordinate(mp.y()); + rect.size.width = mr.width(); + rect.size.height = mr.height(); + return rect; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint +{ + // We dont support cursor movements using mouse while composing. + Q_UNUSED(thePoint); + return NSNotFound; +} + +- (NSArray*) validAttributesForMarkedText +{ + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return nil; + + // Support only underline color/style. + return [NSArray arrayWithObjects:NSUnderlineColorAttributeName, + NSUnderlineStyleAttributeName, nil]; } -(void)registerDragTypes -- cgit v1.2.3 From 0353430806fb14b438cf7d68c68d8cdbcb57ef45 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Tue, 6 Mar 2012 22:12:18 +0000 Subject: Clean up src.pro Removing (some) stale assumptions about dependencies from src.pro file Change-Id: I713e3ad8c164321ef035e6c62b25e18e45d1d3ef Reviewed-by: Oswald Buddenhagen --- src/src.pro | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/src.pro b/src/src.pro index 21916b31f4..1c38dce6bc 100644 --- a/src/src.pro +++ b/src/src.pro @@ -62,13 +62,7 @@ src_concurrent.target = sub-concurrent src_opengl.depends = src_gui src_widgets src_sql.depends = src_corelib src_testlib.depends = src_corelib src_gui src_widgets - src_plugins.depends = src_gui src_sql src_xml - qpa: src_plugins.depends = src_platformsupport - contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2) { - src_plugins.depends += src_opengl - src_declarative.depends += src_opengl - src_webkit.depends += src_opengl - } + src_plugins.depends = src_gui src_sql src_xml src_platformsupport } -- cgit v1.2.3 From 612040a0cd702e4c764e5cbb5d0c091497650c6a Mon Sep 17 00:00:00 2001 From: Alexei Rousskikh Date: Mon, 12 Mar 2012 14:33:39 -0400 Subject: Trailing comma should result in an error during JSON parsing 1. QJsonParseError::MissingObject defined 2. QJsonDocument::fromJson() will result in defined error after parsing of something like "{ 'key':1 , }" or "[ {'key':1}, ]" Change-Id: I8e6234a03b8aca4e5ad6180f273f91066b86d7a1 Reviewed-by: Lars Knoll --- src/corelib/json/qjsondocument.h | 3 ++- src/corelib/json/qjsonparser.cpp | 7 +++++++ tests/auto/corelib/json/tst_qtjson.cpp | 13 +++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/corelib/json/qjsondocument.h b/src/corelib/json/qjsondocument.h index 7eca0302db..e39dc6a27c 100644 --- a/src/corelib/json/qjsondocument.h +++ b/src/corelib/json/qjsondocument.h @@ -67,7 +67,8 @@ struct Q_CORE_EXPORT QJsonParseError IllegalNumber, StringEscapeSequence, StringUTF8Scan, - EndOfString + EndOfString, + MissingObject }; int offset; diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp index a83685da22..b1e6a5a5c7 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/json/qjsonparser.cpp @@ -244,6 +244,10 @@ bool Parser::parseObject() if (token != ValueSeparator) break; token = nextToken(); + if (token == EndObject) { + lastError = QJsonParseError::MissingObject; + return false; + } } DEBUG << "end token=" << token; @@ -449,6 +453,9 @@ bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset) DEBUG << "value: object"; END; return true; + case EndArray: + lastError = QJsonParseError::MissingObject; + return false; default: --json; if (!parseNumber(val, baseOffset)) diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index 079ff6e76b..87820d2e78 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -120,6 +120,8 @@ private Q_SLOTS: void assignObjects(); void assignArrays(); + + void testTrailingComma(); private: QString testDataDir; }; @@ -1807,5 +1809,16 @@ void TestQtJson::assignArrays() QCOMPARE(inner.at(0).toDouble(), 2.); } +void TestQtJson::testTrailingComma() +{ + const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" }; + + for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) { + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(jsons[i], &error); + QCOMPARE(error.error, QJsonParseError::MissingObject); + } +} + QTEST_MAIN(TestQtJson) #include "tst_qtjson.moc" -- cgit v1.2.3 From 13c57d0f68cffb139311e8e22a074099eb28a88f Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 28 Feb 2012 22:42:02 +0100 Subject: QSqlTableModel::isDirty(): new overloaded method Checks if model has any changes to submit. Includes new test covering isDirty(index) as well the new overloaded function. Task-number: QTBUG-3108 Change-Id: I0ccbda45d5d9f06434cf1e1c037a9efb76d0cc37 Reviewed-by: Honglei Zhang --- dist/changes-5.0.0 | 3 + src/sql/models/qsqltablemodel.cpp | 18 +++ src/sql/models/qsqltablemodel.h | 2 + .../models/qsqltablemodel/tst_qsqltablemodel.cpp | 162 +++++++++++++++++++++ 4 files changed, 185 insertions(+) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index ba1adde6c0..80ea702b76 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -420,6 +420,9 @@ done after committing. This includes deleted rows which remain in the model as blank rows until the application calls select(). Instead, selectRow() is called to refresh only the affected row. +* QSqlTableModel::isDirty(): New overloaded method to check whether model +has any changes to submit. QTBUG-3108 + **************************************************************************** * Database Drivers * **************************************************************************** diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 5fed167070..30e01b06e7 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -468,6 +468,24 @@ QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, in return QSqlQueryModel::headerData(section, orientation, role); } +/*! + \overload + \since 5.0 + + Returns true if the model contains modified values that have not been + committed to the datase, otherwise false. +*/ +bool QSqlTableModel::isDirty() const +{ + Q_D(const QSqlTableModel); + QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin(); + const QSqlTableModelPrivate::CacheMap::ConstIterator e = d->cache.constEnd(); + for (; i != e; i++) + if (!i.value().submitted()) + return true; + return false; +} + /*! Returns true if the value at the index \a index is dirty, otherwise false. Dirty values are values that were modified in the model diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h index 13316bc4ed..62e09869c9 100644 --- a/src/sql/models/qsqltablemodel.h +++ b/src/sql/models/qsqltablemodel.h @@ -79,7 +79,9 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + bool isDirty() const; bool isDirty(const QModelIndex &index) const; + void clear(); virtual void setEditStrategy(EditStrategy strategy); diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp index 448111cd9f..7dcc109cdc 100644 --- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp @@ -95,6 +95,8 @@ private slots: void removeInsertedRow(); void removeInsertedRows_data() { generic_data(); } void removeInsertedRows(); + void isDirty_data() { generic_data_with_strategies(); } + void isDirty(); void setFilter_data() { generic_data(); } void setFilter(); void setInvalidFilter_data() { generic_data(); } @@ -956,6 +958,166 @@ void tst_QSqlTableModel::removeInsertedRows() QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); } +void tst_QSqlTableModel::isDirty() +{ + QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setEditStrategy(submitpolicy); + model.setTable(test); + QFAIL_SQL(model, isDirty()); + + model.setSort(0, Qt::AscendingOrder); + QVERIFY_SQL(model, select()); + QFAIL_SQL(model, isDirty()); + + if (submitpolicy != QSqlTableModel::OnFieldChange) { + // setData() followed by revertAll() + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setData(model.index(0, 1), QString("sam i am"))); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + model.revertAll(); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + + // setData() followed by select(), which clears changes + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setData(model.index(0, 1), QString("sam i am"))); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + } + + // setData() followed by submitAll() + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setData(model.index(0, 1), QString("sam i am"))); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + if (submitpolicy != QSqlTableModel::OnFieldChange) { + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + } + QVERIFY_SQL(model, submitAll()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + // check status after refreshing underlying query + QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + //restore original state + QVERIFY_SQL(model, setData(model.index(0, 1), QString("harry"))); + QVERIFY_SQL(model, submitAll()); + QVERIFY_SQL(model, select()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + + QSqlRecord newvals = model.record(0); + newvals.setValue(1, QString("sam i am")); + newvals.setGenerated(1, true); + if (submitpolicy != QSqlTableModel::OnFieldChange) { + // setRecord() followed by revertAll() + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setRecord(0, newvals)); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + model.revertAll(); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + + // setRecord() followed by select(), which clears changes + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setRecord(0, newvals)); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + } + + // setRecord() followed by submitAll() + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QVERIFY_SQL(model, setRecord(0, newvals)); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + if (submitpolicy != QSqlTableModel::OnFieldChange) { + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + } + QVERIFY_SQL(model, submitAll()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + // check status after refreshing underlying query + QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("sam i am")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + //restore original state + QVERIFY_SQL(model, setData(model.index(0, 1), QString("harry"))); + QVERIFY_SQL(model, submitAll()); + QVERIFY_SQL(model, select()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + + // insertRow() + QVERIFY_SQL(model, insertRow(0)); + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + model.revertAll(); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + + // removeRow() + QSqlRecord saved_rec = model.record(0); + QVERIFY_SQL(model, removeRow(0)); + if (submitpolicy == QSqlTableModel::OnManualSubmit) { + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + } + QVERIFY_SQL(model, submitAll()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + QVERIFY_SQL(model, select()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("trond")); + + // insertRecord(), put back the removed row + for (int i = saved_rec.count() - 1; i >= 0; --i) + saved_rec.setGenerated(i, true); + QVERIFY_SQL(model, insertRecord(0, saved_rec)); + if (submitpolicy == QSqlTableModel::OnManualSubmit) { + QVERIFY_SQL(model, isDirty()); + QVERIFY_SQL(model, isDirty(model.index(0, 1))); + } + QVERIFY_SQL(model, submitAll()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + QVERIFY_SQL(model, select()); + QFAIL_SQL(model, isDirty()); + QFAIL_SQL(model, isDirty(model.index(0, 1))); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); +} + void tst_QSqlTableModel::emptyTable() { QFETCH(QString, dbName); -- cgit v1.2.3 From 0850b5d76a242abe5beef05e2566957b695099a8 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 6 Mar 2012 10:39:34 +0100 Subject: Cleanup after the qsf cache file if it fails to be written to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is possible that although a qsf cache file could be opened that it could not be written to, therefore it should clean up after itself in these cases so that it does not cause a problem later on. Task-number: QTBUG-24122 Change-Id: I1999759837607657ddc3f967eeda370ce9991a16 Reviewed-by: Jørgen Lind --- src/gui/text/qfontengine_qpf.cpp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index fb898a850f..64596ebaf5 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -246,16 +246,32 @@ QList QFontEngineQPF::cleanUpAfterClientCrash(const QList &cras int fd = QT_OPEN(fileName.constData(), O_RDONLY, 0); if (fd >= 0) { - void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0); - if (header && header != MAP_FAILED) { - quint32 lockValue = reinterpret_cast(header)->lock; + QT_STATBUF st; + int nDataSize = 0; + if (QT_FSTAT(fd, &st)) { +#if defined(DEBUG_FONTENGINE) + qDebug() << "stat failed! " << fileName; +#endif + } else { + nDataSize = st.st_size; + } - if (lockValue && crashedClientIds.contains(lockValue)) { - removedFonts.append(fileName); - QFile::remove(QFile::decodeName(fileName)); - } + if (nDataSize >= (int)sizeof(QFontEngineQPF::Header)) { + void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0); + if (header && header != MAP_FAILED) { + quint32 lockValue = reinterpret_cast(header)->lock; - ::munmap(header, sizeof(QFontEngineQPF::Header)); + if (lockValue && crashedClientIds.contains(lockValue)) { + removedFonts.append(fileName); + QFile::remove(QFile::decodeName(fileName)); + } + + ::munmap(header, sizeof(QFontEngineQPF::Header)); + } + } else { +#if defined(DEBUG_FONTENGINE) + qDebug() << "Unsufficient header data in QSF file " << fileName; +#endif } QT_CLOSE(fd); } @@ -363,6 +379,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng #if defined(DEBUG_FONTENGINE) qErrnoWarning(errno, "QFontEngineQPF: write() failed for %s", encodedName.constData()); #endif + QFile::remove(fileName); return; } } else { -- cgit v1.2.3 From 3e45d4824611b07835aa7a816d0aee3f5c49e87e Mon Sep 17 00:00:00 2001 From: Balazs Kelemen Date: Thu, 8 Mar 2012 17:02:15 +0100 Subject: Fix QFont hinting preference with fontconfig Consider if the hinting preference of the QFont is not PreferDefaultHinting. Change-Id: I0f50b320356787b6c1eabee5f009e7d326a06925 Reviewed-by: Jiang Jiang --- .../fontconfig/qfontconfigdatabase.cpp | 49 ++++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 69ec3ba08a..28a99cfd17 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -515,24 +515,37 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: FcCharSet *charset; if (match) { QFontEngineFT::HintStyle default_hint_style; - - //hinting - int hint_style = 0; - if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) - hint_style = QFontEngineFT::HintFull; - switch (hint_style) { - case FC_HINT_NONE: - default_hint_style = QFontEngineFT::HintNone; - break; - case FC_HINT_SLIGHT: - default_hint_style = QFontEngineFT::HintLight; - break; - case FC_HINT_MEDIUM: - default_hint_style = QFontEngineFT::HintMedium; - break; - default: - default_hint_style = QFontEngineFT::HintFull; - break; + if (f.hintingPreference != QFont::PreferDefaultHinting) { + switch (f.hintingPreference) { + case QFont::PreferNoHinting: + default_hint_style = QFontEngineFT::HintNone; + break; + case QFont::PreferVerticalHinting: + default_hint_style = QFontEngineFT::HintLight; + break; + case QFont::PreferFullHinting: + default: + default_hint_style = QFontEngineFT::HintFull; + break; + } + } else { + int hint_style = 0; + if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) + hint_style = QFontEngineFT::HintFull; + switch (hint_style) { + case FC_HINT_NONE: + default_hint_style = QFontEngineFT::HintNone; + break; + case FC_HINT_SLIGHT: + default_hint_style = QFontEngineFT::HintLight; + break; + case FC_HINT_MEDIUM: + default_hint_style = QFontEngineFT::HintMedium; + break; + default: + default_hint_style = QFontEngineFT::HintFull; + break; + } } engine->setDefaultHintStyle(default_hint_style); -- cgit v1.2.3 From 703b4a0e20b2eae982ea48e075db480da9851a9a Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Tue, 13 Mar 2012 13:12:09 +1000 Subject: Move variant animation interpolators from QtWidgets to QtGui There is no reason these interpolators need to stay in QtWidgets library. Change-Id: I27db49fea2cfd8f0ef417dc52edf66dd1835e7a1 Reviewed-by: Michael Brasser Reviewed-by: Martin Jones --- src/gui/animation/animation.pri | 2 + src/gui/animation/qguivariantanimation.cpp | 95 ++++++++++++++++++++++++++ src/gui/gui.pro | 3 +- src/widgets/animation/animation.pri | 3 - src/widgets/animation/qguivariantanimation.cpp | 95 -------------------------- src/widgets/widgets.pro | 1 - 6 files changed, 99 insertions(+), 100 deletions(-) create mode 100644 src/gui/animation/animation.pri create mode 100644 src/gui/animation/qguivariantanimation.cpp delete mode 100644 src/widgets/animation/animation.pri delete mode 100644 src/widgets/animation/qguivariantanimation.cpp diff --git a/src/gui/animation/animation.pri b/src/gui/animation/animation.pri new file mode 100644 index 0000000000..add9ae7119 --- /dev/null +++ b/src/gui/animation/animation.pri @@ -0,0 +1,2 @@ +SOURCES += \ + animation/qguivariantanimation.cpp diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp new file mode 100644 index 0000000000..c344a18b8a --- /dev/null +++ b/src/gui/animation/qguivariantanimation.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used 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. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include + +#ifndef QT_NO_ANIMATION + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress) +{ + return QColor(qBound(0,_q_interpolate(f.red(), t.red(), progress),255), + qBound(0,_q_interpolate(f.green(), t.green(), progress),255), + qBound(0,_q_interpolate(f.blue(), t.blue(), progress),255), + qBound(0,_q_interpolate(f.alpha(), t.alpha(), progress),255)); +} + +template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress) +{ + return QQuaternion::slerp(f, t, progress); +} + +static void qRegisterGuiGetInterpolator() +{ + qRegisterAnimationInterpolator(_q_interpolateVariant); + qRegisterAnimationInterpolator(_q_interpolateVariant); + qRegisterAnimationInterpolator(_q_interpolateVariant); + qRegisterAnimationInterpolator(_q_interpolateVariant); + qRegisterAnimationInterpolator(_q_interpolateVariant); +} +Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator) + +static void qUnregisterGuiGetInterpolator() +{ + // casts required by Sun CC 5.5 + qRegisterAnimationInterpolator( + (QVariant (*)(const QColor &, const QColor &, qreal))0); + qRegisterAnimationInterpolator( + (QVariant (*)(const QVector2D &, const QVector2D &, qreal))0); + qRegisterAnimationInterpolator( + (QVariant (*)(const QVector3D &, const QVector3D &, qreal))0); + qRegisterAnimationInterpolator( + (QVariant (*)(const QVector4D &, const QVector4D &, qreal))0); + qRegisterAnimationInterpolator( + (QVariant (*)(const QQuaternion &, const QQuaternion &, qreal))0); +} +Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator) + +QT_END_NAMESPACE + +#endif //QT_NO_ANIMATION diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 2cee31fce1..e6a820b5c4 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -31,6 +31,7 @@ include(painting/painting.pri) include(util/util.pri) include(math3d/math3d.pri) include(opengl/opengl.pri) +include(animation/animation.pri) QMAKE_LIBS += $$QMAKE_LIBS_GUI @@ -150,4 +151,4 @@ win32:!contains(QT_CONFIG, directwrite) { sse2: SOURCES += $$SSE2_SOURCES ssse3: SOURCES += $$SSSE3_SOURCES iwmmxt: SOURCES += $$IWMMXT_SOURCES - } + } \ No newline at end of file diff --git a/src/widgets/animation/animation.pri b/src/widgets/animation/animation.pri deleted file mode 100644 index 27763ca003..0000000000 --- a/src/widgets/animation/animation.pri +++ /dev/null @@ -1,3 +0,0 @@ -# Qt gui animation module - -SOURCES += animation/qguivariantanimation.cpp diff --git a/src/widgets/animation/qguivariantanimation.cpp b/src/widgets/animation/qguivariantanimation.cpp deleted file mode 100644 index c344a18b8a..0000000000 --- a/src/widgets/animation/qguivariantanimation.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used 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. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include -#include - -#ifndef QT_NO_ANIMATION - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress) -{ - return QColor(qBound(0,_q_interpolate(f.red(), t.red(), progress),255), - qBound(0,_q_interpolate(f.green(), t.green(), progress),255), - qBound(0,_q_interpolate(f.blue(), t.blue(), progress),255), - qBound(0,_q_interpolate(f.alpha(), t.alpha(), progress),255)); -} - -template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress) -{ - return QQuaternion::slerp(f, t, progress); -} - -static void qRegisterGuiGetInterpolator() -{ - qRegisterAnimationInterpolator(_q_interpolateVariant); - qRegisterAnimationInterpolator(_q_interpolateVariant); - qRegisterAnimationInterpolator(_q_interpolateVariant); - qRegisterAnimationInterpolator(_q_interpolateVariant); - qRegisterAnimationInterpolator(_q_interpolateVariant); -} -Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator) - -static void qUnregisterGuiGetInterpolator() -{ - // casts required by Sun CC 5.5 - qRegisterAnimationInterpolator( - (QVariant (*)(const QColor &, const QColor &, qreal))0); - qRegisterAnimationInterpolator( - (QVariant (*)(const QVector2D &, const QVector2D &, qreal))0); - qRegisterAnimationInterpolator( - (QVariant (*)(const QVector3D &, const QVector3D &, qreal))0); - qRegisterAnimationInterpolator( - (QVariant (*)(const QVector4D &, const QVector4D &, qreal))0); - qRegisterAnimationInterpolator( - (QVariant (*)(const QQuaternion &, const QQuaternion &, qreal))0); -} -Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator) - -QT_END_NAMESPACE - -#endif //QT_NO_ANIMATION diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro index 8f6a9713f6..596e8a994a 100644 --- a/src/widgets/widgets.pro +++ b/src/widgets/widgets.pro @@ -25,7 +25,6 @@ mac:include(kernel/mac.pri) win32:include(kernel/win.pri) #modules -include(animation/animation.pri) include(kernel/kernel.pri) include(styles/styles.pri) include(widgets/widgets.pri) -- cgit v1.2.3 From 0bb95b183b28208a9ecf88e25cc22b8086201a2b Mon Sep 17 00:00:00 2001 From: Rick Stockton Date: Thu, 8 Mar 2012 14:33:15 -0800 Subject: Cocoa platform plugin: Add support for up to 16 mouse buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OS-X provides a buttonNumber within Event data for otherMouseDown: and otherMouseUp: Events. Instead of mapping all occurences of these event types to Qt::MiddleButton, this Update uses that data to support a total of 16 mouse buttons. Task-number: QTBUG-24702 Change-Id: I3cffb32498f98ea182509d7c42f3fc6634155ebb Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 96 +++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 6206d53423..4ab5e32a8e 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -336,7 +336,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::RightButton; + switch ([theEvent buttonNumber]) { + case 3: + m_buttons |= Qt::MiddleButton; + break; + case 4: + m_buttons |= Qt::ExtraButton1; // AKA Qt::BackButton + break; + case 5: + m_buttons |= Qt::ExtraButton2; // AKA Qt::ForwardButton + break; + case 6: + m_buttons |= Qt::ExtraButton3; + break; + case 7: + m_buttons |= Qt::ExtraButton4; + break; + case 8: + m_buttons |= Qt::ExtraButton5; + break; + case 9: + m_buttons |= Qt::ExtraButton6; + break; + case 10: + m_buttons |= Qt::ExtraButton7; + break; + case 11: + m_buttons |= Qt::ExtraButton8; + break; + case 12: + m_buttons |= Qt::ExtraButton9; + break; + case 13: + m_buttons |= Qt::ExtraButton10; + break; + case 14: + m_buttons |= Qt::ExtraButton11; + break; + case 15: + m_buttons |= Qt::ExtraButton12; + break; + case 16: + m_buttons |= Qt::ExtraButton13; + break; + default: + m_buttons |= Qt::MiddleButton; + break; + } [self handleMouseEvent:theEvent]; } @@ -349,7 +395,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseUp:(NSEvent *)theEvent { - m_buttons &= QFlag(~int(Qt::MiddleButton)); + switch ([theEvent buttonNumber]) { + case 3: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + case 4: + m_buttons &= QFlag(~int(Qt::ExtraButton1)); // AKA Qt::BackButton + break; + case 5: + m_buttons &= QFlag(~int(Qt::ExtraButton2)); // AKA Qt::ForwardButton + break; + case 6: + m_buttons &= QFlag(~int(Qt::ExtraButton3)); + break; + case 7: + m_buttons &= QFlag(~int(Qt::ExtraButton4)); + break; + case 8: + m_buttons &= QFlag(~int(Qt::ExtraButton5)); + break; + case 9: + m_buttons &= QFlag(~int(Qt::ExtraButton6)); + break; + case 10: + m_buttons &= QFlag(~int(Qt::ExtraButton7)); + break; + case 11: + m_buttons &= QFlag(~int(Qt::ExtraButton8)); + break; + case 12: + m_buttons &= QFlag(~int(Qt::ExtraButton9)); + break; + case 13: + m_buttons &= QFlag(~int(Qt::ExtraButton10)); + break; + case 14: + m_buttons &= QFlag(~int(Qt::ExtraButton11)); + break; + case 15: + m_buttons &= QFlag(~int(Qt::ExtraButton12)); + break; + case 16: + m_buttons &= QFlag(~int(Qt::ExtraButton13)); + break; + default: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + } [self handleMouseEvent:theEvent]; } -- cgit v1.2.3 From 6694181bb78433284c9c12ab4096782e755c3473 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Mon, 12 Mar 2012 22:40:31 +0100 Subject: qdoc: Update to prepare to run on a directory. This change sets some default file extensions to accept to generate documentation. It also removes support for the sourceModules qdocconf variable which is not used anymore. It was used just after modularization. Change-Id: Iabdcfb534dc662bd44e0928036fd68ee4e460b07 Reviewed-by: Martin Smith --- src/tools/qdoc/config.h | 1 - src/tools/qdoc/main.cpp | 23 ++--------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h index 461e0b969c..6a89684e79 100644 --- a/src/tools/qdoc/config.h +++ b/src/tools/qdoc/config.h @@ -171,7 +171,6 @@ private: #define CONFIG_SHOWINTERNAL "showinternal" #define CONFIG_SOURCEDIRS "sourcedirs" #define CONFIG_SOURCEENCODING "sourceencoding" -#define CONFIG_SOURCEMODULES "sourcemodules" #define CONFIG_SOURCES "sources" #define CONFIG_SPURIOUS "spurious" #define CONFIG_STYLEDIRS "styledirs" diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index 11a54b4d38..85e97cdec9 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -76,6 +76,7 @@ QT_BEGIN_NAMESPACE /* The default indent for code is 4. The default value for false is 0. + The default supported file extensions are cpp, h, qdoc and qml. The default language is c++. The default output format is html. The default tab size is 8. @@ -87,6 +88,7 @@ static const struct { } defaults[] = { { CONFIG_CODEINDENT, "4" }, { CONFIG_FALSEHOODS, "0" }, + { CONFIG_FILEEXTENSIONS, "*.cpp *.h *.qdoc *.qml"}, { CONFIG_LANGUAGE, "Cpp" }, { CONFIG_OUTPUTFORMATS, "HTML" }, { CONFIG_TABSIZE, "8" }, @@ -173,27 +175,6 @@ static void processQdocconfFile(const QString &fileName) Location::initialize(config); config.load(fileName); - QStringList sourceModules; - sourceModules = config.getStringList(CONFIG_SOURCEMODULES); - Location sourceModulesLocation = config.lastLocation(); - - if (!sourceModules.isEmpty()) { - Location::information(tr("qdoc will generate documentation for the modules found in the sourcemodules variable.")); - foreach (const QString& sourceModule, sourceModules) { - QString qdocconf = sourceModule; - if (!qdocconf.endsWith(".qdocconf")) - qdocconf += "/doc/config/module.qdocconf"; - QFile f(qdocconf); - if (!f.exists()) { - sourceModulesLocation.warning(tr("Can't find module's qdoc config file '%1'").arg(qdocconf)); - } - else { - Location::information(tr(" Including: %1").arg(qdocconf)); - config.load(qdocconf); - } - } - } - /* Add the defines to the configuration variables. */ -- cgit v1.2.3 From 1de1a50603a50fde4b9ac0400a66f54ff4a0cbb1 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Mon, 12 Mar 2012 21:14:37 +0100 Subject: take opportunity to use const Change-Id: Ief12d4b55e1705c758dae8078cf52948fcd9565b Reviewed-by: Richard J. Moore --- src/widgets/styles/qstylesheetstyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 7a0cc09452..c909def969 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -2505,7 +2505,7 @@ void QStyleSheetStyle::setProperties(QWidget *w) // properties in the order they are specified. QHash propertyHash; QVector properties; - QVector decls = declarations(styleRules(w), QString()); + const QVector decls = declarations(styleRules(w), QString()); // run through the declarations in order for (int i = 0; i < decls.count(); i++) { @@ -2521,7 +2521,7 @@ void QStyleSheetStyle::setProperties(QWidget *w) qWarning() << w << " does not have a property named " << property; continue; } - QMetaProperty metaProperty = metaObject->property(index); + const QMetaProperty metaProperty = metaObject->property(index); if (!metaProperty.isWritable() || !metaProperty.isDesignable()) { qWarning() << w << " cannot design property named " << property; continue; -- cgit v1.2.3 From 8be558e99d69fbfda495882e1bda1c64585485a6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Mar 2012 08:57:15 +0100 Subject: Fix icon suffixes in systray example. Change-Id: If464befa88f26a881557724b4fc175f0a82c90b6 Reviewed-by: Friedemann Kleint --- examples/desktop/systray/window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/desktop/systray/window.cpp b/examples/desktop/systray/window.cpp index 73dc910d3b..c75e3590ba 100644 --- a/examples/desktop/systray/window.cpp +++ b/examples/desktop/systray/window.cpp @@ -167,9 +167,9 @@ void Window::createIconGroupBox() iconLabel = new QLabel("Icon:"); iconComboBox = new QComboBox; - iconComboBox->addItem(QIcon(":/images/bad.svg"), tr("Bad")); - iconComboBox->addItem(QIcon(":/images/heart.svg"), tr("Heart")); - iconComboBox->addItem(QIcon(":/images/trash.svg"), tr("Trash")); + iconComboBox->addItem(QIcon(":/images/bad.png"), tr("Bad")); + iconComboBox->addItem(QIcon(":/images/heart.png"), tr("Heart")); + iconComboBox->addItem(QIcon(":/images/trash.png"), tr("Trash")); showIconCheckBox = new QCheckBox(tr("Show icon")); showIconCheckBox->setChecked(true); -- cgit v1.2.3 From c68737add39360040e5b0cd93f01f229d6a8bbc9 Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Thu, 1 Mar 2012 10:36:38 +0100 Subject: QNam: only init channels when needed. Each channel will create a socket that will allocate memory for the read and write buffers. This change will instead initialize channels only when they are needed. Change-Id: I112b4c7b944a7dd345414f06260c92803394eaed Reviewed-by: Shane Kearns --- src/network/access/qhttpnetworkconnection.cpp | 108 ++++++++++++--------- .../access/qhttpnetworkconnectionchannel.cpp | 67 ++++++++++++- .../access/qhttpnetworkconnectionchannel_p.h | 11 +++ 3 files changed, 139 insertions(+), 47 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 6aa3a5a5f4..95b81c437d 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -123,8 +123,8 @@ void QHttpNetworkConnectionPrivate::init() //push session down to channels channels[i].networkSession = networkSession; #endif - channels[i].init(); } + delayedConnectionTimer.setSingleShot(true); QObject::connect(&delayedConnectionTimer, SIGNAL(timeout()), q, SLOT(_q_connectDelayedChannel())); } @@ -135,12 +135,14 @@ void QHttpNetworkConnectionPrivate::pauseConnection() // Disable all socket notifiers for (int i = 0; i < channelCount; i++) { + if (channels[i].socket) { #ifndef QT_NO_SSL - if (encrypt) - QSslSocketPrivate::pauseSocketNotifiers(static_cast(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::pauseSocketNotifiers(static_cast(channels[i].socket)); + else #endif - QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket); + QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket); + } } } @@ -149,16 +151,18 @@ void QHttpNetworkConnectionPrivate::resumeConnection() state = RunningState; // Enable all socket notifiers for (int i = 0; i < channelCount; i++) { + if (channels[i].socket) { #ifndef QT_NO_SSL - if (encrypt) - QSslSocketPrivate::resumeSocketNotifiers(static_cast(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::resumeSocketNotifiers(static_cast(channels[i].socket)); + else #endif - QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket); + QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket); - // Resume pending upload if needed - if (channels[i].state == QHttpNetworkConnectionChannel::WritingState) - QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection); + // Resume pending upload if needed + if (channels[i].state == QHttpNetworkConnectionChannel::WritingState) + QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection); + } } // queue _q_startNextRequest @@ -346,11 +350,15 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, QNetworkReply::NetworkError errorCode) { Q_Q(QHttpNetworkConnection); - if (socket && reply) { + + int i = 0; + if (socket) + i = indexOf(socket); + + if (reply) { // this error matters only to this reply reply->d_func()->errorString = errorDetail(errorCode, socket); emit reply->finishedWithError(errorCode, reply->d_func()->errorString); - int i = indexOf(socket); // remove the corrupt data if any reply->d_func()->eraseData(); @@ -358,7 +366,8 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, channels[i].close(); channels[i].reply = 0; channels[i].request = QHttpNetworkRequest(); - channels[i].requeueCurrentlyPipelinedRequests(); + if (socket) + channels[i].requeueCurrentlyPipelinedRequests(); // send the next request QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); @@ -582,9 +591,9 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket) { - Q_ASSERT(socket); - - int i = indexOf(socket); + int i = 0; + if (socket) + i = indexOf(socket); if (!highPriorityQueue.isEmpty()) { // remove from queue before sendRequest! else we might pipeline the same request again @@ -740,15 +749,15 @@ bool QHttpNetworkConnectionPrivate::fillPipeline(QList &queue, } -QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket, - const QString &extraDetail) +QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket, const QString &extraDetail) { - Q_ASSERT(socket); - QString errorString; switch (errorCode) { case QNetworkReply::HostNotFoundError: - errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName()); + if (socket) + errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName()); + else + errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(hostName); break; case QNetworkReply::ConnectionRefusedError: errorString = QCoreApplication::translate("QHttp", "Connection refused"); @@ -891,9 +900,11 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() return; // try to get a free AND connected socket for (int i = 0; i < channelCount; ++i) { - if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { - if (dequeueRequest(channels[i].socket)) - channels[i].sendRequest(); + if (channels[i].socket) { + if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { + if (dequeueRequest(channels[i].socket)) + channels[i].sendRequest(); + } } } @@ -908,7 +919,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) return; for (int i = 0; i < channelCount; i++) - if (channels[i].socket->state() == QAbstractSocket::ConnectedState) + if (channels[i].socket && channels[i].socket->state() == QAbstractSocket::ConnectedState) fillPipeline(channels[i].socket); // If there is not already any connected channels we need to connect a new one. @@ -916,11 +927,19 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() // connected or not. This is to reuse connected channels before we connect new once. int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count(); for (int i = 0; i < channelCount; ++i) { - if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState)) - queuedRequest--; - if ( queuedRequest <=0 ) - break; - if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) { + bool connectChannel = false; + if (channels[i].socket) { + if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState)) + queuedRequest--; + if ( queuedRequest <=0 ) + break; + if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) + connectChannel = true; + } else { // not previously used channel + connectChannel = true; + } + + if (connectChannel) { if (networkLayerState == IPv4) channels[i].networkLayerPreference = QAbstractSocket::IPv4Protocol; else if (networkLayerState == IPv6) @@ -928,6 +947,9 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() channels[i].ensureConnection(); queuedRequest--; } + + if ( queuedRequest <=0 ) + break; } } @@ -958,8 +980,8 @@ void QHttpNetworkConnectionPrivate::startHostInfoLookup() #ifndef QT_NO_NETWORKPROXY if (networkProxy.capabilities() & QNetworkProxy::HostNameLookupCapability) { lookupHost = networkProxy.hostName(); - } else if (channels[0].socket->proxy().capabilities() & QNetworkProxy::HostNameLookupCapability) { - lookupHost = channels[0].socket->proxy().hostName(); + } else if (channels[0].proxy.capabilities() & QNetworkProxy::HostNameLookupCapability) { + lookupHost = channels[0].proxy.hostName(); } #endif QHostAddress temp; @@ -1169,13 +1191,13 @@ void QHttpNetworkConnection::setTransparentProxy(const QNetworkProxy &networkPro { Q_D(QHttpNetworkConnection); for (int i = 0; i < d->channelCount; ++i) - d->channels[i].socket->setProxy(networkProxy); + d->channels[i].setProxy(networkProxy); } QNetworkProxy QHttpNetworkConnection::transparentProxy() const { Q_D(const QHttpNetworkConnection); - return d->channels[0].socket->proxy(); + return d->channels[0].proxy; } #endif @@ -1190,7 +1212,7 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config // set the config on all channels for (int i = 0; i < d->channelCount; ++i) - static_cast(d->channels[i].socket)->setSslConfiguration(config); + d->channels[i].setSslConfiguration(config); } void QHttpNetworkConnection::ignoreSslErrors(int channel) @@ -1201,13 +1223,11 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel) if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { - static_cast(d->channels[i].socket)->ignoreSslErrors(); - d->channels[i].ignoreAllSslErrors = true; + d->channels[i].ignoreSslErrors(); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(); - d->channels[channel].ignoreAllSslErrors = true; + d->channels[channel].ignoreSslErrors(); } } @@ -1219,13 +1239,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList &errors, int if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { - static_cast(d->channels[i].socket)->ignoreSslErrors(errors); - d->channels[i].ignoreSslErrorsList = errors; + d->channels[i].ignoreSslErrors(errors); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(errors); - d->channels[channel].ignoreSslErrorsList = errors; + d->channels[channel].ignoreSslErrors(errors); } } diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 3991bffa47..a009222bd5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) , ssl(false) + , isInitialized(false) , state(IdleState) , reply(0) , written(0) @@ -152,19 +153,38 @@ void QHttpNetworkConnectionChannel::init() QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), this, SLOT(_q_encryptedBytesWritten(qint64)), Qt::DirectConnection); + + if (ignoreAllSslErrors) + sslSocket->ignoreSslErrors(); + + if (!ignoreSslErrorsList.isEmpty()) + sslSocket->ignoreSslErrors(ignoreSslErrorsList); + + if (!sslConfiguration.isNull()) + sslSocket->setSslConfiguration(sslConfiguration); } + #endif + +#ifndef QT_NO_NETWORKPROXY + if (proxy.type() != QNetworkProxy::NoProxy) + socket->setProxy(proxy); +#endif + isInitialized = true; } void QHttpNetworkConnectionChannel::close() { - if (socket->state() == QAbstractSocket::UnconnectedState) + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) state = QHttpNetworkConnectionChannel::IdleState; else state = QHttpNetworkConnectionChannel::ClosingState; - socket->close(); + if (socket) + socket->close(); } @@ -527,6 +547,9 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF() bool QHttpNetworkConnectionChannel::ensureConnection() { + if (!isInitialized) + init(); + QAbstractSocket::SocketState socketState = socket->state(); // resend this request after we receive the disconnected signal @@ -835,6 +858,46 @@ bool QHttpNetworkConnectionChannel::resetUploadData() } } +#ifndef QT_NO_NETWORKPROXY + +void QHttpNetworkConnectionChannel::setProxy(const QNetworkProxy &networkProxy) +{ + if (socket) + socket->setProxy(networkProxy); + + proxy = networkProxy; +} + +#endif + +#ifndef QT_NO_SSL + +void QHttpNetworkConnectionChannel::ignoreSslErrors() +{ + if (socket) + static_cast(socket)->ignoreSslErrors(); + + ignoreAllSslErrors = true; +} + + +void QHttpNetworkConnectionChannel::ignoreSslErrors(const QList &errors) +{ + if (socket) + static_cast(socket)->ignoreSslErrors(errors); + + ignoreSslErrorsList = errors; +} + +void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration &config) +{ + if (socket) + static_cast(socket)->setSslConfiguration(config); + + sslConfiguration = config; +} + +#endif void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 7da9b514d6..2648cba2a5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -72,6 +72,7 @@ #ifndef QT_NO_SSL # include # include +# include #else # include #endif @@ -100,6 +101,7 @@ public: }; QAbstractSocket *socket; bool ssl; + bool isInitialized; ChannelState state; QHttpNetworkRequest request; // current request QHttpNetworkReply *reply; // current reply for this request @@ -118,6 +120,10 @@ public: #ifndef QT_NO_SSL bool ignoreAllSslErrors; QList ignoreSslErrorsList; + QSslConfiguration sslConfiguration; + void ignoreSslErrors(); + void ignoreSslErrors(const QList &errors); + void setSslConfiguration(const QSslConfiguration &config); #endif #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession; @@ -144,6 +150,11 @@ public: void setConnection(QHttpNetworkConnection *c); QPointer connection; +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy proxy; + void setProxy(const QNetworkProxy &networkProxy); +#endif + void init(); void close(); -- cgit v1.2.3 From 76ddc9bc0c14b01e2e3c760cade5265da4f4a5c1 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 7 Mar 2012 19:09:33 +0100 Subject: Autotest details of QAccessibleEvent. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ieec33c23e7b18cfedf061088d6561203a5e7ac39 Reviewed-by: Jan-Arve Sæther --- src/testlib/qtestaccessible.h | 23 +++++++++---- .../other/qaccessibility/tst_qaccessibility.cpp | 39 +++++++++++++--------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index f9b1b97ac6..048e048789 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE class QObject; -typedef QList EventList; +// Use pointers since we subclass QAccessibleEvent +typedef QList EventList; bool operator==(const QAccessibleEvent &l, const QAccessibleEvent &r) { @@ -100,8 +101,18 @@ public: static bool verifyEvent(const QAccessibleEvent& ev) { if (eventList().isEmpty()) - return FALSE; - return eventList().takeFirst() == ev; + return false; + QAccessibleEvent *first = eventList().takeFirst(); + bool res = *first == ev; + delete first; + return res; + } + static bool containsEvent(const QAccessibleEvent &event) { + Q_FOREACH (QAccessibleEvent *ev, eventList()) { + if (*ev == event) + return true; + } + return false; } private: @@ -134,12 +145,12 @@ private: eventList().append(copyEvent(event)); } - static QAccessibleEvent copyEvent(const QAccessibleEvent &event) + static QAccessibleEvent *copyEvent(const QAccessibleEvent &event) { if (event.type() == QAccessible::StateChanged) - return QAccessibleStateChangeEvent(static_cast(&event)->changedStates(), + return new QAccessibleStateChangeEvent(static_cast(&event)->changedStates(), event.object(), event.child()); - return QAccessibleEvent(event.type(), event.object(), event.child()); + return new QAccessibleEvent(event.type(), event.object(), event.child()); } static EventList &eventList() diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 0edda96f2a..24469c74d0 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -403,8 +403,8 @@ void tst_QAccessibility::cleanup() qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(), QString(QTest::currentTestFunction()).toAscii().constData()); for (int i = 0; i < list.count(); ++i) - qWarning(" %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i).object(), - eventName(list.at(i).type()).toAscii().constData(), list.at(i).child()); + qWarning(" %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i)->object(), + eventName(list.at(i)->type()).toAscii().constData(), list.at(i)->child()); } QTestAccessibility::clearEvents(); } @@ -730,16 +730,16 @@ void tst_QAccessibility::hideShowTest() window->show(); QVERIFY(!state(window).invisible); QVERIFY(!state(child).invisible); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectShow, window))); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectShow, child))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectShow, window))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectShow, child))); QTestAccessibility::clearEvents(); // hide() and veryfy that both window and child are invisible and get ObjectHide events. window->hide(); QVERIFY(state(window).invisible); QVERIFY(state(child).invisible); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectHide, window))); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectHide, child))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectHide, window))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectHide, child))); QTestAccessibility::clearEvents(); delete window; @@ -963,6 +963,9 @@ void tst_QAccessibility::buttonTest() delete menu; } + + QTestAccessibility::clearEvents(); + { // test check box interface = QAccessible::queryAccessibleInterface(&checkBox); actionInterface = interface->actionInterface(); @@ -970,11 +973,16 @@ void tst_QAccessibility::buttonTest() QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QVERIFY(!interface->state().checked); actionInterface->doAction(QAccessibleActionInterface::checkAction()); + QTest::qWait(500); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction()); QVERIFY(interface->state().checked); QVERIFY(checkBox.isChecked()); + QAccessible::State st; + st.checked = true; + QVERIFY_EVENT(QAccessibleStateChangeEvent(st, &checkBox)); delete interface; + } // test radiobutton interface = QAccessible::queryAccessibleInterface(&radio); @@ -1050,12 +1058,12 @@ void tst_QAccessibility::scrollBarTest() scrollBar->resize(200, 50); scrollBar->show(); QVERIFY(!scrollBarInterface->state().invisible); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectShow, scrollBar))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectShow, scrollBar))); QTestAccessibility::clearEvents(); scrollBar->hide(); QVERIFY(scrollBarInterface->state().invisible); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::ObjectHide, scrollBar))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::ObjectHide, scrollBar))); QTestAccessibility::clearEvents(); // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum. @@ -1495,9 +1503,8 @@ void tst_QAccessibility::spinBoxTest() QTestAccessibility::clearEvents(); QTest::keyPress(spinBox, Qt::Key_Up); QTest::qWait(200); - EventList events = QTestAccessibility::events(); QAccessibleEvent expectedEvent(QAccessible::ValueChanged, spinBox); - QVERIFY(events.contains(expectedEvent)); + QVERIFY(QTestAccessibility::containsEvent(expectedEvent)); delete spinBox; QTestAccessibility::clearEvents(); } @@ -1767,7 +1774,7 @@ void tst_QAccessibility::lineEditTest() le->setFocus(Qt::TabFocusReason); QTestAccessibility::clearEvents(); le2->setFocus(Qt::TabFocusReason); - QTRY_VERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::Focus, le2))); + QTRY_VERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::Focus, le2))); le->setText(QLatin1String("500")); le->setValidator(new QIntValidator()); @@ -1787,7 +1794,7 @@ void tst_QAccessibility::lineEditTest() le3->deselect(); le3->setCursorPosition(3); QCOMPARE(textIface->cursorPosition(), 3); - QTRY_VERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::TextCaretMoved, le3))); + QTRY_VERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::TextCaretMoved, le3))); QCOMPARE(textIface->selectionCount(), 0); QTestAccessibility::clearEvents(); @@ -2158,11 +2165,11 @@ void tst_QAccessibility::listTest() // Check for events QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center()); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::Selection, listView, 2))); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::Focus, listView, 2))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::Selection, listView, 2))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::Focus, listView, 2))); QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center()); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::Selection, listView, 3))); - QVERIFY(QTestAccessibility::events().contains(QAccessibleEvent(QAccessible::Focus, listView, 3))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::Selection, listView, 3))); + QVERIFY(QTestAccessibility::containsEvent(QAccessibleEvent(QAccessible::Focus, listView, 3))); listView->addItem("Munich"); QCOMPARE(iface->childCount(), 4); -- cgit v1.2.3 From 6d85d77a5def22ef8a50505f3c7634146db73421 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 7 Mar 2012 19:38:39 +0100 Subject: Clean up test, check radio button and checkbox. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4dcfa2014256aee10feb08146ae6fc3f402ac8fb Reviewed-by: Jan-Arve Sæther --- tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 24469c74d0..3cd7d7c211 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -981,9 +981,12 @@ void tst_QAccessibility::buttonTest() QAccessible::State st; st.checked = true; QVERIFY_EVENT(QAccessibleStateChangeEvent(st, &checkBox)); + checkBox.setChecked(false); + QVERIFY_EVENT(QAccessibleStateChangeEvent(st, &checkBox)); delete interface; } + { // test radiobutton interface = QAccessible::queryAccessibleInterface(&radio); actionInterface = interface->actionInterface(); @@ -994,8 +997,12 @@ void tst_QAccessibility::buttonTest() QTest::qWait(500); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QVERIFY(interface->state().checked); - QVERIFY(checkBox.isChecked()); + QVERIFY(radio.isChecked()); + QAccessible::State st; + st.checked = true; + QVERIFY_EVENT(QAccessibleStateChangeEvent(st, &radio)); delete interface; + } // // test standard toolbutton // QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test)); @@ -1045,8 +1052,6 @@ void tst_QAccessibility::buttonTest() // QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open")); // QCOMPARE(test->state(2), (int)QAccessible::HasPopup); // test->release(); - - QTestAccessibility::clearEvents(); } void tst_QAccessibility::scrollBarTest() -- cgit v1.2.3 From ba6952b28d17b6b34f65510be645e414fa1ef6a2 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 14 Feb 2012 10:01:17 +0100 Subject: Remove -arch argument and #define QT_ARCH from configures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not try to detect the host or target architectures using uname or similar, and do not override with the -arch or -host-arch configure arguments. The configures will still accept the -arch and -host-arch arguments, but it ignores them and instead outputs a warning stating that these arguments are obsolete and should not be used. Set QT_ARCH and QT_HOST_ARCH qconfig.pri variables based on the compiler target. This is done by running qmake (twice when cross-compiling) on config.tests/arch/arch.pro, which preprocesses a file that contains all knowns processors. On Windows, configure.exe has never run any config.tests before, and does not currently have a function to run a program and capture its output. Use _popen() to accomplish this (as qmake does for its system() function). This needs to be done after qmake is built, as does the mkspecs/qconfig.pri generation. As a side effect, the configure steps have been slightly re-ordered, but the overall result is the same. The displayConfig() call is moved to just before generating Makefiles, so that it can show the detected architecture(s). Change-Id: I77666c77a93b48848f87648d08e79a42f721683f Reviewed-by: Morten Johan Sørvig Reviewed-by: Oswald Buddenhagen --- config.tests/arch/arch.cpp | 70 ++++++++ config.tests/arch/arch.pro | 7 + configure | 299 +++++++++---------------------- src/corelib/global/qprocessordetection.h | 4 + tools/configure/configureapp.cpp | 121 ++++++++++--- tools/configure/configureapp.h | 2 + tools/configure/environment.cpp | 22 +++ tools/configure/environment.h | 1 + tools/configure/main.cpp | 10 +- 9 files changed, 297 insertions(+), 239 deletions(-) create mode 100644 config.tests/arch/arch.cpp create mode 100644 config.tests/arch/arch.pro diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp new file mode 100644 index 0000000000..0c12565f7c --- /dev/null +++ b/config.tests/arch/arch.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used 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. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// NOTE: This file is not meant to be compiled, only preprocessed. +#include "../../src/corelib/global/qprocessordetection.h" +#if defined(Q_PROCESSOR_ALPHA) +alpha +#elif defined(Q_PROCESSOR_ARM) +arm +#elif defined(Q_PROCESSOR_AVR32) +avr32 +#elif defined(Q_PROCESSOR_BLACKFIN) +bfin +#elif defined(Q_PROCESSOR_X86_32) +i386 +#elif defined(Q_PROCESSOR_X86_64) +x86_64 +#elif defined(Q_PROCESSOR_IA64) +ia64 +#elif defined(Q_PROCESSOR_MIPS) +mips +#elif defined(Q_PROCESSOR_POWER) +power +#elif defined(Q_PROCESSOR_S390) +s390 +#elif defined(Q_PROCESSOR_SH) +sh +#elif defined(Q_PROCESSOR_SPARC) +sparc +#else +unknown +#endif diff --git a/config.tests/arch/arch.pro b/config.tests/arch/arch.pro new file mode 100644 index 0000000000..108f262a55 --- /dev/null +++ b/config.tests/arch/arch.pro @@ -0,0 +1,7 @@ +CONFIG -= qt debug_and_release +# Detect target by preprocessing a file that uses Q_PROCESSOR_* macros from qprocessordetection.h +COMMAND = $$QMAKE_CXX $$QMAKE_CXXFLAGS -E $$PWD/arch.cpp +# 'false' as second argument to system() prevents qmake from stripping newlines +COMPILER_ARCH = $$system($$COMMAND, false) +# Message back to configure so that it can set QT_ARCH and QT_HOST_ARCH +message($$COMPILER_ARCH) diff --git a/configure b/configure index e2df6028fd..04f6005a8b 100755 --- a/configure +++ b/configure @@ -693,8 +693,13 @@ CFG_V8SNAPSHOT=auto CFG_DECLARATIVE_DEBUG=yes CFG_JAVASCRIPTCORE_JIT=auto +# Target architecture CFG_ARCH= +# Host architecture, same as CFG_ARCH when not cross-compiling CFG_HOST_ARCH= +# Set when the -arch or -host-arch arguments are used +OPT_OBSOLETE_HOST_ARG=no + CFG_USE_GNUMAKE=no CFG_IM=yes CFG_XINPUT2=auto @@ -742,7 +747,6 @@ CFG_GETIFADDRS=auto CFG_INOTIFY=auto CFG_RPATH=yes CFG_FRAMEWORK=auto -CFG_MAC_ARCHS= MAC_CONFIG_TEST_COMMANDLINE= # used to make the configure tests run with the correct arch's and SDK settings CFG_MAC_DWARF2=auto CFG_MAC_HARFBUZZ=no @@ -1201,17 +1205,8 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; - arch) - # if this is a Mac then "windows" probably means - # we are cross-compiling for MinGW - if [ "$BUILD_ON_MAC" = "yes" ] && [ "$VAL" != "windows" ]; then - CFG_MAC_ARCHS="$CFG_MAC_ARCHS $VAL" - else - CFG_ARCH=$VAL - fi - ;; - host-arch) - CFG_HOST_ARCH=$VAL + arch|host-arch) + OPT_OBSOLETE_HOST_ARG=yes ;; harfbuzz) if [ "$BUILD_ON_MAC" = "yes" ] && [ "$VAL" = "yes" ]; then @@ -2420,13 +2415,6 @@ if [ "$UNAME_SYSTEM" = "SunOS" ]; then fi fi -#------------------------------------------------------------------------------- -# determine the system architecture -#------------------------------------------------------------------------------- -if [ "$OPT_VERBOSE" = "yes" ]; then - echo "Determining system architecture... ($UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_MACHINE)" -fi - if [ "$CFG_RTOS_ENABLED" = "no" ]; then case `basename "$XPLATFORM"` in qnx-* | vxworks-*) @@ -2441,153 +2429,6 @@ if [ "$CFG_RTOS_ENABLED" = "no" ]; then esac fi -if [ -z "${CFG_HOST_ARCH}" ]; then - case "$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_MACHINE" in - GNU:*:*) - CFG_HOST_ARCH=`echo ${UNAME_MACHINE} | sed -e 's,[-/].*$,,'` - case "$CFG_HOST_ARCH" in - i?86) - CFG_HOST_ARCH=i386 - ;; - esac - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " GNU/Hurd ($CFG_HOST_ARCH)" - fi - ;; - IRIX*:*:*) - CFG_HOST_ARCH=`uname -p` - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " SGI ($CFG_HOST_ARCH)" - fi - ;; - SunOS:5*:*) - case "$UNAME_MACHINE" in - sun4u*|sun4v*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " Sun SPARC (sparc)" - fi - CFG_HOST_ARCH=sparc - ;; - i86pc) - case "$PLATFORM" in - *-64*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 64-bit AMD 80x86 (x86_64)" - fi - CFG_HOST_ARCH=x86_64 - ;; - *) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 32-bit Intel 80x86 (i386)" - fi - CFG_HOST_ARCH=i386 - ;; - esac - esac - ;; - AIX:*:00????????00) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 64-bit IBM PowerPC (powerpc)" - fi - CFG_HOST_ARCH=powerpc - ;; - HP-UX:*:9000*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " HP PA-RISC (parisc)" - fi - CFG_HOST_ARCH=parisc - ;; - *:*:i?86) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 32-bit Intel 80x86 (i386)" - fi - CFG_HOST_ARCH=i386 - ;; - *:*:x86_64|*:*:amd64) - if [ "$PLATFORM" = "linux-g++-32" -o "$PLATFORM" = "linux-icc-32" ]; then - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 32 bit on 64-bit AMD 80x86 (i386)" - fi - CFG_HOST_ARCH=i386 - else - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 64-bit AMD 80x86 (x86_64)" - fi - CFG_HOST_ARCH=x86_64 - fi - ;; - *:*:ppc) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 32-bit PowerPC (powerpc)" - fi - CFG_HOST_ARCH=powerpc - ;; - *:*:ppc64) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " 64-bit PowerPC (powerpc)" - fi - CFG_HOST_ARCH=powerpc - ;; - *:*:s390*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " IBM S/390 (s390)" - fi - CFG_HOST_ARCH=s390 - ;; - *:*:arm*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " ARM (arm)" - fi - CFG_HOST_ARCH=arm - ;; - Linux:*:sparc*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " Linux on SPARC" - fi - CFG_HOST_ARCH=sparc - ;; - QNX:*:*) - case "$UNAME_MACHINE" in - x86pc) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " QNX on Intel 80x86 (i386)" - fi - CFG_HOST_ARCH=i386 - ;; - esac - ;; - *:*:*) - if [ "$OPT_VERBOSE" = "yes" ]; then - echo " Trying '$UNAME_MACHINE'..." - fi - CFG_HOST_ARCH="$UNAME_MACHINE" - ;; - esac -fi - -if [ "$XPLATFORM_MINGW" = "yes" ]; then - [ -z "$CFG_ARCH" ] && CFG_ARCH="windows" -elif [ "$PLATFORM_MAC" = "yes" ] || [ -z "$CFG_ARCH" ]; then - CFG_ARCH=$CFG_HOST_ARCH -fi - -# for compatibility -COMPAT_ARCH= -case "$CFG_ARCH" in -arm*) - # previously, armv6 was a different arch - CFG_ARCH=arm - COMPAT_ARCH=armv6 - ;; -esac - -if [ "$OPT_VERBOSE" = "yes" ]; then - echo "System architecture: '$CFG_ARCH'" - if [ "$PLATFORM_QPA" = "yes" ]; then - echo "Host architecture: '$CFG_HOST_ARCH'" - fi -fi - #------------------------------------------------------------------------------- # tests that don't need qmake (must be run before displaying help) #------------------------------------------------------------------------------- @@ -3548,9 +3389,6 @@ Qt/Mac only: * -dwarf2 ............ Enable dwarf2 debugging symbols. -no-dwarf2 ......... Disable dwarf2 debugging symbols. - -arch ....... Build Qt for . Supported arch values: x86 x86_64. - Only one arch value can be specified. - -sdk ......... Build Qt using Apple provided SDK . This option requires gcc 4. To use a different SDK with gcc 3.3, set the SDKROOT environment variable. @@ -4038,6 +3876,33 @@ fi # Build qmake # tests that need qmake #------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# determine the target and host architectures +#------------------------------------------------------------------------------- + +# Use config.tests/arch/arch.pro to has the compiler tell us what the target architecture is +CFG_ARCH=`"$outpath/bin/qmake" -spec "$XQMAKESPEC" -o /dev/null "$relpath/config.tests/arch/arch.pro" 2>&1 | sed -e "s,^Project MESSAGE: ,," -e "s,^#.*$,,g" | grep -v "^$"` +[ -z "$CFG_ARCH" ] && CFG_ARCH="unknown" +if [ "$QMAKESPEC" != "$XQMAKESPEC" ]; then + # Do the same test again, using the host compiler + CFG_HOST_ARCH=`"$outpath/bin/qmake" -spec "$QMAKESPEC" -o /dev/null "$relpath/config.tests/arch/arch.pro" 2>&1 | sed -e "s,^Project MESSAGE: ,," -e "s,^#.*$,,g" | grep -v "^$"` + [ -z "$CFG_HOST_ARCH" ] && CFG_HOST_ARCH="unknown" +else + # not cross compiling, host == target + CFG_HOST_ARCH="$CFG_ARCH" +fi + +if [ "$OPT_VERBOSE" = "yes" ]; then + echo "System architecture: '$CFG_ARCH'" + if [ "$PLATFORM_QPA" = "yes" ]; then + echo "Host architecture: '$CFG_HOST_ARCH'" + fi +fi + +#------------------------------------------------------------------------------- +# functionality tests +#------------------------------------------------------------------------------- + # detect availability of float math.h functions if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/floatmath "floatmath" $L_FLAGS $I_FLAGS $l_FLAGS; then CFG_USE_FLOATMATH=yes @@ -4143,6 +4008,8 @@ if [ "$CFG_ARCH" = "arm" ] && [ "${CFG_NEON}" = "auto" ]; then else CFG_NEON=no fi +elif [ "$CFG_ARCH" != "arm" ]; then + CFG_NEON=no fi [ "$XPLATFORM_MINGW" = "yes" ] && QMakeVar add styles "windowsxp windowsvista" @@ -5522,29 +5389,27 @@ if [ "$CFG_MAC_DWARF2" = "yes" ]; then QT_CONFIG="$QT_CONFIG dwarf2" fi -# Set the default Mac OS X arch if there are no "-arch" arguments on the configure line +# Detect the default arch (x86 or x86_64) on Mac OS X if [ "$BUILD_ON_MAC" = "yes" ]; then - DEFAULT_ARCH="$CFG_MAC_ARCHS" - if [ -z "$DEFAULT_ARCH" ]; then - case `file "${outpath}/bin/qmake"` in - *i?86) - DEFAULT_ARCH=x86 - ;; - *x86_64) - DEFAULT_ARCH=x86_64 - ;; - *ppc|*ppc64|*) - # unsupported/unknown - ;; - esac - fi + DEFAULT_ARCH= + case `file "${outpath}/bin/qmake"` in + *i?86) + DEFAULT_ARCH=x86 + ;; + *x86_64) + DEFAULT_ARCH=x86_64 + ;; + *ppc|*ppc64|*) + # unsupported/unknown + ;; + esac + if [ -n "$DEFAULT_ARCH" ]; then [ "$OPT_VERBOSE" = "yes" ] && echo "Setting default Mac OS X architechture to $DEFAULT_ARCH." QT_CONFIG="$QT_CONFIG $DEFAULT_ARCH" QMAKE_CONFIG="$QMAKE_CONFIG $DEFAULT_ARCH" - # Make the application arch follow the Qt arch for single arch builds. - # (for multiple-arch builds, set CONFIG manually in the application .pro file) - [ `echo "$DEFAULT_ARCH" | wc -w` -eq 1 ] && QTCONFIG_CONFIG="$QTCONFIG_CONFIG $DEFAULT_ARCH" + # Make the application arch follow the Qt arch + QTCONFIG_CONFIG="$QTCONFIG_CONFIG $DEFAULT_ARCH" fi fi @@ -6156,17 +6021,6 @@ cat >>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" [ '!' -z "$LicenseKeyExt" ] && echo "#define QT_PRODUCT_LICENSEKEY \"$LicenseKeyExt\"" >>"$outpath/src/corelib/global/qconfig.h.new" @@ -6389,6 +6243,7 @@ cat >>"$QTCONFIG.tmp" < will be used (when + available). The generic implementations are generally as fast + as and always as safe as a specialized implementation. + + If no generic implementation is available, Qt will use a + fallback UNIX implementation which uses a single + pthread_mutex_t to protect all atomic operations. This implementation is the slow (but safe) fallback implementation for architectures Qt does not yet support. EOF @@ -7042,6 +6900,21 @@ cat <] [-qt-sql-]\n" - "[-plugin-sql-] [-system-sqlite] [-arch ]\n" + "[-plugin-sql-] [-system-sqlite]\n" "[-D ] [-I ] [-L ]\n" "[-help] [-no-dsp] [-dsp] [-no-vcproj] [-vcproj]\n" "[-no-qmake] [-qmake] [-dont-process] [-process]\n" @@ -1623,13 +1617,6 @@ bool Configure::displayHelp() desc("DIRECTWRITE", "no", "-no-directwrite", "Do not build support for DirectWrite font rendering"); desc("DIRECTWRITE", "yes", "-directwrite", "Build support for DirectWrite font rendering (experimental, requires DirectWrite availability on target systems, e.g. Windows Vista with Platform Update, Windows 7, etc.)"); - desc( "-arch ", "Specify an architecture.\n" - "Available values for :"); - desc("ARCHITECTURE","windows", "", " windows", ' '); - desc("ARCHITECTURE","windowsce", "", " windowsce", ' '); - desc("ARCHITECTURE","boundschecker", "", " boundschecker", ' '); - desc("ARCHITECTURE","generic", "", " generic\n", ' '); - desc( "-no-style-