diff options
220 files changed, 1621 insertions, 805 deletions
@@ -6551,10 +6551,10 @@ echo " Configure summary" echo if [ "$XPLATFORM" = "$PLATFORM" ]; then # the missing space before $CFG_FEATURES is intentional - echo "Build type: $PLATFORM ($CFG_ARCH, CPU features:${CFG_CPUFEATURES- none detected})" + echo "Build type: $PLATFORM ($CFG_ARCH, CPU features:${CFG_CPUFEATURES:- none detected})" else - echo "Building on: $PLATFORM ($CFG_HOST_ARCH, CPU features:${CFG_HOST_CPUFEATURES- none detected})" - echo "Building for: $XPLATFORM ($CFG_ARCH, CPU features:${CFG_CPUFEATURES- none detected})" + echo "Building on: $PLATFORM ($CFG_HOST_ARCH, CPU features:${CFG_HOST_CPUFEATURES:- none detected})" + echo "Building for: $XPLATFORM ($CFG_ARCH, CPU features:${CFG_CPUFEATURES:- none detected})" fi diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index f5a4422601..01950e650c 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -255,7 +255,12 @@ manifestmeta.ios.tags = ios # add a generic thumbnail image to examples that do not have any images in their documentation manifestmeta.thumbnail.attributes = "imageUrl:qthelp\://org.qt-project.qtdoc.$QT_VERSION_TAG/qtdoc/images/qt-codesample.png" -manifestmeta.thumbnail.names = "QtConcurrent/Map Example" \ +manifestmeta.thumbnail.names = "QtCore/Contiguous Cache Example" \ + "QtCore/Custom Type Example" \ + "QtCore/JSON Save Game Example" \ + "QtCore/Semaphores Example" \ + "QtCore/Wait Conditions Example" \ + "QtConcurrent/Map Example" \ "QtConcurrent/QtConcurrent Word Count Example" \ "QtConcurrent/Run Function Example" \ "QtGui/Raster Window Example" \ diff --git a/examples/corelib/corelib.pro b/examples/corelib/corelib.pro new file mode 100644 index 0000000000..ec6e19c2b5 --- /dev/null +++ b/examples/corelib/corelib.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs +CONFIG += no_docs_target + +SUBDIRS = \ + ipc \ + json \ + threads \ + tools diff --git a/examples/ipc/README b/examples/corelib/ipc/README index 83a157a42e..83a157a42e 100644 --- a/examples/ipc/README +++ b/examples/corelib/ipc/README diff --git a/examples/ipc/doc/images/localfortuneclient-example.png b/examples/corelib/ipc/doc/images/localfortuneclient-example.png Binary files differindex 614784bf0f..614784bf0f 100644 --- a/examples/ipc/doc/images/localfortuneclient-example.png +++ b/examples/corelib/ipc/doc/images/localfortuneclient-example.png diff --git a/examples/ipc/doc/images/localfortuneserver-example.png b/examples/corelib/ipc/doc/images/localfortuneserver-example.png Binary files differindex 2f04c7528e..2f04c7528e 100644 --- a/examples/ipc/doc/images/localfortuneserver-example.png +++ b/examples/corelib/ipc/doc/images/localfortuneserver-example.png diff --git a/examples/ipc/doc/images/sharedmemory-example_1.png b/examples/corelib/ipc/doc/images/sharedmemory-example_1.png Binary files differindex 53244d3f52..53244d3f52 100644 --- a/examples/ipc/doc/images/sharedmemory-example_1.png +++ b/examples/corelib/ipc/doc/images/sharedmemory-example_1.png diff --git a/examples/ipc/doc/images/sharedmemory-example_2.png b/examples/corelib/ipc/doc/images/sharedmemory-example_2.png Binary files differindex fc71aed56e..fc71aed56e 100644 --- a/examples/ipc/doc/images/sharedmemory-example_2.png +++ b/examples/corelib/ipc/doc/images/sharedmemory-example_2.png diff --git a/examples/ipc/doc/src/localfortuneclient.qdoc b/examples/corelib/ipc/doc/src/localfortuneclient.qdoc index a68f4bad0c..d7a90fd946 100644 --- a/examples/ipc/doc/src/localfortuneclient.qdoc +++ b/examples/corelib/ipc/doc/src/localfortuneclient.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example localfortuneclient + \example ipc/localfortuneclient \title Local Fortune Client Example \ingroup examples-ipc \brief Demonstrates using QLocalSocket for a simple local service client. diff --git a/examples/ipc/doc/src/localfortuneserver.qdoc b/examples/corelib/ipc/doc/src/localfortuneserver.qdoc index 13f7f3ca74..47c28e0eb0 100644 --- a/examples/ipc/doc/src/localfortuneserver.qdoc +++ b/examples/corelib/ipc/doc/src/localfortuneserver.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example localfortuneserver + \example ipc/localfortuneserver \title Local Fortune Server Example \ingroup examples-ipc \brief Demonstrates using QLocalServer and QLocalSocket for serving a simple local service. diff --git a/examples/ipc/doc/src/sharedmemory.qdoc b/examples/corelib/ipc/doc/src/sharedmemory.qdoc index b9f0c86d44..60b949df2d 100644 --- a/examples/ipc/doc/src/sharedmemory.qdoc +++ b/examples/corelib/ipc/doc/src/sharedmemory.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example sharedmemory + \example ipc/sharedmemory \title Shared Memory Example \ingroup examples-ipc \brief Demonstrates doing inter-process communication using shared memory with @@ -40,7 +40,7 @@ dialog is displayed and then control is passed to the application in the standard way. - \snippet sharedmemory/main.cpp 0 + \snippet ipc/sharedmemory/main.cpp 0 Two instances of class Dialog appear. @@ -51,12 +51,12 @@ loadFromFile() and loadFromMemory() that correspond to the two buttons on the dialog. - \snippet sharedmemory/dialog.h 0 + \snippet ipc/sharedmemory/dialog.h 0 The constructor builds the user interface widgets and connects the clicked() signal of each button to the corresponding slot function. - \snippet sharedmemory/dialog.cpp 0 + \snippet ipc/sharedmemory/dialog.cpp 0 Note that "QSharedMemoryExample" is passed to the \l {QSharedMemory} {QSharedMemory()} constructor to be used as the key. This will be @@ -69,7 +69,7 @@ that segment is detached from the process, so we can be assured of starting off the example correctly. - \snippet sharedmemory/dialog.cpp 1 + \snippet ipc/sharedmemory/dialog.cpp 1 The user is then asked to select an image file using QFileDialog::getOpenFileName(). The selected file is loaded into a @@ -85,7 +85,7 @@ to the image data, which we then use to do a memcopy() from the QBuffer into the shared memory segment. - \snippet sharedmemory/dialog.cpp 2 + \snippet ipc/sharedmemory/dialog.cpp 2 Note that we \l {QSharedMemory::} {lock()} the shared memory segment before we copy into it, and we \l {QSharedMemory::} {unlock()} it @@ -117,7 +117,7 @@ then streams the data into a QImage and \l {QSharedMemory::unlock()} {unlocks} the segment. - \snippet sharedmemory/dialog.cpp 3 + \snippet ipc/sharedmemory/dialog.cpp 3 In this case, the function does \l {QSharedMemory::} {detach()} from the segment, because now we are effectively finished using diff --git a/examples/ipc/ipc.pro b/examples/corelib/ipc/ipc.pro index 4b4b3870a4..4b4b3870a4 100644 --- a/examples/ipc/ipc.pro +++ b/examples/corelib/ipc/ipc.pro diff --git a/examples/ipc/localfortuneclient/client.cpp b/examples/corelib/ipc/localfortuneclient/client.cpp index 267f5329c8..267f5329c8 100644 --- a/examples/ipc/localfortuneclient/client.cpp +++ b/examples/corelib/ipc/localfortuneclient/client.cpp diff --git a/examples/ipc/localfortuneclient/client.h b/examples/corelib/ipc/localfortuneclient/client.h index 61b1cd26a4..61b1cd26a4 100644 --- a/examples/ipc/localfortuneclient/client.h +++ b/examples/corelib/ipc/localfortuneclient/client.h diff --git a/examples/ipc/localfortuneclient/localfortuneclient.pro b/examples/corelib/ipc/localfortuneclient/localfortuneclient.pro index c52a173ed5..912c0f3b8e 100644 --- a/examples/ipc/localfortuneclient/localfortuneclient.pro +++ b/examples/corelib/ipc/localfortuneclient/localfortuneclient.pro @@ -4,5 +4,5 @@ SOURCES = client.cpp \ QT += network widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/ipc/localfortuneclient +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/localfortuneclient INSTALLS += target diff --git a/examples/ipc/localfortuneclient/main.cpp b/examples/corelib/ipc/localfortuneclient/main.cpp index f197d7f6cb..f197d7f6cb 100644 --- a/examples/ipc/localfortuneclient/main.cpp +++ b/examples/corelib/ipc/localfortuneclient/main.cpp diff --git a/examples/ipc/localfortuneserver/localfortuneserver.pro b/examples/corelib/ipc/localfortuneserver/localfortuneserver.pro index 9eed28ef74..88190c45bd 100644 --- a/examples/ipc/localfortuneserver/localfortuneserver.pro +++ b/examples/corelib/ipc/localfortuneserver/localfortuneserver.pro @@ -4,5 +4,5 @@ SOURCES = server.cpp \ QT += network widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/ipc/localfortuneserver +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/localfortuneserver INSTALLS += target diff --git a/examples/ipc/localfortuneserver/main.cpp b/examples/corelib/ipc/localfortuneserver/main.cpp index 0ae70e14ef..0ae70e14ef 100644 --- a/examples/ipc/localfortuneserver/main.cpp +++ b/examples/corelib/ipc/localfortuneserver/main.cpp diff --git a/examples/ipc/localfortuneserver/server.cpp b/examples/corelib/ipc/localfortuneserver/server.cpp index 6130aaa1c3..6130aaa1c3 100644 --- a/examples/ipc/localfortuneserver/server.cpp +++ b/examples/corelib/ipc/localfortuneserver/server.cpp diff --git a/examples/ipc/localfortuneserver/server.h b/examples/corelib/ipc/localfortuneserver/server.h index 4ec7f9b8ef..4ec7f9b8ef 100644 --- a/examples/ipc/localfortuneserver/server.h +++ b/examples/corelib/ipc/localfortuneserver/server.h diff --git a/examples/ipc/sharedmemory/dialog.cpp b/examples/corelib/ipc/sharedmemory/dialog.cpp index c504f3a202..c504f3a202 100644 --- a/examples/ipc/sharedmemory/dialog.cpp +++ b/examples/corelib/ipc/sharedmemory/dialog.cpp diff --git a/examples/ipc/sharedmemory/dialog.h b/examples/corelib/ipc/sharedmemory/dialog.h index fbc39ed4c0..fbc39ed4c0 100644 --- a/examples/ipc/sharedmemory/dialog.h +++ b/examples/corelib/ipc/sharedmemory/dialog.h diff --git a/examples/ipc/sharedmemory/dialog.ui b/examples/corelib/ipc/sharedmemory/dialog.ui index e99d6fb3c4..e99d6fb3c4 100644 --- a/examples/ipc/sharedmemory/dialog.ui +++ b/examples/corelib/ipc/sharedmemory/dialog.ui diff --git a/examples/ipc/sharedmemory/image.png b/examples/corelib/ipc/sharedmemory/image.png Binary files differindex dd93453063..dd93453063 100644 --- a/examples/ipc/sharedmemory/image.png +++ b/examples/corelib/ipc/sharedmemory/image.png diff --git a/examples/ipc/sharedmemory/main.cpp b/examples/corelib/ipc/sharedmemory/main.cpp index 0e9f84f3e3..0e9f84f3e3 100644 --- a/examples/ipc/sharedmemory/main.cpp +++ b/examples/corelib/ipc/sharedmemory/main.cpp diff --git a/examples/ipc/sharedmemory/qt.png b/examples/corelib/ipc/sharedmemory/qt.png Binary files differindex 60ef558efe..60ef558efe 100644 --- a/examples/ipc/sharedmemory/qt.png +++ b/examples/corelib/ipc/sharedmemory/qt.png diff --git a/examples/ipc/sharedmemory/sharedmemory.pro b/examples/corelib/ipc/sharedmemory/sharedmemory.pro index a392f9542d..c1b634732e 100644 --- a/examples/ipc/sharedmemory/sharedmemory.pro +++ b/examples/corelib/ipc/sharedmemory/sharedmemory.pro @@ -11,5 +11,5 @@ FORMS += dialog.ui EXAMPLE_FILES = *.png # install -target.path = $$[QT_INSTALL_EXAMPLES]/ipc/sharedmemory +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/sharedmemory INSTALLS += target diff --git a/examples/json/json.pro b/examples/corelib/json/json.pro index af4d3e6f0f..af4d3e6f0f 100644 --- a/examples/json/json.pro +++ b/examples/corelib/json/json.pro diff --git a/examples/json/savegame/character.cpp b/examples/corelib/json/savegame/character.cpp index ef30f0eaf4..ef30f0eaf4 100644 --- a/examples/json/savegame/character.cpp +++ b/examples/corelib/json/savegame/character.cpp diff --git a/examples/json/savegame/character.h b/examples/corelib/json/savegame/character.h index 32369820f4..32369820f4 100644 --- a/examples/json/savegame/character.h +++ b/examples/corelib/json/savegame/character.h diff --git a/examples/json/savegame/doc/src/savegame.qdoc b/examples/corelib/json/savegame/doc/src/savegame.qdoc index 872f2faf42..1de12c38b9 100644 --- a/examples/json/savegame/doc/src/savegame.qdoc +++ b/examples/corelib/json/savegame/doc/src/savegame.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example savegame + \example json/savegame \title JSON Save Game Example \brief The JSON Save Game example demonstrates how to save and load a @@ -50,12 +50,12 @@ It provides read() and write() functions to serialise its member variables. - \snippet savegame/character.h 0 + \snippet json/savegame/character.h 0 Of particular interest to us are the read and write function implementations: - \snippet savegame/character.cpp 0 + \snippet json/savegame/character.cpp 0 In the read() function, we assign Character's members values from the QJsonObject argument. You can use either \l QJsonObject::operator[]() or @@ -64,7 +64,7 @@ could check if the keys are valid before attempting to read them with QJsonObject::contains(), but we assume that they are. - \snippet savegame/character.cpp 1 + \snippet json/savegame/character.cpp 1 In the write() function, we do the reverse of the read() function; assign values from the Character object to the JSON object. As with accessing @@ -74,13 +74,13 @@ Next up is the Level class: - \snippet savegame/level.h 0 + \snippet json/savegame/level.h 0 We want to have several levels in our game, each with several NPCs, so we keep a QList of Character objects. We also provide the familiar read() and write() functions. - \snippet savegame/level.cpp 0 + \snippet json/savegame/level.cpp 0 Containers can be written and read to and from JSON using QJsonArray. In our case, we construct a QJsonArray from the value associated with the key @@ -94,7 +94,7 @@ element is used as the key to construct the container when reading it back in. - \snippet savegame/level.cpp 1 + \snippet json/savegame/level.cpp 1 Again, the write() function is similar to the read() function, except reversed. @@ -102,7 +102,7 @@ Having established the Character and Level classes, we can move on to the Game class: - \snippet savegame/game.h 0 + \snippet json/savegame/game.h 0 First of all, we define the \c SaveFormat enum. This will allow us to specify the format in which the game should be saved: \c Json or \c Binary. @@ -112,12 +112,12 @@ The read() and write() functions are used by saveGame() and loadGame(). - \snippet savegame/game.cpp 0 + \snippet json/savegame/game.cpp 0 To setup a new game, we create the player and populate the levels and their NPCs. - \snippet savegame/game.cpp 1 + \snippet json/savegame/game.cpp 1 The first thing we do in the read() function is tell the player to read itself. We then clear the levels list so that calling loadGame() on the same @@ -125,11 +125,11 @@ We then populate the level list by reading each Level from a QJsonArray. - \snippet savegame/game.cpp 2 + \snippet json/savegame/game.cpp 2 We write the game to JSON similarly to how we write Level. - \snippet savegame/game.cpp 3 + \snippet json/savegame/game.cpp 3 When loading a saved game in loadGame(), the first thing we do is open the save file based on which format it was saved to; \c "save.json" for JSON, @@ -144,7 +144,7 @@ After constructing the QJsonDocument, we instruct the Game object to read itself and then return \c true to indicate success. - \snippet savegame/game.cpp 4 + \snippet json/savegame/game.cpp 4 Not surprisingly, saveGame() looks very much like loadGame(). We determine the file extension based on the format, print a warning and return \c false @@ -155,7 +155,7 @@ We are now ready to enter main(): - \snippet savegame/main.cpp 0 + \snippet json/savegame/main.cpp 0 Since we're only interested in demonstrating \e serialization of a game with JSON, our game is not actually playable. Therefore, we only need @@ -163,7 +163,7 @@ the player had a great time and made lots of progress, altering the internal state of our Character, Level and Game objects. - \snippet savegame/main.cpp 1 + \snippet json/savegame/main.cpp 1 When the player has finished, we save their game. For demonstration purposes, we serialize to both JSON and binary. You can examine the contents diff --git a/examples/json/savegame/game.cpp b/examples/corelib/json/savegame/game.cpp index a08071b208..a08071b208 100644 --- a/examples/json/savegame/game.cpp +++ b/examples/corelib/json/savegame/game.cpp diff --git a/examples/json/savegame/game.h b/examples/corelib/json/savegame/game.h index 9216a373d1..9216a373d1 100644 --- a/examples/json/savegame/game.h +++ b/examples/corelib/json/savegame/game.h diff --git a/examples/json/savegame/level.cpp b/examples/corelib/json/savegame/level.cpp index afbd3e0fa0..afbd3e0fa0 100644 --- a/examples/json/savegame/level.cpp +++ b/examples/corelib/json/savegame/level.cpp diff --git a/examples/json/savegame/level.h b/examples/corelib/json/savegame/level.h index 6cdf508c87..6cdf508c87 100644 --- a/examples/json/savegame/level.h +++ b/examples/corelib/json/savegame/level.h diff --git a/examples/json/savegame/main.cpp b/examples/corelib/json/savegame/main.cpp index 1b44306bb0..1b44306bb0 100644 --- a/examples/json/savegame/main.cpp +++ b/examples/corelib/json/savegame/main.cpp diff --git a/examples/json/savegame/savegame.pro b/examples/corelib/json/savegame/savegame.pro index fd754ace80..6706444506 100644 --- a/examples/json/savegame/savegame.pro +++ b/examples/corelib/json/savegame/savegame.pro @@ -8,7 +8,7 @@ CONFIG -= app_bundle TEMPLATE = app # install -target.path = $$[QT_INSTALL_EXAMPLES]/json/savegame +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/json/savegame INSTALLS += target SOURCES += main.cpp \ diff --git a/examples/threads/README b/examples/corelib/threads/README index 6c20844564..6c20844564 100644 --- a/examples/threads/README +++ b/examples/corelib/threads/README diff --git a/examples/threads/doc/images/mandelbrot-example.png b/examples/corelib/threads/doc/images/mandelbrot-example.png Binary files differindex f5817834e1..f5817834e1 100644 --- a/examples/threads/doc/images/mandelbrot-example.png +++ b/examples/corelib/threads/doc/images/mandelbrot-example.png diff --git a/examples/threads/doc/images/mandelbrot_scroll1.png b/examples/corelib/threads/doc/images/mandelbrot_scroll1.png Binary files differindex b800455821..b800455821 100644 --- a/examples/threads/doc/images/mandelbrot_scroll1.png +++ b/examples/corelib/threads/doc/images/mandelbrot_scroll1.png diff --git a/examples/threads/doc/images/mandelbrot_scroll2.png b/examples/corelib/threads/doc/images/mandelbrot_scroll2.png Binary files differindex 704ea0a7c1..704ea0a7c1 100644 --- a/examples/threads/doc/images/mandelbrot_scroll2.png +++ b/examples/corelib/threads/doc/images/mandelbrot_scroll2.png diff --git a/examples/threads/doc/images/mandelbrot_scroll3.png b/examples/corelib/threads/doc/images/mandelbrot_scroll3.png Binary files differindex 8b48211444..8b48211444 100644 --- a/examples/threads/doc/images/mandelbrot_scroll3.png +++ b/examples/corelib/threads/doc/images/mandelbrot_scroll3.png diff --git a/examples/threads/doc/images/mandelbrot_zoom1.png b/examples/corelib/threads/doc/images/mandelbrot_zoom1.png Binary files differindex 30190e44eb..30190e44eb 100644 --- a/examples/threads/doc/images/mandelbrot_zoom1.png +++ b/examples/corelib/threads/doc/images/mandelbrot_zoom1.png diff --git a/examples/threads/doc/images/mandelbrot_zoom2.png b/examples/corelib/threads/doc/images/mandelbrot_zoom2.png Binary files differindex 148ac777b8..148ac777b8 100644 --- a/examples/threads/doc/images/mandelbrot_zoom2.png +++ b/examples/corelib/threads/doc/images/mandelbrot_zoom2.png diff --git a/examples/threads/doc/images/mandelbrot_zoom3.png b/examples/corelib/threads/doc/images/mandelbrot_zoom3.png Binary files differindex a669f4b5fe..a669f4b5fe 100644 --- a/examples/threads/doc/images/mandelbrot_zoom3.png +++ b/examples/corelib/threads/doc/images/mandelbrot_zoom3.png diff --git a/examples/threads/doc/images/queuedcustomtype-example.png b/examples/corelib/threads/doc/images/queuedcustomtype-example.png Binary files differindex 4399b631d7..4399b631d7 100644 --- a/examples/threads/doc/images/queuedcustomtype-example.png +++ b/examples/corelib/threads/doc/images/queuedcustomtype-example.png diff --git a/examples/threads/doc/src/mandelbrot.qdoc b/examples/corelib/threads/doc/src/mandelbrot.qdoc index c1393769f1..75d424e6a4 100644 --- a/examples/threads/doc/src/mandelbrot.qdoc +++ b/examples/corelib/threads/doc/src/mandelbrot.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example mandelbrot + \example threads/mandelbrot \title Mandelbrot Example \ingroup qtconcurrent-mtexamples @@ -101,7 +101,7 @@ We'll start with the definition of the \c RenderThread class: - \snippet mandelbrot/renderthread.h 0 + \snippet threads/mandelbrot/renderthread.h 0 The class inherits QThread so that it gains the ability to run in a separate thread. Apart from the constructor and destructor, \c @@ -117,7 +117,7 @@ \section1 RenderThread Class Implementation - \snippet mandelbrot/renderthread.cpp 0 + \snippet threads/mandelbrot/renderthread.cpp 0 In the constructor, we initialize the \c restart and \c abort variables to \c false. These variables control the flow of the \c @@ -126,7 +126,7 @@ We also initialize the \c colormap array, which contains a series of RGB colors. - \snippet mandelbrot/renderthread.cpp 1 + \snippet threads/mandelbrot/renderthread.cpp 1 The destructor can be called at any point while the thread is active. We set \c abort to \c true to tell \c run() to stop @@ -147,7 +147,7 @@ until \c run() has exited before the base class destructor is invoked. - \snippet mandelbrot/renderthread.cpp 2 + \snippet threads/mandelbrot/renderthread.cpp 2 The \c render() function is called by the \c MandelbrotWidget whenever it needs to generate a new image of the Mandelbrot set. @@ -161,7 +161,7 @@ computation and start again with the new parameters) and wakes up the thread, which might be sleeping. - \snippet mandelbrot/renderthread.cpp 3 + \snippet threads/mandelbrot/renderthread.cpp 3 \c run() is quite a big function, so we'll break it down into parts. @@ -177,10 +177,10 @@ The \c forever keyword is, like \c foreach, a Qt pseudo-keyword. - \snippet mandelbrot/renderthread.cpp 4 - \snippet mandelbrot/renderthread.cpp 5 - \snippet mandelbrot/renderthread.cpp 6 - \snippet mandelbrot/renderthread.cpp 7 + \snippet threads/mandelbrot/renderthread.cpp 4 + \snippet threads/mandelbrot/renderthread.cpp 5 + \snippet threads/mandelbrot/renderthread.cpp 6 + \snippet threads/mandelbrot/renderthread.cpp 7 Then comes the core of the algorithm. Instead of trying to create a perfect Mandelbrot set image, we do multiple passes and @@ -197,15 +197,15 @@ The core algorithm is beyond the scope of this tutorial. - \snippet mandelbrot/renderthread.cpp 8 - \snippet mandelbrot/renderthread.cpp 9 + \snippet threads/mandelbrot/renderthread.cpp 8 + \snippet threads/mandelbrot/renderthread.cpp 9 Once we're done with all the iterations, we call QWaitCondition::wait() to put the thread to sleep by calling, unless \c restart is \c true. There's no use in keeping a worker thread looping indefinitely while there's nothing to do. - \snippet mandelbrot/renderthread.cpp 10 + \snippet threads/mandelbrot/renderthread.cpp 10 The \c rgbFromWaveLength() function is a helper function that converts a wave length to a RGB value compatible with 32-bit @@ -217,7 +217,7 @@ The \c MandelbrotWidget class uses \c RenderThread to draw the Mandelbrot set on screen. Here's the class definition: - \snippet mandelbrot/mandelbrotwidget.h 0 + \snippet threads/mandelbrot/mandelbrotwidget.h 0 The widget reimplements many event handlers from QWidget. In addition, it has an \c updatePixmap() slot that we'll connect to @@ -230,12 +230,12 @@ \section1 MandelbrotWidget Class Implementation - \snippet mandelbrot/mandelbrotwidget.cpp 0 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 0 The implementation starts with a few contants that we'll need later on. - \snippet mandelbrot/mandelbrotwidget.cpp 1 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 1 The interesting part of the constructor is the qRegisterMetaType() and QObject::connect() calls. Let's start @@ -258,19 +258,19 @@ template function qRegisterMetaType() before we can use QImage as parameter in queued connections. - \snippet mandelbrot/mandelbrotwidget.cpp 2 - \snippet mandelbrot/mandelbrotwidget.cpp 3 - \snippet mandelbrot/mandelbrotwidget.cpp 4 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 2 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 3 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 4 In \l{QWidget::paintEvent()}{paintEvent()}, we start by filling the background with black. If we have nothing yet to paint (\c pixmap is null), we print a message on the widget asking the user to be patient and return from the function immediately. - \snippet mandelbrot/mandelbrotwidget.cpp 5 - \snippet mandelbrot/mandelbrotwidget.cpp 6 - \snippet mandelbrot/mandelbrotwidget.cpp 7 - \snippet mandelbrot/mandelbrotwidget.cpp 8 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 5 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 6 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 7 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 8 If the pixmap has the right scale factor, we draw the pixmap directly onto the widget. Otherwise, we scale and translate the \l{Coordinate @@ -280,12 +280,12 @@ QPainter::save() and QPainter::restore() make sure that any painting performed afterwards uses the standard coordinate system. - \snippet mandelbrot/mandelbrotwidget.cpp 9 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 9 At the end of the paint event handler, we draw a text string and a semi-transparent rectangle on top of the fractal. - \snippet mandelbrot/mandelbrotwidget.cpp 10 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 10 Whenever the user resizes the widget, we call \c render() to start generating a new image, with the same \c centerX, \c @@ -295,13 +295,13 @@ called by Qt when the widget is shown the first time to generate the image the very first time. - \snippet mandelbrot/mandelbrotwidget.cpp 11 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 11 The key press event handler provides a few keyboard bindings for the benefit of users who don't have a mouse. The \c zoom() and \c scroll() functions will be covered later. - \snippet mandelbrot/mandelbrotwidget.cpp 12 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 12 The wheel event handler is reimplemented to make the mouse wheel control the zoom level. QWheelEvent::delta() returns the angle of @@ -312,18 +312,18 @@ (i.e., +30 degrees), the zoom factor becomes \c ZoomInFactor to the second power, i.e. 0.8 * 0.8 = 0.64. - \snippet mandelbrot/mandelbrotwidget.cpp 13 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 13 When the user presses the left mouse button, we store the mouse pointer position in \c lastDragPos. - \snippet mandelbrot/mandelbrotwidget.cpp 14 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 14 When the user moves the mouse pointer while the left mouse button is pressed, we adjust \c pixmapOffset to paint the pixmap at a shifted position and call QWidget::update() to force a repaint. - \snippet mandelbrot/mandelbrotwidget.cpp 15 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 15 When the left mouse button is released, we update \c pixmapOffset just like we did on a mouse move and we reset \c lastDragPos to a @@ -332,7 +332,7 @@ because areas revealed when dragging the pixmap are drawn in black.) - \snippet mandelbrot/mandelbrotwidget.cpp 16 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 16 The \c updatePixmap() slot is invoked when the worker thread has finished rendering an image. We start by checking whether a drag @@ -349,14 +349,14 @@ be converted into a pixmap. It's better to do the conversion once and for all here, rather than in \c paintEvent(). - \snippet mandelbrot/mandelbrotwidget.cpp 17 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 17 In \c zoom(), we recompute \c curScale. Then we call QWidget::update() to draw a scaled pixmap, and we ask the worker thread to render a new image corresponding to the new \c curScale value. - \snippet mandelbrot/mandelbrotwidget.cpp 18 + \snippet threads/mandelbrot/mandelbrotwidget.cpp 18 \c scroll() is similar to \c zoom(), except that the affected parameters are \c centerX and \c centerY. @@ -366,5 +366,5 @@ The application's multithreaded nature has no impact on its \c main() function, which is as simple as usual: - \snippet mandelbrot/main.cpp 0 + \snippet threads/mandelbrot/main.cpp 0 */ diff --git a/examples/threads/doc/src/queuedcustomtype.qdoc b/examples/corelib/threads/doc/src/queuedcustomtype.qdoc index 40ec2668de..cca68b4513 100644 --- a/examples/threads/doc/src/queuedcustomtype.qdoc +++ b/examples/corelib/threads/doc/src/queuedcustomtype.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example queuedcustomtype + \example threads/queuedcustomtype \title Queued Custom Type Example \brief Demonstrates multi-thread programming using Qt \ingroup qtconcurrent-mtexamples @@ -57,7 +57,7 @@ constructor and destructor in the public section of the class that the meta-object system requires. It describes a colored rectangle. - \snippet queuedcustomtype/block.h custom type definition and meta-type declaration + \snippet threads/queuedcustomtype/block.h custom type definition and meta-type declaration We will still need to register it with the meta-object system at run-time by calling the qRegisterMetaType() template function before @@ -74,7 +74,7 @@ \c Block object. The rest of the class is concerned with managing the user interface and handling images. - \snippet queuedcustomtype/window.h Window class definition + \snippet threads/queuedcustomtype/window.h Window class definition The \c Window class also contains a worker thread, provided by a \c RenderThread object. This will emit signals to send \c Block objects @@ -87,22 +87,22 @@ interface containing a label and two push buttons that are connected to slots in the same class. - \snippet queuedcustomtype/window.cpp Window constructor start - \snippet queuedcustomtype/window.cpp set up widgets and connections - \snippet queuedcustomtype/window.cpp connecting signal with custom type + \snippet threads/queuedcustomtype/window.cpp Window constructor start + \snippet threads/queuedcustomtype/window.cpp set up widgets and connections + \snippet threads/queuedcustomtype/window.cpp connecting signal with custom type In the last of these connections, we connect a signal in the \c RenderThread object to the \c addBlock(Block) slot in the window. \dots - \snippet queuedcustomtype/window.cpp Window constructor finish + \snippet threads/queuedcustomtype/window.cpp Window constructor finish The rest of the constructor simply sets up the layout of the window. The \c addBlock(Block) slot receives blocks from the rendering thread via the signal-slot connection set up in the constructor: - \snippet queuedcustomtype/window.cpp Adding blocks to the display + \snippet threads/queuedcustomtype/window.cpp Adding blocks to the display We simply paint these onto the label as they arrive. @@ -112,7 +112,7 @@ and using the \c sendBlock(Block) signal to send them to other components in the example. - \snippet queuedcustomtype/renderthread.h RenderThread class definition + \snippet threads/queuedcustomtype/renderthread.h RenderThread class definition The constructor and destructor are not quoted here. These take care of setting up the thread's internal state and cleaning up when it is destroyed. @@ -120,13 +120,13 @@ Processing is started with the \c processImage() function, which calls the \c RenderThread class's reimplementation of the QThread::run() function: - \snippet queuedcustomtype/renderthread.cpp processing the image (start) + \snippet threads/queuedcustomtype/renderthread.cpp processing the image (start) Ignoring the details of the way the image is processed, we see that the signal containing a block is emitted in the usual way: \dots - \snippet queuedcustomtype/renderthread.cpp processing the image (finish) + \snippet threads/queuedcustomtype/renderthread.cpp processing the image (finish) Each signal that is emitted will be queued and delivered later to the window's \c addBlock(Block) slot. @@ -137,7 +137,7 @@ \c Block class as a custom type with the meta-object system by calling the qRegisterMetaType() template function: - \snippet queuedcustomtype/main.cpp main function + \snippet threads/queuedcustomtype/main.cpp main function This call is placed here to ensure that the type is registered before any signal-slot connections are made that use it. diff --git a/examples/threads/doc/src/semaphores.qdoc b/examples/corelib/threads/doc/src/semaphores.qdoc index e90045f824..0b1a2e852e 100644 --- a/examples/threads/doc/src/semaphores.qdoc +++ b/examples/corelib/threads/doc/src/semaphores.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example semaphores + \example threads/semaphores \title Semaphores Example \brief Demonstrates multi-thread programming using Qt \ingroup qtconcurrent-mtexamples @@ -61,7 +61,7 @@ Let's start by reviewing the circular buffer and the associated semaphores: - \snippet semaphores/semaphores.cpp 0 + \snippet threads/semaphores/semaphores.cpp 0 \c DataSize is the amout of data that the producer will generate. To keep the example as simple as possible, we make it a constant. @@ -89,8 +89,8 @@ Let's review the code for the \c Producer class: - \snippet semaphores/semaphores.cpp 1 - \snippet semaphores/semaphores.cpp 2 + \snippet threads/semaphores/semaphores.cpp 1 + \snippet threads/semaphores/semaphores.cpp 2 The producer generates \c DataSize bytes of data. Before it writes a byte to the circular buffer, it must acquire a "free" @@ -106,8 +106,8 @@ Let's now turn to the \c Consumer class: - \snippet semaphores/semaphores.cpp 3 - \snippet semaphores/semaphores.cpp 4 + \snippet threads/semaphores/semaphores.cpp 3 + \snippet threads/semaphores/semaphores.cpp 4 The code is very similar to the producer, except that this time we acquire a "used" byte and release a "free" byte, instead of @@ -118,8 +118,8 @@ In \c main(), we create the two threads and call QThread::wait() to ensure that both threads get time to finish before we exit: - \snippet semaphores/semaphores.cpp 5 - \snippet semaphores/semaphores.cpp 6 + \snippet threads/semaphores/semaphores.cpp 5 + \snippet threads/semaphores/semaphores.cpp 6 So what happens when we run the program? Initially, the producer thread is the only one that can do anything; the consumer is diff --git a/examples/threads/doc/src/waitconditions.qdoc b/examples/corelib/threads/doc/src/waitconditions.qdoc index 25c9ce88fb..aff6997b55 100644 --- a/examples/threads/doc/src/waitconditions.qdoc +++ b/examples/corelib/threads/doc/src/waitconditions.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example waitconditions + \example threads/waitconditions \title Wait Conditions Example \brief Demonstrates multi-thread programming using Qt \ingroup qtconcurrent-mtexamples @@ -61,7 +61,7 @@ Let's start by reviewing the circular buffer and the associated synchronization tools: - \snippet waitconditions/waitconditions.cpp 0 + \snippet threads/waitconditions/waitconditions.cpp 0 \c DataSize is the amount of data that the producer will generate. To keep the example as simple as possible, we make it a constant. @@ -86,8 +86,8 @@ Let's review the code for the \c Producer class: - \snippet waitconditions/waitconditions.cpp 1 - \snippet waitconditions/waitconditions.cpp 2 + \snippet threads/waitconditions/waitconditions.cpp 1 + \snippet threads/waitconditions/waitconditions.cpp 2 The producer generates \c DataSize bytes of data. Before it writes a byte to the circular buffer, it must first check whether @@ -110,8 +110,8 @@ Let's turn to the \c Consumer class: - \snippet waitconditions/waitconditions.cpp 3 - \snippet waitconditions/waitconditions.cpp 4 + \snippet threads/waitconditions/waitconditions.cpp 3 + \snippet threads/waitconditions/waitconditions.cpp 4 The code is very similar to the producer. Before we read the byte, we check whether the buffer is empty (\c numUsedBytes is 0) @@ -126,8 +126,8 @@ In \c main(), we create the two threads and call QThread::wait() to ensure that both threads get time to finish before we exit: - \snippet waitconditions/waitconditions.cpp 5 - \snippet waitconditions/waitconditions.cpp 6 + \snippet threads/waitconditions/waitconditions.cpp 5 + \snippet threads/waitconditions/waitconditions.cpp 6 So what happens when we run the program? Initially, the producer thread is the only one that can do anything; the consumer is diff --git a/examples/threads/mandelbrot/main.cpp b/examples/corelib/threads/mandelbrot/main.cpp index 8334d94f9c..8334d94f9c 100644 --- a/examples/threads/mandelbrot/main.cpp +++ b/examples/corelib/threads/mandelbrot/main.cpp diff --git a/examples/threads/mandelbrot/mandelbrot.pro b/examples/corelib/threads/mandelbrot/mandelbrot.pro index 45f21baf08..5a01a405f2 100644 --- a/examples/threads/mandelbrot/mandelbrot.pro +++ b/examples/corelib/threads/mandelbrot/mandelbrot.pro @@ -9,5 +9,5 @@ SOURCES = main.cpp \ unix:!mac:!vxworks:!integrity:LIBS += -lm # install -target.path = $$[QT_INSTALL_EXAMPLES]/threads/mandelbrot +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/mandelbrot INSTALLS += target diff --git a/examples/threads/mandelbrot/mandelbrotwidget.cpp b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp index 633d4a1ec5..633d4a1ec5 100644 --- a/examples/threads/mandelbrot/mandelbrotwidget.cpp +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp diff --git a/examples/threads/mandelbrot/mandelbrotwidget.h b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h index 183edf2e26..183edf2e26 100644 --- a/examples/threads/mandelbrot/mandelbrotwidget.h +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h diff --git a/examples/threads/mandelbrot/renderthread.cpp b/examples/corelib/threads/mandelbrot/renderthread.cpp index 5779c65c9c..5779c65c9c 100644 --- a/examples/threads/mandelbrot/renderthread.cpp +++ b/examples/corelib/threads/mandelbrot/renderthread.cpp diff --git a/examples/threads/mandelbrot/renderthread.h b/examples/corelib/threads/mandelbrot/renderthread.h index 881870665f..881870665f 100644 --- a/examples/threads/mandelbrot/renderthread.h +++ b/examples/corelib/threads/mandelbrot/renderthread.h diff --git a/examples/threads/queuedcustomtype/block.cpp b/examples/corelib/threads/queuedcustomtype/block.cpp index 07bd58cd97..07bd58cd97 100644 --- a/examples/threads/queuedcustomtype/block.cpp +++ b/examples/corelib/threads/queuedcustomtype/block.cpp diff --git a/examples/threads/queuedcustomtype/block.h b/examples/corelib/threads/queuedcustomtype/block.h index f9930340e2..f9930340e2 100644 --- a/examples/threads/queuedcustomtype/block.h +++ b/examples/corelib/threads/queuedcustomtype/block.h diff --git a/examples/threads/queuedcustomtype/main.cpp b/examples/corelib/threads/queuedcustomtype/main.cpp index 98933c66f3..98933c66f3 100644 --- a/examples/threads/queuedcustomtype/main.cpp +++ b/examples/corelib/threads/queuedcustomtype/main.cpp diff --git a/examples/threads/queuedcustomtype/queuedcustomtype.pro b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro index 8b18b13ba6..77421eb638 100644 --- a/examples/threads/queuedcustomtype/queuedcustomtype.pro +++ b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro @@ -8,7 +8,7 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/threads/mandelbrot +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/mandelbrot INSTALLS += target diff --git a/examples/threads/queuedcustomtype/renderthread.cpp b/examples/corelib/threads/queuedcustomtype/renderthread.cpp index 50a638987f..50a638987f 100644 --- a/examples/threads/queuedcustomtype/renderthread.cpp +++ b/examples/corelib/threads/queuedcustomtype/renderthread.cpp diff --git a/examples/threads/queuedcustomtype/renderthread.h b/examples/corelib/threads/queuedcustomtype/renderthread.h index 5630926d41..5630926d41 100644 --- a/examples/threads/queuedcustomtype/renderthread.h +++ b/examples/corelib/threads/queuedcustomtype/renderthread.h diff --git a/examples/threads/queuedcustomtype/window.cpp b/examples/corelib/threads/queuedcustomtype/window.cpp index 8afb8b6782..8afb8b6782 100644 --- a/examples/threads/queuedcustomtype/window.cpp +++ b/examples/corelib/threads/queuedcustomtype/window.cpp diff --git a/examples/threads/queuedcustomtype/window.h b/examples/corelib/threads/queuedcustomtype/window.h index cb648f1be2..cb648f1be2 100644 --- a/examples/threads/queuedcustomtype/window.h +++ b/examples/corelib/threads/queuedcustomtype/window.h diff --git a/examples/threads/semaphores/semaphores.cpp b/examples/corelib/threads/semaphores/semaphores.cpp index f519e5f323..f519e5f323 100644 --- a/examples/threads/semaphores/semaphores.cpp +++ b/examples/corelib/threads/semaphores/semaphores.cpp diff --git a/examples/threads/semaphores/semaphores.pro b/examples/corelib/threads/semaphores/semaphores.pro index 7dfe7c3ba0..69154e57eb 100644 --- a/examples/threads/semaphores/semaphores.pro +++ b/examples/corelib/threads/semaphores/semaphores.pro @@ -5,5 +5,5 @@ CONFIG -= app_bundle CONFIG += console # install -target.path = $$[QT_INSTALL_EXAMPLES]/threads/semaphores +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/semaphores INSTALLS += target diff --git a/examples/threads/threads.pro b/examples/corelib/threads/threads.pro index e47da84a06..e47da84a06 100644 --- a/examples/threads/threads.pro +++ b/examples/corelib/threads/threads.pro diff --git a/examples/threads/waitconditions/waitconditions.cpp b/examples/corelib/threads/waitconditions/waitconditions.cpp index b0336f4c2b..b0336f4c2b 100644 --- a/examples/threads/waitconditions/waitconditions.cpp +++ b/examples/corelib/threads/waitconditions/waitconditions.cpp diff --git a/examples/threads/waitconditions/waitconditions.pro b/examples/corelib/threads/waitconditions/waitconditions.pro index 7f9491a0b1..2dbe7df68a 100644 --- a/examples/threads/waitconditions/waitconditions.pro +++ b/examples/corelib/threads/waitconditions/waitconditions.pro @@ -5,5 +5,5 @@ CONFIG += console SOURCES += waitconditions.cpp # install -target.path = $$[QT_INSTALL_EXAMPLES]/threads/waitconditions +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/waitconditions INSTALLS += target diff --git a/examples/tools/README b/examples/corelib/tools/README index db5c107c82..db5c107c82 100644 --- a/examples/tools/README +++ b/examples/corelib/tools/README diff --git a/examples/tools/contiguouscache/contiguouscache.pro b/examples/corelib/tools/contiguouscache/contiguouscache.pro index d384a1845a..fb2267fc64 100644 --- a/examples/tools/contiguouscache/contiguouscache.pro +++ b/examples/corelib/tools/contiguouscache/contiguouscache.pro @@ -5,5 +5,5 @@ SOURCES = randomlistmodel.cpp \ main.cpp # install -target.path = $$[QT_INSTALL_EXAMPLES]/tools/contiguouscache +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/contiguouscache INSTALLS += target diff --git a/examples/tools/contiguouscache/main.cpp b/examples/corelib/tools/contiguouscache/main.cpp index 62fa8dcf42..62fa8dcf42 100644 --- a/examples/tools/contiguouscache/main.cpp +++ b/examples/corelib/tools/contiguouscache/main.cpp diff --git a/examples/tools/contiguouscache/randomlistmodel.cpp b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp index cd1a301dc7..cd1a301dc7 100644 --- a/examples/tools/contiguouscache/randomlistmodel.cpp +++ b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp diff --git a/examples/tools/contiguouscache/randomlistmodel.h b/examples/corelib/tools/contiguouscache/randomlistmodel.h index 3acafc23ff..3acafc23ff 100644 --- a/examples/tools/contiguouscache/randomlistmodel.h +++ b/examples/corelib/tools/contiguouscache/randomlistmodel.h diff --git a/examples/tools/customtype/customtype.pro b/examples/corelib/tools/customtype/customtype.pro index d05540f403..1bd792db85 100644 --- a/examples/tools/customtype/customtype.pro +++ b/examples/corelib/tools/customtype/customtype.pro @@ -4,5 +4,5 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/tools/customcompleter +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter INSTALLS += target diff --git a/examples/tools/customtype/main.cpp b/examples/corelib/tools/customtype/main.cpp index 8e97d3db96..8e97d3db96 100644 --- a/examples/tools/customtype/main.cpp +++ b/examples/corelib/tools/customtype/main.cpp diff --git a/examples/tools/customtype/message.cpp b/examples/corelib/tools/customtype/message.cpp index eb8befc36f..eb8befc36f 100644 --- a/examples/tools/customtype/message.cpp +++ b/examples/corelib/tools/customtype/message.cpp diff --git a/examples/tools/customtype/message.h b/examples/corelib/tools/customtype/message.h index cdc4e39caf..cdc4e39caf 100644 --- a/examples/tools/customtype/message.h +++ b/examples/corelib/tools/customtype/message.h diff --git a/examples/tools/customtypesending/customtypesending.pro b/examples/corelib/tools/customtypesending/customtypesending.pro index faa07bf339..672f6569c2 100644 --- a/examples/tools/customtypesending/customtypesending.pro +++ b/examples/corelib/tools/customtypesending/customtypesending.pro @@ -6,5 +6,5 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/tools/customcompleter +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter INSTALLS += target diff --git a/examples/tools/customtypesending/main.cpp b/examples/corelib/tools/customtypesending/main.cpp index 5f01e2a154..5f01e2a154 100644 --- a/examples/tools/customtypesending/main.cpp +++ b/examples/corelib/tools/customtypesending/main.cpp diff --git a/examples/tools/customtypesending/message.cpp b/examples/corelib/tools/customtypesending/message.cpp index 9b53b8757d..9b53b8757d 100644 --- a/examples/tools/customtypesending/message.cpp +++ b/examples/corelib/tools/customtypesending/message.cpp diff --git a/examples/tools/customtypesending/message.h b/examples/corelib/tools/customtypesending/message.h index 3e5f17db2b..3e5f17db2b 100644 --- a/examples/tools/customtypesending/message.h +++ b/examples/corelib/tools/customtypesending/message.h diff --git a/examples/tools/customtypesending/window.cpp b/examples/corelib/tools/customtypesending/window.cpp index aa4a7eab3c..aa4a7eab3c 100644 --- a/examples/tools/customtypesending/window.cpp +++ b/examples/corelib/tools/customtypesending/window.cpp diff --git a/examples/tools/customtypesending/window.h b/examples/corelib/tools/customtypesending/window.h index 0889800064..0889800064 100644 --- a/examples/tools/customtypesending/window.h +++ b/examples/corelib/tools/customtypesending/window.h diff --git a/examples/tools/doc/contiguouscache.qdoc b/examples/corelib/tools/doc/src/contiguouscache.qdoc index 2f7ea716e6..e88b2629b8 100644 --- a/examples/tools/doc/contiguouscache.qdoc +++ b/examples/corelib/tools/doc/src/contiguouscache.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example contiguouscache + \example tools/contiguouscache \title Contiguous Cache Example \brief The Contiguous Cache example shows how to use QContiguousCache to manage memory usage for @@ -40,7 +40,7 @@ a view requests an item at row N it is also likely to ask for items at rows near to N. - \snippet contiguouscache/randomlistmodel.cpp 0 + \snippet tools/contiguouscache/randomlistmodel.cpp 0 After getting the row, the class determines if the row is in the bounds of the contiguous cache's current range. It would have been equally valid to @@ -74,7 +74,7 @@ to see how the cache range is kept for a local number of rows when running the example. - \snippet contiguouscache/randomlistmodel.cpp 1 + \snippet tools/contiguouscache/randomlistmodel.cpp 1 It is also worth considering pre-fetching items into the cache outside of the application's paint routine. This can be done either with a separate thread diff --git a/examples/tools/doc/src/customtype.qdoc b/examples/corelib/tools/doc/src/customtype.qdoc index e016933e04..f03fafec30 100644 --- a/examples/tools/doc/src/customtype.qdoc +++ b/examples/corelib/tools/doc/src/customtype.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example customtype + \example tools/customtype \title Custom Type Example \brief The Custom Type example shows how to integrate a custom type into Qt's @@ -56,7 +56,7 @@ of information (a QString and a QStringList), each of which can be read using trivial getter functions: - \snippet customtype/message.h custom type definition + \snippet tools/customtype/message.h custom type definition The default constructor, copy constructor and destructor are all required, and must be public, if the type is to be integrated into the @@ -67,14 +67,14 @@ To enable the type to be used with QVariant, we declare it using the Q_DECLARE_METATYPE() macro: - \snippet customtype/message.h custom type meta-type declaration + \snippet tools/customtype/message.h custom type meta-type declaration We do not need to write any additional code to accompany this macro. To allow us to see a readable description of each \c Message object when it is sent to the debug output stream, we define a streaming operator: - \snippet customtype/message.h custom type streaming operator + \snippet tools/customtype/message.h custom type streaming operator This facility is useful if you need to insert tracing statements in your code for debugging purposes. @@ -84,11 +84,11 @@ The implementation of the default constructor, copy constructor and destructor are straightforward for the \c Message class: - \snippet customtype/message.cpp Message class implementation + \snippet tools/customtype/message.cpp Message class implementation The streaming operator is implemented in the following way: - \snippet customtype/message.cpp custom type streaming operator + \snippet tools/customtype/message.cpp custom type streaming operator Here, we want to represent each value depending on how many lines are stored in the message body. We stream text to the QDebug object passed to the @@ -99,7 +99,7 @@ We include the code for the getter functions for completeness: - \snippet customtype/message.cpp getter functions + \snippet tools/customtype/message.cpp getter functions With the type fully defined, implemented, and integrated with the meta-object system, we can now use it. @@ -109,13 +109,13 @@ In the example's \c{main()} function, we show how a \c Message object can be printed to the console by sending it to the debug stream: - \snippet customtype/main.cpp printing a custom type + \snippet tools/customtype/main.cpp printing a custom type You can use the type with QVariant in exactly the same way as you would use standard Qt value types. Here's how to store a value using the QVariant::setValue() function: - \snippet customtype/main.cpp storing a custom value + \snippet tools/customtype/main.cpp storing a custom value Alternatively, the QVariant::fromValue() and qVariantSetValue() functions can be used if you are using a compiler without support for member template @@ -124,7 +124,7 @@ The value can be retrieved using the QVariant::value() member template function: - \snippet customtype/main.cpp retrieving a custom value + \snippet tools/customtype/main.cpp retrieving a custom value Alternatively, the qVariantValue() template function can be used if you are using a compiler without support for member template functions. diff --git a/examples/tools/tools.pro b/examples/corelib/tools/tools.pro index 36fa776980..36fa776980 100644 --- a/examples/tools/tools.pro +++ b/examples/corelib/tools/tools.pro diff --git a/examples/examples.pro b/examples/examples.pro index 052802b803..bcc13704dc 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -2,18 +2,15 @@ TEMPLATE = subdirs CONFIG += no_docs_target SUBDIRS = \ + corelib \ dbus \ embedded \ gui \ - ipc \ - json \ network \ qpa \ qtconcurrent \ qtestlib \ sql \ - threads \ - tools \ touch \ widgets \ xml diff --git a/examples/opengl/threadedqopenglwidget/glwidget.cpp b/examples/opengl/threadedqopenglwidget/glwidget.cpp index d447f0c716..ecf1287045 100644 --- a/examples/opengl/threadedqopenglwidget/glwidget.cpp +++ b/examples/opengl/threadedqopenglwidget/glwidget.cpp @@ -42,8 +42,6 @@ #include <math.h> #include <QGuiApplication> -const int bubbleNum = 8; - GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent) { diff --git a/examples/opengl/threadedqopenglwidget/glwidget.h b/examples/opengl/threadedqopenglwidget/glwidget.h index 8319faf322..c063e846dc 100644 --- a/examples/opengl/threadedqopenglwidget/glwidget.h +++ b/examples/opengl/threadedqopenglwidget/glwidget.h @@ -100,7 +100,7 @@ class GLWidget : public QOpenGLWidget { Q_OBJECT public: - GLWidget(QWidget *parent); + explicit GLWidget(QWidget *parent = 0); ~GLWidget(); protected: diff --git a/examples/opengl/threadedqopenglwidget/main.cpp b/examples/opengl/threadedqopenglwidget/main.cpp index 75b7f5e46f..2c94469b7c 100644 --- a/examples/opengl/threadedqopenglwidget/main.cpp +++ b/examples/opengl/threadedqopenglwidget/main.cpp @@ -40,10 +40,19 @@ #include <QApplication> #include <QMainWindow> +#include <QDesktopWidget> #include <QSurfaceFormat> +#include <QOpenGLContext> #include "mainwindow.h" #include "glwidget.h" +static QString getGlString(QOpenGLFunctions *functions, GLenum name) +{ + if (const GLubyte *p = functions->glGetString(name)) + return QString::fromLatin1(reinterpret_cast<const char *>(p)); + return QString(); +} + int main( int argc, char ** argv ) { QApplication a( argc, argv ); @@ -54,20 +63,38 @@ int main( int argc, char ** argv ) // Two top-level windows with two QOpenGLWidget children in each. // The rendering for the four QOpenGLWidgets happens on four separate threads. - MainWindow mw1; - mw1.setMinimumSize(800, 400); - mw1.show(); + GLWidget topLevelGlWidget; + QPoint pos = QApplication::desktop()->availableGeometry(&topLevelGlWidget).topLeft() + QPoint(200, 200); + topLevelGlWidget.setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example top level")); + topLevelGlWidget.resize(200, 200); + topLevelGlWidget.move(pos); + topLevelGlWidget.show(); + + const QString glInfo = getGlString(topLevelGlWidget.context()->functions(), GL_VENDOR) + + QLatin1Char('/') + getGlString(topLevelGlWidget.context()->functions(), GL_RENDERER); + + const bool supportsThreading = !glInfo.contains(QLatin1String("nouveau"), Qt::CaseInsensitive) + && !glInfo.contains(QLatin1String("ANGLE"), Qt::CaseInsensitive); + + const QString toolTip = supportsThreading ? glInfo : glInfo + QStringLiteral("\ndoes not support threaded OpenGL."); + topLevelGlWidget.setToolTip(toolTip); + + QScopedPointer<MainWindow> mw1; QScopedPointer<MainWindow> mw2; - if (!QApplication::arguments().contains(QStringLiteral("--single"))) { + if (supportsThreading && !QApplication::arguments().contains(QStringLiteral("--single"))) { + pos += QPoint(100, 100); + mw1.reset(new MainWindow); + mw1->setToolTip(toolTip); + mw1->move(pos); + mw1->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #1")); + mw1->show(); + pos += QPoint(100, 100); mw2.reset(new MainWindow); - mw2->setMinimumSize(800, 400); + mw2->setToolTip(toolTip); + mw2->move(pos); + mw2->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #2")); mw2->show(); - - // And a top-level. - GLWidget *bonus = new GLWidget(0); - bonus->resize(200, 200); - bonus->show(); } return a.exec(); diff --git a/examples/opengl/threadedqopenglwidget/mainwindow.cpp b/examples/opengl/threadedqopenglwidget/mainwindow.cpp index 29c59573cf..de866f5615 100644 --- a/examples/opengl/threadedqopenglwidget/mainwindow.cpp +++ b/examples/opengl/threadedqopenglwidget/mainwindow.cpp @@ -43,6 +43,7 @@ MainWindow::MainWindow() { + setMinimumSize(800, 400); GLWidget *glwidget1 = new GLWidget(this); glwidget1->resize(400, 400); diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf index 8a70ce041a..3834a55ac5 100644 --- a/mkspecs/features/qt_plugin.prf +++ b/mkspecs/features/qt_plugin.prf @@ -17,6 +17,12 @@ TEMPLATE = lib CONFIG += plugin DESTDIR = $$MODULE_BASE_OUTDIR/plugins/$$PLUGIN_TYPE +win32:CONFIG(shared, static|shared) { + # Embed a VERSIONINFO resource into the plugin's DLL. + isEmpty(VERSION): VERSION = $$QT_VERSION + CONFIG += skip_target_version_ext +} + tool_plugin { !build_pass:contains(QT_CONFIG, build_all): CONFIG += release } else:if(win32|mac):!macx-xcode { diff --git a/mkspecs/macx-clang-32/qmake.conf b/mkspecs/macx-clang-32/qmake.conf index e0c4bd57b7..87c601ee74 100644 --- a/mkspecs/macx-clang-32/qmake.conf +++ b/mkspecs/macx-clang-32/qmake.conf @@ -11,7 +11,7 @@ include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CFLAGS += -arch i386 QMAKE_OBJECTIVE_CFLAGS += -arch i386 diff --git a/mkspecs/macx-clang/qmake.conf b/mkspecs/macx-clang/qmake.conf index f28b728bd9..d14b11179a 100644 --- a/mkspecs/macx-clang/qmake.conf +++ b/mkspecs/macx-clang/qmake.conf @@ -11,6 +11,6 @@ include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 load(qt_config) diff --git a/mkspecs/macx-g++-32/qmake.conf b/mkspecs/macx-g++-32/qmake.conf index 6ef78aacbf..2a8197ebbd 100644 --- a/mkspecs/macx-g++-32/qmake.conf +++ b/mkspecs/macx-g++-32/qmake.conf @@ -14,7 +14,7 @@ include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/g++-macx.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CFLAGS += -arch i386 QMAKE_OBJECTIVE_CFLAGS += -arch i386 diff --git a/mkspecs/macx-g++/qmake.conf b/mkspecs/macx-g++/qmake.conf index a6c075a2ce..9c44f278e9 100644 --- a/mkspecs/macx-g++/qmake.conf +++ b/mkspecs/macx-g++/qmake.conf @@ -14,6 +14,6 @@ include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/g++-macx.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 load(qt_config) diff --git a/mkspecs/macx-g++40/qmake.conf b/mkspecs/macx-g++40/qmake.conf index f40315a602..0f2dd6bb71 100644 --- a/mkspecs/macx-g++40/qmake.conf +++ b/mkspecs/macx-g++40/qmake.conf @@ -14,7 +14,7 @@ include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/g++-macx.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CC = gcc-4.0 QMAKE_CXX = g++-4.0 diff --git a/mkspecs/macx-g++42/qmake.conf b/mkspecs/macx-g++42/qmake.conf index 25383e9cb6..e003193e1b 100644 --- a/mkspecs/macx-g++42/qmake.conf +++ b/mkspecs/macx-g++42/qmake.conf @@ -14,7 +14,7 @@ include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/g++-macx.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_CC = gcc-4.2 QMAKE_CXX = g++-4.2 diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index 521e64e364..a1783c97ad 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -85,7 +85,7 @@ QMAKE_CXXFLAGS_PRECOMPILE = -c -pch-create ${QMAKE_PCH_OUTPUT} -include ${QMAKE_ QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 include(../common/macx.conf) diff --git a/mkspecs/macx-llvm/qmake.conf b/mkspecs/macx-llvm/qmake.conf index 7bdef70943..cf4e00cd61 100644 --- a/mkspecs/macx-llvm/qmake.conf +++ b/mkspecs/macx-llvm/qmake.conf @@ -14,7 +14,7 @@ include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/llvm.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvmgcc42 diff --git a/mkspecs/unsupported/linux-libc++-clang/qmake.conf b/mkspecs/unsupported/linux-libc++-clang/qmake.conf deleted file mode 100644 index bf0abb2a54..0000000000 --- a/mkspecs/unsupported/linux-libc++-clang/qmake.conf +++ /dev/null @@ -1,20 +0,0 @@ -# -# qmake configuration for linux-clang -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += incremental - -QMAKE_INCREMENTAL_STYLE = sublib - -include(../../common/linux.conf) -include(../../common/gcc-base-unix.conf) -include(../../common/clang.conf) - -QMAKE_CFLAGS_RELEASE = -Os -QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE - -QMAKE_CXXFLAGS_CXX11 += -std=c++11 -stdlib=libc++ -QMAKE_LFLAGS_CXX11 += -stdlib=libc++ -lc++abi - -load(qt_config) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 6dad8888ce..ed5be81d80 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -1090,8 +1090,6 @@ public class QtActivityDelegate Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); return; } - - m_layout.requestLayout(); } public void destroySurface(int id) { diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java index 6de66fe512..80028e1b02 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java @@ -174,6 +174,9 @@ public class QtInputConnection extends BaseInputConnection QtExtractedText qExtractedText = QtNativeInputConnection.getExtractedText(request.hintMaxChars, request.hintMaxLines, flags); + if (qExtractedText == null) + return null; + ExtractedText extractedText = new ExtractedText(); extractedText.partialEndOffset = qExtractedText.partialEndOffset; extractedText.partialStartOffset = qExtractedText.partialStartOffset; diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index e526c0a210..0c52bc7530 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -99,7 +99,7 @@ import android.view.ActionMode.Callback; public class QtActivity extends Activity { private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished - private static final int MINISTRO_API_LEVEL = 4; // Ministro api level (check IMinistro.aidl file) + private static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file) private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0 diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml index 664ab0abec..4d68673cb0 100644 --- a/src/android/templates/res/values/libs.xml +++ b/src/android/templates/res/values/libs.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> <resources> <array name="qt_sources"> - <item>https://download.qt-project.org/ministro/android/qt5/qt-5.3</item> + <item>https://download.qt-project.org/ministro/android/qt5/qt-5.4</item> </array> <!-- The following is handled automatically by the deployment tool. It should diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index 7c879cbbfd..5a14ba9088 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -4,7 +4,7 @@ project = QtCore description = Qt Core Reference Documentation version = $QT_VERSION -examplesinstallpath = core +examplesinstallpath = corelib qhp.projects = QtCore @@ -35,10 +35,7 @@ sourcedirs += .. exampledirs += \ ../ \ snippets \ - ../../../examples/threads/ \ - ../../../examples/tools/ \ - ../../../examples/ipc/ \ - ../../../examples/json/ \ + ../../../examples/corelib \ ../../../examples/network/dnslookup imagedirs += images diff --git a/src/corelib/doc/src/custom-types.qdoc b/src/corelib/doc/src/custom-types.qdoc index bac4a90829..81ce698735 100644 --- a/src/corelib/doc/src/custom-types.qdoc +++ b/src/corelib/doc/src/custom-types.qdoc @@ -61,7 +61,7 @@ The following \c Message class definition includes these members: - \snippet customtype/message.h custom type definition + \snippet tools/customtype/message.h custom type definition The class also provides a constructor for normal use and two public member functions that are used to obtain the private data. @@ -77,7 +77,7 @@ to this class, we invoke the Q_DECLARE_METATYPE() macro on the class in the header file where it is defined: - \snippet customtype/message.h custom type meta-type declaration + \snippet tools/customtype/message.h custom type meta-type declaration This now makes it possible for \c Message values to be stored in QVariant objects and retrieved later. See the \l{Custom Type Example} for code that demonstrates @@ -104,19 +104,19 @@ The \l{Queued Custom Type Example} declares a \c Block class which is registered in the \c{main.cpp} file: - \snippet queuedcustomtype/main.cpp main start + \snippet threads/queuedcustomtype/main.cpp main start \dots - \snippet queuedcustomtype/main.cpp register meta-type for queued communications + \snippet threads/queuedcustomtype/main.cpp register meta-type for queued communications \dots - \snippet queuedcustomtype/main.cpp main finish + \snippet threads/queuedcustomtype/main.cpp main finish This type is later used in a signal-slot connection in the \c{window.cpp} file: - \snippet queuedcustomtype/window.cpp Window constructor start + \snippet threads/queuedcustomtype/window.cpp Window constructor start \dots - \snippet queuedcustomtype/window.cpp connecting signal with custom type + \snippet threads/queuedcustomtype/window.cpp connecting signal with custom type \dots - \snippet queuedcustomtype/window.cpp Window constructor finish + \snippet threads/queuedcustomtype/window.cpp Window constructor finish If a type is used in a queued connection without being registered, a warning will be printed at the console; for example: @@ -131,18 +131,18 @@ It is often quite useful to make a custom type printable for debugging purposes, as in the following code: - \snippet customtype/main.cpp printing a custom type + \snippet tools/customtype/main.cpp printing a custom type This is achieved by creating a streaming operator for the type, which is often defined in the header file for that type: - \snippet customtype/message.h custom type streaming operator + \snippet tools/customtype/message.h custom type streaming operator The implementation for the \c Message type in the \l{Custom Type Example} goes to some effort to make the printable representation as readable as possible: - \snippet customtype/message.cpp custom type streaming operator + \snippet tools/customtype/message.cpp custom type streaming operator The output sent to the debug stream can, of course, be made as simple or as complicated as you like. Note that the value returned by this function is diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index ac60d47c7e..8e52c50322 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -730,8 +730,6 @@ /* C++11 features supported in GCC 4.4: */ # define Q_COMPILER_AUTO_FUNCTION # define Q_COMPILER_AUTO_TYPE -# define Q_COMPILER_DEFAULT_MEMBERS -# define Q_COMPILER_DELETE_MEMBERS # define Q_COMPILER_EXTERN_TEMPLATES # define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_UNICODE_STRINGS @@ -748,6 +746,11 @@ # define Q_COMPILER_CLASS_ENUM # endif # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + /* Pre-4.6 compilers implement a non-final snapshot of N2346, hence default and delete + * functions are supported only if they are public. Starting from 4.6, GCC handles + * final version - the access modifier is not relevant. */ +# define Q_COMPILER_DEFAULT_MEMBERS +# define Q_COMPILER_DELETE_MEMBERS /* C++11 features supported in GCC 4.6: */ # define Q_COMPILER_CONSTEXPR # define Q_COMPILER_NULLPTR diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index e86d986581..04c38b5f27 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2502,7 +2502,9 @@ QString QSysInfo::productVersion() // fall through // Android and Blackberry should not fall through to the Unix code -#elif defined(Q_OS_ANDROID) +#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + return QJNIObjectPrivate::getStaticObjectField("android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString(); +#elif defined(Q_OS_ANDROID) // Q_OS_ANDROID_NO_SDK // TBD #elif defined(Q_OS_BLACKBERRY) deviceinfo_details_t *deviceInfo; diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 2a4f2dd4d6..f356bab42d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -653,9 +653,10 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info) int pos; - // skip trailing [with XXX] for templates (gcc) + // Skip trailing [with XXX] for templates (gcc), but make + // sure to not affect Objective-C message names. pos = info.size() - 1; - if (info.endsWith(']')) { + if (info.endsWith(']') && !(info.startsWith('+') || info.startsWith('-'))) { while (--pos) { if (info.at(pos) == '[') info.truncate(pos); diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index 8691a44d8d..8d1c59e159 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -608,9 +608,9 @@ qint64 QFileDevice::size() const } /*! - Sets the file size (in bytes) \a sz. Returns \c true if the file if the + Sets the file size (in bytes) \a sz. Returns \c true if the resize succeeds; false otherwise. If \a sz is larger than the file - currently is the new bytes will be set to 0, if \a sz is smaller the + currently is, the new bytes will be set to 0; if \a sz is smaller, the file is simply truncated. \sa size() diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index cf1218cb41..147acda3d6 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -66,7 +66,8 @@ class QFileSystemMetaData { public: QFileSystemMetaData() - : knownFlagsMask(0) + : knownFlagsMask(0), + size_(-1) { } diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 5d5a29243e..3963a9cb11 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QFSFileEnginePrivate; -class Q_AUTOTEST_EXPORT QFSFileEngine : public QAbstractFileEngine +class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine { Q_DECLARE_PRIVATE(QFSFileEngine) public: diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index e9ee8d9458..8af1487834 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -398,9 +398,11 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) // hard-wired implementation of // qt.*.debug=false // qt.debug=false - char c; - if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.')) - debug = false; + if (const char *categoryName = cat->categoryName()) { + // == "qt" or startsWith("qt.") + if (strcmp(categoryName, "qt") == 0 || strncmp(categoryName, "qt.", 3) == 0) + debug = false; + } QString categoryName = QLatin1String(cat->categoryName()); foreach (const QLoggingRule &item, reg->rules) { diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index e009191be9..e76a836954 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -538,6 +538,13 @@ void QProcessPrivate::Channel::clear() setWorkingDirectory(). By default, processes are run in the current working directory of the calling process. + The positioning and the screen Z-order of windows belonging to + GUI applications started with QProcess are controlled by + the underlying windowing system. For Qt 5 applications, the + positioning can be specified using the \c{-qwindowgeometry} + command line option; X11 applications generally accept a + \c{-geometry} command line option. + \note On QNX, setting the working directory may cause all application threads, with the exception of the QProcess caller thread, to temporarily freeze during the spawning process, diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 980fb58865..ee6b7e13f4 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -634,7 +634,7 @@ bool QProcessPrivate::drainOutputPipes() someReadyReadEmitted |= readyReadEmitted; if (!readOperationActive || !readyReadEmitted) break; - Sleep(100); + QThread::yieldCurrentThread(); } return someReadyReadEmitted; diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index f6cd5aa7c9..d896da176a 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -100,6 +100,10 @@ using namespace ABI::Windows::Storage; #define CSIDL_APPDATA 0x001a // <username>\Application Data #endif +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID) +#define Q_XDG_PLATFORM +#endif + // ************************************************************************ // QConfFile @@ -1041,7 +1045,9 @@ static void initDefaultPaths(QMutexLocker *locker) windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator()); #else -#ifdef QT_NO_STANDARDPATHS +#if defined(QT_NO_STANDARDPATHS) || !defined(Q_XDG_PLATFORM) + // Non XDG platforms (OS X, iOS, Blackberry, Android...) have used this code path erroneously + // for some time now. Moving away from that would require migrating existing settings. QString userPath; char *env = getenv("XDG_CONFIG_HOME"); if (env == 0) { @@ -1056,6 +1062,9 @@ static void initDefaultPaths(QMutexLocker *locker) userPath += QFile::decodeName(env); } #else + // When using a proper XDG platform, use QStandardPaths rather than the above hand-written code; + // it makes the use of test mode from unit tests possible. + // Ideally all platforms should use this, but see above for the migration issue. QString userPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); #endif userPath += QLatin1Char('/'); @@ -3112,6 +3121,10 @@ bool QSettings::isWritable() const void QSettings::setValue(const QString &key, const QVariant &value) { Q_D(QSettings); + if (key.isEmpty()) { + qWarning("QSettings::setValue: Empty key passed"); + return; + } QString k = d->actualKey(key); d->set(k, value); d->requestUpdate(); @@ -3244,6 +3257,10 @@ bool QSettings::event(QEvent *event) QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const { Q_D(const QSettings); + if (key.isEmpty()) { + qWarning("QSettings::value: Empty key passed"); + return QVariant(); + } QVariant result = defaultValue; QString k = d->actualKey(key); d->get(k, &result); diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 68ab03976f..74a7ea1988 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -3375,7 +3375,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const QAbstractItemModel, it is not suitable for use with tree views; you will need to subclass QAbstractItemModel if you want to provide a model for that purpose. If you need to use a number of list models to manage data, - it may be more appropriate to subclass QAbstractTableModel class instead. + it may be more appropriate to subclass QAbstractTableModel instead. Simple models can be created by subclassing this class and implementing the minimum number of required functions. For example, we could implement @@ -3399,7 +3399,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const default ones provided by the roleNames() function, you must override it. For editable list models, you must also provide an implementation of - setData(), implement the flags() function so that it returns a value + setData(), and implement the flags() function so that it returns a value containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}. Note that QAbstractListModel provides a default implementation of diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 7816edd3f9..a3d00faf31 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -639,7 +639,6 @@ void QEventDispatcherWin32::createInternalHwnd() { Q_D(QEventDispatcherWin32); - Q_ASSERT(!d->internalHwnd); if (d->internalHwnd) return; d->internalHwnd = qt_create_internal_window(this); @@ -664,9 +663,6 @@ void QEventDispatcherWin32::createInternalHwnd() // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); - - // trigger a call to sendPostedEvents() - wakeUp(); } QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent) @@ -686,8 +682,10 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherWin32); - if (!d->internalHwnd) + if (!d->internalHwnd) { createInternalHwnd(); + wakeUp(); // trigger a call to sendPostedEvents() + } d->interrupt = false; emit awake(); diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index f9bb06a5c5..369c276615 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -65,8 +65,8 @@ class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher Q_OBJECT Q_DECLARE_PRIVATE(QEventDispatcherWin32) +protected: void createInternalHwnd(); - friend class QGuiEventDispatcherWin32; public: explicit QEventDispatcherWin32(QObject *parent = 0); diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 173127b063..452e3464d6 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -80,38 +80,22 @@ static QString toDotEncodedClassName(const char *className) return QString::fromLatin1(className).replace(QLatin1Char('/'), QLatin1Char('.')); } -static jclass getCachedClass(const QString &classDotEnc) +static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0) { QHash<QString, jclass>::iterator it = cachedClasses->find(classDotEnc); + const bool found = (it != cachedClasses->end()); - if (it == cachedClasses->end()) - return 0; - - return it.value(); -} - -static jclass findClass(const char *className, JNIEnv *env) -{ - const QString &classDotEnc = toDotEncodedClassName(className); - jclass clazz = getCachedClass(classDotEnc); - if (clazz != 0) - return clazz; - - jclass fclazz = env->FindClass(className); - if (!exceptionCheckAndClear(env)) { - clazz = static_cast<jclass>(env->NewGlobalRef(fclazz)); - env->DeleteLocalRef(fclazz); - } + if (isCached != 0) + *isCached = found; - cachedClasses->insert(classDotEnc, clazz); - return clazz; + return found ? it.value() : 0; } -static jclass loadClass(const char *className, JNIEnv *env) +static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env) { - const QString &classDotEnc = toDotEncodedClassName(className); - jclass clazz = getCachedClass(classDotEnc); - if (clazz != 0) + bool isCached = false; + jclass clazz = getCachedClass(classDotEnc, &isCached); + if (clazz != 0 || isCached) return clazz; QJNIObjectPrivate classLoader = QtAndroidPrivate::classLoader(); @@ -130,6 +114,11 @@ static jclass loadClass(const char *className, JNIEnv *env) return clazz; } +inline static jclass loadClass(const char *className, JNIEnv *env) +{ + return loadClassDotEnc(toDotEncodedClassName(className), env); +} + typedef QHash<QString, jmethodID> JMethodIDHash; Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID) @@ -224,12 +213,28 @@ JNIEnv *QJNIEnvironmentPrivate::operator->() jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env) { - jclass clazz = 0; - if (env != 0) - clazz = ::findClass(className, env); + const QString &classDotEnc = toDotEncodedClassName(className); + bool isCached = false; + jclass clazz = getCachedClass(classDotEnc, &isCached); + + const bool found = (clazz != 0) || (clazz == 0 && isCached); + + if (found) + return clazz; + + if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass()) + jclass fclazz = env->FindClass(className); + if (!exceptionCheckAndClear(env)) { + clazz = static_cast<jclass>(env->NewGlobalRef(fclazz)); + env->DeleteLocalRef(fclazz); + } + + if (clazz != 0) + cachedClasses->insert(classDotEnc, clazz); + } - if (clazz == 0) - clazz = loadClass(className, QJNIEnvironmentPrivate()); + if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader... + clazz = loadClassDotEnc(classDotEnc, QJNIEnvironmentPrivate()); return clazz; } diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp index c0f8897b3b..eb1019534c 100644 --- a/src/corelib/kernel/qtcore_eval.cpp +++ b/src/corelib/kernel/qtcore_eval.cpp @@ -111,10 +111,11 @@ static EvaluationStatus qt_eval_is_supported() static int qt_eval_days_left() { - const char *expiry_date = const_cast<const char*>(qt_eval_expiry_date + 12); + const volatile char *const expiry_date = qt_eval_expiry_date + 12; QDate today = QDate::currentDate(); - QDate lastday = QDate::fromString(QString::fromLatin1(expiry_date), Qt::ISODate); + QDate lastday = QDate::fromString( + QString::fromLatin1(const_cast<const char*>(expiry_date)), Qt::ISODate); return today.daysTo(lastday); } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 4fa07b17d4..69d4bd7d99 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -4452,7 +4452,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) if (size == 10) return QDateTime(date); - isoString = isoString.right(11); + isoString = isoString.right(isoString.length() - 11); int offset = 0; // Check end of string for Time Zone definition, either Z for UTC or [+-]HH:MM for Offset if (isoString.endsWith(QLatin1Char('Z'))) { diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 4ef94f72d7..ec1e78c358 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -36,7 +36,7 @@ #include <QtCore/qstring.h> #include <QtCore/qnamespace.h> -#include <QtCore/qsharedpointer.h> +#include <QtCore/qshareddata.h> #include <limits> diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index b4ecc65f29..f7bf6ed28b 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -1478,6 +1478,8 @@ QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing) bool hasConfig; stream >> hasConfig; + delete easing.d_ptr->config; + easing.d_ptr->config = Q_NULLPTR; if (hasConfig) { QEasingCurveFunction *config = curveToFunctionObject(type); stream >> config->_p; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 7de7d74595..ae44e4185a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8951,7 +8951,7 @@ QStringRef QStringRef::right(int n) const { if (uint(n) >= uint(m_size)) return *this; - return QStringRef(m_string, n + m_position, m_size - n); + return QStringRef(m_string, m_size - n + m_position, n); } /*! diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index ec9a8fdcf0..5be9f19b3e 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -463,9 +463,14 @@ const QMimeData* QClipboard::mimeData(Mode mode) const void QClipboard::setMimeData(QMimeData* src, Mode mode) { QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard(); - if (!clipboard->supportsMode(mode)) return; - - clipboard->setMimeData(src,mode); + if (!clipboard->supportsMode(mode)) { + if (src != 0) { + qWarning("Data set on unsupported clipboard mode. QMimeData object will be deleted."); + src->deleteLater(); + } + } else { + clipboard->setMimeData(src,mode); + } } /*! diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index f99f28d6e0..a8539e8013 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -897,12 +897,11 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, when keys are pressed or released. A key event contains a special accept flag that indicates whether - the receiver will handle the key event. You should call ignore() - if the key press or release event is not handled by your widget. - A key event is propagated up the parent widget chain until a - widget accepts it with accept() or an event filter consumes it. - Key events for multimedia keys are ignored by default. You should - call accept() if your widget handles those events. + the receiver will handle the key event. This flag is set by default, + so there is no need to call accept() when acting on a key event. + Calling ignore() on a key event will propagate it to the parent widget. + The event is propagated up the parent widget chain until a widget + accepts it or an event filter consumes it. The QWidget::setEnable() function can be used to enable or disable mouse and keyboard events for a widget. diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp index 56c4fbbf8b..5cf77de5d8 100644 --- a/src/gui/kernel/qoffscreensurface.cpp +++ b/src/gui/kernel/qoffscreensurface.cpp @@ -64,6 +64,12 @@ QT_BEGIN_NAMESPACE typically use a pixel buffer (pbuffer). If the platform doesn't implement or support offscreen surfaces, QOffscreenSurface will use an invisible QWindow internally. + \note Due to the fact that QOffscreenSurface is backed by a QWindow on some platforms, + cross-platform applications must ensure that create() is only called on the main (GUI) + thread. The QOffscreenSurface is then safe to be used with + \l{QOpenGLContext::makeCurrent()}{makeCurrent()} on other threads, but the + initialization and destruction must always happen on the main (GUI) thread. + \note In order to create an offscreen surface that is guaranteed to be compatible with a given context and window, make sure to set the format to the context's or the window's actual format, that is, the QSurfaceFormat returned from @@ -152,6 +158,8 @@ QOffscreenSurface::SurfaceType QOffscreenSurface::surfaceType() const Call destroy() to free the platform resources if necessary. + \note Some platforms require this function to be called on the main (GUI) thread. + \sa destroy() */ void QOffscreenSurface::create() diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 51b4a6a079..07a7c601fa 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -350,16 +350,6 @@ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context return previous; } -void QOpenGLContextPrivate::setGlobalShareContext(QOpenGLContext *context) -{ - qt_gl_set_global_share_context(context); -} - -QOpenGLContext *QOpenGLContextPrivate::globalShareContext() -{ - return qt_gl_global_share_context(); -} - int QOpenGLContextPrivate::maxTextureSize() { if (max_texture_size != -1) diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 7c45737d0a..d5a3126176 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -241,9 +241,6 @@ public: static QOpenGLContext *setCurrentContext(QOpenGLContext *context); - static void setGlobalShareContext(QOpenGLContext *context); - static QOpenGLContext *globalShareContext(); - int maxTextureSize(); static QOpenGLContextPrivate *get(QOpenGLContext *context) diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp index 2b6692c461..158fb248dc 100644 --- a/src/gui/kernel/qopenglwindow.cpp +++ b/src/gui/kernel/qopenglwindow.cpp @@ -211,8 +211,11 @@ public: context->makeCurrent(q); } + const int deviceWidth = q->width() * q->devicePixelRatio(); + const int deviceHeight = q->height() * q->devicePixelRatio(); + const QSize deviceSize(deviceWidth, deviceHeight); if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { - if (!fbo || fbo->size() != q->size() * q->devicePixelRatio()) { + if (!fbo || fbo->size() != deviceSize) { QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); if (q->requestedFormat().samples() > 0) { @@ -221,15 +224,13 @@ public: else qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling"); } - fbo.reset(new QOpenGLFramebufferObject(q->size() * q->devicePixelRatio(), fboFormat)); + fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat)); markWindowAsDirty(); } } else { markWindowAsDirty(); } - const int deviceWidth = q->width() * q->devicePixelRatio(); - const int deviceHeight = q->height() * q->devicePixelRatio(); paintDevice->setSize(QSize(deviceWidth, deviceHeight)); paintDevice->setDevicePixelRatio(q->devicePixelRatio()); context->functions()->glViewport(0, 0, deviceWidth, deviceHeight); @@ -252,11 +253,13 @@ public: context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject()); if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) { + const int deviceWidth = q->width() * q->devicePixelRatio(); + const int deviceHeight = q->height() * q->devicePixelRatio(); QOpenGLExtensions extensions(context.data()); extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle()); extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject()); - extensions.glBlitFramebuffer(0, 0, q->width(), q->height(), - 0, 0, q->width(), q->height(), + extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight, + 0, 0, deviceWidth, deviceHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) { @@ -591,7 +594,7 @@ int QOpenGLWindow::metric(PaintDeviceMetric metric) const break; case PdmDevicePixelRatio: if (d->paintDevice) - return d->paintDevice->devicePixelRatio(); + return devicePixelRatio(); break; default: break; diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index c832de0be6..0093ef1538 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -108,11 +108,6 @@ public: virtual void setFont(const QFont &font) { Q_UNUSED(font); } virtual void setMenuType(MenuType type) { Q_UNUSED(type); } - virtual void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) - { - showPopup(parentWindow, QRect(pos, QSize()), item); - } - virtual void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) { Q_UNUSED(parentWindow); diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index d03a3f7be8..bd95a8614f 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -201,9 +201,13 @@ bool QWindowSystemInterface::tryHandleShortcutEvent(QWindow *w, ulong timestamp, #ifndef QT_NO_SHORTCUT QGuiApplicationPrivate::modifier_buttons = mods; + QObject *focus = w->focusObject(); + if (!focus) + focus = w; + QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count); qevent.setTimestamp(timestamp); - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(w, &qevent); + return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent); #else Q_UNUSED(w) Q_UNUSED(timestamp) @@ -231,9 +235,13 @@ bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, ulong ti #ifndef QT_NO_SHORTCUT QGuiApplicationPrivate::modifier_buttons = mods; + QObject *focus = w->focusObject(); + if (!focus) + focus = w; + QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); qevent.setTimestamp(timestamp); - return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(w, &qevent); + return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent); #else Q_UNUSED(w) Q_UNUSED(timestamp) diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index f82401c973..adf5428c49 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -11,6 +11,7 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) { opengl/qopenglframebufferobject.h \ opengl/qopenglframebufferobject_p.h \ opengl/qopenglpaintdevice.h \ + opengl/qopenglpaintdevice_p.h \ opengl/qopenglbuffer.h \ opengl/qopenglshaderprogram.h \ opengl/qopenglextensions_p.h \ diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp index 59bca6efdf..e908fd8e91 100644 --- a/src/gui/opengl/qopenglpaintdevice.cpp +++ b/src/gui/opengl/qopenglpaintdevice.cpp @@ -35,6 +35,7 @@ #include <qpaintengine.h> #include <qthreadstorage.h> +#include <private/qopenglpaintdevice_p.h> #include <private/qobject_p.h> #include <private/qopenglcontext_p.h> #include <private/qopenglframebufferobject_p.h> @@ -98,23 +99,6 @@ QT_BEGIN_NAMESPACE */ -class QOpenGLPaintDevicePrivate -{ -public: - QOpenGLPaintDevicePrivate(const QSize &size); - - QSize size; - QOpenGLContext *ctx; - - qreal dpmx; - qreal dpmy; - qreal devicePixelRatio; - - bool flipped; - - QPaintEngine *engine; -}; - /*! Constructs a QOpenGLPaintDevice. @@ -152,6 +136,14 @@ QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height) } /*! + \internal + */ +QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd) + : d_ptr(dd) +{ +} + +/*! Destroys the QOpenGLPaintDevice. */ @@ -355,7 +347,10 @@ bool QOpenGLPaintDevice::paintFlipped() const frame buffer object or context when different QOpenGLPaintDevice instances are issuing draw calls alternately. - QPainter::beginNativePainting will also trigger this method. + \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger + this method. + + The default implementation does nothing. */ void QOpenGLPaintDevice::ensureActiveTarget() { diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h index e1be9b525d..dda3bfe43f 100644 --- a/src/gui/opengl/qopenglpaintdevice.h +++ b/src/gui/opengl/qopenglpaintdevice.h @@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE - class QOpenGLPaintDevicePrivate; class Q_GUI_EXPORT QOpenGLPaintDevice : public QPaintDevice @@ -54,6 +53,7 @@ public: QOpenGLPaintDevice(); explicit QOpenGLPaintDevice(const QSize &size); QOpenGLPaintDevice(int width, int height); + QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd); virtual ~QOpenGLPaintDevice(); int devType() const { return QInternal::OpenGL; } diff --git a/mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h b/src/gui/opengl/qopenglpaintdevice_p.h index 0f0c60b148..0b01129a84 100644 --- a/mkspecs/unsupported/linux-libc++-clang/qplatformdefs.h +++ b/src/gui/opengl/qopenglpaintdevice_p.h @@ -3,7 +3,7 @@ ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the qmake spec of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage @@ -31,62 +31,51 @@ ** ****************************************************************************/ -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H +#ifndef QOPENGL_PAINTDEVICE_P_H +#define QOPENGL_PAINTDEVICE_P_H -// Get Qt defines/settings +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Qt OpenGL classes. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// -#include "qglobal.h" +#include <qopenglpaintdevice.h> -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs +QT_BEGIN_NAMESPACE -// 1) need to reset default environment if _BSD_SOURCE is defined -// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0 -// 3) it seems older glibc need this to include the X/Open stuff -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif +class QOpenGLContext; +class QPaintEngine; -#include <unistd.h> +class Q_GUI_EXPORT QOpenGLPaintDevicePrivate +{ +public: + QOpenGLPaintDevicePrivate(const QSize &size); + virtual ~QOpenGLPaintDevicePrivate() { } + static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); } -// We are hot - unistd.h should have turned on the specific APIs we requested + virtual void beginPaint() { } + virtual void endPaint() { } -#include <features.h> -#include <pthread.h> -#include <dirent.h> -#include <fcntl.h> -#include <grp.h> -#include <pwd.h> -#include <signal.h> +public: + QSize size; + QOpenGLContext *ctx; -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/ipc.h> -#include <sys/time.h> -#include <sys/shm.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <netinet/in.h> -#ifndef QT_NO_IPV6IFNAME -#include <net/if.h> -#endif + qreal dpmx; + qreal dpmy; + qreal devicePixelRatio; -#define QT_USE_XOPEN_LFS_EXTENSIONS -#include "../../common/posix/qplatformdefs.h" + bool flipped; -#undef QT_SOCKLEN_T + QPaintEngine *engine; +}; -#if defined(__GLIBC__) && (__GLIBC__ >= 2) -#define QT_SOCKLEN_T socklen_t -#else -#define QT_SOCKLEN_T int -#endif +QT_END_NAMESPACE -#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf -#endif - -#endif // QPLATFORMDEFS_H +#endif // QOPENGL_PAINTDEVICE_P_H diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index 21bc4a95e8..c490726359 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -59,6 +59,7 @@ #include "qopenglgradientcache_p.h" #include "qopengltexturecache_p.h" #include "qopenglpaintengine_p.h" +#include "qopenglpaintdevice_p.h" #include <string.h> //for memcpy #include <qmath.h> @@ -1994,6 +1995,8 @@ bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev) d->ctx = QOpenGLContext::currentContext(); d->ctx->d_func()->active_engine = this; + QOpenGLPaintDevicePrivate::get(d->device)->beginPaint(); + d->funcs.initializeOpenGLFunctions(); for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) @@ -2044,6 +2047,8 @@ bool QOpenGL2PaintEngineEx::end() { Q_D(QOpenGL2PaintEngineEx); + QOpenGLPaintDevicePrivate::get(d->device)->endPaint(); + QOpenGLContext *ctx = d->ctx; d->funcs.glUseProgram(0); d->transferMode(BrushDrawingMode); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 12c7929047..34e22a30b8 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2597,8 +2597,7 @@ QRegion QPainter::clipRegion() const extern QPainterPath qt_regionToPath(const QRegion ®ion); /*! - Returns the currently clip as a path. Note that the clip path is - given in logical coordinates. + Returns the current clip path in logical coordinates. \warning QPainter does not store the combined clip explicitly as this is handled by the underlying QPaintEngine, so the path is diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 9caebc6ec6..54fcbac308 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -1452,7 +1452,8 @@ qreal QFont::letterSpacing() const Letter spacing changes the default spacing between individual letters in the font. The spacing between the letters can be - made smaller as well as larger. + made smaller as well as larger either in percentage of the + character width or in pixels, depending on the selected spacing type. \sa letterSpacing(), letterSpacingType(), setWordSpacing() */ diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 60f971a2fb..ad170e187c 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -384,12 +384,15 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 sockAddrIPv6.sin6_port = htons(port); QString scopeid = addr.scopeId(); - bool ok; - sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); + + if (!scopeid.isEmpty()) { + bool ok; + sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); #ifndef QT_NO_IPV6IFNAME - if (!ok) - sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); + if (!ok) + sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); #endif + } Q_IPV6ADDR ip6 = addr.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); @@ -498,11 +501,16 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); + QString scopeid = address.scopeId(); + + if (!scopeid.isEmpty()) { + bool ok; + sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); #ifndef QT_NO_IPV6IFNAME - sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data()); -#else - sockAddrIPv6.sin6_scope_id = address.scopeId().toInt(); + if (!ok) + sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); #endif + } Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); sockAddrSize = sizeof(sockAddrIPv6); @@ -917,12 +925,15 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l Q_IPV6ADDR tmp = host.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); QString scopeid = host.scopeId(); - bool ok; - sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); + + if (!scopeid.isEmpty()) { + bool ok; + sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); #ifndef QT_NO_IPV6IFNAME - if (!ok) - sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); + if (!ok) + sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); #endif + } sockAddrSize = sizeof(sockAddrIPv6); sockAddrPtr = (struct sockaddr *)&sockAddrIPv6; } else if (host.protocol() == QAbstractSocket::IPv4Protocol) { diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 8d38a5fd54..13bddcb3ea 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -662,7 +662,13 @@ QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectI return str; } +/*! + \fn uint qHash(const QSslCertificate &key, uint seed) + Returns the hash value for the \a key, using \a seed to seed the calculation. + \since 5.4 + \relates QHash +*/ #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QSslCertificate &certificate) diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index d1290b1d42..e34ea97fc4 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -59,6 +59,10 @@ class QSslKey; class QSslCertificateExtension; class QStringList; +class QSslCertificate; +// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4) +Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed = 0) Q_DECL_NOTHROW; + class QSslCertificatePrivate; class Q_NETWORK_EXPORT QSslCertificate { @@ -145,6 +149,8 @@ private: QExplicitlySharedDataPointer<QSslCertificatePrivate> d; friend class QSslCertificatePrivate; friend class QSslSocketBackendPrivate; + + friend Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW; }; Q_DECLARE_SHARED(QSslCertificate) diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp index 664f5eba08..1906c72ff8 100644 --- a/src/network/ssl/qsslcertificate_openssl.cpp +++ b/src/network/ssl/qsslcertificate_openssl.cpp @@ -62,6 +62,17 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const return false; } +uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW +{ + if (X509 * const x509 = key.d->x509) { + (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash + // (if someone knows a better way...) + return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed); + } else { + return seed; + } +} + bool QSslCertificate::isNull() const { return d->null; @@ -683,7 +694,7 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr #endif int size = der.size(); - while (count == -1 || certificates.size() < count) { + while (size > 0 && (count == -1 || certificates.size() < count)) { if (X509 *x509 = q_d2i_X509(0, &data, size)) { certificates << QSslCertificate_from_X509(x509); q_X509_free(x509); diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp index 16df4a8f73..d74042a95f 100644 --- a/src/network/ssl/qsslcertificate_qt.cpp +++ b/src/network/ssl/qsslcertificate_qt.cpp @@ -67,6 +67,12 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const return d->derData == other.d->derData; } +uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW +{ + // DER is the native encoding here, so toDer() is just "return d->derData": + return qHash(key.toDer(), seed); +} + bool QSslCertificate::isNull() const { return d->null; diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index 26be1d56e6..f4c6b21598 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -124,13 +124,16 @@ QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSsl bool client = (mode == QSslSocket::SslClientMode); bool reinitialized = false; + bool unsupportedProtocol = false; init_context: switch (sslContext->sslConfiguration.protocol()) { case QSsl::SslV2: #ifndef OPENSSL_NO_SSL2 sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method()); #else - sslContext->ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error + // SSL 2 not supported by the system, but chosen deliberately -> error + sslContext->ctx = 0; + unsupportedProtocol = true; #endif break; case QSsl::SslV3: @@ -149,14 +152,18 @@ init_context: #if OPENSSL_VERSION_NUMBER >= 0x10001000L sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method()); #else - sslContext->ctx = 0; // TLS 1.1 not supported by the system, but chosen deliberately -> error + // TLS 1.1 not supported by the system, but chosen deliberately -> error + sslContext->ctx = 0; + unsupportedProtocol = true; #endif break; case QSsl::TlsV1_2: #if OPENSSL_VERSION_NUMBER >= 0x10001000L sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method()); #else - sslContext->ctx = 0; // TLS 1.2 not supported by the system, but chosen deliberately -> error + // TLS 1.2 not supported by the system, but chosen deliberately -> error + sslContext->ctx = 0; + unsupportedProtocol = true; #endif break; } @@ -169,7 +176,9 @@ init_context: goto init_context; } - sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg( + unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl() + ); sslContext->errorCode = QSslError::UnspecifiedError; return sslContext; } diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp index ff30098347..5004e561a8 100644 --- a/src/network/ssl/qsslerror.cpp +++ b/src/network/ssl/qsslerror.cpp @@ -305,6 +305,19 @@ QSslCertificate QSslError::certificate() const return d->certificate; } +/*! + Returns the hash value for the \a key, using \a seed to seed the calculation. + \since 5.4 + \relates QHash +*/ +uint qHash(const QSslError &key, uint seed) Q_DECL_NOTHROW +{ + // 2x boost::hash_combine inlined: + seed ^= qHash(key.error()) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= qHash(key.certificate()) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; +} + #ifndef QT_NO_DEBUG_STREAM //class QDebug; QDebug operator<<(QDebug debug, const QSslError &error) diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index d25546b68b..c00532e294 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -102,6 +102,8 @@ private: }; Q_DECLARE_SHARED(QSslError) +Q_NETWORK_EXPORT uint qHash(const QSslError &key, uint seed = 0) Q_DECL_NOTHROW; + #ifndef QT_NO_DEBUG_STREAM class QDebug; Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslError &error); diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index c9ddd9ec1b..da4c72be01 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -65,16 +65,6 @@ using namespace ABI::Windows::Storage::Streams; QT_BEGIN_NAMESPACE -// For QSet<QSslError> -inline uint qHash(const QSslError &error, uint seed) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(error))) -{ return (qHash(error.error()) ^ seed); } - -// For QSet<QSslCertificate> -inline uint qHash(const QSslCertificate &certificate, uint seed) - Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(certificate))) -{ return (qHash(certificate.handle()) ^ seed); } - bool QSslSocketPrivate::s_libraryLoaded = true; bool QSslSocketPrivate::s_loadRootCertsOnDemand = true; bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index b7f4c55d3d..80153cd18f 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -487,6 +487,11 @@ QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize size.setWidth(w <= 0 ? screenResolution.width() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(w)); size.setHeight(h <= 0 ? screenResolution.height() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(h)); + + if (w <= 0 || h <= 0) + qWarning("Unable to query physical screen size, defaulting to %d dpi.\n" + "To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH " + "and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).", defaultPhysicalDpi); } return size; diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 62dc9a9c6b..2b9883eb36 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -587,92 +587,18 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) { if (!usrPtr) return 0; - QFontDef fontDef = f; - QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - bool forcedAntialiasSetting = !antialias; - engine = new QFontEngineFT(fontDef); - - const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); - bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")); - if (useXftConf) { - void *antialiasResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", - QGuiApplication::primaryScreen()); - int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource)); - if (antialiasingEnabled > 0) { - antialias = antialiasingEnabled - 1; - forcedAntialiasSetting = true; - } - } + QFontEngineFT *engine = new QFontEngineFT(f); + engine->face_id = fid; - QFontEngine::GlyphFormat format; - // try and get the pattern - FcPattern *pattern = FcPatternCreate(); + setupFontEngine(engine, f); - FcValue value; - value.type = FcTypeString; - QByteArray cs = fontDef.family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern,FC_FAMILY,value,true); - - value.u.s = (const FcChar8 *)fid.filename.data(); - FcPatternAdd(pattern,FC_FILE,value,true); - - value.type = FcTypeInteger; - value.u.i = fid.index; - FcPatternAdd(pattern,FC_INDEX,value,true); - - FcResult result; - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcPattern *match = FcFontMatch(0, pattern, &result); - if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)f.hintingPreference, match, useXftConf)); - - FcBool fc_autohint; - if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) - engine->forceAutoHint = fc_autohint; - -#if defined(FT_LCD_FILTER_H) - int lcdFilter; - if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch) - engine->lcdFilterType = lcdFilter; -#endif - - if (!forcedAntialiasSetting) { - FcBool fc_antialias; - if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch) - antialias = fc_antialias; - } - - if (antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; - if (!(f.styleStrategy & QFont::NoSubpixelAntialias)) - subpixelType = subpixelTypeFromMatch(match, useXftConf); - engine->subpixelType = subpixelType; - - format = (subpixelType == QFontEngine::Subpixel_None) - ? QFontEngine::Format_A8 - : QFontEngine::Format_A32; - } else - format = QFontEngine::Format_Mono; - - FcPatternDestroy(match); - } else - format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono; - - FcPatternDestroy(pattern); - - if (!engine->init(fid, antialias, format) || engine->invalid()) { + if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) { delete engine; engine = 0; } @@ -686,74 +612,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal p if (engine == 0) return 0; - QFontDef fontDef = engine->fontDef; - - bool forcedAntialiasSetting = false; - const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); - bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")); - if (useXftConf) { - void *antialiasResource = - QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", - QGuiApplication::primaryScreen()); - int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource)); - if (antialiasingEnabled > 0) { - engine->antialias = antialiasingEnabled - 1; - forcedAntialiasSetting = true; - } - } - - QFontEngine::GlyphFormat format; - // try and get the pattern - FcPattern *pattern = FcPatternCreate(); - - FcValue value; - value.type = FcTypeString; - QByteArray cs = fontDef.family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern,FC_FAMILY,value,true); - - FcResult result; - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcPattern *match = FcFontMatch(0, pattern, &result); - if (match) { - engine->setDefaultHintStyle(defaultHintStyleFromMatch(hintingPreference, match, useXftConf)); - - FcBool fc_autohint; - if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) - engine->forceAutoHint = fc_autohint; - -#if defined(FT_LCD_FILTER_H) - int lcdFilter; - if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch) - engine->lcdFilterType = lcdFilter; -#endif - - if (!forcedAntialiasSetting) { - FcBool fc_antialias; - if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch) - engine->antialias = fc_antialias; - } - - if (engine->antialias) { - QFontEngine::SubpixelAntialiasingType subpixelType = subpixelTypeFromMatch(match, useXftConf); - engine->subpixelType = subpixelType; - - format = subpixelType == QFontEngine::Subpixel_None - ? QFontEngine::Format_A8 - : QFontEngine::Format_A32; - } else - format = QFontEngine::Format_Mono; - FcPatternDestroy(match); - } else - format = QFontEngine::Format_A8; - - FcPatternDestroy(pattern); - - engine->defaultFormat = format; - engine->glyphFormat = format; + setupFontEngine(engine, engine->fontDef); return engine; } @@ -947,4 +806,94 @@ QFont QFontconfigDatabase::defaultFont() const return QFont(resolved); } +void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const +{ + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + bool forcedAntialiasSetting = !antialias; + + const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); + bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")); + if (useXftConf) { + void *antialiasResource = + QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", + QGuiApplication::primaryScreen()); + int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource)); + if (antialiasingEnabled > 0) { + antialias = antialiasingEnabled - 1; + forcedAntialiasSetting = true; + } + } + + QFontEngine::GlyphFormat format; + // try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + QFontEngine::FaceId fid = engine->faceId(); + + if (!fid.filename.isEmpty()) { + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern,FC_FILE,value,true); + + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern,FC_INDEX,value,true); + } + + if (fontDef.pixelSize > 0.1) + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize); + + FcResult result; + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcPattern *match = FcFontMatch(0, pattern, &result); + if (match) { + engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf)); + + FcBool fc_autohint; + if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch) + engine->forceAutoHint = fc_autohint; + +#if defined(FT_LCD_FILTER_H) + int lcdFilter; + if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch) + engine->lcdFilterType = lcdFilter; +#endif + + if (!forcedAntialiasSetting) { + FcBool fc_antialias; + if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch) + antialias = fc_antialias; + } + + if (antialias) { + QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None; + if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) + subpixelType = subpixelTypeFromMatch(match, useXftConf); + engine->subpixelType = subpixelType; + + format = (subpixelType == QFontEngine::Subpixel_None) + ? QFontEngine::Format_A8 + : QFontEngine::Format_A32; + } else + format = QFontEngine::Format_Mono; + + FcPatternDestroy(match); + } else + format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono; + + FcPatternDestroy(pattern); + + engine->antialias = antialias; + engine->defaultFormat = format; + engine->glyphFormat = format; +} + QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index 91ecb52e7b..745d12b825 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE +class QFontEngineFT; + class QFontconfigDatabase : public QBasicFontDatabase { public: @@ -61,6 +63,9 @@ public: QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); QString resolveFontFamilyAlias(const QString &family) const; QFont defaultFont() const; + +private: + void setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const; }; QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 52cb928615..fc289579ea 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -759,6 +759,50 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f) } } +static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f) +{ +#ifdef Q_OS_IOS + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) { + // Use Dynamic Type to resolve theme fonts if possible, to get + // correct font sizes and style based on user configuration. + NSString *textStyle = 0; + switch (f) { + case QPlatformTheme::TitleBarFont: + case QPlatformTheme::HeaderViewFont: + textStyle = UIFontTextStyleHeadline; + break; + case QPlatformTheme::MdiSubWindowTitleFont: + textStyle = UIFontTextStyleSubheadline; + break; + case QPlatformTheme::TipLabelFont: + case QPlatformTheme::SmallFont: + textStyle = UIFontTextStyleFootnote; + break; + case QPlatformTheme::MiniFont: + textStyle = UIFontTextStyleCaption2; + break; + case QPlatformTheme::FixedFont: + // Fall back to regular code path, as iOS doesn't provide + // an appropriate text style for this theme font. + break; + default: + textStyle = UIFontTextStyleBody; + break; + } + + if (textStyle) { + UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle]; + return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc)); + } + } +#endif // Q_OS_IOS + + // OSX default case and iOS fallback case + CTFontUIFontType fontType = fontTypeFromTheme(f); + QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL); + return CTFontCopyFontDescriptor(ctFont); +} + const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const { if (m_themeFonts.isEmpty()) { @@ -773,11 +817,7 @@ const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const { - CTFontUIFontType fontType = fontTypeFromTheme(f); - - QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL); - CTFontDescriptorRef fontDesc = CTFontCopyFontDescriptor(ctFont); - + CTFontDescriptorRef fontDesc = fontDescriptorFromTheme(f); FontDescription fd; getFontDescription(fontDesc, &fd); m_systemFontDescriptors.insert(fontDesc); diff --git a/src/platformsupport/linuxaccessibility/application.cpp b/src/platformsupport/linuxaccessibility/application.cpp index 856d84d109..3e7fd45a09 100644 --- a/src/platformsupport/linuxaccessibility/application.cpp +++ b/src/platformsupport/linuxaccessibility/application.cpp @@ -197,7 +197,9 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event) QKeyEvent* QSpiApplicationAdaptor::copyKeyEvent(QKeyEvent* old) { - return new QKeyEvent(old->type(), old->key(), old->modifiers(), old->text(), old->isAutoRepeat(), old->count()); + return new QKeyEvent(old->type(), old->key(), old->modifiers(), + old->nativeScanCode(), old->nativeVirtualKey(), old->nativeModifiers(), + old->text(), old->isAutoRepeat(), old->count()); } void QSpiApplicationAdaptor::notifyKeyboardListenerCallback(const QDBusMessage& message) diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp index 733b6f131f..7499df8596 100644 --- a/src/plugins/bearer/connman/qconnmanengine.cpp +++ b/src/plugins/bearer/connman/qconnmanengine.cpp @@ -442,7 +442,7 @@ QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QS } else if (currentTechnology == QLatin1String("hspa")) { return QNetworkConfiguration::BearerHSPA; } else if (currentTechnology == QLatin1String("lte")) { - return QNetworkConfiguration::BearerWiMAX; //not exact + return QNetworkConfiguration::BearerLTE; } } return QNetworkConfiguration::BearerUnknown; diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp index c0aaed2525..4e90f61876 100644 --- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp +++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp @@ -442,7 +442,7 @@ void TableGenerator::parseKeySequence(char *line) void TableGenerator::printComposeTable() const { #ifdef DEBUG_GENERATOR - if (composeTable().isEmpty()) + if (m_composeTable.isEmpty()) return; QString output; diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index f55bc40a55..3c3a4b4b2e 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -26,6 +26,7 @@ INCLUDEPATH += \ $$QT_SOURCE_TREE/src/3rdparty/android SOURCES += $$PWD/androidplatformplugin.cpp \ + $$PWD/androiddeadlockprotector.cpp \ $$PWD/androidjnimain.cpp \ $$PWD/androidjniaccessibility.cpp \ $$PWD/androidjniinput.cpp \ @@ -53,6 +54,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/qandroideventdispatcher.cpp HEADERS += $$PWD/qandroidplatformintegration.h \ + $$PWD/androidandroiddeadlockprotector.h \ $$PWD/androidjnimain.h \ $$PWD/androidjniaccessibility.h \ $$PWD/androidjniinput.h \ diff --git a/src/plugins/platforms/android/androiddeadlockprotector.cpp b/src/plugins/platforms/android/androiddeadlockprotector.cpp new file mode 100644 index 0000000000..e53e0c2447 --- /dev/null +++ b/src/plugins/platforms/android/androiddeadlockprotector.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "androiddeadlockprotector.h" + +QAtomicInt AndroidDeadlockProtector::s_blocked(0); + diff --git a/src/plugins/platforms/android/androiddeadlockprotector.h b/src/plugins/platforms/android/androiddeadlockprotector.h new file mode 100644 index 0000000000..a0a82aa9d1 --- /dev/null +++ b/src/plugins/platforms/android/androiddeadlockprotector.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ANDROID_DEADLOCKPROTECTOR_H +#define ANDROID_DEADLOCKPROTECTOR_H + +#include <QAtomicInt> + +QT_BEGIN_NAMESPACE + +class AndroidDeadlockProtector +{ +public: + AndroidDeadlockProtector() + : m_acquired(0) + { + } + + ~AndroidDeadlockProtector() { + if (m_acquired) + s_blocked.storeRelease(0); + } + + bool acquire() { + m_acquired = s_blocked.testAndSetAcquire(0, 1); + return m_acquired; + } + +private: + static QAtomicInt s_blocked; + int m_acquired; +}; + +QT_END_NAMESPACE + +#endif // ANDROID_DEADLOCKPROTECTOR_H + diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp index 7229fd7af5..5c927da9c5 100644 --- a/src/plugins/platforms/android/androidjniaccessibility.cpp +++ b/src/plugins/platforms/android/androidjniaccessibility.cpp @@ -187,18 +187,30 @@ if (!clazz) { \ //__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); - static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId) + + static jstring descriptionForAccessibleObject_helper(JNIEnv *env, QAccessibleInterface *iface) { QString desc; - QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { desc = iface->text(QAccessible::Name); if (desc.isEmpty()) desc = iface->text(QAccessible::Description); + if (desc.isEmpty()) { + desc = iface->text(QAccessible::Value); + if (desc.isEmpty()) { + if (QAccessibleValueInterface *valueIface = iface->valueInterface()) { + desc= valueIface->currentValue().toString(); + } + } + } } + return env->NewString((jchar*) desc.constData(), (jsize) desc.size()); + } - jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size()); - return jdesc; + static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId) + { + QAccessibleInterface *iface = interfaceFromId(objectId); + return descriptionForAccessibleObject_helper(env, iface); } static bool populateNode(JNIEnv *env, jobject /*thiz*/, jint objectId, jobject node) @@ -216,11 +228,8 @@ if (!clazz) { \ const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction()); // try to fill in the text property, this is what the screen reader reads - QString desc = iface->text(QAccessible::Value); - if (desc.isEmpty()) - desc = iface->text(QAccessible::Name); - if (desc.isEmpty()) - desc = iface->text(QAccessible::Description); + jstring jdesc = descriptionForAccessibleObject_helper(env, iface); + if (QAccessibleTextInterface *textIface = iface->textInterface()) { if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) { int startSelection; @@ -252,7 +261,6 @@ if (!clazz) { \ env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo - jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size()); //CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc) env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc); diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index a23d05520c..a3848c9c2b 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -38,6 +38,7 @@ #include "androidjnimain.h" #include "androidjniinput.h" #include "qandroideventdispatcher.h" +#include "androiddeadlockprotector.h" #include <QDebug> #include <qevent.h> #include <qguiapplication.h> @@ -519,6 +520,10 @@ bool QAndroidInputContext::isAnimating() const void QAndroidInputContext::showInputPanel() { + if (QGuiApplication::applicationState() != Qt::ApplicationActive) { + connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState))); + return; + } QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe(); if (query.isNull()) return; @@ -541,6 +546,14 @@ void QAndroidInputContext::showInputPanel() query->value(Qt::ImHints).toUInt()); } +void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state) +{ + if (state != Qt::ApplicationActive) + return; + disconnect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState))); + showInputPanel(); +} + void QAndroidInputContext::hideInputPanel() { QtAndroidInput::hideSoftwareKeyboard(); @@ -642,13 +655,13 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right // Android docs say the cursor must not move jboolean QAndroidInputContext::finishComposingText() { + if (m_composingText.isEmpty()) + return JNI_TRUE; // not composing + QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe(); if (query.isNull()) return JNI_FALSE; - if (m_composingText.isEmpty()) - return JNI_TRUE; // not composing - const int blockPos = getBlockPosition(query); const int localCursorPos = m_composingCursor - blockPos; @@ -986,6 +999,9 @@ QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery q const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) return retval; + AndroidDeadlockProtector protector; + if (!inMainThread && !protector.acquire()) + return retval; QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe", inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, @@ -1003,6 +1019,9 @@ QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMet const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) return QSharedPointer<QInputMethodQueryEvent>(); + AndroidDeadlockProtector protector; + if (!inMainThread && !protector.acquire()) + return QSharedPointer<QInputMethodQueryEvent>(); QInputMethodQueryEvent *queryEvent = 0; QMetaObject::invokeMethod(this, "focusObjectInputMethodQueryUnsafe", @@ -1040,7 +1059,9 @@ void QAndroidInputContext::sendInputMethodEventThreadSafe(QInputMethodEvent *eve const bool inMainThread = qGuiApp->thread() == QThread::currentThread(); if (QAndroidEventDispatcherStopper::stopped() && !inMainThread) return; - + AndroidDeadlockProtector protector; + if (!inMainThread && !protector.acquire()) + return; QMetaObject::invokeMethod(this, "sendInputMethodEventUnsafe", inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection, Q_ARG(QInputMethodEvent*, event)); diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index 670a051139..2ebb155d2a 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -112,6 +112,9 @@ public: public slots: void updateCursorPosition(); +private slots: + void showInputPanelLater(Qt::ApplicationState); + private: void sendInputMethodEventThreadSafe(QInputMethodEvent *event); Q_INVOKABLE void sendInputMethodEventUnsafe(QInputMethodEvent *event); diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp index 86fd152bff..fb73db8455 100644 --- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp +++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp @@ -44,19 +44,19 @@ QAndroidPlatformClipboard::QAndroidPlatformClipboard() QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode) { - if (QClipboard::Clipboard != mode || !QtAndroidClipboard::hasClipboardText()) - return 0; - - m_mimeData.setText(QtAndroidClipboard::clipboardText()); + Q_ASSERT(supportsMode(mode)); + m_mimeData.setText(QtAndroidClipboard::hasClipboardText() + ? QtAndroidClipboard::clipboardText() + : QString()); return &m_mimeData; } void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) { - if (!data || !data->hasText() || QClipboard::Clipboard != mode) - return; - - QtAndroidClipboard::setClipboardText(data->text()); + Q_ASSERT(supportsMode(mode)); + QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString()); + if (data != 0) + data->deleteLater(); } bool QAndroidPlatformClipboard::supportsMode(QClipboard::Mode mode) const diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp index 8afc35c57a..8dc8e84f0a 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp @@ -37,6 +37,7 @@ #include "qandroidplatformscreen.h" #include "androidjnimain.h" #include "qandroideventdispatcher.h" +#include "androiddeadlockprotector.h" #include <QSurfaceFormat> #include <QtGui/private/qwindow_p.h> @@ -120,6 +121,10 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config) QMutexLocker lock(&m_surfaceMutex); if (m_nativeSurfaceId == -1) { + AndroidDeadlockProtector protector; + if (!protector.acquire()) + return m_eglSurface; + const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint); m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32); m_surfaceWaitCondition.wait(&m_surfaceMutex); diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 09e5d7e346..8a07735e5f 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -43,6 +43,7 @@ #include "qandroidplatformwindow.h" #include "androidjnimain.h" #include "androidjnimenu.h" +#include "androiddeadlockprotector.h" #include <android/bitmap.h> #include <android/native_window_jni.h> @@ -299,6 +300,9 @@ void QAndroidPlatformScreen::doRedraw() QMutexLocker lock(&m_surfaceMutex); if (m_id == -1 && m_rasterSurfaces) { m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth); + AndroidDeadlockProtector protector; + if (!protector.acquire()) + return; m_surfaceWaitCondition.wait(&m_surfaceMutex); } diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h index 5ebdad79f1..2c34ef9278 100644 --- a/src/plugins/platforms/cocoa/qcocoaclipboard.h +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h @@ -40,8 +40,10 @@ QT_BEGIN_NAMESPACE -class QCocoaClipboard : public QPlatformClipboard +class QCocoaClipboard : public QObject, public QPlatformClipboard { + Q_OBJECT + public: QCocoaClipboard(); @@ -49,6 +51,10 @@ public: void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); bool supportsMode(QClipboard::Mode mode) const; bool ownsMode(QClipboard::Mode mode) const; + +private Q_SLOTS: + void handleApplicationStateChanged(Qt::ApplicationState state); + protected: QMacPasteboard *pasteboardForMode(QClipboard::Mode mode) const; diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm index f6c424d4fd..1a23da8a8e 100644 --- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qcocoaclipboard.h" -#include "qmacclipboard.h" QT_BEGIN_NAMESPACE @@ -48,7 +47,7 @@ QCocoaClipboard::QCocoaClipboard() :m_clipboard(new QMacPasteboard(kPasteboardClipboard, QMacInternalPasteboardMime::MIME_CLIP)) ,m_find(new QMacPasteboard(kPasteboardFind, QMacInternalPasteboardMime::MIME_CLIP)) { - + connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QCocoaClipboard::handleApplicationStateChanged); } QMimeData *QCocoaClipboard::mimeData(QClipboard::Mode mode) @@ -94,4 +93,17 @@ QMacPasteboard *QCocoaClipboard::pasteboardForMode(QClipboard::Mode mode) const return 0; } +void QCocoaClipboard::handleApplicationStateChanged(Qt::ApplicationState state) +{ + if (state != Qt::ApplicationActive) + return; + + if (m_clipboard->sync()) + emitChanged(QClipboard::Clipboard); + if (m_find->sync()) + emitChanged(QClipboard::FindBuffer); +} + +#include "moc_qcocoaclipboard.cpp" + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 736e02a3ca..d849389907 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -366,9 +366,14 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) } bool wasMerged = cocoaItem->isMerged(); - NSMenu *oldMenu = wasMerged ? [getMenuLoader() applicationMenu] : m_nativeMenu; - NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem]; + NSMenu *oldMenu = m_nativeMenu; + if (wasMerged) { + QPlatformMenuItem::MenuRole role = cocoaItem->effectiveRole(); + if (role >= QPlatformMenuItem::ApplicationSpecificRole && role < QPlatformMenuItem::CutRole) + oldMenu = [getMenuLoader() applicationMenu]; + } + NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem]; if (cocoaItem->sync() != oldItem) { // native item was changed for some reason if (oldItem) { diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 3d3b6bf598..791b0805d0 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -256,8 +256,8 @@ NSMenuItem *QCocoaMenuItem::sync() if (depth == 3 || !menubar) break; // Menu item too deep in the hierarchy, or not connected to any menubar - m_detectedRole = detectMenuRole(m_text); - switch (m_detectedRole) { + MenuRole newDetectedRole = detectMenuRole(m_text); + switch (newDetectedRole) { case QPlatformMenuItem::AboutRole: if (m_text.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1) mergeItem = [loader aboutMenuItem]; @@ -271,12 +271,15 @@ NSMenuItem *QCocoaMenuItem::sync() mergeItem = [loader quitMenuItem]; break; default: - if (m_detectedRole >= CutRole && m_detectedRole < RoleCount && menubar) - mergeItem = menubar->itemForRole(m_detectedRole); + if (newDetectedRole >= CutRole && newDetectedRole < RoleCount && menubar) + mergeItem = menubar->itemForRole(newDetectedRole); if (!m_text.isEmpty()) m_textSynced = true; break; } + + m_detectedRole = newDetectedRole; + break; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 10a92667c1..06680228bc 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -420,12 +420,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; #pragma clang diagnostic ignored "-Wobjc-method-access" enum { NSWindowOcclusionStateVisible = 1UL << 1 }; #endif - // Older versions managed in -[QNSView viewDidMoveToWindow]. - // Support QWidgetAction in NSMenu. Mavericks only sends this notification. - // Ideally we should support this in Qt as well, in order to disable animations - // when the window is occluded. if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) m_platformWindow->exposeWindow(); + else + m_platformWindow->obscureWindow(); #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 #pragma clang diagnostic pop #endif diff --git a/src/plugins/platforms/ios/qiosclipboard.h b/src/plugins/platforms/ios/qiosclipboard.h index 7d758e3a56..f532eba3de 100644 --- a/src/plugins/platforms/ios/qiosclipboard.h +++ b/src/plugins/platforms/ios/qiosclipboard.h @@ -36,6 +36,7 @@ #import <UIKit/UIKit.h> +#include <QMimeData> #include <qpa/qplatformclipboard.h> @class QUIClipboard; @@ -46,6 +47,8 @@ class QIOSClipboard : public QPlatformClipboard { public: QIOSClipboard(); + ~QIOSClipboard(); + QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; void setMimeData(QMimeData *mimeData, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; @@ -53,6 +56,7 @@ public: private: QUIClipboard *m_clipboard; + QMap<QClipboard::Mode, QMimeData *> m_mimeData; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm index e18ad53b2c..5ed6d3be62 100644 --- a/src/plugins/platforms/ios/qiosclipboard.mm +++ b/src/plugins/platforms/ios/qiosclipboard.mm @@ -194,10 +194,17 @@ QIOSClipboard::QIOSClipboard() { } +QIOSClipboard::~QIOSClipboard() +{ + qDeleteAll(m_mimeData); +} + QMimeData *QIOSClipboard::mimeData(QClipboard::Mode mode) { Q_ASSERT(supportsMode(mode)); - return new QIOSMimeData(mode); + if (!m_mimeData.contains(mode)) + return *m_mimeData.insert(mode, new QIOSMimeData(mode)); + return m_mimeData[mode]; } void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) @@ -209,6 +216,8 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode) pb.items = [NSArray array]; return; } + + mimeData->deleteLater(); NSMutableDictionary *pbItem = [NSMutableDictionary dictionaryWithCapacity:mimeData->formats().size()]; foreach (const QString &mimeType, mimeData->formats()) { diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 13e91889a2..b403154321 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -322,7 +322,7 @@ bool QIOSInputContext::isInputPanelVisible() const void QIOSInputContext::cursorRectangleChanged() { - if (!m_keyboardListener->m_keyboardVisibleAndDocked) + if (!m_keyboardListener->m_keyboardVisibleAndDocked || !qApp->focusObject()) return; // Check if the cursor has changed position inside the input item. Since @@ -399,6 +399,8 @@ void QIOSInputContext::scroll(int y) animation.toValue = [NSValue valueWithCATransform3D:translationTransform]; [rootView.layer addAnimation:animation forKey:@"AnimateSubLayerTransform"]; rootView.layer.sublayerTransform = translationTransform; + + [rootView.qtViewController updateProperties]; } completion:^(BOOL){ if (self) diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index c247c16514..005b06547e 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -88,8 +88,9 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; - (id)targetForAction:(SEL)action withSender:(id)sender { + Q_UNUSED(sender); BOOL containsPrefix = ([NSStringFromSelector(action) rangeOfString:kSelectorPrefix].location != NSNotFound); - return (containsPrefix && [sender isKindOfClass:[UIMenuController class]]) ? self : 0; + return containsPrefix ? self : 0; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h index cbb28aec0d..586edd589d 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.h +++ b/src/plugins/platforms/ios/qiosviewcontroller.h @@ -41,6 +41,7 @@ class QIOSScreen; @property (nonatomic, assign) BOOL changingOrientation; @property (nonatomic, assign) BOOL prefersStatusBarHidden; +@property (nonatomic, assign) UIStatusBarAnimation preferredStatusBarUpdateAnimation; - (id)initWithQIOSScreen:(QIOSScreen *)screen; - (void)updateProperties; diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index ca8d48bf6d..a2d81e3b6c 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -150,6 +150,7 @@ // Status bar may be initially hidden at startup through Info.plist self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false); + self.preferredStatusBarUpdateAnimation = UIStatusBarAnimationNone; QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() { [self updateProperties]; @@ -182,47 +183,6 @@ // ------------------------------------------------------------------------- -- (void)updateProperties -{ - if (!isQtApplication()) - return; - - QWindow *focusWindow = QGuiApplication::focusWindow(); - - // If we don't have a focus window we leave the statusbar - // as is, so that the user can activate a new window with - // the same window state without the status bar jumping - // back and forth. - if (!focusWindow) - return; - - // We only care about changes to focusWindow that involves our screen - if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen) - return; - - // All decisions are based on the the top level window - focusWindow = qt_window_private(focusWindow)->topLevelWindow(); - - bool currentStatusBarVisibility = self.prefersStatusBarHidden; - self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen; - if (self.prefersStatusBarHidden != currentStatusBarVisibility) { -#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) { - [self setNeedsStatusBarAppearanceUpdate]; - } else -#endif - { - [[UIApplication sharedApplication] - setStatusBarHidden:self.prefersStatusBarHidden - withAnimation:UIStatusBarAnimationNone]; - } - - [self.view setNeedsLayout]; - } -} - -// ------------------------------------------------------------------------- - -(BOOL)shouldAutorotate { // Until a proper orientation and rotation API is in place, we always auto rotate. @@ -298,6 +258,54 @@ m_screen->updateProperties(); } +// ------------------------------------------------------------------------- + +- (void)updateProperties +{ + if (!isQtApplication()) + return; + + QWindow *focusWindow = QGuiApplication::focusWindow(); + + // If we don't have a focus window we leave the statusbar + // as is, so that the user can activate a new window with + // the same window state without the status bar jumping + // back and forth. + if (!focusWindow) + return; + + // We only care about changes to focusWindow that involves our screen + if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen) + return; + + // All decisions are based on the the top level window + focusWindow = qt_window_private(focusWindow)->topLevelWindow(); + + bool hasScrolledRootViewDueToVirtualKeyboard = + !CATransform3DIsIdentity(self.view.layer.sublayerTransform); + + bool currentStatusBarVisibility = self.prefersStatusBarHidden; + self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen + || hasScrolledRootViewDueToVirtualKeyboard; + self.preferredStatusBarUpdateAnimation = hasScrolledRootViewDueToVirtualKeyboard ? + UIStatusBarAnimationFade : UIStatusBarAnimationNone; + + if (self.prefersStatusBarHidden != currentStatusBarVisibility) { +#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) { + [self setNeedsStatusBarAppearanceUpdate]; + } else +#endif + { + [[UIApplication sharedApplication] + setStatusBarHidden:self.prefersStatusBarHidden + withAnimation:self.preferredStatusBarUpdateAnimation]; + } + + [self.view setNeedsLayout]; + } +} + #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0) - (UIStatusBarStyle)preferredStatusBarStyle { diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 5bbd76fb36..65b4f6dd7d 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -42,11 +42,6 @@ class QIOSContext; class QIOSWindow; -@interface UIView (QIOS) -@property(readonly) QWindow *qwindow; -@property(readonly) UIViewController *viewController; -@end - QT_BEGIN_NAMESPACE @class QUIView; @@ -71,6 +66,8 @@ public: void raise() { raiseOrLower(true); } void lower() { raiseOrLower(false); } + + bool shouldAutoActivateWindow() const; void requestActivateWindow(); qreal devicePixelRatio() const; @@ -95,9 +92,6 @@ private: void updateWindowLevel(); bool blockedByModal(); - inline Qt::WindowType windowType() { return static_cast<Qt::WindowType>(int(window()->flags() & Qt::WindowType_Mask)); } - inline bool windowIsPopup() { return windowType() & Qt::Popup & ~Qt::Window; } - friend class QIOSScreen; }; diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index e29ff53876..b0c5f15306 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -117,24 +117,39 @@ void QIOSWindow::setVisible(bool visible) return; } - if (visible) { + if (visible && shouldAutoActivateWindow()) { requestActivateWindow(); - } else { - // Activate top-most visible QWindow: + } else if (!visible && qGuiApp->focusWindow() == window()) { + // Our window was active/focus window but now hidden, so relinquish + // focus to the next possible window in the stack. NSArray *subviews = m_view.viewController.view.subviews; for (int i = int(subviews.count) - 1; i >= 0; --i) { UIView *view = [subviews objectAtIndex:i]; - if (!view.hidden) { - QWindow *w = view.qwindow; - if (w && w->isTopLevel()) { - static_cast<QIOSWindow *>(w->handle())->requestActivateWindow(); - break; - } - } + if (view.hidden) + continue; + + QWindow *w = view.qwindow; + if (!w || !w->isTopLevel()) + continue; + + QIOSWindow *iosWindow = static_cast<QIOSWindow *>(w->handle()); + if (!iosWindow->shouldAutoActivateWindow()) + continue; + + iosWindow->requestActivateWindow(); + break; } } } +bool QIOSWindow::shouldAutoActivateWindow() const +{ + // We don't want to do automatic window activation for popup windows + // (including Tool, ToolTip and SplashScreen windows), unless they + // are standalone (no parent/transient parent), and hence not active. + return !(window()->type() & Qt::Popup) || !window()->isActive(); +} + void QIOSWindow::setOpacity(qreal level) { m_view.alpha = qBound(0.0, level, 1.0); @@ -280,7 +295,7 @@ void QIOSWindow::raiseOrLower(bool raise) void QIOSWindow::updateWindowLevel() { - Qt::WindowType type = windowType(); + Qt::WindowType type = window()->type(); if (type == Qt::ToolTip) m_windowLevel = 120; diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h index fe71e5bed7..6550c61ad0 100644 --- a/src/plugins/platforms/ios/quiview.h +++ b/src/plugins/platforms/ios/quiview.h @@ -62,7 +62,9 @@ class QIOSWindow; - (void)clearAccessibleCache; @end -@interface QUIView (QtHelpers) +@interface UIView (QtHelpers) +- (QWindow *)qwindow; +- (UIViewController *)viewController; - (QIOSViewController*)qtViewController; @end diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 200b07b5fc..c46ed4c0b1 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -271,7 +271,7 @@ m_activeTouches[touch].id = m_nextTouchId++; } - if (m_activeTouches.size() == 1) { + if (m_qioswindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) { QPlatformWindow *topLevel = m_qioswindow; while (QPlatformWindow *p = topLevel->parent()) topLevel = p; @@ -340,11 +340,16 @@ QWindowSystemInterface::flushWindowSystemEvents(); } -- (id)targetForAction:(SEL)action withSender:(id)sender +- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { // Check first if QIOSMenu should handle the action before continuing up the responder chain - id target = [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender]; - return target ? target : [super targetForAction:action withSender:sender]; + return [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender] != 0; +} + +- (id)forwardingTargetForSelector:(SEL)selector +{ + Q_UNUSED(selector) + return QIOSMenu::menuActionTarget(); } @end diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp index 73988b6db5..593b5eac7a 100644 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp +++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp @@ -62,6 +62,7 @@ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) : QEventDispatcherWin32(parent), m_flags(0) { setObjectName(QStringLiteral("QWindowsGuiEventDispatcher")); + createInternalHwnd(); // QTBUG-40881: Do not delay registering timers, etc. for QtMfc. } bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 7e70e7258d..fc3443aba5 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -841,8 +841,8 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_layout_index_t baseLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_DEPRESSED); xkb_layout_index_t latchedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LATCHED); xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED); - xkb_mod_index_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - xkb_mod_index_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); + xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); + xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, baseLayout, latchedLayout, lockedLayout); @@ -861,6 +861,10 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt"); xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); + Q_ASSERT(shiftMod < 32); + Q_ASSERT(altMod < 32); + Q_ASSERT(controlMod < 32); + xkb_mod_mask_t depressed; struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; @@ -903,7 +907,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const Qt::KeyboardModifiers mods = modifiers & ~neededMods; qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, event->nativeScanCode())); - if (qtKey == baseQtKey) + if (qtKey == baseQtKey || qtKey == 0) continue; result += (qtKey + mods); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index c4cf3b4416..0c2e9d047c 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -251,6 +251,27 @@ QXcbWindow::QXcbWindow(QWindow *window) m_window = window->winId(); } +#ifdef Q_COMPILER_CLASS_ENUM +enum : quint32 { +#else +enum { +#endif + baseEventMask + = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE, + + defaultEventMask = baseEventMask + | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE + | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW + | XCB_EVENT_MASK_POINTER_MOTION, + + transparentForInputEventMask = baseEventMask + | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_RESIZE_REDIRECT + | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT + | XCB_EVENT_MASK_COLOR_MAP_CHANGE | XCB_EVENT_MASK_OWNER_GRAB_BUTTON +}; + void QXcbWindow::create() { destroy(); @@ -285,18 +306,7 @@ void QXcbWindow::create() // XCB_CW_SAVE_UNDER type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer, // XCB_CW_EVENT_MASK - XCB_EVENT_MASK_EXPOSURE - | XCB_EVENT_MASK_STRUCTURE_NOTIFY - | XCB_EVENT_MASK_KEY_PRESS - | XCB_EVENT_MASK_KEY_RELEASE - | XCB_EVENT_MASK_BUTTON_PRESS - | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_BUTTON_MOTION - | XCB_EVENT_MASK_ENTER_WINDOW - | XCB_EVENT_MASK_LEAVE_WINDOW - | XCB_EVENT_MASK_POINTER_MOTION - | XCB_EVENT_MASK_PROPERTY_CHANGE - | XCB_EVENT_MASK_FOCUS_CHANGE + defaultEventMask }; // Parameters to XCreateWindow() are frame corner + inner size. @@ -985,14 +995,15 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) if (type == Qt::Popup) flags |= Qt::X11BypassWindowManagerHint; - if (flags & Qt::WindowTransparentForInput) { - uint32_t mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_VISIBILITY_CHANGE - | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_RESIZE_REDIRECT - | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT - | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE - | XCB_EVENT_MASK_COLOR_MAP_CHANGE | XCB_EVENT_MASK_OWNER_GRAB_BUTTON; - xcb_change_window_attributes(xcb_connection(), xcb_window(), XCB_CW_EVENT_MASK, &mask); - } + const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; + const quint32 values[] = { + // XCB_CW_OVERRIDE_REDIRECT + (flags & Qt::BypassWindowManagerHint) ? 1u : 0, + // XCB_CW_EVENT_MASK + (flags & Qt::WindowTransparentForInput) ? transparentForInputEventMask : defaultEventMask + }; + + xcb_change_window_attributes(xcb_connection(), xcb_window(), mask, values); setNetWmWindowFlags(flags); setMotifWindowFlags(flags); diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp index c480753675..f107645ab5 100644 --- a/src/testlib/qbenchmarkvalgrind.cpp +++ b/src/testlib/qbenchmarkvalgrind.cpp @@ -45,33 +45,15 @@ QT_BEGIN_NAMESPACE -// Returns \c true iff a sufficiently recent valgrind is available. +// Returns \c true if valgrind is available. bool QBenchmarkValgrindUtils::haveValgrind() { #ifdef NVALGRIND return false; #else QProcess process; - QStringList args; - args << QLatin1String("--version"); - process.start(QLatin1String("valgrind"), args); - if (!process.waitForFinished(-1)) - return false; - const QByteArray out = process.readAllStandardOutput(); - QRegExp rx(QLatin1String("^valgrind-([0-9]+).([0-9]+).[0-9]+")); - if (rx.indexIn(QLatin1String(out.data())) == -1) - return false; - bool ok; - const int major = rx.cap(1).toInt(&ok); - if (!ok) - return false; - const int minor = rx.cap(2).toInt(&ok); - if (!ok) - return false; -// return (major > 3 || (major == 3 && minor >= 3)); // v >= 3.3 for --callgrind-out-file option - Q_UNUSED(major); - Q_UNUSED(minor); - return true; // skip version restriction for now + process.start(QLatin1String("valgrind"), QStringList(QLatin1String("--version"))); + return process.waitForStarted() && process.waitForFinished(-1); #endif } diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 4b4c88a176..51908bc9e3 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -1264,11 +1264,11 @@ void QDocDatabase::findAllSince(InnerNode* node) nsmap.value().insert(name,(*child)); } } - // Recursively find child nodes with since commands. - if ((*child)->isInnerNode()) { - findAllSince(static_cast<InnerNode *>(*child)); - } } + // Recursively find child nodes with since commands. + if ((*child)->isInnerNode()) + findAllSince(static_cast<InnerNode *>(*child)); + ++child; } } diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 6d4cc12d5c..11a99d136d 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -610,11 +610,18 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file) const QString filename = nodes.at(nodes.size()-1); RCCFileInfo *s = new RCCFileInfo(file); s->m_parent = parent; - if (parent->m_children.contains(filename)) { - foreach (const QString &fileName, m_fileNames) - qWarning("%s: Warning: potential duplicate alias detected: '%s'", - qPrintable(fileName), qPrintable(filename)); + typedef QHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator; + const ChildConstIterator cbegin = parent->m_children.constFind(filename); + const ChildConstIterator cend = parent->m_children.constEnd(); + for (ChildConstIterator it = cbegin; it != cend; ++it) { + if (it.key() == filename && it.value()->m_language == s->m_language && + it.value()->m_country == s->m_country) { + foreach (const QString &name, m_fileNames) + qWarning("%s: Warning: potential duplicate alias detected: '%s'", + qPrintable(name), qPrintable(filename)); + break; } + } parent->m_children.insertMulti(filename, s); return true; } diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index e20ad65441..3fbb17ff3f 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -2405,12 +2405,11 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) } break; #endif - case Qt::Key_A: - if (event->modifiers() & Qt::ControlModifier) { + default: { + if (event == QKeySequence::SelectAll && selectionMode() != NoSelection) { selectAll(); break; } - default: { #ifdef Q_WS_MAC if (event->key() == Qt::Key_O && event->modifiers() & Qt::ControlModifier && currentIndex().isValid()) { emit activated(currentIndex()); diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 543f59d7d1..8a4e0c8ffd 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -45,6 +45,7 @@ #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qopenglextensions_p.h> #include <QtGui/private/qfont_p.h> +#include <QtGui/private/qopenglpaintdevice_p.h> #include <QtWidgets/private/qwidget_p.h> QT_BEGIN_NAMESPACE @@ -239,6 +240,28 @@ QT_BEGIN_NAMESPACE \note Avoid calling winId() on a QOpenGLWidget. This function triggers the creation of a native window, resulting in reduced performance and possibly rendering glitches. + \section1 Differences to QGLWidget + + Besides the main conceptual difference of being backed by a framebuffer object, there + are a number of smaller, internal differences between QOpenGLWidget and the older + QGLWidget: + + \list + + \li OpenGL state when invoking paintGL(). QOpenGLWidget sets up the viewport via + glViewport(). It does not perform any clearing. + + \li Clearing when starting to paint via QPainter. Unlike regular widgets, QGLWidget + defaulted to a value of \c true for + \l{QWidget::autoFillBackground()}{autoFillBackground}. It then performed clearing to the + palette's background color every time QPainter::begin() was used. QOpenGLWidget does not + follow this: \l{QWidget::autoFillBackground()}{autoFillBackground} defaults to false, + like for any other widget. The only exception is when being used as a viewport for other + widgets like QGraphicsView. In such a case autoFillBackground will be automatically set + to true to ensure compatibility with QGLWidget-based viewports. + + \endlist + \section1 Multisampling To enable multisampling, set the number of requested samples on the @@ -432,16 +455,26 @@ QT_BEGIN_NAMESPACE due to resizing the widget. */ -class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice +class QOpenGLWidgetPaintDevicePrivate : public QOpenGLPaintDevicePrivate { public: - QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) : w(widget) { } - void ensureActiveTarget() Q_DECL_OVERRIDE; + QOpenGLWidgetPaintDevicePrivate(QOpenGLWidget *widget) + : QOpenGLPaintDevicePrivate(QSize()), + w(widget) { } + + void beginPaint() Q_DECL_OVERRIDE; -private: QOpenGLWidget *w; }; +class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice +{ +public: + QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) + : QOpenGLPaintDevice(new QOpenGLWidgetPaintDevicePrivate(widget)) { } + void ensureActiveTarget() Q_DECL_OVERRIDE; +}; + class QOpenGLWidgetPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QOpenGLWidget) @@ -454,7 +487,8 @@ public: initialized(false), fakeHidden(false), paintDevice(0), - inBackingStorePaint(false) + inBackingStorePaint(false), + flushPending(false) { requestedFormat = QSurfaceFormat::defaultFormat(); } @@ -478,6 +512,7 @@ public: void endBackingStorePainting() Q_DECL_OVERRIDE { inBackingStorePaint = false; } void beginCompose() Q_DECL_OVERRIDE; void endCompose() Q_DECL_OVERRIDE; + void initializeViewportFramebuffer() Q_DECL_OVERRIDE; void resizeViewportFramebuffer() Q_DECL_OVERRIDE; void resolveSamples() Q_DECL_OVERRIDE; @@ -490,22 +525,54 @@ public: QOpenGLPaintDevice *paintDevice; bool inBackingStorePaint; QSurfaceFormat requestedFormat; + bool flushPending; }; +void QOpenGLWidgetPaintDevicePrivate::beginPaint() +{ + // NB! autoFillBackground is and must be false by default. Otherwise we would clear on + // every QPainter begin() which is not desirable. This is only for legacy use cases, + // like using QOpenGLWidget as the viewport of a graphics view, that expect clearing + // with the palette's background color. + if (w->autoFillBackground()) { + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + if (w->testAttribute(Qt::WA_TranslucentBackground)) { + f->glClearColor(0, 0, 0, 0); + } else { + QColor c = w->palette().brush(w->backgroundRole()).color(); + float alpha = c.alphaF(); + f->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); + } + f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } +} + void QOpenGLWidgetPaintDevice::ensureActiveTarget() { - QOpenGLWidgetPrivate *d = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(w)); - if (!d->initialized) + QOpenGLWidgetPaintDevicePrivate *d = static_cast<QOpenGLWidgetPaintDevicePrivate *>(d_ptr.data()); + QOpenGLWidgetPrivate *wd = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(d->w)); + if (!wd->initialized) return; - if (QOpenGLContext::currentContext() != d->context) - w->makeCurrent(); + if (QOpenGLContext::currentContext() != wd->context) + d->w->makeCurrent(); else - d->fbo->bind(); + wd->fbo->bind(); + + // When used as a viewport, drawing is done via opening a QPainter on the widget + // without going through paintEvent(). We will have to make sure a glFlush() is done + // before the texture is accessed also in this case. + wd->flushPending = true; } GLuint QOpenGLWidgetPrivate::textureId() const { + Q_Q(const QOpenGLWidget); + if (!q->isWindow() && q->internalWinId()) { + qWarning() << "QOpenGLWidget cannot be used as a native child widget." + << "Consider setting Qt::AA_DontCreateNativeWidgetAncestors and Siblings."; + return 0; + } return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0); } @@ -566,6 +633,11 @@ void QOpenGLWidgetPrivate::recreateFbo() void QOpenGLWidgetPrivate::beginCompose() { Q_Q(QOpenGLWidget); + if (flushPending) { + flushPending = false; + q->makeCurrent(); + context->functions()->glFlush(); + } emit q->aboutToCompose(); } @@ -647,9 +719,10 @@ void QOpenGLWidgetPrivate::invokeUserPaint() { Q_Q(QOpenGLWidget); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio()); + f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio()); q->paintGL(); + f->glFlush(); } void QOpenGLWidgetPrivate::render() @@ -661,7 +734,6 @@ void QOpenGLWidgetPrivate::render() q->makeCurrent(); invokeUserPaint(); - context->functions()->glFlush(); } extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -680,6 +752,14 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer() return res; } +void QOpenGLWidgetPrivate::initializeViewportFramebuffer() +{ + Q_Q(QOpenGLWidget); + // Legacy behavior for compatibility with QGLWidget when used as a graphics view + // viewport: enable clearing on each painter begin. + q->setAutoFillBackground(true); +} + void QOpenGLWidgetPrivate::resizeViewportFramebuffer() { Q_Q(QOpenGLWidget); @@ -923,7 +1003,6 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e) d->recreateFbo(); resizeGL(width(), height()); d->invokeUserPaint(); - d->context->functions()->glFlush(); d->resolveSamples(); } diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h index 9730ec1206..41adf5c58a 100644 --- a/src/widgets/kernel/qsizepolicy.h +++ b/src/widgets/kernel/qsizepolicy.h @@ -150,6 +150,10 @@ private: quint32 data; }; }; +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) +// Can't add in Qt 5, as QList<QSizePolicy> would be BiC: +Q_DECLARE_TYPEINFO(QSizePolicy, Q_PRIMITIVE_TYPE); +#endif Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 00cf39bdbf..af1745d845 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6543,10 +6543,15 @@ void QWidget::clearFocus() QWidget *w = this; while (w) { + // Just like setFocus(), we update (clear) the focus_child of our parents if (w->d_func()->focus_child == this) w->d_func()->focus_child = 0; w = w->parentWidget(); } + // Since focus_child is the basis for the top level QWidgetWindow's focusObject() + // we need to report this change to the rest of Qt, but we match setFocus() and + // do it at the end of the function. + #ifndef QT_NO_GRAPHICSVIEW QWExtra *topData = d_func()->extra; if (topData && topData->proxyWidget) @@ -6567,11 +6572,15 @@ void QWidget::clearFocus() QAccessible::updateAccessibility(&event); #endif } + } - if (QTLWExtra *extra = window()->d_func()->maybeTopData()) { - if (extra->window) - emit extra->window->focusObjectChanged(extra->window->focusObject()); - } + // Since we've unconditionally cleared the focus_child of our parents, we need + // to report this to the rest of Qt. Note that the focus_child is not the same + // thing as the application's focusWidget, which is why this piece of code is + // not inside the hasFocus() block above. + if (QTLWExtra *extra = window()->d_func()->maybeTopData()) { + if (extra->window) + emit extra->window->focusObjectChanged(extra->window->focusObject()); } } @@ -9686,7 +9695,8 @@ void QWidget::setInputMethodHints(Qt::InputMethodHints hints) if (d->imHints == hints) return; d->imHints = hints; - qApp->inputMethod()->update(Qt::ImHints); + if (this == qApp->focusObject()) + qApp->inputMethod()->update(Qt::ImHints); #endif //QT_NO_IM } @@ -11029,7 +11039,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->createTLSysExtra(); #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); - if (on && !internalWinId() && hasFocus() + if (on && !internalWinId() && this == qApp->focusObject() && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { qApp->inputMethod()->commit(); qApp->inputMethod()->update(Qt::ImEnabled); @@ -11038,7 +11048,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) parentWidget()->d_func()->enforceNativeChildren(); if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); - if (isEnabled() && focusWidget->isEnabled() + if (isEnabled() && focusWidget->isEnabled() && this == qApp->focusObject() && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) { qApp->inputMethod()->update(Qt::ImEnabled); } @@ -11564,7 +11574,8 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable) void QWidget::updateMicroFocus() { // updating everything since this is currently called for any kind of state change - qApp->inputMethod()->update(Qt::ImQueryAll); + if (this == qApp->focusObject()) + qApp->inputMethod()->update(Qt::ImQueryAll); } /*! diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 75a60fe3c4..d5a91f18d6 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -641,6 +641,8 @@ public: } } static void sendComposeStatus(QWidget *w, bool end); + // Called on setViewport(). + virtual void initializeViewportFramebuffer() { } // When using a QOpenGLWidget as viewport with QAbstractScrollArea, resize events are // filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget // since the fbo must be resized. We need an alternative way to notify. diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index cd57c1611e..d40fc84d77 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -73,8 +73,10 @@ public: void clearFocusObject() { - if (QApplicationPrivate::focus_widget) - QApplicationPrivate::focus_widget->clearFocus(); + Q_Q(QWidgetWindow); + QWidget *widget = q->widget(); + if (widget && widget->focusWidget()) + widget->focusWidget()->clearFocus(); } }; diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 142bd5882e..ef3795c9a1 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -3099,7 +3099,8 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co val = 2; break; case PM_SubMenuOverlap: - return -1; // Do not dpi-scale because the value is magic + val = -1; + break; case PM_DockWidgetHandleExtent: case PM_SplitterWidth: val = 4; diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index a4838d5777..090716f7f9 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1113,9 +1113,9 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath) { CGContextSaveGState(cg); + [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; - [NSGraphicsContext saveGraphicsState]; NSSetFocusRingStyle(NSFocusRingOnly); [focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos [focusRingPath fill]; @@ -1661,10 +1661,34 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti tdi->kind = kThemeSmallSlider; break; } + + bool usePlainKnob = slider->tickPosition == QSlider::NoTicks + || slider->tickPosition == QSlider::TicksBothSides; + tdi->bounds = qt_hirectForQRect(slider->rect); - tdi->min = slider->minimum; - tdi->max = slider->maximum; - tdi->value = slider->sliderPosition; + if (isScrollbar || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_9) { + tdi->min = slider->minimum; + tdi->max = slider->maximum; + tdi->value = slider->sliderPosition; + } else { + // Fix min and max positions. HITheme seems confused when it comes to rendering + // a slider at those positions. We give it a hand by extending and offsetting + // the slider range accordingly. See also comment for CC_Slider in drawComplexControl() + tdi->min = 0; + if (slider->orientation == Qt::Horizontal) + tdi->max = 10 * slider->rect.width(); + else + tdi->max = 10 * slider->rect.height(); + + if (usePlainKnob || slider->orientation == Qt::Horizontal) { + int endsCorrection = usePlainKnob ? 25 : 10; + tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum) + / (slider->maximum - slider->minimum) - endsCorrection; + } else { + tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum) + / (slider->maximum - slider->minimum) - 20; + } + } tdi->attributes = kThemeTrackShowThumb; if (slider->upsideDown) tdi->attributes |= kThemeTrackRightToLeft; @@ -1681,7 +1705,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti // Tiger broke reverse scroll bars so put them back and "fake it" if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) { tdi->attributes &= ~kThemeTrackRightToLeft; - tdi->value = tdi->max - slider->sliderPosition; + tdi->value = tdi->max - tdi->value; } tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive @@ -1689,7 +1713,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti if (!isScrollbar) { if (slider->state & QStyle::QStyle::State_HasFocus) tdi->attributes |= kThemeTrackHasFocus; - if (slider->tickPosition == QSlider::NoTicks || slider->tickPosition == QSlider::TicksBothSides) + if (usePlainKnob) tdi->trackInfo.slider.thumbDir = kThemeThumbPlain; else if (slider->tickPosition == QSlider::TicksAbove) tdi->trackInfo.slider.thumbDir = kThemeThumbUpward; @@ -1811,10 +1835,17 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons NSView *bv = cocoaControls[widget]; if (!bv) { - if (widget.first == QCocoaPopupButton) + if (widget.first == QCocoaPopupButton + || widget.first == QCocoaPullDownButton) bv = [[NSPopUpButton alloc] init]; else if (widget.first == QCocoaComboBox) bv = [[NSComboBox alloc] init]; + else if (widget.first == QCocoaHorizontalSlider) + bv = [[NSSlider alloc] init]; + else if (widget.first == QCocoaVerticalSlider) + // Cocoa sets the orientation from the view's frame + // at construction time, and it cannot be changed later. + bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 10, 100)]; else bv = [[NSButton alloc] init]; @@ -1841,6 +1872,11 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons bc.bezelStyle = NSRoundedBezelStyle; break; } + case QCocoaPullDownButton: { + NSPopUpButton *bc = (NSPopUpButton *)bv; + bc.pullsDown = YES; + break; + } default: break; } @@ -1883,12 +1919,18 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons *offset = QPoint(7, 5); else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini)) *offset = QPoint(2, -1); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge)) + *offset = QPoint(3, -1); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall)) + *offset = QPoint(2, 1); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini)) + *offset = QPoint(5, 0); } return bv; } -void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p) const +void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p, QCocoaDrawRectBlock drawRectBlock) const { QMacCGContext ctx(p); CGContextSaveGState(ctx); @@ -1897,11 +1939,14 @@ void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPain [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]]; - CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); + NSRect rect = NSMakeRect(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); [backingStoreNSView addSubview:view]; - view.frame = NSRectFromCGRect(rect); - [view drawRect:NSRectFromCGRect(rect)]; + view.frame = rect; + if (drawRectBlock) + drawRectBlock(rect, (CGContextRef)ctx); + else + [view drawRect:rect]; [view removeFromSuperviewWithoutNeedingDisplay]; [NSGraphicsContext restoreGraphicsState]; @@ -3828,21 +3873,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else if (d->pressedButton == opt->styleObject) d->pressedButton = 0; + bool hasMenu = btn->features & QStyleOptionButton::HasMenu; HIThemeButtonDrawInfo bdi; d->initHIThemePushButton(btn, w, tds, &bdi); if (yosemiteOrLater) { - // HITheme is not drawing a nice focus frame around buttons. - // We'll do it ourselves further down. - bdi.adornment &= ~kThemeAdornmentFocus; - - // We can't rely on an animation existing to test for the default look. That means a bit - // more logic (notice that the logic is slightly different for the bevel and the label). - if (tds == kThemeStateActive - && (btn->features & QStyleOptionButton::DefaultButton - || (btn->features & QStyleOptionButton::AutoDefaultButton - && d->autoDefaultButton == btn->styleObject))) - bdi.adornment |= kThemeAdornmentDefault; + if (!hasMenu) { + // HITheme is not drawing a nice focus frame around buttons. + // We'll do it ourselves further down. + bdi.adornment &= ~kThemeAdornmentFocus; + + // We can't rely on an animation existing to test for the default look. That means a bit + // more logic (notice that the logic is slightly different for the bevel and the label). + if (tds == kThemeStateActive + && (btn->features & QStyleOptionButton::DefaultButton + || (btn->features & QStyleOptionButton::AutoDefaultButton + && d->autoDefaultButton == btn->styleObject))) + bdi.adornment |= kThemeAdornmentDefault; + } } else { // the default button animation is paused meanwhile any button // is pressed or an auto-default button is animated instead @@ -3882,8 +3930,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; } - bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - if (hasMenu && bdi.state == kThemeStatePressed && QSysInfo::macVersion() > QSysInfo::MV_10_6) + if (hasMenu && yosemiteOrLater && bdi.kind != kThemeBevelButton) { + QCocoaWidget w = cocoaWidgetFromHIThemeButtonKind(bdi.kind); + QPoint offset; + NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(QCocoaWidget(QCocoaPullDownButton, w.second), &offset); + [pdb highlight:(bdi.state == kThemeStatePressed)]; + pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; + QRect rect = opt->rect; + rect.adjust(0, 0, w.second == QAquaSizeSmall ? -4 : w.second == QAquaSizeMini ? -9 : -6, 0); + p->translate(offset); + d->drawNSViewInRect(pdb, rect, p); + p->translate(-offset); + } else if (hasMenu && bdi.state == kThemeStatePressed && QSysInfo::macVersion() > QSysInfo::MV_10_6) d->drawColorlessButton(newRect, &bdi, p, opt); else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); @@ -3919,7 +3977,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath); } - if (hasMenu) { + if (hasMenu && (!yosemiteOrLater || bdi.kind == kThemeBevelButton)) { int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); QRect ir = btn->rect; int arrowXOffset = 0; @@ -3973,7 +4031,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter bool hasIcon = !btn.icon.isNull(); bool hasText = !btn.text.isEmpty(); - if (QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) { + if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) { if (tds == kThemeStatePressed || (tds == kThemeStateActive && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) @@ -5325,6 +5383,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex // because on Tiger I only "fake" the reverse stuff. bool reverseHorizontal = (slider->direction == Qt::RightToLeft && slider->orientation == Qt::Horizontal); + if ((reverseHorizontal && slider->activeSubControls == SC_ScrollBarAddLine) || (!reverseHorizontal @@ -5375,6 +5434,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex tdi.attributes |= kThemeTrackHideTrack; } + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + const bool isHorizontal = slider->orientation == Qt::Horizontal; + #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { bool wasActive = false; @@ -5459,8 +5521,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } } - const bool isHorizontal = slider->orientation == Qt::Horizontal; - CGContextSaveGState(cg); [NSGraphicsContext saveGraphicsState]; @@ -5545,9 +5605,86 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex { d->stopAnimation(opt->styleObject); - HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, - kHIThemeOrientationNormal); + if (usingYosemiteOrLater && cc == CC_Slider) { + // Fix min and max positions. (See also getSliderInfo() + // for the slider values adjustments.) + // HITheme seems to have forgotten how to render + // a slide at those positions, leaving a gap between + // the knob and the ends of the track. + // We fix this by rendering the track first, and then + // the knob on top. However, in order to not clip the + // knob, we reduce the the drawing rect for the track. + HIRect bounds = tdi.bounds; + if (isHorizontal) { + tdi.bounds.size.width -= 2; + tdi.bounds.origin.x += 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) + tdi.bounds.origin.y -= 2; + else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) + tdi.bounds.origin.y += 3; + } else { + tdi.bounds.size.height -= 2; + tdi.bounds.origin.y += 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right + tdi.bounds.origin.x -= 4; + else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left + tdi.bounds.origin.x += 2; + } + + // Yosemite demands its blue progress track when no tickmarks are present + if (!(slider->subControls & SC_SliderTickmarks)) { + QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; + NSSlider *sl = (NSSlider *)d->cocoaControl(QCocoaWidget(sliderKind, QAquaSizeLarge), 0); + sl.minValue = slider->minimum; + sl.maxValue = slider->maximum; + sl.intValue = slider->sliderValue; + sl.enabled = slider->state & QStyle::State_Enabled; + d->drawNSViewInRect(sl, opt->rect, p, ^(NSRect rect, CGContextRef ctx) { + if (slider->upsideDown) { + if (isHorizontal) { + CGContextTranslateCTM(ctx, rect.size.width, 0); + CGContextScaleCTM(ctx, -1, 1); + } + } else if (!isHorizontal) { + CGContextTranslateCTM(ctx, 0, rect.size.height); + CGContextScaleCTM(ctx, 1, -1); + } + [sl.cell drawBarInside:tdi.bounds flipped:NO]; + // No need to restore the CTM later, the context has been saved + // and will be restored at the end of drawNSViewInRect() + }); + tdi.attributes |= kThemeTrackHideTrack; + } else { + tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus); + HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, + kHIThemeOrientationNormal); + tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb; + } + + tdi.bounds = bounds; + } + if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { + + HIRect bounds; + if (usingYosemiteOrLater) { + // As part of fixing the min and max positions, + // we need to adjust the tickmarks as well + bounds = tdi.bounds; + if (slider->orientation == Qt::Horizontal) { + tdi.bounds.size.width += 2; + tdi.bounds.origin.x -= 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) + tdi.bounds.origin.y -= 2; + } else { + tdi.bounds.size.height += 3; + tdi.bounds.origin.y -= 3; + tdi.bounds.origin.y += 1; + if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left + tdi.bounds.origin.x -= 2; + } + } + if (qt_mac_is_metal(widget)) { if (tdi.enableState == kThemeTrackInactive) tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like @@ -5569,16 +5706,37 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex cg, kHIThemeOrientationNormal); tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; + if (usingYosemiteOrLater) { + if (slider->orientation == Qt::Vertical) + tdi.bounds.origin.x -= 2; + } HIThemeDrawTrackTickMarks(&tdi, numMarks, cg, kHIThemeOrientationNormal); + // Reset to plain thumb to be drawn further down + tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; } else { HIThemeDrawTrackTickMarks(&tdi, numMarks, cg, kHIThemeOrientationNormal); + } + if (usingYosemiteOrLater) + tdi.bounds = bounds; + } + + if (usingYosemiteOrLater && cc == CC_Slider) { + // Still as part of fixing the min and max positions, + // we also adjust the knob position. We can do this + // because it's rendered separately from the track. + if (slider->orientation == Qt::Vertical) { + if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right + tdi.bounds.origin.x -= 2; } } + + HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, + kHIThemeOrientationNormal); } } break; diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h index b6267c43e6..080f944ef8 100644 --- a/src/widgets/styles/qmacstyle_mac_p_p.h +++ b/src/widgets/styles/qmacstyle_mac_p_p.h @@ -126,12 +126,17 @@ enum QCocoaWidgetKind { QCocoaCheckBox, QCocoaComboBox, // Editable QComboBox QCocoaPopupButton, // Non-editable QComboBox + QCocoaPullDownButton, // QPushButton with menu QCocoaPushButton, - QCocoaRadioButton + QCocoaRadioButton, + QCocoaHorizontalSlider, + QCocoaVerticalSlider }; typedef QPair<QCocoaWidgetKind, QAquaWidgetSize> QCocoaWidget; +typedef void (^QCocoaDrawRectBlock)(NSRect, CGContextRef); + #define SIZE(large, small, mini) \ (controlSize == QAquaSizeLarge ? (large) : controlSize == QAquaSizeSmall ? (small) : (mini)) @@ -201,7 +206,7 @@ public: NSView *cocoaControl(QCocoaWidget widget, QPoint *offset) const; - void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p) const; + void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p, QCocoaDrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window); public: diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 3b75591998..4cafeafcec 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -609,6 +609,9 @@ void QAbstractScrollArea::setViewport(QWidget *widget) #endif #endif d->layoutChildren(); +#ifndef QT_NO_OPENGL + QWidgetPrivate::get(d->viewport)->initializeViewportFramebuffer(); +#endif if (isVisible()) d->viewport->show(); setupViewport(widget); diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 2fa197b2c8..44e22555db 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2439,7 +2439,7 @@ bool QComboBoxPrivate::showNativePopup() offset = QPoint(-1, 7); else if (q->testAttribute(Qt::WA_MacMiniSize)) offset = QPoint(-2, 6); - menu->showPopup(tlw, tlw->mapFromGlobal(q->mapToGlobal(offset)), currentItem); + menu->showPopup(tlw, QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize()), currentItem); menu->deleteLater(); Q_FOREACH (QPlatformMenuItem *item, items) item->deleteLater(); diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index affea4f9a3..a4c22de15b 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -3114,6 +3114,8 @@ static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* i QStyleOption opt; item->setIconSize(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, 0)); } + } else { + item->setIcon(QIcon()); } item->setVisible(action->isVisible()); item->setShortcut(action->shortcut()); diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 3d3f42605e..bb3f2d74a8 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -636,6 +636,9 @@ void QToolButton::setMenu(QMenu* menu) { Q_D(QToolButton); + if (d->menuAction == (menu ? menu->menuAction() : 0)) + return; + if (d->menuAction) removeAction(d->menuAction); diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index bedb0ba689..106bdf2dec 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -2948,29 +2948,12 @@ bool QXmlSimpleReader::feature(const QString& name, bool *ok) const \li If enabled, the original prefixed names and attributes used for namespace declarations are reported. - \row \li \e http://trolltech.com/xml/features/report-whitespace-only-CharData - \li true - \li Obsolete, use the following string instead. - If enabled, CharData that consist of - only whitespace characters are reported - using QXmlContentHandler::characters(). If disabled, whitespace is silently - discarded. \row \li \e http://qt-project.org/xml/features/report-whitespace-only-CharData \li true \li If enabled, CharData that consist of only whitespace characters are reported using QXmlContentHandler::characters(). If disabled, whitespace is silently discarded. - \row \li \e http://trolltech.com/xml/features/report-start-end-entity - \li false - \li Obsolete, use the following string instead. - If enabled, the parser reports - QXmlContentHandler::startEntity() and - QXmlContentHandler::endEntity() events, so character data - might be reported in chunks. - If disabled, the parser does not report these events, but - silently substitutes the entities, and reports the character - data in one chunk. \row \li \e http://qt-project.org/xml/features/report-start-end-entity \li false \li If enabled, the parser reports diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index f7d8bda190..35bd518b3a 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -670,6 +670,22 @@ void tst_qmessagehandler::cleanupFuncinfo_data() QTest::newRow("gcc_39") << "int TestClass1::operator>(int)" << "TestClass1::operator>"; + + QTest::newRow("objc_1") + << "-[SomeClass someMethod:withArguments:]" + << "-[SomeClass someMethod:withArguments:]"; + + QTest::newRow("objc_2") + << "+[SomeClass withClassMethod:withArguments:]" + << "+[SomeClass withClassMethod:withArguments:]"; + + QTest::newRow("objc_3") + << "-[SomeClass someMethodWithoutArguments]" + << "-[SomeClass someMethodWithoutArguments]"; + + QTest::newRow("objc_4") + << "__31-[SomeClass someMethodSchedulingBlock]_block_invoke" + << "__31-[SomeClass someMethodSchedulingBlock]_block_invoke"; } #endif diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 77a60997a6..3e68e4859f 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -118,6 +118,7 @@ private slots: void testUpdateRequestEvent(); void testThreadSafety(); void testEmptyData(); + void testEmptyKey(); void testResourceFiles(); void testRegistryShortRootNames(); void trailingWhitespace(); @@ -2025,6 +2026,16 @@ void tst_QSettings::testEmptyData() QFile::remove(filename); } +void tst_QSettings::testEmptyKey() +{ + QSettings settings; + QTest::ignoreMessage(QtWarningMsg, "QSettings::value: Empty key passed"); + const QVariant value = settings.value(QString()); + QCOMPARE(value, QVariant()); + QTest::ignoreMessage(QtWarningMsg, "QSettings::setValue: Empty key passed"); + settings.setValue(QString(), value); +} + void tst_QSettings::testResourceFiles() { QSettings settings(":/resourcefile.ini", QSettings::IniFormat); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 05c4066cbd..a35896283a 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1604,7 +1604,7 @@ void tst_QMetaType::automaticTemplateRegistration() #endif // Q_COMPILER_VARIADIC_MACROS -#define TEST_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \ +#define TEST_OWNING_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \ { \ SMARTPOINTER < ELEMENT_TYPE > sp(new ELEMENT_TYPE); \ sp.data()->setObjectName("Test name"); \ @@ -1615,22 +1615,34 @@ void tst_QMetaType::automaticTemplateRegistration() QCOMPARE(extractedPtr.data()->objectName(), sp.data()->objectName()); \ } - TEST_SMARTPOINTER(QSharedPointer, QObject, SharedPointerToQObject, qSharedPointerFromVariant) - TEST_SMARTPOINTER(QSharedPointer, QFile, SharedPointerToQObject, qSharedPointerFromVariant) - TEST_SMARTPOINTER(QSharedPointer, QTemporaryFile, SharedPointerToQObject, qSharedPointerFromVariant) - TEST_SMARTPOINTER(QSharedPointer, MyObject, SharedPointerToQObject, qSharedPointerFromVariant) + TEST_OWNING_SMARTPOINTER(QSharedPointer, QObject, SharedPointerToQObject, qSharedPointerFromVariant) + TEST_OWNING_SMARTPOINTER(QSharedPointer, QFile, SharedPointerToQObject, qSharedPointerFromVariant) + TEST_OWNING_SMARTPOINTER(QSharedPointer, QTemporaryFile, SharedPointerToQObject, qSharedPointerFromVariant) + TEST_OWNING_SMARTPOINTER(QSharedPointer, MyObject, SharedPointerToQObject, qSharedPointerFromVariant) +#undef TEST_OWNING_SMARTPOINTER - TEST_SMARTPOINTER(QWeakPointer, QObject, WeakPointerToQObject, qWeakPointerFromVariant) - TEST_SMARTPOINTER(QWeakPointer, QFile, WeakPointerToQObject, qWeakPointerFromVariant) - TEST_SMARTPOINTER(QWeakPointer, QTemporaryFile, WeakPointerToQObject, qWeakPointerFromVariant) - TEST_SMARTPOINTER(QWeakPointer, MyObject, WeakPointerToQObject, qWeakPointerFromVariant) +#define TEST_NONOWNING_SMARTPOINTER(SMARTPOINTER, ELEMENT_TYPE, FLAG_TEST, FROMVARIANTFUNCTION) \ + { \ + ELEMENT_TYPE elem; \ + SMARTPOINTER < ELEMENT_TYPE > sp(&elem); \ + sp.data()->setObjectName("Test name"); \ + QVariant v = QVariant::fromValue(sp); \ + QCOMPARE(v.typeName(), #SMARTPOINTER "<" #ELEMENT_TYPE ">"); \ + QVERIFY(QMetaType::typeFlags(::qMetaTypeId<SMARTPOINTER < ELEMENT_TYPE > >()) & QMetaType::FLAG_TEST); \ + SMARTPOINTER < QObject > extractedPtr = FROMVARIANTFUNCTION<QObject>(v); \ + QCOMPARE(extractedPtr.data()->objectName(), sp.data()->objectName()); \ + } - TEST_SMARTPOINTER(QPointer, QObject, TrackingPointerToQObject, qPointerFromVariant) - TEST_SMARTPOINTER(QPointer, QFile, TrackingPointerToQObject, qPointerFromVariant) - TEST_SMARTPOINTER(QPointer, QTemporaryFile, TrackingPointerToQObject, qPointerFromVariant) - TEST_SMARTPOINTER(QPointer, MyObject, TrackingPointerToQObject, qPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QObject, WeakPointerToQObject, qWeakPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QFile, WeakPointerToQObject, qWeakPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QWeakPointer, QTemporaryFile, WeakPointerToQObject, qWeakPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QWeakPointer, MyObject, WeakPointerToQObject, qWeakPointerFromVariant) -#undef TEST_SMARTPOINTER + TEST_NONOWNING_SMARTPOINTER(QPointer, QObject, TrackingPointerToQObject, qPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QPointer, QFile, TrackingPointerToQObject, qPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QPointer, QTemporaryFile, TrackingPointerToQObject, qPointerFromVariant) + TEST_NONOWNING_SMARTPOINTER(QPointer, MyObject, TrackingPointerToQObject, qPointerFromVariant) +#undef TEST_NONOWNING_SMARTPOINTER } template <typename T> diff --git a/tests/auto/corelib/kernel/qmimedata/tst_qmimedata.cpp b/tests/auto/corelib/kernel/qmimedata/tst_qmimedata.cpp index 1f1777f3b4..f4c267e321 100644 --- a/tests/auto/corelib/kernel/qmimedata/tst_qmimedata.cpp +++ b/tests/auto/corelib/kernel/qmimedata/tst_qmimedata.cpp @@ -327,5 +327,5 @@ void tst_QMimeData::setUrls() const QCOMPARE(mimeData.hasText(), false); } -QTEST_MAIN(tst_QMimeData) +QTEST_APPLESS_MAIN(tst_QMimeData) #include "tst_qmimedata.moc" diff --git a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp index 09d5db1475..689b008551 100644 --- a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp +++ b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp @@ -345,7 +345,8 @@ void tst_QPointer::threadSafety() void tst_QPointer::qvariantCast() { - QPointer<QFile> tracking = new QFile; + QFile file; + QPointer<QFile> tracking = &file; tracking->setObjectName("A test name"); QVariant v = QVariant::fromValue(tracking); diff --git a/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp b/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp index 182fa8b461..820039b6a9 100644 --- a/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp +++ b/tests/auto/corelib/statemachine/qstate/tst_qstate.cpp @@ -76,35 +76,35 @@ void tst_QState::assignProperty() { QStateMachine machine; - QObject *object = new QObject(); - object->setProperty("fooBar", 10); + QObject object; + object.setProperty("fooBar", 10); QState *s1 = new QState(&machine); - s1->assignProperty(object, "fooBar", 20); + s1->assignProperty(&object, "fooBar", 20); machine.setInitialState(s1); machine.start(); QCoreApplication::processEvents(); - QCOMPARE(object->property("fooBar").toInt(), 20); + QCOMPARE(object.property("fooBar").toInt(), 20); } void tst_QState::assignPropertyTwice() { QStateMachine machine; - QObject *object = new QObject(); - object->setProperty("fooBar", 10); + QObject object; + object.setProperty("fooBar", 10); QState *s1 = new QState(&machine); - s1->assignProperty(object, "fooBar", 20); - s1->assignProperty(object, "fooBar", 30); + s1->assignProperty(&object, "fooBar", 20); + s1->assignProperty(&object, "fooBar", 30); machine.setInitialState(s1); machine.start(); QCoreApplication::processEvents(); - QCOMPARE(object->property("fooBar").toInt(), 30); + QCOMPARE(object.property("fooBar").toInt(), 30); } class EventTestTransition: public QAbstractTransition diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index f6bdb6c53b..9c2c8bf12a 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -906,11 +906,12 @@ void tst_QThreadPool::waitForDone() void tst_QThreadPool::waitForDoneTimeout() { + QMutex mutex; class BlockedTask : public QRunnable { public: - QMutex mutex; - BlockedTask() { setAutoDelete(false); } + QMutex &mutex; + explicit BlockedTask(QMutex &m) : mutex(m) {} void run() { @@ -922,11 +923,10 @@ void tst_QThreadPool::waitForDoneTimeout() QThreadPool threadPool; - BlockedTask *task = new BlockedTask; - task->mutex.lock(); - threadPool.start(task); + mutex.lock(); + threadPool.start(new BlockedTask(mutex)); QVERIFY(!threadPool.waitForDone(100)); - task->mutex.unlock(); + mutex.unlock(); QVERIFY(threadPool.waitForDone(400)); } diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 1fa434395e..d5a628889c 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -2112,7 +2112,8 @@ void tst_QSharedPointer::qvariantCast() // Intentionally does not compile. // QWeakPointer<int> sop = qWeakPointerFromVariant<int>(v); - QWeakPointer<QFile> tracking = new QFile; + QFile file; + QWeakPointer<QFile> tracking = &file; tracking.data()->setObjectName("A test name"); v = QVariant::fromValue(tracking); diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp index a38707ef08..3ba901061c 100644 --- a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp +++ b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp @@ -1870,9 +1870,9 @@ void tst_QStringRef::right() QStringRef ref = originalString.rightRef(originalString.size() - 1); QCOMPARE(ref.toString(), QLatin1String("OrginalString")); - QCOMPARE(ref.right(ref.size() - 6).toString(), QLatin1String("String")); + QCOMPARE(ref.right(6).toString(), QLatin1String("String")); QCOMPARE(ref.right(ref.size()).toString(), QLatin1String("OrginalString")); - QCOMPARE(ref.right(0).toString(), QLatin1String("OrginalString")); + QCOMPARE(ref.right(0).toString(), QLatin1String("")); QStringRef nullRef; QVERIFY(nullRef.isNull()); diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp index 167e4b41bc..a88f41f7b8 100644 --- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp @@ -340,8 +340,10 @@ void tst_QClipboard::setMimeData() data->setText("foo"); QGuiApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); - QGuiApplication::clipboard()->setMimeData(data, QClipboard::Selection); - QGuiApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer); + if (QGuiApplication::clipboard()->supportsSelection()) + QGuiApplication::clipboard()->setMimeData(data, QClipboard::Selection); + if (QGuiApplication::clipboard()->supportsFindBuffer()) + QGuiApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer); QSignalSpy spySelection(QGuiApplication::clipboard(), SIGNAL(selectionChanged())); QSignalSpy spyData(QGuiApplication::clipboard(), SIGNAL(dataChanged())); @@ -373,8 +375,10 @@ void tst_QClipboard::setMimeData() data->setText("foo"); QGuiApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); - QGuiApplication::clipboard()->setMimeData(data, QClipboard::Selection); - QGuiApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer); + if (QGuiApplication::clipboard()->supportsSelection()) + QGuiApplication::clipboard()->setMimeData(data, QClipboard::Selection); + if (QGuiApplication::clipboard()->supportsFindBuffer()) + QGuiApplication::clipboard()->setMimeData(data, QClipboard::FindBuffer); QMimeData *newData = new QMimeData; newData->setText("bar"); @@ -385,8 +389,10 @@ void tst_QClipboard::setMimeData() spyFindBuffer.clear(); QGuiApplication::clipboard()->setMimeData(newData, QClipboard::Clipboard); - QGuiApplication::clipboard()->setMimeData(newData, QClipboard::Selection); // used to crash on X11 - QGuiApplication::clipboard()->setMimeData(newData, QClipboard::FindBuffer); + if (QGuiApplication::clipboard()->supportsSelection()) + QGuiApplication::clipboard()->setMimeData(newData, QClipboard::Selection); // used to crash on X11 + if (QGuiApplication::clipboard()->supportsFindBuffer()) + QGuiApplication::clipboard()->setMimeData(newData, QClipboard::FindBuffer); if (QGuiApplication::clipboard()->supportsSelection()) QCOMPARE(spySelection.count(), 1); diff --git a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp index 7f571fba89..02e00afe50 100644 --- a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp +++ b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp @@ -116,8 +116,8 @@ void tst_QOpenGLWindow::basic() QVERIFY(w.paintCount >= 1); // Check that something has been drawn; - QCOMPARE(w.img.size(), w.size()); - QVERIFY(w.img.pixel(5, 5) == qRgb(255, 0, 0)); + QCOMPARE(w.img.size(), w.size() * w.devicePixelRatio()); + QVERIFY(w.img.pixel(QPoint(5, 5) * w.devicePixelRatio()) == qRgb(255, 0, 0)); // Check that the viewport was properly set. w.makeCurrent(); @@ -168,9 +168,9 @@ void tst_QOpenGLWindow::painter() w.show(); QTest::qWaitForWindowExposed(&w); - QCOMPARE(w.img.size(), w.size()); - QVERIFY(w.img.pixel(5, 5) == qRgb(0, 0, 255)); - QVERIFY(w.img.pixel(200, 5) == qRgb(255, 0, 0)); + QCOMPARE(w.img.size(), w.size() * w.devicePixelRatio()); + QVERIFY(w.img.pixel(QPoint(5, 5) * w.devicePixelRatio()) == qRgb(0, 0, 255)); + QVERIFY(w.img.pixel(QPoint(200, 5) * w.devicePixelRatio()) == qRgb(255, 0, 0)); } class PartialPainterWindow : public QOpenGLWindow @@ -222,10 +222,10 @@ void tst_QOpenGLWindow::partial() // Now since the painting went to an extra framebuffer, all the rects should // be present since everything is preserved between the frames. QImage img = w.grabFramebuffer(); - QCOMPARE(img.size(), w.size()); - QCOMPARE(img.pixel(5, 5), qRgb(0, 0, 255)); - QCOMPARE(img.pixel(15, 5), qRgb(0, 255, 0)); - QCOMPARE(img.pixel(25, 5), qRgb(0, 0, 255)); + QCOMPARE(img.size(), w.size() * w.devicePixelRatio()); + QCOMPARE(img.pixel(QPoint(5, 5) * w.devicePixelRatio()), qRgb(0, 0, 255)); + QCOMPARE(img.pixel(QPoint(15, 5) * w.devicePixelRatio()), qRgb(0, 255, 0)); + QCOMPARE(img.pixel(QPoint(25, 5) * w.devicePixelRatio()), qRgb(0, 0, 255)); } class PaintUnderOverWindow : public QOpenGLWindow diff --git a/tests/auto/network/kernel/kernel.pro b/tests/auto/network/kernel/kernel.pro index 8594ad5932..bb13c7dd7d 100644 --- a/tests/auto/network/kernel/kernel.pro +++ b/tests/auto/network/kernel/kernel.pro @@ -14,6 +14,9 @@ winrt: SUBDIRS -= \ qnetworkproxy \ qnetworkproxyfactory \ +osx: SUBDIRS -= \ # QTBUG-41847 + qhostinfo \ + !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qauthenticator \ qhostinfo \ diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 67cbd5059f..49ff1b48fe 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -70,6 +70,7 @@ public slots: #ifndef QT_NO_SSL private slots: + void hash(); void emptyConstructor(); void constructor_data(); void constructor(); @@ -164,6 +165,14 @@ void tst_QSslCertificate::cleanupTestCase() #ifndef QT_NO_SSL +void tst_QSslCertificate::hash() +{ + // mostly a compile-only test, to check that qHash(QSslCertificate) is found. + QSet<QSslCertificate> certs; + certs << QSslCertificate(); + QCOMPARE(certs.size(), 1); +} + static QByteArray readFile(const QString &absFilePath) { QFile file(absFilePath); diff --git a/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp index 58136f9a68..7fd6dc8233 100644 --- a/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp +++ b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp @@ -64,6 +64,7 @@ public: #ifndef QT_NO_SSL private slots: void constructing(); + void hash(); #endif private: @@ -79,6 +80,14 @@ void tst_QSslError::constructing() QSslError error; } +void tst_QSslError::hash() +{ + // mostly a compile-only test, to check that qHash(QSslError) is found + QSet<QSslError> errors; + errors << QSslError(); + QCOMPARE(errors.size(), 1); +} + #endif // QT_NO_SSL QTEST_MAIN(tst_QSslError) diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index 47345bfc43..8253a283f5 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -784,12 +784,19 @@ void tst_Compiler::cxx11_default_members() #ifndef Q_COMPILER_DEFAULT_MEMBERS QSKIP("Compiler does not support C++11 feature"); #else - struct DefaultMembers + class DefaultMembers { + protected: DefaultMembers() = default; + public: DefaultMembers(int) {} }; - DefaultMembers dm; + class DefaultMembersChild: public DefaultMembers + { + public: + DefaultMembersChild():DefaultMembers() {}; + }; + DefaultMembersChild dm; Q_UNUSED(dm); #endif } @@ -799,9 +806,11 @@ void tst_Compiler::cxx11_delete_members() #ifndef Q_COMPILER_DELETE_MEMBERS QSKIP("Compiler does not support C++11 feature"); #else - struct DeleteMembers + class DeleteMembers { + protected: DeleteMembers() = delete; + public: DeleteMembers(const DeleteMembers &) = delete; ~DeleteMembers() = delete; }; diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index f5dfa5d617..565eac2cba 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -117,6 +117,9 @@ private slots: void selectColumn_data(); void selectColumn(); + void selectall_data(); + void selectall(); + void visualRect_data(); void visualRect(); @@ -1884,6 +1887,162 @@ void tst_QTableView::selectColumn() QCOMPARE(view.selectionModel()->selectedIndexes().at(i).column(), column); } +void tst_QTableView::selectall_data() +{ + QTest::addColumn<int>("rowCount"); + QTest::addColumn<int>("columnCount"); + QTest::addColumn<int>("row"); + QTest::addColumn<int>("column"); + QTest::addColumn<int>("rowSpan"); + QTest::addColumn<int>("columnSpan"); + QTest::addColumn<int>("hideRow"); + QTest::addColumn<int>("hideColumn"); + QTest::addColumn<int>("moveRowFrom"); + QTest::addColumn<int>("moveRowTo"); + QTest::addColumn<int>("moveColumnFrom"); + QTest::addColumn<int>("moveColumnTo"); + QTest::addColumn<int>("rowHeight"); + QTest::addColumn<int>("columnWidth"); + QTest::addColumn<int>("selectedCount"); // ### make this more detailed + + QTest::newRow("no span, no hidden, no moved") + << 10 << 10 // dim + << -1 << -1 // pos + << 1 << 1 // span + << -1 << -1 // hide + << -1 << -1 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 100; // selected count + + QTest::newRow("row span, no hidden, no moved") + << 10 << 10 // dim + << 1 << 1 // pos + << 2 << 1 // span + << -1 << -1 // hide + << -1 << -1 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 99; // selected count + + QTest::newRow("col span, no hidden, no moved") + << 10 << 10 // dim + << 1 << 1 // pos + << 1 << 2 // span + << -1 << -1 // hide + << -1 << -1 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 99; // selected count + + QTest::newRow("no span, row hidden, no moved") + << 10 << 10 // dim + << -1 << -1 // pos + << 1 << 1 // span + << 1 << -1 // hide + << -1 << -1 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 90; // selected count + + QTest::newRow("no span, col hidden, no moved") + << 10 << 10 // dim + << -1 << -1 // pos + << 1 << 1 // span + << -1 << 1 // hide + << -1 << -1 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 90; // selected count + + QTest::newRow("no span, no hidden, row moved") + << 10 << 10 // dim + << -1 << -1 // pos + << 1 << 1 // span + << -1 << -1 // hide + << 1 << 3 // move row + << -1 << -1 // move col + << 40 << 40 // cell size + << 100; // selected count + + QTest::newRow("no span, no hidden, col moved") + << 10 << 10 // dim + << -1 << -1 // pos + << 1 << 1 // span + << -1 << -1 // hide + << -1 << -1 // move row + << 1 << 3 // move col + << 40 << 40 // cell size + << 100; // selected count +} + +void QTest__keySequence(QWidget* widget, QKeySequence ks) +{ + for (int i=0; i<ks.count(); ++i) + { + Qt::Key key = Qt::Key(ks[i] & ~Qt::KeyboardModifierMask); + Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(ks[i] & Qt::KeyboardModifierMask); + QTest::keyClick(widget, key, modifiers); + } +} + +void tst_QTableView::selectall() +{ + QFETCH(int, rowCount); + QFETCH(int, columnCount); + QFETCH(int, row); + QFETCH(int, column); + QFETCH(int, rowSpan); + QFETCH(int, columnSpan); + QFETCH(int, hideRow); + QFETCH(int, hideColumn); + QFETCH(int, moveRowFrom); + QFETCH(int, moveRowTo); + QFETCH(int, moveColumnFrom); + QFETCH(int, moveColumnTo); + QFETCH(int, rowHeight); + QFETCH(int, columnWidth); + QFETCH(int, selectedCount); + + QtTestTableModel model(rowCount, columnCount); + + QtTestTableView view; + view.show(); + view.setModel(&model); + + view.setSpan(row, column, rowSpan, columnSpan); + + view.hideRow(hideRow); + view.hideColumn(hideColumn); + + view.verticalHeader()->moveSection(moveRowFrom, moveRowTo); + view.horizontalHeader()->moveSection(moveColumnFrom, moveColumnTo); + + for (int r = 0; r < rowCount; ++r) + view.setRowHeight(r, rowHeight); + for (int c = 0; c < columnCount; ++c) + view.setColumnWidth(c, columnWidth); + + // try slot first + view.clearSelection(); + QCOMPARE(view.selectedIndexes().count(), 0); + view.selectAll(); + QCOMPARE(view.selectedIndexes().count(), selectedCount); + + // try by key sequence + view.clearSelection(); + QCOMPARE(view.selectedIndexes().count(), 0); + QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll)); + QCOMPARE(view.selectedIndexes().count(), selectedCount); + + // check again with no selection mode + view.clearSelection(); + view.setSelectionMode(QAbstractItemView::NoSelection); + QCOMPARE(view.selectedIndexes().count(), 0); + QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll)); + QCOMPARE(view.selectedIndexes().count(), 0); +} + void tst_QTableView::visualRect_data() { QTest::addColumn<int>("rowCount"); diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 34bb4cfdf6..ec3e8ece6a 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -10274,6 +10274,7 @@ public slots: QTimer::singleShot(100, this, SLOT(doMouseMoves())); modal->exec(); delete modal; + modal = Q_NULLPTR; } void doMouseMoves() diff --git a/tests/manual/transientwindow/mainwindow.cpp b/tests/manual/transientwindow/mainwindow.cpp index 62deb14bc4..436e30c569 100644 --- a/tests/manual/transientwindow/mainwindow.cpp +++ b/tests/manual/transientwindow/mainwindow.cpp @@ -53,6 +53,7 @@ void MainWindow::toggleVisible() m_window->setTransientParent(windowHandle()); m_window->setMinimumSize(QSize(200, 100)); m_window->setTitle("Transient Window"); + m_window->setFlags(Qt::Dialog); } m_window->setVisible(!m_window->isVisible()); } |