From cf8f369f8575dcb9ca4d5116f3afc7cff4a080af Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 15 Oct 2014 13:50:27 +0200 Subject: Move Qt Core examples under a common subdirectory Qt Core examples were scattered into several subdirectories under qtbase/examples. This caused an issue with the example manifest file generated by QDoc; it expects to find all examples under a common directory in order to produde correct paths to the example .pro files. Qt Creator will not find the examples without a valid manifest file. This change moves the examples and edits the documentation files accordingly. Task-number: QTBUG-41963 Change-Id: I51d86782e0ba21c5c9bae5f15401ec774abe5cf8 Reviewed-by: Friedemann Kleint Reviewed-by: Oswald Buddenhagen Reviewed-by: Leena Miettinen --- examples/corelib/corelib.pro | 8 + examples/corelib/ipc/README | 5 + .../ipc/doc/images/localfortuneclient-example.png | Bin 0 -> 8402 bytes .../ipc/doc/images/localfortuneserver-example.png | Bin 0 -> 5715 bytes .../ipc/doc/images/sharedmemory-example_1.png | Bin 0 -> 14926 bytes .../ipc/doc/images/sharedmemory-example_2.png | Bin 0 -> 21976 bytes .../corelib/ipc/doc/src/localfortuneclient.qdoc | 40 +++ .../corelib/ipc/doc/src/localfortuneserver.qdoc | 39 +++ examples/corelib/ipc/doc/src/sharedmemory.qdoc | 131 ++++++++ examples/corelib/ipc/ipc.pro | 6 + examples/corelib/ipc/localfortuneclient/client.cpp | 153 +++++++++ examples/corelib/ipc/localfortuneclient/client.h | 82 +++++ .../ipc/localfortuneclient/localfortuneclient.pro | 8 + examples/corelib/ipc/localfortuneclient/main.cpp | 51 +++ .../ipc/localfortuneserver/localfortuneserver.pro | 8 + examples/corelib/ipc/localfortuneserver/main.cpp | 55 +++ examples/corelib/ipc/localfortuneserver/server.cpp | 111 +++++++ examples/corelib/ipc/localfortuneserver/server.h | 69 ++++ examples/corelib/ipc/sharedmemory/dialog.cpp | 188 +++++++++++ examples/corelib/ipc/sharedmemory/dialog.h | 70 ++++ examples/corelib/ipc/sharedmemory/dialog.ui | 47 +++ examples/corelib/ipc/sharedmemory/image.png | Bin 0 -> 10199 bytes examples/corelib/ipc/sharedmemory/main.cpp | 53 +++ examples/corelib/ipc/sharedmemory/qt.png | Bin 0 -> 2383 bytes examples/corelib/ipc/sharedmemory/sharedmemory.pro | 15 + examples/corelib/json/json.pro | 2 + examples/corelib/json/savegame/character.cpp | 101 ++++++ examples/corelib/json/savegame/character.h | 76 +++++ .../corelib/json/savegame/doc/src/savegame.qdoc | 184 ++++++++++ examples/corelib/json/savegame/game.cpp | 164 +++++++++ examples/corelib/json/savegame/game.h | 75 +++++ examples/corelib/json/savegame/level.cpp | 83 +++++ examples/corelib/json/savegame/level.h | 65 ++++ examples/corelib/json/savegame/main.cpp | 70 ++++ examples/corelib/json/savegame/savegame.pro | 22 ++ examples/corelib/threads/README | 7 + .../threads/doc/images/mandelbrot-example.png | Bin 0 -> 84202 bytes .../threads/doc/images/mandelbrot_scroll1.png | Bin 0 -> 19615 bytes .../threads/doc/images/mandelbrot_scroll2.png | Bin 0 -> 13901 bytes .../threads/doc/images/mandelbrot_scroll3.png | Bin 0 -> 18976 bytes .../threads/doc/images/mandelbrot_zoom1.png | Bin 0 -> 16000 bytes .../threads/doc/images/mandelbrot_zoom2.png | Bin 0 -> 8163 bytes .../threads/doc/images/mandelbrot_zoom3.png | Bin 0 -> 9848 bytes .../doc/images/queuedcustomtype-example.png | Bin 0 -> 44851 bytes examples/corelib/threads/doc/src/mandelbrot.qdoc | 370 +++++++++++++++++++++ .../corelib/threads/doc/src/queuedcustomtype.qdoc | 166 +++++++++ examples/corelib/threads/doc/src/semaphores.qdoc | 147 ++++++++ .../corelib/threads/doc/src/waitconditions.qdoc | 154 +++++++++ examples/corelib/threads/mandelbrot/main.cpp | 53 +++ examples/corelib/threads/mandelbrot/mandelbrot.pro | 13 + .../threads/mandelbrot/mandelbrotwidget.cpp | 239 +++++++++++++ .../corelib/threads/mandelbrot/mandelbrotwidget.h | 86 +++++ .../corelib/threads/mandelbrot/renderthread.cpp | 215 ++++++++++++ examples/corelib/threads/mandelbrot/renderthread.h | 87 +++++ .../corelib/threads/queuedcustomtype/block.cpp | 73 ++++ examples/corelib/threads/queuedcustomtype/block.h | 70 ++++ examples/corelib/threads/queuedcustomtype/main.cpp | 128 +++++++ .../threads/queuedcustomtype/queuedcustomtype.pro | 14 + .../threads/queuedcustomtype/renderthread.cpp | 109 ++++++ .../threads/queuedcustomtype/renderthread.h | 76 +++++ .../corelib/threads/queuedcustomtype/window.cpp | 136 ++++++++ examples/corelib/threads/queuedcustomtype/window.h | 76 +++++ examples/corelib/threads/semaphores/semaphores.cpp | 112 +++++++ examples/corelib/threads/semaphores/semaphores.pro | 9 + examples/corelib/threads/threads.pro | 7 + .../threads/waitconditions/waitconditions.cpp | 137 ++++++++ .../threads/waitconditions/waitconditions.pro | 9 + examples/corelib/tools/README | 9 + .../tools/contiguouscache/contiguouscache.pro | 9 + examples/corelib/tools/contiguouscache/main.cpp | 55 +++ .../tools/contiguouscache/randomlistmodel.cpp | 96 ++++++ .../tools/contiguouscache/randomlistmodel.h | 66 ++++ examples/corelib/tools/customtype/customtype.pro | 8 + examples/corelib/tools/customtype/main.cpp | 73 ++++ examples/corelib/tools/customtype/message.cpp | 89 +++++ examples/corelib/tools/customtype/message.h | 75 +++++ .../tools/customtypesending/customtypesending.pro | 10 + examples/corelib/tools/customtypesending/main.cpp | 67 ++++ .../corelib/tools/customtypesending/message.cpp | 71 ++++ examples/corelib/tools/customtypesending/message.h | 71 ++++ .../corelib/tools/customtypesending/window.cpp | 79 +++++ examples/corelib/tools/customtypesending/window.h | 72 ++++ .../corelib/tools/doc/src/contiguouscache.qdoc | 83 +++++ examples/corelib/tools/doc/src/customtype.qdoc | 143 ++++++++ examples/corelib/tools/tools.pro | 7 + 85 files changed, 5557 insertions(+) create mode 100644 examples/corelib/corelib.pro create mode 100644 examples/corelib/ipc/README create mode 100644 examples/corelib/ipc/doc/images/localfortuneclient-example.png create mode 100644 examples/corelib/ipc/doc/images/localfortuneserver-example.png create mode 100644 examples/corelib/ipc/doc/images/sharedmemory-example_1.png create mode 100644 examples/corelib/ipc/doc/images/sharedmemory-example_2.png create mode 100644 examples/corelib/ipc/doc/src/localfortuneclient.qdoc create mode 100644 examples/corelib/ipc/doc/src/localfortuneserver.qdoc create mode 100644 examples/corelib/ipc/doc/src/sharedmemory.qdoc create mode 100644 examples/corelib/ipc/ipc.pro create mode 100644 examples/corelib/ipc/localfortuneclient/client.cpp create mode 100644 examples/corelib/ipc/localfortuneclient/client.h create mode 100644 examples/corelib/ipc/localfortuneclient/localfortuneclient.pro create mode 100644 examples/corelib/ipc/localfortuneclient/main.cpp create mode 100644 examples/corelib/ipc/localfortuneserver/localfortuneserver.pro create mode 100644 examples/corelib/ipc/localfortuneserver/main.cpp create mode 100644 examples/corelib/ipc/localfortuneserver/server.cpp create mode 100644 examples/corelib/ipc/localfortuneserver/server.h create mode 100644 examples/corelib/ipc/sharedmemory/dialog.cpp create mode 100644 examples/corelib/ipc/sharedmemory/dialog.h create mode 100644 examples/corelib/ipc/sharedmemory/dialog.ui create mode 100644 examples/corelib/ipc/sharedmemory/image.png create mode 100644 examples/corelib/ipc/sharedmemory/main.cpp create mode 100644 examples/corelib/ipc/sharedmemory/qt.png create mode 100644 examples/corelib/ipc/sharedmemory/sharedmemory.pro create mode 100644 examples/corelib/json/json.pro create mode 100644 examples/corelib/json/savegame/character.cpp create mode 100644 examples/corelib/json/savegame/character.h create mode 100644 examples/corelib/json/savegame/doc/src/savegame.qdoc create mode 100644 examples/corelib/json/savegame/game.cpp create mode 100644 examples/corelib/json/savegame/game.h create mode 100644 examples/corelib/json/savegame/level.cpp create mode 100644 examples/corelib/json/savegame/level.h create mode 100644 examples/corelib/json/savegame/main.cpp create mode 100644 examples/corelib/json/savegame/savegame.pro create mode 100644 examples/corelib/threads/README create mode 100644 examples/corelib/threads/doc/images/mandelbrot-example.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_scroll1.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_scroll2.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_scroll3.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_zoom1.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_zoom2.png create mode 100644 examples/corelib/threads/doc/images/mandelbrot_zoom3.png create mode 100644 examples/corelib/threads/doc/images/queuedcustomtype-example.png create mode 100644 examples/corelib/threads/doc/src/mandelbrot.qdoc create mode 100644 examples/corelib/threads/doc/src/queuedcustomtype.qdoc create mode 100644 examples/corelib/threads/doc/src/semaphores.qdoc create mode 100644 examples/corelib/threads/doc/src/waitconditions.qdoc create mode 100644 examples/corelib/threads/mandelbrot/main.cpp create mode 100644 examples/corelib/threads/mandelbrot/mandelbrot.pro create mode 100644 examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp create mode 100644 examples/corelib/threads/mandelbrot/mandelbrotwidget.h create mode 100644 examples/corelib/threads/mandelbrot/renderthread.cpp create mode 100644 examples/corelib/threads/mandelbrot/renderthread.h create mode 100644 examples/corelib/threads/queuedcustomtype/block.cpp create mode 100644 examples/corelib/threads/queuedcustomtype/block.h create mode 100644 examples/corelib/threads/queuedcustomtype/main.cpp create mode 100644 examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro create mode 100644 examples/corelib/threads/queuedcustomtype/renderthread.cpp create mode 100644 examples/corelib/threads/queuedcustomtype/renderthread.h create mode 100644 examples/corelib/threads/queuedcustomtype/window.cpp create mode 100644 examples/corelib/threads/queuedcustomtype/window.h create mode 100644 examples/corelib/threads/semaphores/semaphores.cpp create mode 100644 examples/corelib/threads/semaphores/semaphores.pro create mode 100644 examples/corelib/threads/threads.pro create mode 100644 examples/corelib/threads/waitconditions/waitconditions.cpp create mode 100644 examples/corelib/threads/waitconditions/waitconditions.pro create mode 100644 examples/corelib/tools/README create mode 100644 examples/corelib/tools/contiguouscache/contiguouscache.pro create mode 100644 examples/corelib/tools/contiguouscache/main.cpp create mode 100644 examples/corelib/tools/contiguouscache/randomlistmodel.cpp create mode 100644 examples/corelib/tools/contiguouscache/randomlistmodel.h create mode 100644 examples/corelib/tools/customtype/customtype.pro create mode 100644 examples/corelib/tools/customtype/main.cpp create mode 100644 examples/corelib/tools/customtype/message.cpp create mode 100644 examples/corelib/tools/customtype/message.h create mode 100644 examples/corelib/tools/customtypesending/customtypesending.pro create mode 100644 examples/corelib/tools/customtypesending/main.cpp create mode 100644 examples/corelib/tools/customtypesending/message.cpp create mode 100644 examples/corelib/tools/customtypesending/message.h create mode 100644 examples/corelib/tools/customtypesending/window.cpp create mode 100644 examples/corelib/tools/customtypesending/window.h create mode 100644 examples/corelib/tools/doc/src/contiguouscache.qdoc create mode 100644 examples/corelib/tools/doc/src/customtype.qdoc create mode 100644 examples/corelib/tools/tools.pro (limited to 'examples/corelib') 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/corelib/ipc/README b/examples/corelib/ipc/README new file mode 100644 index 0000000000..83a157a42e --- /dev/null +++ b/examples/corelib/ipc/README @@ -0,0 +1,5 @@ +These examples demonstrate IPC support in Qt. + + +Documentation for these examples can be found via the Examples +link in the main Qt documentation. diff --git a/examples/corelib/ipc/doc/images/localfortuneclient-example.png b/examples/corelib/ipc/doc/images/localfortuneclient-example.png new file mode 100644 index 0000000000..614784bf0f Binary files /dev/null and b/examples/corelib/ipc/doc/images/localfortuneclient-example.png differ diff --git a/examples/corelib/ipc/doc/images/localfortuneserver-example.png b/examples/corelib/ipc/doc/images/localfortuneserver-example.png new file mode 100644 index 0000000000..2f04c7528e Binary files /dev/null and b/examples/corelib/ipc/doc/images/localfortuneserver-example.png differ diff --git a/examples/corelib/ipc/doc/images/sharedmemory-example_1.png b/examples/corelib/ipc/doc/images/sharedmemory-example_1.png new file mode 100644 index 0000000000..53244d3f52 Binary files /dev/null and b/examples/corelib/ipc/doc/images/sharedmemory-example_1.png differ diff --git a/examples/corelib/ipc/doc/images/sharedmemory-example_2.png b/examples/corelib/ipc/doc/images/sharedmemory-example_2.png new file mode 100644 index 0000000000..fc71aed56e Binary files /dev/null and b/examples/corelib/ipc/doc/images/sharedmemory-example_2.png differ diff --git a/examples/corelib/ipc/doc/src/localfortuneclient.qdoc b/examples/corelib/ipc/doc/src/localfortuneclient.qdoc new file mode 100644 index 0000000000..d7a90fd946 --- /dev/null +++ b/examples/corelib/ipc/doc/src/localfortuneclient.qdoc @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example ipc/localfortuneclient + \title Local Fortune Client Example + \ingroup examples-ipc + \brief Demonstrates using QLocalSocket for a simple local service client. + + The Local Fortune Client example shows how to create a client for a simple + local service using QLocalSocket. It is intended to be run alongside the + \l{Local Fortune Server Example}. + + \image localfortuneclient-example.png Screenshot of the Local Fortune Client example + +*/ diff --git a/examples/corelib/ipc/doc/src/localfortuneserver.qdoc b/examples/corelib/ipc/doc/src/localfortuneserver.qdoc new file mode 100644 index 0000000000..47c28e0eb0 --- /dev/null +++ b/examples/corelib/ipc/doc/src/localfortuneserver.qdoc @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example ipc/localfortuneserver + \title Local Fortune Server Example + \ingroup examples-ipc + \brief Demonstrates using QLocalServer and QLocalSocket for serving a simple local service. + + The Local Fortune Server example shows how to create a server for a simple + local service. It is intended to be run alongside the + \l{Local Fortune Client Example} + + \image localfortuneserver-example.png Screenshot of the Local Fortune Server example + */ diff --git a/examples/corelib/ipc/doc/src/sharedmemory.qdoc b/examples/corelib/ipc/doc/src/sharedmemory.qdoc new file mode 100644 index 0000000000..60b949df2d --- /dev/null +++ b/examples/corelib/ipc/doc/src/sharedmemory.qdoc @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example ipc/sharedmemory + \title Shared Memory Example + \ingroup examples-ipc + \brief Demonstrates doing inter-process communication using shared memory with + the QSharedMemory class. + + The Shared Memory example shows how to use the QSharedMemory class + to implement inter-process communication using shared memory. To + build the example, run make. To run the example, start two instances + of the executable. The main() function creates an \l {QApplication} + {application} and an instance of our example's Dialog class. The + dialog is displayed and then control is passed to the application in + the standard way. + + \snippet ipc/sharedmemory/main.cpp 0 + + Two instances of class Dialog appear. + + \image sharedmemory-example_1.png Screenshot of the Shared Memory example + + Class Dialog inherits QDialog. It encapsulates the user interface + and an instance of QSharedMemory. It also has two public slots, + loadFromFile() and loadFromMemory() that correspond to the two + buttons on the dialog. + + \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 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 + used by the system as the identifier of the underlying shared memory + segment. + + Click the \tt {Load Image From File...} button on one of the + dialogs. The loadFromFile() slot is invoked. First, it tests whether + a shared memory segment is already attached to the process. If so, + that segment is detached from the process, so we can be assured of + starting off the example correctly. + + \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 + QImage. Using a QImage lets us ensure that the selected file is a + valid image, and it also allows us to immediately display the image + in the dialog using setPixmap(). + + Next the image is streamed into a QBuffer using a QDataStream. This + gives us the size, which we then use to \l {QSharedMemory::} + {create()} our shared memory segment. Creating a shared memory + segment automatically \l {QSharedMemory::attach()} {attaches} the + segment to the process. Using a QBuffer here lets us get a pointer + to the image data, which we then use to do a memcopy() from the + QBuffer into the shared memory segment. + + \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 + again immediately after the copy. This ensures we have exclusive + access to the shared memory segment to do our memcopy(). If some + other process has the segment lock, then our process will block + until the lock becomes available. + + Note also that the function does not \l {QSharedMemory::} {detach()} + from the shared memory segment after the memcopy() and + unlock(). Recall that when the last process detaches from a shared + memory segment, the segment is released by the operating + system. Since this process only one that is attached to the shared + memory segment at the moment, if loadFromFile() detached from the + shared memory segment, the segment would be destroyed before we get + to the next step. + + When the function returns, if the file you selected was qt.png, your + first dialog looks like this. + + \image sharedmemory-example_2.png Screenshot of the Shared Memory example + + In the second dialog, click the \tt {Display Image From Shared + Memory} button. The loadFromMemory() slot is invoked. It first \l + {QSharedMemory::attach()} {attaches} the process to the same shared + memory segment created by the first process. Then it \l + {QSharedMemory::lock()} {locks} the segment for exclusive access and + links a QBuffer to the image data in the shared memory segment. It + then streams the data into a QImage and \l {QSharedMemory::unlock()} + {unlocks} the segment. + + \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 + it. Finally, the QImage is displayed. At this point, both dialogs + should be showing the same image. When you close the first dialog, + the Dialog destructor calls the QSharedMemory destructor, which + detaches from the shared memory segment. Since this is the last + process to be detached from the segment, the operating system will + now release the shared memory. + + */ diff --git a/examples/corelib/ipc/ipc.pro b/examples/corelib/ipc/ipc.pro new file mode 100644 index 0000000000..4b4b3870a4 --- /dev/null +++ b/examples/corelib/ipc/ipc.pro @@ -0,0 +1,6 @@ +requires(qtHaveModule(widgets)) + +TEMPLATE = subdirs +# no QSharedMemory +!vxworks:!qnx:SUBDIRS = sharedmemory +!wince*:qtHaveModule(network): SUBDIRS += localfortuneserver localfortuneclient diff --git a/examples/corelib/ipc/localfortuneclient/client.cpp b/examples/corelib/ipc/localfortuneclient/client.cpp new file mode 100644 index 0000000000..267f5329c8 --- /dev/null +++ b/examples/corelib/ipc/localfortuneclient/client.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "client.h" + +Client::Client(QWidget *parent) + : QDialog(parent) +{ + hostLabel = new QLabel(tr("&Server name:")); + hostLineEdit = new QLineEdit("fortune"); + + hostLabel->setBuddy(hostLineEdit); + + statusLabel = new QLabel(tr("This examples requires that you run the " + "Fortune Server example as well.")); + statusLabel->setWordWrap(true); + + getFortuneButton = new QPushButton(tr("Get Fortune")); + getFortuneButton->setDefault(true); + + quitButton = new QPushButton(tr("Quit")); + + buttonBox = new QDialogButtonBox; + buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole); + buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); + + socket = new QLocalSocket(this); + + connect(hostLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(enableGetFortuneButton())); + connect(getFortuneButton, SIGNAL(clicked()), + this, SLOT(requestNewFortune())); + connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); + connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune())); + connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), + this, SLOT(displayError(QLocalSocket::LocalSocketError))); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->addWidget(hostLabel, 0, 0); + mainLayout->addWidget(hostLineEdit, 0, 1); + mainLayout->addWidget(statusLabel, 2, 0, 1, 2); + mainLayout->addWidget(buttonBox, 3, 0, 1, 2); + setLayout(mainLayout); + + setWindowTitle(tr("Fortune Client")); + hostLineEdit->setFocus(); +} + +void Client::requestNewFortune() +{ + getFortuneButton->setEnabled(false); + blockSize = 0; + socket->abort(); + socket->connectToServer(hostLineEdit->text()); +} + +void Client::readFortune() +{ + QDataStream in(socket); + in.setVersion(QDataStream::Qt_4_0); + + if (blockSize == 0) { + if (socket->bytesAvailable() < (int)sizeof(quint16)) + return; + in >> blockSize; + } + + if (in.atEnd()) + return; + + QString nextFortune; + in >> nextFortune; + + if (nextFortune == currentFortune) { + QTimer::singleShot(0, this, SLOT(requestNewFortune())); + return; + } + + currentFortune = nextFortune; + statusLabel->setText(currentFortune); + getFortuneButton->setEnabled(true); +} + +void Client::displayError(QLocalSocket::LocalSocketError socketError) +{ + switch (socketError) { + case QLocalSocket::ServerNotFoundError: + QMessageBox::information(this, tr("Fortune Client"), + tr("The host was not found. Please check the " + "host name and port settings.")); + break; + case QLocalSocket::ConnectionRefusedError: + QMessageBox::information(this, tr("Fortune Client"), + tr("The connection was refused by the peer. " + "Make sure the fortune server is running, " + "and check that the host name and port " + "settings are correct.")); + break; + case QLocalSocket::PeerClosedError: + break; + default: + QMessageBox::information(this, tr("Fortune Client"), + tr("The following error occurred: %1.") + .arg(socket->errorString())); + } + + getFortuneButton->setEnabled(true); +} + +void Client::enableGetFortuneButton() +{ + getFortuneButton->setEnabled(!hostLineEdit->text().isEmpty()); +} diff --git a/examples/corelib/ipc/localfortuneclient/client.h b/examples/corelib/ipc/localfortuneclient/client.h new file mode 100644 index 0000000000..61b1cd26a4 --- /dev/null +++ b/examples/corelib/ipc/localfortuneclient/client.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLIENT_H +#define CLIENT_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QDialogButtonBox; +class QLabel; +class QLineEdit; +class QPushButton; +class QLocalSocket; +QT_END_NAMESPACE + +class Client : public QDialog +{ + Q_OBJECT + +public: + Client(QWidget *parent = 0); + +private slots: + void requestNewFortune(); + void readFortune(); + void displayError(QLocalSocket::LocalSocketError socketError); + void enableGetFortuneButton(); + +private: + QLabel *hostLabel; + QLineEdit *hostLineEdit; + QLabel *statusLabel; + QPushButton *getFortuneButton; + QPushButton *quitButton; + QDialogButtonBox *buttonBox; + + QLocalSocket *socket; + QString currentFortune; + quint16 blockSize; +}; + +#endif diff --git a/examples/corelib/ipc/localfortuneclient/localfortuneclient.pro b/examples/corelib/ipc/localfortuneclient/localfortuneclient.pro new file mode 100644 index 0000000000..912c0f3b8e --- /dev/null +++ b/examples/corelib/ipc/localfortuneclient/localfortuneclient.pro @@ -0,0 +1,8 @@ +HEADERS = client.h +SOURCES = client.cpp \ + main.cpp +QT += network widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/localfortuneclient +INSTALLS += target diff --git a/examples/corelib/ipc/localfortuneclient/main.cpp b/examples/corelib/ipc/localfortuneclient/main.cpp new file mode 100644 index 0000000000..f197d7f6cb --- /dev/null +++ b/examples/corelib/ipc/localfortuneclient/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "client.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Client client; + client.show(); + return app.exec(); +} diff --git a/examples/corelib/ipc/localfortuneserver/localfortuneserver.pro b/examples/corelib/ipc/localfortuneserver/localfortuneserver.pro new file mode 100644 index 0000000000..88190c45bd --- /dev/null +++ b/examples/corelib/ipc/localfortuneserver/localfortuneserver.pro @@ -0,0 +1,8 @@ +HEADERS = server.h +SOURCES = server.cpp \ + main.cpp +QT += network widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/localfortuneserver +INSTALLS += target diff --git a/examples/corelib/ipc/localfortuneserver/main.cpp b/examples/corelib/ipc/localfortuneserver/main.cpp new file mode 100644 index 0000000000..0ae70e14ef --- /dev/null +++ b/examples/corelib/ipc/localfortuneserver/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +#include "server.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Server server; + server.show(); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + return app.exec(); +} diff --git a/examples/corelib/ipc/localfortuneserver/server.cpp b/examples/corelib/ipc/localfortuneserver/server.cpp new file mode 100644 index 0000000000..6130aaa1c3 --- /dev/null +++ b/examples/corelib/ipc/localfortuneserver/server.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +#include "server.h" +#include +#include + +Server::Server(QWidget *parent) + : QDialog(parent) +{ + statusLabel = new QLabel; + statusLabel->setWordWrap(true); + quitButton = new QPushButton(tr("Quit")); + quitButton->setAutoDefault(false); + + server = new QLocalServer(this); + if (!server->listen("fortune")) { + QMessageBox::critical(this, tr("Fortune Server"), + tr("Unable to start the server: %1.") + .arg(server->errorString())); + close(); + return; + } + + statusLabel->setText(tr("The server is running.\n" + "Run the Fortune Client example now.")); + + fortunes << tr("You've been leading a dog's life. Stay off the furniture.") + << tr("You've got to think about tomorrow.") + << tr("You will be surprised by a loud noise.") + << tr("You will feel hungry again in another hour.") + << tr("You might have mail.") + << tr("You cannot kill time without injuring eternity.") + << tr("Computers are not intelligent. They only think they are."); + + connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); + connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune())); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(1); + buttonLayout->addWidget(quitButton); + buttonLayout->addStretch(1); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(statusLabel); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); + + setWindowTitle(tr("Fortune Server")); +} + +void Server::sendFortune() +{ + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_0); + out << (quint16)0; + out << fortunes.at(qrand() % fortunes.size()); + out.device()->seek(0); + out << (quint16)(block.size() - sizeof(quint16)); + + QLocalSocket *clientConnection = server->nextPendingConnection(); + connect(clientConnection, SIGNAL(disconnected()), + clientConnection, SLOT(deleteLater())); + + clientConnection->write(block); + clientConnection->flush(); + clientConnection->disconnectFromServer(); +} diff --git a/examples/corelib/ipc/localfortuneserver/server.h b/examples/corelib/ipc/localfortuneserver/server.h new file mode 100644 index 0000000000..4ec7f9b8ef --- /dev/null +++ b/examples/corelib/ipc/localfortuneserver/server.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SERVER_H +#define SERVER_H + +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QPushButton; +class QLocalServer; +QT_END_NAMESPACE + +class Server : public QDialog +{ + Q_OBJECT + +public: + Server(QWidget *parent = 0); + +private slots: + void sendFortune(); + +private: + QLabel *statusLabel; + QPushButton *quitButton; + QLocalServer *server; + QStringList fortunes; +}; + +#endif diff --git a/examples/corelib/ipc/sharedmemory/dialog.cpp b/examples/corelib/ipc/sharedmemory/dialog.cpp new file mode 100644 index 0000000000..c504f3a202 --- /dev/null +++ b/examples/corelib/ipc/sharedmemory/dialog.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" +#include +#include +#include + +/*! + \class Dialog + + \brief This class is a simple example of how to use QSharedMemory. + + It is a simple dialog that presents a few buttons. To compile the + example, run make in qt/examples/ipc. Then run the executable twice + to create two processes running the dialog. In one of the processes, + press the button to load an image into a shared memory segment, and + then select an image file to load. Once the first process has loaded + and displayed the image, in the second process, press the button to + read the same image from shared memory. The second process displays + the same image loaded from its new loaction in shared memory. +*/ + +/*! + The class contains a data member \l {QSharedMemory} {sharedMemory}, + which is initialized with the key "QSharedMemoryExample" to force + all instances of Dialog to access the same shared memory segment. + The constructor also connects the clicked() signal from each of the + three dialog buttons to the slot function appropriate for handling + each button. +*/ +//! [0] +Dialog::Dialog(QWidget *parent) + : QDialog(parent), sharedMemory("QSharedMemoryExample") +{ + ui.setupUi(this); + connect(ui.loadFromFileButton, SIGNAL(clicked()), SLOT(loadFromFile())); + connect(ui.loadFromSharedMemoryButton, + SIGNAL(clicked()), + SLOT(loadFromMemory())); + setWindowTitle(tr("SharedMemory Example")); +} +//! [0] + +/*! + This slot function is called when the \tt {Load Image From File...} + button is pressed on the firs Dialog process. First, it tests + whether the process is already connected to a shared memory segment + and, if so, detaches from that segment. This ensures that we always + start the example from the beginning if we run it multiple times + with the same two Dialog processes. After detaching from an existing + shared memory segment, the user is prompted to select an image file. + The selected file is loaded into a QImage. The QImage is displayed + in the Dialog and streamed into a QBuffer with a QDataStream. + + Next, it gets a new shared memory segment from the system big enough + to hold the image data in the QBuffer, and it locks the segment to + prevent the second Dialog process from accessing it. Then it copies + the image from the QBuffer into the shared memory segment. Finally, + it unlocks the shared memory segment so the second Dialog process + can access it. + + After this function runs, the user is expected to press the \tt + {Load Image from Shared Memory} button on the second Dialog process. + + \sa loadFromMemory() + */ +//! [1] +void Dialog::loadFromFile() +{ + if (sharedMemory.isAttached()) + detach(); + + ui.label->setText(tr("Select an image file")); + QString fileName = QFileDialog::getOpenFileName(0, QString(), QString(), + tr("Images (*.png *.xpm *.jpg)")); + QImage image; + if (!image.load(fileName)) { + ui.label->setText(tr("Selected file is not an image, please select another.")); + return; + } + ui.label->setPixmap(QPixmap::fromImage(image)); +//! [1] //! [2] + + // load into shared memory + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + QDataStream out(&buffer); + out << image; + int size = buffer.size(); + + if (!sharedMemory.create(size)) { + ui.label->setText(tr("Unable to create shared memory segment.")); + return; + } + sharedMemory.lock(); + char *to = (char*)sharedMemory.data(); + const char *from = buffer.data().data(); + memcpy(to, from, qMin(sharedMemory.size(), size)); + sharedMemory.unlock(); +} +//! [2] + +/*! + This slot function is called in the second Dialog process, when the + user presses the \tt {Load Image from Shared Memory} button. First, + it attaches the process to the shared memory segment created by the + first Dialog process. Then it locks the segment for exclusive + access, copies the image data from the segment into a QBuffer, and + streams the QBuffer into a QImage. Then it unlocks the shared memory + segment, detaches from it, and finally displays the QImage in the + Dialog. + + \sa loadFromFile() + */ +//! [3] +void Dialog::loadFromMemory() +{ + if (!sharedMemory.attach()) { + ui.label->setText(tr("Unable to attach to shared memory segment.\n" \ + "Load an image first.")); + return; + } + + QBuffer buffer; + QDataStream in(&buffer); + QImage image; + + sharedMemory.lock(); + buffer.setData((char*)sharedMemory.constData(), sharedMemory.size()); + buffer.open(QBuffer::ReadOnly); + in >> image; + sharedMemory.unlock(); + + sharedMemory.detach(); + ui.label->setPixmap(QPixmap::fromImage(image)); +} +//! [3] + +/*! + This private function is called by the destructor to detach the + process from its shared memory segment. When the last process + detaches from a shared memory segment, the system releases the + shared memory. + */ +void Dialog::detach() +{ + if (!sharedMemory.detach()) + ui.label->setText(tr("Unable to detach from shared memory.")); +} + diff --git a/examples/corelib/ipc/sharedmemory/dialog.h b/examples/corelib/ipc/sharedmemory/dialog.h new file mode 100644 index 0000000000..fbc39ed4c0 --- /dev/null +++ b/examples/corelib/ipc/sharedmemory/dialog.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include +#include +#include "ui_dialog.h" + +//! [0] +class Dialog : public QDialog +{ + Q_OBJECT + + public: + Dialog(QWidget *parent = 0); + + public slots: + void loadFromFile(); + void loadFromMemory(); + + private: + void detach(); + + private: + Ui::Dialog ui; + QSharedMemory sharedMemory; +}; +//! [0] + +#endif + diff --git a/examples/corelib/ipc/sharedmemory/dialog.ui b/examples/corelib/ipc/sharedmemory/dialog.ui new file mode 100644 index 0000000000..e99d6fb3c4 --- /dev/null +++ b/examples/corelib/ipc/sharedmemory/dialog.ui @@ -0,0 +1,47 @@ + + Dialog + + + + 0 + 0 + 451 + 322 + + + + Dialog + + + + + + Load Image From File... + + + + + + + Launch two of these dialogs. In the first, press the top button and load an image from a file. In the second, press the bottom button and display the loaded image from shared memory. + + + Qt::AlignCenter + + + true + + + + + + + Display Image From Shared Memory + + + + + + + + diff --git a/examples/corelib/ipc/sharedmemory/image.png b/examples/corelib/ipc/sharedmemory/image.png new file mode 100644 index 0000000000..dd93453063 Binary files /dev/null and b/examples/corelib/ipc/sharedmemory/image.png differ diff --git a/examples/corelib/ipc/sharedmemory/main.cpp b/examples/corelib/ipc/sharedmemory/main.cpp new file mode 100644 index 0000000000..0e9f84f3e3 --- /dev/null +++ b/examples/corelib/ipc/sharedmemory/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "dialog.h" + +//! [0] +int main(int argc, char *argv[]) +{ + QApplication application(argc, argv); + Dialog dialog; + dialog.show(); + return application.exec(); +} +//! [0] + diff --git a/examples/corelib/ipc/sharedmemory/qt.png b/examples/corelib/ipc/sharedmemory/qt.png new file mode 100644 index 0000000000..60ef558efe Binary files /dev/null and b/examples/corelib/ipc/sharedmemory/qt.png differ diff --git a/examples/corelib/ipc/sharedmemory/sharedmemory.pro b/examples/corelib/ipc/sharedmemory/sharedmemory.pro new file mode 100644 index 0000000000..c1b634732e --- /dev/null +++ b/examples/corelib/ipc/sharedmemory/sharedmemory.pro @@ -0,0 +1,15 @@ +QT += widgets + +SOURCES += main.cpp \ + dialog.cpp + +HEADERS += dialog.h + +# Forms and resources +FORMS += dialog.ui + +EXAMPLE_FILES = *.png + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/ipc/sharedmemory +INSTALLS += target diff --git a/examples/corelib/json/json.pro b/examples/corelib/json/json.pro new file mode 100644 index 0000000000..af4d3e6f0f --- /dev/null +++ b/examples/corelib/json/json.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = savegame diff --git a/examples/corelib/json/savegame/character.cpp b/examples/corelib/json/savegame/character.cpp new file mode 100644 index 0000000000..ef30f0eaf4 --- /dev/null +++ b/examples/corelib/json/savegame/character.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "character.h" + +Character::Character() : + mLevel(0), + mClassType(Warrior) { +} + +Character::Character(const QString &name, int level, Character::ClassType classType) : + mName(name), + mLevel(level), + mClassType(classType) +{ +} + +QString Character::name() const +{ + return mName; +} + +void Character::setName(const QString &name) +{ + mName = name; +} + +int Character::level() const +{ + return mLevel; +} + +void Character::setLevel(int level) +{ + mLevel = level; +} + +Character::ClassType Character::classType() const +{ + return mClassType; +} + +void Character::setClassType(Character::ClassType classType) +{ + mClassType = classType; +} + +//! [0] +void Character::read(const QJsonObject &json) +{ + mName = json["name"].toString(); + mLevel = json["level"].toDouble(); + mClassType = ClassType(qRound(json["classType"].toDouble())); +} +//! [0] + +//! [1] +void Character::write(QJsonObject &json) const +{ + json["name"] = mName; + json["level"] = mLevel; + json["classType"] = mClassType; +} +//! [1] diff --git a/examples/corelib/json/savegame/character.h b/examples/corelib/json/savegame/character.h new file mode 100644 index 0000000000..32369820f4 --- /dev/null +++ b/examples/corelib/json/savegame/character.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHARACTER_H +#define CHARACTER_H + +#include +#include + +//! [0] +class Character +{ +public: + enum ClassType { + Warrior, Mage, Archer + }; + + Character(); + Character(const QString &name, int level, ClassType classType); + + QString name() const; + void setName(const QString &name); + + int level() const; + void setLevel(int level); + + ClassType classType() const; + void setClassType(ClassType classType); + + void read(const QJsonObject &json); + void write(QJsonObject &json) const; +private: + QString mName; + int mLevel; + ClassType mClassType; +}; +//! [0] + +#endif // CHARACTER_H diff --git a/examples/corelib/json/savegame/doc/src/savegame.qdoc b/examples/corelib/json/savegame/doc/src/savegame.qdoc new file mode 100644 index 0000000000..1de12c38b9 --- /dev/null +++ b/examples/corelib/json/savegame/doc/src/savegame.qdoc @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example json/savegame + \title JSON Save Game Example + + \brief The JSON Save Game example demonstrates how to save and load a + small game using QJsonDocument, QJsonObject and QJsonArray. + + Many games provide save functionality, so that the player's progress through + the game can be saved and loaded at a later time. The process of saving a + game generally involves serializing each game object's member variables + to a file. Many formats can be used for this purpose, one of which is JSON. + With QJsonDocument, you also have the ability to serialize a document in a + binary format, which is great if you don't want the save file to be + readable, or if you need to keep the file size down. + + In this example, we'll demonstrate how to save and load a simple game to + and from JSON and binary formats. + + \section1 The Character Class + + The Character class represents a non-player character (NPC) in our game, and + stores the player's name, level, and class type. + + It provides read() and write() functions to serialise its member variables. + + \snippet json/savegame/character.h 0 + + Of particular interest to us are the read and write function + implementations: + + \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 + QJsonObject::value() to access values within the JSON object; both are + const functions and return QJsonValue::Undefined if the key is invalid. We + could check if the keys are valid before attempting to read them with + QJsonObject::contains(), but we assume that they are. + + \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 + values, there are two ways to set values on a QJsonObject: + \l QJsonObject::operator[]() and QJsonObject::insert(). Both will override + any existing value at the given key. + + Next up is the Level class: + + \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 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 + \c "npcs". Then, for each QJsonValue element in the array, we call + toObject() to get the Character's JSON object. The Character object can then + read their JSON and be appended to our NPC list. + + \note \l{Container Classes}{Associate containers} can be written by storing + the key in each value object (if it's not already). With this approach, the + container is stored as a regular array of objects, but the index of each + element is used as the key to construct the container when reading it back + in. + + \snippet json/savegame/level.cpp 1 + + Again, the write() function is similar to the read() function, except + reversed. + + Having established the Character and Level classes, we can move on to + the Game class: + + \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. + + Next, we provide accessors for the player and levels. We then expose three + functions: newGame(), saveGame() and loadGame(). + + The read() and write() functions are used by saveGame() and loadGame(). + + \snippet json/savegame/game.cpp 0 + + To setup a new game, we create the player and populate the levels and their + NPCs. + + \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 + Game object twice doesn't result in old levels hanging around. + + We then populate the level list by reading each Level from a QJsonArray. + + \snippet json/savegame/game.cpp 2 + + We write the game to JSON similarly to how we write Level. + + \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, + and \c "save.dat" for binary. We print a warning and return \c false if the + file couldn't be opened. + + Since QJsonDocument's \l{QJsonDocument::fromJson()}{fromJson()} and + \l{QJsonDocument::fromBinaryData()}{fromBinaryData()} functions both take a + QByteArray, we can read the entire contents of the save file into one, + regardless of the save format. + + After constructing the QJsonDocument, we instruct the Game object to read + itself and then return \c true to indicate success. + + \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 + if the opening of the file fails. We then write the Game object to a + QJsonDocument, and call either QJsonDocument::toJson() or to + QJsonDocument::toBinaryData() to save the game, depending on which format + was specified. + + We are now ready to enter main(): + + \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 + QCoreApplication and have no event loop. We create our game and assume that + the player had a great time and made lots of progress, altering the internal + state of our Character, Level and Game objects. + + \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 + of the files in the same directory as the executable, although the binary + save file will contain some garbage characters (which is normal). + + To show that the saved files can be loaded again, we call loadGame() for + each format, returning \c 1 on failure. Assuming everything went well, we + return \c 0 to indicate success. + + That concludes our example. As you can see, serialization with Qt's JSON + classes is very simple and convenient. The advantages of using QJsonDocument + and friends over QDataStream, for example, is that you not only get + human-readable JSON files, but you also have the option to use a binary + format if it's required, \e without rewriting any code. + + \sa {JSON Support in Qt}, {Data Storage} +*/ diff --git a/examples/corelib/json/savegame/game.cpp b/examples/corelib/json/savegame/game.cpp new file mode 100644 index 0000000000..a08071b208 --- /dev/null +++ b/examples/corelib/json/savegame/game.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "game.h" + +#include +#include +#include + +Game::Game() +{ +} + +const Character &Game::player() const +{ + return mPlayer; +} + +const QList &Game::levels() const { + return mLevels; +} + +//! [0] +void Game::newGame() { + mPlayer = Character(); + mPlayer.setName(QStringLiteral("Hero")); + mPlayer.setClassType(Character::Archer); + mPlayer.setLevel(15); + + mLevels.clear(); + + Level village; + QList villageNpcs; + villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"), 10, Character::Warrior)); + villageNpcs.append(Character(QStringLiteral("Terry the Trader"), 10, Character::Warrior)); + village.setNpcs(villageNpcs); + mLevels.append(village); + + Level dungeon; + QList dungeonNpcs; + dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"), 20, Character::Mage)); + dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #1"), 5, Character::Warrior)); + dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #2"), 5, Character::Warrior)); + dungeon.setNpcs(dungeonNpcs); + mLevels.append(dungeon); +} +//! [0] + +//! [3] +bool Game::loadGame(Game::SaveFormat saveFormat) +{ + QFile loadFile(saveFormat == Json + ? QStringLiteral("save.json") + : QStringLiteral("save.dat")); + + if (!loadFile.open(QIODevice::ReadOnly)) { + qWarning("Couldn't open save file."); + return false; + } + + QByteArray saveData = loadFile.readAll(); + + QJsonDocument loadDoc(saveFormat == Json + ? QJsonDocument::fromJson(saveData) + : QJsonDocument::fromBinaryData(saveData)); + + read(loadDoc.object()); + + return true; +} +//! [3] + +//! [4] +bool Game::saveGame(Game::SaveFormat saveFormat) const +{ + QFile saveFile(saveFormat == Json + ? QStringLiteral("save.json") + : QStringLiteral("save.dat")); + + if (!saveFile.open(QIODevice::WriteOnly)) { + qWarning("Couldn't open save file."); + return false; + } + + QJsonObject gameObject; + write(gameObject); + QJsonDocument saveDoc(gameObject); + saveFile.write(saveFormat == Json + ? saveDoc.toJson() + : saveDoc.toBinaryData()); + + return true; +} +//! [4] + +//! [1] +void Game::read(const QJsonObject &json) +{ + mPlayer.read(json["player"].toObject()); + + mLevels.clear(); + QJsonArray levelArray = json["levels"].toArray(); + for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex) { + QJsonObject levelObject = levelArray[levelIndex].toObject(); + Level level; + level.read(levelObject); + mLevels.append(level); + } +} +//! [1] + +//! [2] +void Game::write(QJsonObject &json) const +{ + QJsonObject playerObject; + mPlayer.write(playerObject); + json["player"] = playerObject; + + QJsonArray levelArray; + foreach (const Level level, mLevels) { + QJsonObject levelObject; + level.write(levelObject); + levelArray.append(levelObject); + } + json["levels"] = levelArray; +} +//! [2] diff --git a/examples/corelib/json/savegame/game.h b/examples/corelib/json/savegame/game.h new file mode 100644 index 0000000000..9216a373d1 --- /dev/null +++ b/examples/corelib/json/savegame/game.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GAME_H +#define GAME_H + +#include +#include + +#include "character.h" +#include "level.h" + +//! [0] +class Game +{ +public: + Game(); + + enum SaveFormat { + Json, Binary + }; + + const Character &player() const; + const QList &levels() const; + + void newGame(); + bool loadGame(SaveFormat saveFormat); + bool saveGame(SaveFormat saveFormat) const; + + void read(const QJsonObject &json); + void write(QJsonObject &json) const; +private: + Character mPlayer; + QList mLevels; +}; +//! [0] + +#endif // GAME_H diff --git a/examples/corelib/json/savegame/level.cpp b/examples/corelib/json/savegame/level.cpp new file mode 100644 index 0000000000..afbd3e0fa0 --- /dev/null +++ b/examples/corelib/json/savegame/level.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "level.h" + +#include + +Level::Level() { +} + +const QList &Level::npcs() const +{ + return mNpcs; +} + +void Level::setNpcs(const QList &npcs) +{ + mNpcs = npcs; +} + +//! [0] +void Level::read(const QJsonObject &json) +{ + mNpcs.clear(); + QJsonArray npcArray = json["npcs"].toArray(); + for (int npcIndex = 0; npcIndex < npcArray.size(); ++npcIndex) { + QJsonObject npcObject = npcArray[npcIndex].toObject(); + Character npc; + npc.read(npcObject); + mNpcs.append(npc); + } +} +//! [0] + +//! [1] +void Level::write(QJsonObject &json) const +{ + QJsonArray npcArray; + foreach (const Character npc, mNpcs) { + QJsonObject npcObject; + npc.write(npcObject); + npcArray.append(npcObject); + } + json["npcs"] = npcArray; +} +//! [1] diff --git a/examples/corelib/json/savegame/level.h b/examples/corelib/json/savegame/level.h new file mode 100644 index 0000000000..6cdf508c87 --- /dev/null +++ b/examples/corelib/json/savegame/level.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LEVEL_H +#define LEVEL_H + +#include +#include + +#include "character.h" + +//! [0] +class Level +{ +public: + Level(); + + const QList &npcs() const; + void setNpcs(const QList &npcs); + + void read(const QJsonObject &json); + void write(QJsonObject &json) const; +private: + QList mNpcs; +}; +//! [0] + +#endif // LEVEL_H diff --git a/examples/corelib/json/savegame/main.cpp b/examples/corelib/json/savegame/main.cpp new file mode 100644 index 0000000000..1b44306bb0 --- /dev/null +++ b/examples/corelib/json/savegame/main.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "game.h" +//! [0] +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + Game game; + game.newGame(); + // Game is played; changes are made... +//! [0] +//! [1] + if (!game.saveGame(Game::Json)) + return 1; + + if (!game.saveGame(Game::Binary)) + return 1; + + Game fromJsonGame; + if (!fromJsonGame.loadGame(Game::Json)) + return 1; + + Game fromBinaryGame; + if (!fromBinaryGame.loadGame(Game::Binary)) + return 1; + + return 0; +} +//! [1] diff --git a/examples/corelib/json/savegame/savegame.pro b/examples/corelib/json/savegame/savegame.pro new file mode 100644 index 0000000000..6706444506 --- /dev/null +++ b/examples/corelib/json/savegame/savegame.pro @@ -0,0 +1,22 @@ +QT += core +QT -= gui + +TARGET = savegame +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/json/savegame +INSTALLS += target + +SOURCES += main.cpp \ + character.cpp \ + game.cpp \ + level.cpp + +HEADERS += \ + character.h \ + game.h \ + level.h diff --git a/examples/corelib/threads/README b/examples/corelib/threads/README new file mode 100644 index 0000000000..6c20844564 --- /dev/null +++ b/examples/corelib/threads/README @@ -0,0 +1,7 @@ +This folder contains examples for the use of the threading-related classes +in Qt Core. For examples using the higher-level Qt Concurrent module, +check out the "qtconcurrent" folder instead. + +Documentation for examples can be found via the Examples and Tutorials link +in the main Qt documentation. The examples and their documentation can also +be opened from the Examples tab of Qt Creator's Welcome mode. diff --git a/examples/corelib/threads/doc/images/mandelbrot-example.png b/examples/corelib/threads/doc/images/mandelbrot-example.png new file mode 100644 index 0000000000..f5817834e1 Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot-example.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_scroll1.png b/examples/corelib/threads/doc/images/mandelbrot_scroll1.png new file mode 100644 index 0000000000..b800455821 Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_scroll1.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_scroll2.png b/examples/corelib/threads/doc/images/mandelbrot_scroll2.png new file mode 100644 index 0000000000..704ea0a7c1 Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_scroll2.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_scroll3.png b/examples/corelib/threads/doc/images/mandelbrot_scroll3.png new file mode 100644 index 0000000000..8b48211444 Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_scroll3.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_zoom1.png b/examples/corelib/threads/doc/images/mandelbrot_zoom1.png new file mode 100644 index 0000000000..30190e44eb Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_zoom1.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_zoom2.png b/examples/corelib/threads/doc/images/mandelbrot_zoom2.png new file mode 100644 index 0000000000..148ac777b8 Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_zoom2.png differ diff --git a/examples/corelib/threads/doc/images/mandelbrot_zoom3.png b/examples/corelib/threads/doc/images/mandelbrot_zoom3.png new file mode 100644 index 0000000000..a669f4b5fe Binary files /dev/null and b/examples/corelib/threads/doc/images/mandelbrot_zoom3.png differ diff --git a/examples/corelib/threads/doc/images/queuedcustomtype-example.png b/examples/corelib/threads/doc/images/queuedcustomtype-example.png new file mode 100644 index 0000000000..4399b631d7 Binary files /dev/null and b/examples/corelib/threads/doc/images/queuedcustomtype-example.png differ diff --git a/examples/corelib/threads/doc/src/mandelbrot.qdoc b/examples/corelib/threads/doc/src/mandelbrot.qdoc new file mode 100644 index 0000000000..75d424e6a4 --- /dev/null +++ b/examples/corelib/threads/doc/src/mandelbrot.qdoc @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example threads/mandelbrot + \title Mandelbrot Example + \ingroup qtconcurrent-mtexamples + + \brief The Mandelbrot example demonstrates multi-thread programming + using Qt. It shows how to use a worker thread to + perform heavy computations without blocking the main thread's + event loop. + + \image mandelbrot-example.png Screenshot of the Mandelbrot example + + The heavy computation here is the Mandelbrot set, probably the + world's most famous fractal. These days, while sophisticated + programs such as \l{http://xaos.sourceforge.net/}{XaoS} that provide real-time zooming in the + Mandelbrot set, the standard Mandelbrot algorithm is just slow + enough for our purposes. + + In real life, the approach described here is applicable to a + large set of problems, including synchronous network I/O and + database access, where the user interface must remain responsive + while some heavy operation is taking place. The \l + {Blocking Fortune Client Example} shows the same principle at + work in a TCP client. + + The Mandelbrot application supports zooming and scrolling using + the mouse or the keyboard. To avoid freezing the main thread's + event loop (and, as a consequence, the application's user + interface), we put all the fractal computation in a separate + worker thread. The thread emits a signal when it is done + rendering the fractal. + + During the time where the worker thread is recomputing the + fractal to reflect the new zoom factor position, the main thread + simply scales the previously rendered pixmap to provide immediate + feedback. The result doesn't look as good as what the worker + thread eventually ends up providing, but at least it makes the + application more responsive. The sequence of screenshots below + shows the original image, the scaled image, and the rerendered + image. + + \table + \row + \li \inlineimage mandelbrot_zoom1.png + \li \inlineimage mandelbrot_zoom2.png + \li \inlineimage mandelbrot_zoom3.png + \endtable + + Similarly, when the user scrolls, the previous pixmap is scrolled + immediately, revealing unpainted areas beyond the edge of the + pixmap, while the image is rendered by the worker thread. + + \table + \row + \li \inlineimage mandelbrot_scroll1.png + \li \inlineimage mandelbrot_scroll2.png + \li \inlineimage mandelbrot_scroll3.png + \endtable + + The application consists of two classes: + + \list + \li \c RenderThread is a QThread subclass that renders + the Mandelbrot set. + \li \c MandelbrotWidget is a QWidget subclass that shows the + Mandelbrot set on screen and lets the user zoom and scroll. + \endlist + + If you are not already familiar with Qt's thread support, we + recommend that you start by reading the \l{Thread Support in Qt} + overview. + + \section1 RenderThread Class Definition + + We'll start with the definition of the \c RenderThread class: + + \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 + render() is the only public function. Whenever the thread is done + rendering an image, it emits the \c renderedImage() signal. + + The protected \c run() function is reimplemented from QThread. It + is automatically called when the thread is started. + + In the \c private section, we have a QMutex, a QWaitCondition, + and a few other data members. The mutex protects the other data + member. + + \section1 RenderThread Class Implementation + + \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 + run() function. + + We also initialize the \c colormap array, which contains a series + of RGB colors. + + \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 + running as soon as possible. We also call + QWaitCondition::wakeOne() to wake up the thread if it's sleeping. + (As we will see when we review \c run(), the thread is put to + sleep when it has nothing to do.) + + The important thing to notice here is that \c run() is executed + in its own thread (the worker thread), whereas the \c + RenderThread constructor and destructor (as well as the \c + render() function) are called by the thread that created the + worker thread. Therefore, we need a mutex to protect accesses to + the \c abort and \c condition variables, which might be accessed + at any time by \c run(). + + At the end of the destructor, we call QThread::wait() to wait + until \c run() has exited before the base class destructor is + invoked. + + \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. + The \c centerX, \c centerY, and \c scaleFactor parameters specify + the portion of the fractal to render; \c resultSize specifies the + size of the resulting QImage. + + The function stores the parameters in member variables. If the + thread isn't already running, it starts it; otherwise, it sets \c + restart to \c true (telling \c run() to stop any unfinished + computation and start again with the new parameters) and wakes up + the thread, which might be sleeping. + + \snippet threads/mandelbrot/renderthread.cpp 3 + + \c run() is quite a big function, so we'll break it down into + parts. + + The function body is an infinite loop which starts by storing the + rendering parameters in local variables. As usual, we protect + accesses to the member variables using the class's mutex. Storing + the member variables in local variables allows us to minimize the + amout of code that needs to be protected by a mutex. This ensures + that the main thread will never have to block for too long when + it needs to access \c{RenderThread}'s member variables (e.g., in + \c render()). + + The \c forever keyword is, like \c foreach, a Qt pseudo-keyword. + + \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 + generate more and more precise (and computationally expensive) + approximations of the fractal. + + If we discover inside the loop that \c restart has been set to \c + true (by \c render()), we break out of the loop immediately, so + that the control quickly returns to the very top of the outer + loop (the \c forever loop) and we fetch the new rendering + parameters. Similarly, if we discover that \c abort has been set + to \c true (by the \c RenderThread destructor), we return from + the function immediately, terminating the thread. + + The core algorithm is beyond the scope of this tutorial. + + \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 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 + \l{QImage}s. It is called from the constructor to initialize the + \c colormap array with pleasing colors. + + \section1 MandelbrotWidget Class Definition + + The \c MandelbrotWidget class uses \c RenderThread to draw the + Mandelbrot set on screen. Here's the class definition: + + \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 + the worker thread's \c renderedImage() signal to update the + display whenever we receive new data from the thread. + + Among the private variables, we have \c thread of type \c + RenderThread and \c pixmap, which contains the last rendered + image. + + \section1 MandelbrotWidget Class Implementation + + \snippet threads/mandelbrot/mandelbrotwidget.cpp 0 + + The implementation starts with a few contants that we'll need + later on. + + \snippet threads/mandelbrot/mandelbrotwidget.cpp 1 + + The interesting part of the constructor is the + qRegisterMetaType() and QObject::connect() calls. Let's start + with the \l{QObject::connect()}{connect()} call. + + Although it looks like a standard signal-slot connection between + two \l{QObject}s, because the signal is emitted in a different + thread than the receiver lives in, the connection is effectively a + \l{Qt::QueuedConnection}{queued connection}. These connections are + asynchronous (i.e., non-blocking), meaning that the slot will be + called at some point after the \c emit statement. What's more, the + slot will be invoked in the thread in which the receiver lives. + Here, the signal is emitted in the worker thread, and the slot is + executed in the GUI thread when control returns to the event loop. + + With queued connections, Qt must store a copy of the arguments + that were passed to the signal so that it can pass them to the + slot later on. Qt knows how to take of copy of many C++ and Qt + types, but QImage isn't one of them. We must therefore call the + template function qRegisterMetaType() before we can use QImage + as parameter in queued connections. + + \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 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 + System}{coordinate system} before we draw the pixmap. By reverse mapping + the widget's rectangle using the scaled painter matrix, we also make sure + that only the exposed areas of the pixmap are drawn. The calls to + QPainter::save() and QPainter::restore() make sure that any painting + performed afterwards uses the standard coordinate system. + + \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 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 + centerY, and \c curScale parameters but with the new widget size. + + Notice that we rely on \c resizeEvent() being automatically + called by Qt when the widget is shown the first time to generate + the image the very first time. + + \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 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 + the wheel mouse movement, in eights of a degree. For most mice, + one wheel step corresponds to 15 degrees. We find out how many + mouse steps we have and determine the zoom factor in consequence. + For example, if we have two wheel steps in the positive direction + (i.e., +30 degrees), the zoom factor becomes \c ZoomInFactor + to the second power, i.e. 0.8 * 0.8 = 0.64. + + \snippet threads/mandelbrot/mandelbrotwidget.cpp 13 + + When the user presses the left mouse button, we store the mouse + pointer position in \c lastDragPos. + + \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 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 + default value. Then, we call \c scroll() to render a new image + for the new position. (Adjusting \c pixmapOffset isn't sufficient + because areas revealed when dragging the pixmap are drawn in + black.) + + \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 + is in effect and do nothing in that case. In the normal case, we + store the image in \c pixmap and reinitialize some of the other + members. At the end, we call QWidget::update() to refresh the + display. + + At this point, you might wonder why we use a QImage for the + parameter and a QPixmap for the data member. Why not stick to one + type? The reason is that QImage is the only class that supports + direct pixel manipulation, which we need in the worker thread. On + the other hand, before an image can be drawn on screen, it must + be converted into a pixmap. It's better to do the conversion once + and for all here, rather than in \c paintEvent(). + + \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 threads/mandelbrot/mandelbrotwidget.cpp 18 + + \c scroll() is similar to \c zoom(), except that the affected + parameters are \c centerX and \c centerY. + + \section1 The main() Function + + The application's multithreaded nature has no impact on its \c + main() function, which is as simple as usual: + + \snippet threads/mandelbrot/main.cpp 0 +*/ diff --git a/examples/corelib/threads/doc/src/queuedcustomtype.qdoc b/examples/corelib/threads/doc/src/queuedcustomtype.qdoc new file mode 100644 index 0000000000..cca68b4513 --- /dev/null +++ b/examples/corelib/threads/doc/src/queuedcustomtype.qdoc @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example threads/queuedcustomtype + \title Queued Custom Type Example + \brief Demonstrates multi-thread programming using Qt + \ingroup qtconcurrent-mtexamples + + \brief The Queued Custom Type example shows how to send custom types between + threads with queued signals and slots. + + \image queuedcustomtype-example.png + + Contents: + + \tableofcontents + + \section1 Overview + + In the \l{Custom Type Example}, we showed how to integrate custom types with + the meta-object system, enabling them to be stored in QVariant objects, written + out in debugging information and used in signal-slot communication. + + In this example, we create a new value class, \c Block, and register it + with the meta-object system to enable us to send instances of it between + threads using queued signals and slots. + + \section1 The Block Class + + The \c Block class is similar to the \c Message class described in the + \l{Custom Type Example}. It provides the default constructor, copy + constructor and destructor in the public section of the class that the + meta-object system requires. It describes a colored rectangle. + + \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 + we make any signal-slot connections that use this type. + Even though we do not intend to use the type with QVariant in this example, + it is good practice to also declare the new type with Q_DECLARE_METATYPE(). + + The implementation of the \c Block class is trivial, so we avoid quoting + it here. + + \section1 The Window Class + + We define a simple \c Window class with a public slot that accepts a + \c Block object. The rest of the class is concerned with managing the + user interface and handling images. + + \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 + to the window's \c addBlock(Block) slot. + + The parts of the \c Window class that are most relevant are the constructor + and the \c addBlock(Block) slot. + + The constructor creates a thread for rendering images, sets up a user + interface containing a label and two push buttons that are connected to + slots in the same class. + + \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 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 threads/queuedcustomtype/window.cpp Adding blocks to the display + + We simply paint these onto the label as they arrive. + + \section1 The RenderThread Class + + The \c RenderThread class processes an image, creating \c Block objects + and using the \c sendBlock(Block) signal to send them to other components + in the example. + + \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. + + Processing is started with the \c processImage() function, which calls the + \c RenderThread class's reimplementation of the QThread::run() function: + + \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 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. + + \section1 Registering the Type + + In the example's \c{main()} function, we perform the registration of the + \c Block class as a custom type with the meta-object system by calling the + qRegisterMetaType() template 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. + + The rest of the \c{main()} function is concerned with setting a seed for + the pseudo-random number generator, creating and showing the window, and + setting a default image. See the source code for the implementation of the + \c createImage() function. + + \section1 Further Reading + + This example showed how a custom type can be registered with the + meta-object system so that it can be used with signal-slot connections + between threads. For ordinary communication involving direct signals and + slots, it is enough to simply declare the type in the way described in the + \l{Custom Type Example}. + + In practice, both the Q_DECLARE_METATYPE() macro and the qRegisterMetaType() + template function can be used to register custom types, but + qRegisterMetaType() is only required if you need to perform signal-slot + communication or need to create and destroy objects of the custom type + at run-time. + + More information on using custom types with Qt can be found in the + \l{Creating Custom Qt Types} document. +*/ diff --git a/examples/corelib/threads/doc/src/semaphores.qdoc b/examples/corelib/threads/doc/src/semaphores.qdoc new file mode 100644 index 0000000000..0b1a2e852e --- /dev/null +++ b/examples/corelib/threads/doc/src/semaphores.qdoc @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example threads/semaphores + \title Semaphores Example + \brief Demonstrates multi-thread programming using Qt + \ingroup qtconcurrent-mtexamples + + \brief The Semaphores example shows how to use QSemaphore to control + access to a circular buffer shared by a producer thread and a + consumer thread. + + The producer writes data to the buffer until it reaches the end + of the buffer, at which point it restarts from the beginning, + overwriting existing data. The consumer thread reads the data as + it is produced and writes it to standard error. + + Semaphores make it possible to have a higher level of concurrency + than mutexes. If accesses to the buffer were guarded by a QMutex, + the consumer thread couldn't access the buffer at the same time + as the producer thread. Yet, there is no harm in having both + threads working on \e{different parts} of the buffer at the same + time. + + The example comprises two classes: \c Producer and \c Consumer. + Both inherit from QThread. The circular buffer used for + communicating between these two classes and the semaphores that + protect it are global variables. + + An alternative to using QSemaphore to solve the producer-consumer + problem is to use QWaitCondition and QMutex. This is what the + \l{Wait Conditions Example} does. + + \section1 Global Variables + + Let's start by reviewing the circular buffer and the associated + semaphores: + + \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. + \c BufferSize is the size of the circular buffer. It is less than + \c DataSize, meaning that at some point the producer will reach + the end of the buffer and restart from the beginning. + + To synchronize the producer and the consumer, we need two + semaphores. The \c freeBytes semaphore controls the "free" area + of the buffer (the area that the producer hasn't filled with data + yet or that the consumer has already read). The \c usedBytes + semaphore controls the "used" area of the buffer (the area that + the producer has filled but that the consumer hasn't read yet). + + Together, the semaphores ensure that the producer is never more + than \c BufferSize bytes ahead of the consumer, and that the + consumer never reads data that the producer hasn't generated yet. + + The \c freeBytes semaphore is initialized with \c BufferSize, + because initially the entire buffer is empty. The \c usedBytes + semaphore is initialized to 0 (the default value if none is + specified). + + \section1 Producer Class + + Let's review the code for the \c Producer class: + + \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" + byte using the \c freeBytes semaphore. The QSemaphore::acquire() + call might block if the consumer hasn't kept up the pace with the + producer. + + At the end, the producer releases a byte using the \c usedBytes + semaphore. The "free" byte has successfully been transformed into + a "used" byte, ready to be read by the consumer. + + \section1 Consumer Class + + Let's now turn to the \c Consumer class: + + \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 + the opposite. + + \section1 The main() Function + + 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 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 + blocked waiting for the \c usedBytes semaphore to be released (its + initial \l{QSemaphore::available()}{available()} count is 0). + Once the producer has put one byte in the buffer, + \c{freeBytes.available()} is \c BufferSize - 1 and + \c{usedBytes.available()} is 1. At that point, two things can + happen: Either the consumer thread takes over and reads that + byte, or the consumer gets to produce a second byte. + + The producer-consumer model presented in this example makes it + possible to write highly concurrent multithreaded applications. + On a multiprocessor machine, the program is potentially up to + twice as fast as the equivalent mutex-based program, since the + two threads can be active at the same time on different parts of + the buffer. + + Be aware though that these benefits aren't always realized. + Acquiring and releasing a QSemaphore has a cost. In practice, it + would probably be worthwhile to divide the buffer into chunks and + to operate on chunks instead of individual bytes. The buffer size + is also a parameter that must be selected carefully, based on + experimentation. +*/ diff --git a/examples/corelib/threads/doc/src/waitconditions.qdoc b/examples/corelib/threads/doc/src/waitconditions.qdoc new file mode 100644 index 0000000000..aff6997b55 --- /dev/null +++ b/examples/corelib/threads/doc/src/waitconditions.qdoc @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example threads/waitconditions + \title Wait Conditions Example + \brief Demonstrates multi-thread programming using Qt + \ingroup qtconcurrent-mtexamples + + \brief The Wait Conditions example shows how to use QWaitCondition and + QMutex to control access to a circular buffer shared by a + producer thread and a consumer thread. + + The producer writes data to the buffer until it reaches the end + of the buffer, at which point it restarts from the beginning, + overwriting existing data. The consumer thread reads the data as + it is produced and writes it to standard error. + + Wait conditions make it possible to have a higher level of + concurrency than what is possible with mutexes alone. If accesses + to the buffer were simply guarded by a QMutex, the consumer + thread couldn't access the buffer at the same time as the + producer thread. Yet, there is no harm in having both threads + working on \e{different parts} of the buffer at the same time. + + The example comprises two classes: \c Producer and \c Consumer. + Both inherit from QThread. The circular buffer used for + communicating between these two classes and the synchronization + tools that protect it are global variables. + + An alternative to using QWaitCondition and QMutex to solve the + producer-consumer problem is to use QSemaphore. This is what the + \l{Semaphores Example} does. + + \section1 Global Variables + + Let's start by reviewing the circular buffer and the associated + synchronization tools: + + \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. + \c BufferSize is the size of the circular buffer. It is less than + \c DataSize, meaning that at some point the producer will reach + the end of the buffer and restart from the beginning. + + To synchronize the producer and the consumer, we need two wait + conditions and one mutex. The \c bufferNotEmpty condition is + signalled when the producer has generated some data, telling the + consumer that it can start reading it. The \c bufferNotFull + condition is signalled when the consumer has read some data, + telling the producer that it can generate more. The \c numUsedBytes + is the number of bytes in the buffer that contain data. + + Together, the wait conditions, the mutex, and the \c numUsedBytes + counter ensure that the producer is never more than \c BufferSize + bytes ahead of the consumer, and that the consumer never reads + data that the producer hasn't generated yet. + + \section1 Producer Class + + Let's review the code for the \c Producer class: + + \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 + the buffer is full (i.e., \c numUsedBytes equals \c BufferSize). + If the buffer is full, the thread waits on the \c bufferNotFull + condition. + + At the end, the producer increments \c numUsedBytes and signalls + that the condition \c bufferNotEmpty is true, since \c + numUsedBytes is necessarily greater than 0. + + We guard all accesses to the \c numUsedBytes variable with a + mutex. In addition, the QWaitCondition::wait() function accepts a + mutex as its argument. This mutex is unlocked before the thread + is put to sleep and locked when the thread wakes up. Furthermore, + the transition from the locked state to the wait state is atomic, + to prevent race conditions from occurring. + + \section1 Consumer Class + + Let's turn to the \c Consumer class: + + \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) + instead of whether it's full and wait on the \c bufferNotEmpty + condition if it's empty. After we've read the byte, we decrement + \c numUsedBytes (instead of incrementing it), and we signal the + \c bufferNotFull condition (instead of the \c bufferNotEmpty + condition). + + \section1 The main() Function + + 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 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 + blocked waiting for the \c bufferNotEmpty condition to be + signalled (\c numUsedBytes is 0). Once the producer has put one + byte in the buffer, \c numUsedBytes is \c BufferSize - 1 and the + \c bufferNotEmpty condition is signalled. At that point, two + things can happen: Either the consumer thread takes over and + reads that byte, or the consumer gets to produce a second byte. + + The producer-consumer model presented in this example makes it + possible to write highly concurrent multithreaded applications. + On a multiprocessor machine, the program is potentially up to + twice as fast as the equivalent mutex-based program, since the + two threads can be active at the same time on different parts of + the buffer. + + Be aware though that these benefits aren't always realized. + Locking and unlocking a QMutex has a cost. In practice, it would + probably be worthwhile to divide the buffer into chunks and to + operate on chunks instead of individual bytes. The buffer size is + also a parameter that must be selected carefully, based on + experimentation. +*/ diff --git a/examples/corelib/threads/mandelbrot/main.cpp b/examples/corelib/threads/mandelbrot/main.cpp new file mode 100644 index 0000000000..8334d94f9c --- /dev/null +++ b/examples/corelib/threads/mandelbrot/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mandelbrotwidget.h" + +#include + +//! [0] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MandelbrotWidget widget; + widget.show(); + return app.exec(); +} +//! [0] diff --git a/examples/corelib/threads/mandelbrot/mandelbrot.pro b/examples/corelib/threads/mandelbrot/mandelbrot.pro new file mode 100644 index 0000000000..5a01a405f2 --- /dev/null +++ b/examples/corelib/threads/mandelbrot/mandelbrot.pro @@ -0,0 +1,13 @@ +QT += widgets + +HEADERS = mandelbrotwidget.h \ + renderthread.h +SOURCES = main.cpp \ + mandelbrotwidget.cpp \ + renderthread.cpp + +unix:!mac:!vxworks:!integrity:LIBS += -lm + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/mandelbrot +INSTALLS += target diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp new file mode 100644 index 0000000000..633d4a1ec5 --- /dev/null +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +#include "mandelbrotwidget.h" + + +//! [0] +const double DefaultCenterX = -0.637011f; +const double DefaultCenterY = -0.0395159f; +const double DefaultScale = 0.00403897f; + +const double ZoomInFactor = 0.8f; +const double ZoomOutFactor = 1 / ZoomInFactor; +const int ScrollStep = 20; +//! [0] + +//! [1] +MandelbrotWidget::MandelbrotWidget(QWidget *parent) + : QWidget(parent) +{ + centerX = DefaultCenterX; + centerY = DefaultCenterY; + pixmapScale = DefaultScale; + curScale = DefaultScale; + + connect(&thread, SIGNAL(renderedImage(QImage,double)), this, SLOT(updatePixmap(QImage,double))); + + setWindowTitle(tr("Mandelbrot")); +#ifndef QT_NO_CURSOR + setCursor(Qt::CrossCursor); +#endif + resize(550, 400); + +} +//! [1] + +//! [2] +void MandelbrotWidget::paintEvent(QPaintEvent * /* event */) +{ + QPainter painter(this); + painter.fillRect(rect(), Qt::black); + + if (pixmap.isNull()) { + painter.setPen(Qt::white); + painter.drawText(rect(), Qt::AlignCenter, tr("Rendering initial image, please wait...")); +//! [2] //! [3] + return; +//! [3] //! [4] + } +//! [4] + +//! [5] + if (curScale == pixmapScale) { +//! [5] //! [6] + painter.drawPixmap(pixmapOffset, pixmap); +//! [6] //! [7] + } else { +//! [7] //! [8] + double scaleFactor = pixmapScale / curScale; + int newWidth = int(pixmap.width() * scaleFactor); + int newHeight = int(pixmap.height() * scaleFactor); + int newX = pixmapOffset.x() + (pixmap.width() - newWidth) / 2; + int newY = pixmapOffset.y() + (pixmap.height() - newHeight) / 2; + + painter.save(); + painter.translate(newX, newY); + painter.scale(scaleFactor, scaleFactor); + QRectF exposed = painter.matrix().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1); + painter.drawPixmap(exposed, pixmap, exposed); + painter.restore(); + } +//! [8] //! [9] + + QString text = tr("Use mouse wheel or the '+' and '-' keys to zoom. " + "Press and hold left mouse button to scroll."); + QFontMetrics metrics = painter.fontMetrics(); + int textWidth = metrics.width(text); + + painter.setPen(Qt::NoPen); + painter.setBrush(QColor(0, 0, 0, 127)); + painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10, metrics.lineSpacing() + 5); + painter.setPen(Qt::white); + painter.drawText((width() - textWidth) / 2, metrics.leading() + metrics.ascent(), text); +} +//! [9] + +//! [10] +void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */) +{ + thread.render(centerX, centerY, curScale, size()); +} +//! [10] + +//! [11] +void MandelbrotWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Plus: + zoom(ZoomInFactor); + break; + case Qt::Key_Minus: + zoom(ZoomOutFactor); + break; + case Qt::Key_Left: + scroll(-ScrollStep, 0); + break; + case Qt::Key_Right: + scroll(+ScrollStep, 0); + break; + case Qt::Key_Down: + scroll(0, -ScrollStep); + break; + case Qt::Key_Up: + scroll(0, +ScrollStep); + break; + default: + QWidget::keyPressEvent(event); + } +} +//! [11] + +#ifndef QT_NO_WHEELEVENT +//! [12] +void MandelbrotWidget::wheelEvent(QWheelEvent *event) +{ + int numDegrees = event->delta() / 8; + double numSteps = numDegrees / 15.0f; + zoom(pow(ZoomInFactor, numSteps)); +} +//! [12] +#endif + +//! [13] +void MandelbrotWidget::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + lastDragPos = event->pos(); +} +//! [13] + +//! [14] +void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + pixmapOffset += event->pos() - lastDragPos; + lastDragPos = event->pos(); + update(); + } +} +//! [14] + +//! [15] +void MandelbrotWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + pixmapOffset += event->pos() - lastDragPos; + lastDragPos = QPoint(); + + int deltaX = (width() - pixmap.width()) / 2 - pixmapOffset.x(); + int deltaY = (height() - pixmap.height()) / 2 - pixmapOffset.y(); + scroll(deltaX, deltaY); + } +} +//! [15] + +//! [16] +void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor) +{ + if (!lastDragPos.isNull()) + return; + + pixmap = QPixmap::fromImage(image); + pixmapOffset = QPoint(); + lastDragPos = QPoint(); + pixmapScale = scaleFactor; + update(); +} +//! [16] + +//! [17] +void MandelbrotWidget::zoom(double zoomFactor) +{ + curScale *= zoomFactor; + update(); + thread.render(centerX, centerY, curScale, size()); +} +//! [17] + +//! [18] +void MandelbrotWidget::scroll(int deltaX, int deltaY) +{ + centerX += deltaX * curScale; + centerY += deltaY * curScale; + update(); + thread.render(centerX, centerY, curScale, size()); +} +//! [18] diff --git a/examples/corelib/threads/mandelbrot/mandelbrotwidget.h b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h new file mode 100644 index 0000000000..183edf2e26 --- /dev/null +++ b/examples/corelib/threads/mandelbrot/mandelbrotwidget.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MANDELBROTWIDGET_H +#define MANDELBROTWIDGET_H + +#include +#include +#include "renderthread.h" + + +//! [0] +class MandelbrotWidget : public QWidget +{ + Q_OBJECT + +public: + MandelbrotWidget(QWidget *parent = 0); + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; +#ifndef QT_NO_WHEELEVENT + void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; +#endif + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + +private slots: + void updatePixmap(const QImage &image, double scaleFactor); + void zoom(double zoomFactor); + +private: + void scroll(int deltaX, int deltaY); + + RenderThread thread; + QPixmap pixmap; + QPoint pixmapOffset; + QPoint lastDragPos; + double centerX; + double centerY; + double pixmapScale; + double curScale; +}; +//! [0] + +#endif // MANDELBROTWIDGET_H diff --git a/examples/corelib/threads/mandelbrot/renderthread.cpp b/examples/corelib/threads/mandelbrot/renderthread.cpp new file mode 100644 index 0000000000..5779c65c9c --- /dev/null +++ b/examples/corelib/threads/mandelbrot/renderthread.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "renderthread.h" + +#include + +#include + +//! [0] +RenderThread::RenderThread(QObject *parent) + : QThread(parent) +{ + restart = false; + abort = false; + + for (int i = 0; i < ColormapSize; ++i) + colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize)); +} +//! [0] + +//! [1] +RenderThread::~RenderThread() +{ + mutex.lock(); + abort = true; + condition.wakeOne(); + mutex.unlock(); + + wait(); +} +//! [1] + +//! [2] +void RenderThread::render(double centerX, double centerY, double scaleFactor, + QSize resultSize) +{ + QMutexLocker locker(&mutex); + + this->centerX = centerX; + this->centerY = centerY; + this->scaleFactor = scaleFactor; + this->resultSize = resultSize; + + if (!isRunning()) { + start(LowPriority); + } else { + restart = true; + condition.wakeOne(); + } +} +//! [2] + +//! [3] +void RenderThread::run() +{ + forever { + mutex.lock(); + QSize resultSize = this->resultSize; + double scaleFactor = this->scaleFactor; + double centerX = this->centerX; + double centerY = this->centerY; + mutex.unlock(); +//! [3] + +//! [4] + int halfWidth = resultSize.width() / 2; +//! [4] //! [5] + int halfHeight = resultSize.height() / 2; + QImage image(resultSize, QImage::Format_RGB32); + + const int NumPasses = 8; + int pass = 0; + while (pass < NumPasses) { + const int MaxIterations = (1 << (2 * pass + 6)) + 32; + const int Limit = 4; + bool allBlack = true; + + for (int y = -halfHeight; y < halfHeight; ++y) { + if (restart) + break; + if (abort) + return; + + uint *scanLine = + reinterpret_cast(image.scanLine(y + halfHeight)); + double ay = centerY + (y * scaleFactor); + + for (int x = -halfWidth; x < halfWidth; ++x) { + double ax = centerX + (x * scaleFactor); + double a1 = ax; + double b1 = ay; + int numIterations = 0; + + do { + ++numIterations; + double a2 = (a1 * a1) - (b1 * b1) + ax; + double b2 = (2 * a1 * b1) + ay; + if ((a2 * a2) + (b2 * b2) > Limit) + break; + + ++numIterations; + a1 = (a2 * a2) - (b2 * b2) + ax; + b1 = (2 * a2 * b2) + ay; + if ((a1 * a1) + (b1 * b1) > Limit) + break; + } while (numIterations < MaxIterations); + + if (numIterations < MaxIterations) { + *scanLine++ = colormap[numIterations % ColormapSize]; + allBlack = false; + } else { + *scanLine++ = qRgb(0, 0, 0); + } + } + } + + if (allBlack && pass == 0) { + pass = 4; + } else { + if (!restart) + emit renderedImage(image, scaleFactor); +//! [5] //! [6] + ++pass; + } +//! [6] //! [7] + } +//! [7] + +//! [8] + mutex.lock(); +//! [8] //! [9] + if (!restart) + condition.wait(&mutex); + restart = false; + mutex.unlock(); + } +} +//! [9] + +//! [10] +uint RenderThread::rgbFromWaveLength(double wave) +{ + double r = 0.0; + double g = 0.0; + double b = 0.0; + + if (wave >= 380.0 && wave <= 440.0) { + r = -1.0 * (wave - 440.0) / (440.0 - 380.0); + b = 1.0; + } else if (wave >= 440.0 && wave <= 490.0) { + g = (wave - 440.0) / (490.0 - 440.0); + b = 1.0; + } else if (wave >= 490.0 && wave <= 510.0) { + g = 1.0; + b = -1.0 * (wave - 510.0) / (510.0 - 490.0); + } else if (wave >= 510.0 && wave <= 580.0) { + r = (wave - 510.0) / (580.0 - 510.0); + g = 1.0; + } else if (wave >= 580.0 && wave <= 645.0) { + r = 1.0; + g = -1.0 * (wave - 645.0) / (645.0 - 580.0); + } else if (wave >= 645.0 && wave <= 780.0) { + r = 1.0; + } + + double s = 1.0; + if (wave > 700.0) + s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0); + else if (wave < 420.0) + s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0); + + r = pow(r * s, 0.8); + g = pow(g * s, 0.8); + b = pow(b * s, 0.8); + return qRgb(int(r * 255), int(g * 255), int(b * 255)); +} +//! [10] diff --git a/examples/corelib/threads/mandelbrot/renderthread.h b/examples/corelib/threads/mandelbrot/renderthread.h new file mode 100644 index 0000000000..881870665f --- /dev/null +++ b/examples/corelib/threads/mandelbrot/renderthread.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RENDERTHREAD_H +#define RENDERTHREAD_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QImage; +QT_END_NAMESPACE + +//! [0] +class RenderThread : public QThread +{ + Q_OBJECT + +public: + RenderThread(QObject *parent = 0); + ~RenderThread(); + + void render(double centerX, double centerY, double scaleFactor, QSize resultSize); + +signals: + void renderedImage(const QImage &image, double scaleFactor); + +protected: + void run() Q_DECL_OVERRIDE; + +private: + uint rgbFromWaveLength(double wave); + + QMutex mutex; + QWaitCondition condition; + double centerX; + double centerY; + double scaleFactor; + QSize resultSize; + bool restart; + bool abort; + + enum { ColormapSize = 512 }; + uint colormap[ColormapSize]; +}; +//! [0] + +#endif // RENDERTHREAD_H diff --git a/examples/corelib/threads/queuedcustomtype/block.cpp b/examples/corelib/threads/queuedcustomtype/block.cpp new file mode 100644 index 0000000000..07bd58cd97 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/block.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "block.h" + +Block::Block() +{ +} + +Block::Block(const Block &other) +{ + m_rect = other.m_rect; + m_color = other.m_color; +} + +Block::~Block() +{ +} + +Block::Block(const QRect &rect, const QColor &color) +{ + m_rect = rect; + m_color = color; +} + +QColor Block::color() const +{ + return m_color; +} + +QRect Block::rect() const +{ + return m_rect; +} diff --git a/examples/corelib/threads/queuedcustomtype/block.h b/examples/corelib/threads/queuedcustomtype/block.h new file mode 100644 index 0000000000..f9930340e2 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/block.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLOCK_H +#define BLOCK_H + +#include +#include +#include +#include + +//! [custom type definition and meta-type declaration] +class Block +{ +public: + Block(); + Block(const Block &other); + ~Block(); + + Block(const QRect &rect, const QColor &color); + + QColor color() const; + QRect rect() const; + +private: + QRect m_rect; + QColor m_color; +}; + +Q_DECLARE_METATYPE(Block); +//! [custom type definition and meta-type declaration] + +#endif diff --git a/examples/corelib/threads/queuedcustomtype/main.cpp b/examples/corelib/threads/queuedcustomtype/main.cpp new file mode 100644 index 0000000000..98933c66f3 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/main.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "block.h" +#include "window.h" + +QImage createImage(int width, int height) +{ + QImage image(width, height, QImage::Format_RGB16); + QPainter painter; + QPen pen; + pen.setStyle(Qt::NoPen); + QBrush brush(Qt::blue); + + painter.begin(&image); + painter.fillRect(image.rect(), brush); + brush.setColor(Qt::white); + painter.setPen(pen); + painter.setBrush(brush); + + static const QPointF points1[3] = { + QPointF(4, 4), + QPointF(7, 4), + QPointF(5.5, 1) + }; + + static const QPointF points2[3] = { + QPointF(1, 4), + QPointF(7, 4), + QPointF(10, 10) + }; + + static const QPointF points3[3] = { + QPointF(4, 4), + QPointF(10, 4), + QPointF(1, 10) + }; + + painter.setWindow(0, 0, 10, 10); + + int x = 0; + int y = 0; + int starWidth = image.width()/3; + int starHeight = image.height()/3; + + QRect rect(x, y, starWidth, starHeight); + + for (int i = 0; i < 9; ++i) { + + painter.setViewport(rect); + painter.drawPolygon(points1, 3); + painter.drawPolygon(points2, 3); + painter.drawPolygon(points3, 3); + + if (i % 3 == 2) { + y = y + starHeight; + rect.moveTop(y); + + x = 0; + rect.moveLeft(x); + + } else { + x = x + starWidth; + rect.moveLeft(x); + } + } + + painter.end(); + return image; +} + +//! [main function] //! [main start] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); +//! [main start] //! [register meta-type for queued communications] + qRegisterMetaType(); +//! [register meta-type for queued communications] + qsrand(QTime::currentTime().elapsed()); + + Window window; + window.show(); + + window.loadImage(createImage(256, 256)); +//! [main finish] + return app.exec(); +} +//! [main finish] //! [main function] diff --git a/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro new file mode 100644 index 0000000000..77421eb638 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro @@ -0,0 +1,14 @@ +HEADERS = block.h \ + renderthread.h \ + window.h +SOURCES = main.cpp \ + block.cpp \ + renderthread.cpp \ + window.cpp +QT += widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/mandelbrot +INSTALLS += target + + diff --git a/examples/corelib/threads/queuedcustomtype/renderthread.cpp b/examples/corelib/threads/queuedcustomtype/renderthread.cpp new file mode 100644 index 0000000000..50a638987f --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/renderthread.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "renderthread.h" + +RenderThread::RenderThread(QObject *parent) + : QThread(parent) +{ + m_abort = false; +} + +RenderThread::~RenderThread() +{ + mutex.lock(); + m_abort = true; + mutex.unlock(); + + wait(); +} + +//![processing the image (start)] +void RenderThread::processImage(const QImage &image) +{ + if (image.isNull()) + return; + + m_image = image; + m_abort = false; + start(); +} + +void RenderThread::run() +{ + int size = qMax(m_image.width()/20, m_image.height()/20); + for (int s = size; s > 0; --s) { + for (int c = 0; c < 400; ++c) { +//![processing the image (start)] + int x1 = qMax(0, (qrand() % m_image.width()) - s/2); + int x2 = qMin(x1 + s/2 + 1, m_image.width()); + int y1 = qMax(0, (qrand() % m_image.height()) - s/2); + int y2 = qMin(y1 + s/2 + 1, m_image.height()); + int n = 0; + int red = 0; + int green = 0; + int blue = 0; + for (int i = y1; i < y2; ++i) { + for (int j = x1; j < x2; ++j) { + QRgb pixel = m_image.pixel(j, i); + red += qRed(pixel); + green += qGreen(pixel); + blue += qBlue(pixel); + n += 1; + } + } +//![processing the image (finish)] + Block block(QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1), + QColor(red/n, green/n, blue/n)); + emit sendBlock(block); + if (m_abort) + return; + msleep(10); + } + } +} +//![processing the image (finish)] + +void RenderThread::stopProcess() +{ + mutex.lock(); + m_abort = true; + mutex.unlock(); +} diff --git a/examples/corelib/threads/queuedcustomtype/renderthread.h b/examples/corelib/threads/queuedcustomtype/renderthread.h new file mode 100644 index 0000000000..5630926d41 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/renderthread.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RENDERTHREAD_H +#define RENDERTHREAD_H + +#include +#include +#include +#include "block.h" + +//! [RenderThread class definition] +class RenderThread : public QThread +{ + Q_OBJECT + +public: + RenderThread(QObject *parent = 0); + ~RenderThread(); + + void processImage(const QImage &image); + +signals: + void sendBlock(const Block &block); + +public slots: + void stopProcess(); + +protected: + void run(); + +private: + bool m_abort; + QImage m_image; + QMutex mutex; +}; +//! [RenderThread class definition] + +#endif diff --git a/examples/corelib/threads/queuedcustomtype/window.cpp b/examples/corelib/threads/queuedcustomtype/window.cpp new file mode 100644 index 0000000000..8afb8b6782 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/window.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "window.h" + +//! [Window constructor start] +Window::Window() +{ + thread = new RenderThread(); +//! [Window constructor start] //! [set up widgets and connections] + + label = new QLabel(); + label->setAlignment(Qt::AlignCenter); + + loadButton = new QPushButton(tr("&Load image...")); + resetButton = new QPushButton(tr("&Stop")); + resetButton->setEnabled(false); + + connect(loadButton, SIGNAL(clicked()), this, SLOT(loadImage())); + connect(resetButton, SIGNAL(clicked()), thread, SLOT(stopProcess())); + connect(thread, SIGNAL(finished()), this, SLOT(resetUi())); +//! [set up widgets and connections] //! [connecting signal with custom type] + connect(thread, SIGNAL(sendBlock(Block)), this, SLOT(addBlock(Block))); +//! [connecting signal with custom type] + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + buttonLayout->addStretch(); + buttonLayout->addWidget(loadButton); + buttonLayout->addWidget(resetButton); + buttonLayout->addStretch(); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(label); + layout->addLayout(buttonLayout); + +//! [Window constructor finish] + setWindowTitle(tr("Queued Custom Type")); +} +//! [Window constructor finish] + +void Window::loadImage() +{ + QStringList formats; + foreach (QByteArray format, QImageReader::supportedImageFormats()) + if (format.toLower() == format) + formats.append("*." + format); + + QString newPath = QFileDialog::getOpenFileName(this, tr("Open Image"), + path, tr("Image files (%1)").arg(formats.join(' '))); + + if (newPath.isEmpty()) + return; + + QImage image(newPath); + if (!image.isNull()) { + loadImage(image); + path = newPath; + } +} + +void Window::loadImage(const QImage &image) +{ + QDesktopWidget desktop; + QImage useImage; + QRect space = desktop.availableGeometry(); + if (image.width() > 0.75*space.width() || image.height() > 0.75*space.height()) + useImage = image.scaled(0.75*space.width(), 0.75*space.height(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + else + useImage = image; + + pixmap = QPixmap(useImage.width(), useImage.height()); + pixmap.fill(qRgb(255, 255, 255)); + label->setPixmap(pixmap); + loadButton->setEnabled(false); + resetButton->setEnabled(true); + thread->processImage(useImage); +} + +//! [Adding blocks to the display] +void Window::addBlock(const Block &block) +{ + QColor color = block.color(); + color.setAlpha(64); + + QPainter painter; + painter.begin(&pixmap); + painter.fillRect(block.rect(), color); + painter.end(); + label->setPixmap(pixmap); +} +//! [Adding blocks to the display] + +void Window::resetUi() +{ + loadButton->setEnabled(true); + resetButton->setEnabled(false); +} diff --git a/examples/corelib/threads/queuedcustomtype/window.h b/examples/corelib/threads/queuedcustomtype/window.h new file mode 100644 index 0000000000..cb648f1be2 --- /dev/null +++ b/examples/corelib/threads/queuedcustomtype/window.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include "renderthread.h" + +class QLabel; +class QPushButton; + +//! [Window class definition] +class Window : public QWidget +{ + Q_OBJECT + +public: + Window(); + void loadImage(const QImage &image); + +public slots: + void addBlock(const Block &block); + +private slots: + void loadImage(); + void resetUi(); + +private: + QLabel *label; + QPixmap pixmap; + QPushButton *loadButton; + QPushButton *resetButton; + QString path; + RenderThread *thread; +}; +//! [Window class definition] + +#endif diff --git a/examples/corelib/threads/semaphores/semaphores.cpp b/examples/corelib/threads/semaphores/semaphores.cpp new file mode 100644 index 0000000000..f519e5f323 --- /dev/null +++ b/examples/corelib/threads/semaphores/semaphores.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +//! [0] +const int DataSize = 100000; + +const int BufferSize = 8192; +char buffer[BufferSize]; + +QSemaphore freeBytes(BufferSize); +QSemaphore usedBytes; +//! [0] + +//! [1] +class Producer : public QThread +//! [1] //! [2] +{ +public: + void run() Q_DECL_OVERRIDE + { + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + for (int i = 0; i < DataSize; ++i) { + freeBytes.acquire(); + buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4]; + usedBytes.release(); + } + } +}; +//! [2] + +//! [3] +class Consumer : public QThread +//! [3] //! [4] +{ + Q_OBJECT +public: + void run() Q_DECL_OVERRIDE + { + for (int i = 0; i < DataSize; ++i) { + usedBytes.acquire(); + fprintf(stderr, "%c", buffer[i % BufferSize]); + freeBytes.release(); + } + fprintf(stderr, "\n"); + } + +signals: + void stringConsumed(const QString &text); + +protected: + bool finish; +}; +//! [4] + +//! [5] +int main(int argc, char *argv[]) +//! [5] //! [6] +{ + QCoreApplication app(argc, argv); + Producer producer; + Consumer consumer; + producer.start(); + consumer.start(); + producer.wait(); + consumer.wait(); + return 0; +} +//! [6] + +#include "semaphores.moc" diff --git a/examples/corelib/threads/semaphores/semaphores.pro b/examples/corelib/threads/semaphores/semaphores.pro new file mode 100644 index 0000000000..69154e57eb --- /dev/null +++ b/examples/corelib/threads/semaphores/semaphores.pro @@ -0,0 +1,9 @@ +SOURCES += semaphores.cpp +QT = core + +CONFIG -= app_bundle +CONFIG += console + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/semaphores +INSTALLS += target diff --git a/examples/corelib/threads/threads.pro b/examples/corelib/threads/threads.pro new file mode 100644 index 0000000000..e47da84a06 --- /dev/null +++ b/examples/corelib/threads/threads.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs +CONFIG += no_docs_target + +SUBDIRS = semaphores \ + waitconditions + +qtHaveModule(widgets): SUBDIRS += mandelbrot diff --git a/examples/corelib/threads/waitconditions/waitconditions.cpp b/examples/corelib/threads/waitconditions/waitconditions.cpp new file mode 100644 index 0000000000..b0336f4c2b --- /dev/null +++ b/examples/corelib/threads/waitconditions/waitconditions.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +//! [0] +const int DataSize = 100000; + +const int BufferSize = 8192; +char buffer[BufferSize]; + +QWaitCondition bufferNotEmpty; +QWaitCondition bufferNotFull; +QMutex mutex; +int numUsedBytes = 0; +//! [0] + +//! [1] +class Producer : public QThread +//! [1] //! [2] +{ +public: + Producer(QObject *parent = NULL) : QThread(parent) + { + } + + void run() Q_DECL_OVERRIDE + { + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + + for (int i = 0; i < DataSize; ++i) { + mutex.lock(); + if (numUsedBytes == BufferSize) + bufferNotFull.wait(&mutex); + mutex.unlock(); + + buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4]; + + mutex.lock(); + ++numUsedBytes; + bufferNotEmpty.wakeAll(); + mutex.unlock(); + } + } +}; +//! [2] + +//! [3] +class Consumer : public QThread +//! [3] //! [4] +{ + Q_OBJECT +public: + Consumer(QObject *parent = NULL) : QThread(parent) + { + } + + void run() Q_DECL_OVERRIDE + { + for (int i = 0; i < DataSize; ++i) { + mutex.lock(); + if (numUsedBytes == 0) + bufferNotEmpty.wait(&mutex); + mutex.unlock(); + + fprintf(stderr, "%c", buffer[i % BufferSize]); + + mutex.lock(); + --numUsedBytes; + bufferNotFull.wakeAll(); + mutex.unlock(); + } + fprintf(stderr, "\n"); + } + +signals: + void stringConsumed(const QString &text); +}; +//! [4] + + +//! [5] +int main(int argc, char *argv[]) +//! [5] //! [6] +{ + QCoreApplication app(argc, argv); + Producer producer; + Consumer consumer; + producer.start(); + consumer.start(); + producer.wait(); + consumer.wait(); + return 0; +} +//! [6] + +#include "waitconditions.moc" diff --git a/examples/corelib/threads/waitconditions/waitconditions.pro b/examples/corelib/threads/waitconditions/waitconditions.pro new file mode 100644 index 0000000000..2dbe7df68a --- /dev/null +++ b/examples/corelib/threads/waitconditions/waitconditions.pro @@ -0,0 +1,9 @@ +QT = core +CONFIG -= moc app_bundle +CONFIG += console + +SOURCES += waitconditions.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/waitconditions +INSTALLS += target diff --git a/examples/corelib/tools/README b/examples/corelib/tools/README new file mode 100644 index 0000000000..db5c107c82 --- /dev/null +++ b/examples/corelib/tools/README @@ -0,0 +1,9 @@ +Qt is equipped with a range of capable tool classes, from containers and +iterators to classes for string handling and manipulation. + +Other classes provide application infrastructure support, handling plugin +loading and managing configuration files. + + +Documentation for these examples can be found via the Examples +link in the main Qt documentation. diff --git a/examples/corelib/tools/contiguouscache/contiguouscache.pro b/examples/corelib/tools/contiguouscache/contiguouscache.pro new file mode 100644 index 0000000000..fb2267fc64 --- /dev/null +++ b/examples/corelib/tools/contiguouscache/contiguouscache.pro @@ -0,0 +1,9 @@ +QT += widgets + +HEADERS = randomlistmodel.h +SOURCES = randomlistmodel.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/contiguouscache +INSTALLS += target diff --git a/examples/corelib/tools/contiguouscache/main.cpp b/examples/corelib/tools/contiguouscache/main.cpp new file mode 100644 index 0000000000..62fa8dcf42 --- /dev/null +++ b/examples/corelib/tools/contiguouscache/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "randomlistmodel.h" +#include +#include + +int main(int c, char **v) +{ + QApplication a(c, v); + + QListView view; + view.setUniformItemSizes(true); + view.setModel(new RandomListModel(&view)); + view.show(); + + return a.exec(); +} diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.cpp b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp new file mode 100644 index 0000000000..cd1a301dc7 --- /dev/null +++ b/examples/corelib/tools/contiguouscache/randomlistmodel.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "randomlistmodel.h" +#include + +static const int bufferSize(500); +static const int lookAhead(100); +static const int halfLookAhead(lookAhead/2); + +RandomListModel::RandomListModel(QObject *parent) +: QAbstractListModel(parent), m_rows(bufferSize), m_count(10000) +{ +} + +RandomListModel::~RandomListModel() +{ +} + +int RandomListModel::rowCount(const QModelIndex &) const +{ + return m_count; +} + +//! [0] +QVariant RandomListModel::data(const QModelIndex &index, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + int row = index.row(); + + if (row > m_rows.lastIndex()) { + if (row - m_rows.lastIndex() > lookAhead) + cacheRows(row-halfLookAhead, qMin(m_count, row+halfLookAhead)); + else while (row > m_rows.lastIndex()) + m_rows.append(fetchRow(m_rows.lastIndex()+1)); + } else if (row < m_rows.firstIndex()) { + if (m_rows.firstIndex() - row > lookAhead) + cacheRows(qMax(0, row-halfLookAhead), row+halfLookAhead); + else while (row < m_rows.firstIndex()) + m_rows.prepend(fetchRow(m_rows.firstIndex()-1)); + } + + return m_rows.at(row); +} + +void RandomListModel::cacheRows(int from, int to) const +{ + for (int i = from; i <= to; ++i) + m_rows.insert(i, fetchRow(i)); +} +//![0] + +//![1] +QString RandomListModel::fetchRow(int position) const +{ + return QString::number(rand() % ++position); +} +//![1] diff --git a/examples/corelib/tools/contiguouscache/randomlistmodel.h b/examples/corelib/tools/contiguouscache/randomlistmodel.h new file mode 100644 index 0000000000..3acafc23ff --- /dev/null +++ b/examples/corelib/tools/contiguouscache/randomlistmodel.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef RANDOMLISTMODEL_H +#define RANDOMLISTMODEL_H + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QTimer) + +class RandomListModel : public QAbstractListModel +{ + Q_OBJECT +public: + RandomListModel(QObject *parent = 0); + ~RandomListModel(); + + int rowCount(const QModelIndex & = QModelIndex()) const Q_DECL_OVERRIDE; + QVariant data(const QModelIndex &, int) const Q_DECL_OVERRIDE; + +private: + void cacheRows(int, int) const; + QString fetchRow(int) const; + + mutable QContiguousCache m_rows; + const int m_count; +}; + +#endif diff --git a/examples/corelib/tools/customtype/customtype.pro b/examples/corelib/tools/customtype/customtype.pro new file mode 100644 index 0000000000..1bd792db85 --- /dev/null +++ b/examples/corelib/tools/customtype/customtype.pro @@ -0,0 +1,8 @@ +HEADERS = message.h +SOURCES = main.cpp \ + message.cpp +QT += widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter +INSTALLS += target diff --git a/examples/corelib/tools/customtype/main.cpp b/examples/corelib/tools/customtype/main.cpp new file mode 100644 index 0000000000..8e97d3db96 --- /dev/null +++ b/examples/corelib/tools/customtype/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "message.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QStringList headers; + headers << "Subject: Hello World" + << "From: address@example.com"; + QString body = "This is a test.\r\n"; + +//! [printing a custom type] + Message message(body, headers); + qDebug() << "Original:" << message; +//! [printing a custom type] + +//! [storing a custom value] + QVariant stored; + stored.setValue(message); +//! [storing a custom value] + + qDebug() << "Stored:" << stored; + +//! [retrieving a custom value] + Message retrieved = stored.value(); + qDebug() << "Retrieved:" << retrieved; + retrieved = qvariant_cast(stored); + qDebug() << "Retrieved:" << retrieved; +//! [retrieving a custom value] + + return 0; +} diff --git a/examples/corelib/tools/customtype/message.cpp b/examples/corelib/tools/customtype/message.cpp new file mode 100644 index 0000000000..c470ab116e --- /dev/null +++ b/examples/corelib/tools/customtype/message.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "message.h" + +//! [Message class implementation] +Message::Message() +{ +} + +Message::Message(const Message &other) +{ + m_body = other.m_body; + m_headers = other.m_headers; +} + +Message::~Message() +{ +} +//! [Message class implementation] + +Message::Message(const QString &body, const QStringList &headers) +{ + m_body = body; + m_headers = headers; +} + +//! [custom type streaming operator] +QDebug operator<<(QDebug dbg, const Message &message) +{ + QStringList pieces = message.body().split("\r\n", QString::SkipEmptyParts); + if (pieces.isEmpty()) + dbg.nospace() << "Message()"; + else if (pieces.size() == 1) + dbg.nospace() << "Message(" << pieces.first() << ")"; + else + dbg.nospace() << "Message(" << pieces.first() << " ...)"; + return dbg.maybeSpace(); +} +//! [custom type streaming operator] + +//! [getter functions] +QString Message::body() const +{ + return m_body; +} + +QStringList Message::headers() const +{ + return m_headers; +} +//! [getter functions] diff --git a/examples/corelib/tools/customtype/message.h b/examples/corelib/tools/customtype/message.h new file mode 100644 index 0000000000..cdc4e39caf --- /dev/null +++ b/examples/corelib/tools/customtype/message.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#include +#include +#include + +//! [custom type definition] +class Message +{ +public: + Message(); + Message(const Message &other); + ~Message(); + + Message(const QString &body, const QStringList &headers); + + QString body() const; + QStringList headers() const; + +private: + QString m_body; + QStringList m_headers; +}; +//! [custom type definition] + +//! [custom type meta-type declaration] +Q_DECLARE_METATYPE(Message); +//! [custom type meta-type declaration] + +//! [custom type streaming operator] +QDebug operator<<(QDebug dbg, const Message &message); +//! [custom type streaming operator] + +#endif diff --git a/examples/corelib/tools/customtypesending/customtypesending.pro b/examples/corelib/tools/customtypesending/customtypesending.pro new file mode 100644 index 0000000000..672f6569c2 --- /dev/null +++ b/examples/corelib/tools/customtypesending/customtypesending.pro @@ -0,0 +1,10 @@ +HEADERS = message.h \ + window.h +SOURCES = main.cpp \ + message.cpp \ + window.cpp +QT += widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter +INSTALLS += target diff --git a/examples/corelib/tools/customtypesending/main.cpp b/examples/corelib/tools/customtypesending/main.cpp new file mode 100644 index 0000000000..5f01e2a154 --- /dev/null +++ b/examples/corelib/tools/customtypesending/main.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "message.h" +#include "window.h" + +//! [main function] +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + Window window1; + QStringList headers; + headers << "Subject: Hello World" + << "From: address@example.com"; + QString body = "This is a test.\r\n"; + Message message(body, headers); + window1.setMessage(message); + + Window window2; + QObject::connect(&window1, SIGNAL(messageSent(Message)), + &window2, SLOT(setMessage(Message))); + QObject::connect(&window2, SIGNAL(messageSent(Message)), + &window1, SLOT(setMessage(Message))); + window1.show(); + window2.show(); + return app.exec(); +} +//! [main function] diff --git a/examples/corelib/tools/customtypesending/message.cpp b/examples/corelib/tools/customtypesending/message.cpp new file mode 100644 index 0000000000..9b53b8757d --- /dev/null +++ b/examples/corelib/tools/customtypesending/message.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "message.h" + +Message::Message() +{ +} + +Message::Message(const Message &other) +{ + m_body = other.m_body; + m_headers = other.m_headers; +} + +Message::~Message() +{ +} + +Message::Message(const QString &body, const QStringList &headers) +{ + m_body = body; + m_headers = headers; +} + +QString Message::body() const +{ + return m_body; +} + +QStringList Message::headers() const +{ + return m_headers; +} diff --git a/examples/corelib/tools/customtypesending/message.h b/examples/corelib/tools/customtypesending/message.h new file mode 100644 index 0000000000..3e5f17db2b --- /dev/null +++ b/examples/corelib/tools/customtypesending/message.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#include +#include +#include + +//! [custom type definition] +class Message +{ +public: + Message(); + Message(const Message &other); + ~Message(); + + Message(const QString &body, const QStringList &headers); + + QString body() const; + QStringList headers() const; + +private: + QString m_body; + QStringList m_headers; +}; +//! [custom type definition] + +//! [custom type meta-type declaration] +Q_DECLARE_METATYPE(Message); +//! [custom type meta-type declaration] + +#endif diff --git a/examples/corelib/tools/customtypesending/window.cpp b/examples/corelib/tools/customtypesending/window.cpp new file mode 100644 index 0000000000..aa4a7eab3c --- /dev/null +++ b/examples/corelib/tools/customtypesending/window.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "window.h" + +//! [Window constructor] +Window::Window() +{ + editor = new QTextEdit(); + QPushButton *sendButton = new QPushButton(tr("&Send message")); + + connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage())); + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + buttonLayout->addStretch(); + buttonLayout->addWidget(sendButton); + buttonLayout->addStretch(); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(editor); + layout->addLayout(buttonLayout); + + setWindowTitle(tr("Custom Type Sending")); +} +//! [Window constructor] + +//! [sending a message] +void Window::sendMessage() +{ + thisMessage = Message(editor->toPlainText(), thisMessage.headers()); + emit messageSent(thisMessage); +} +//! [sending a message] + +//! [receiving a message] +void Window::setMessage(const Message &message) +{ + thisMessage = message; + editor->setPlainText(thisMessage.body()); +} +//! [receiving a message] diff --git a/examples/corelib/tools/customtypesending/window.h b/examples/corelib/tools/customtypesending/window.h new file mode 100644 index 0000000000..0889800064 --- /dev/null +++ b/examples/corelib/tools/customtypesending/window.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include +#include "message.h" + +QT_FORWARD_DECLARE_CLASS(QTextEdit) + +//! [Window class definition] +class Window : public QWidget +{ + Q_OBJECT + +public: + Window(); + +signals: + void messageSent(const Message &message); + +public slots: + void setMessage(const Message &message); + +private slots: + void sendMessage(); + +private: + Message thisMessage; + QTextEdit *editor; +}; +//! [Window class definition] + +#endif diff --git a/examples/corelib/tools/doc/src/contiguouscache.qdoc b/examples/corelib/tools/doc/src/contiguouscache.qdoc new file mode 100644 index 0000000000..e88b2629b8 --- /dev/null +++ b/examples/corelib/tools/doc/src/contiguouscache.qdoc @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example tools/contiguouscache + \title Contiguous Cache Example + + \brief The Contiguous Cache example shows how to use QContiguousCache to manage memory usage for + very large models. In some environments memory is limited and, even when it + isn't, users still dislike an application using excessive memory. + Using QContiguousCache to manage a list, rather than loading + the entire list into memory, allows the application to limit the amount + of memory it uses, regardless of the size of the data set it accesses + + The simplest way to use QContiguousCache is to cache as items are requested. When + a view requests an item at row N it is also likely to ask for items at rows near + to N. + + \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 + simply have the following code instead. + + \code + while (row > m_rows.lastIndex()) + m_rows.append(fetchWord(m_rows.lastIndex()+1); + while (row < m_rows.firstIndex()) + m_rows.prepend(fetchWord(m_rows.firstIndex()-1); + \endcode + + However a list will often jump rows if the scroll bar is used directly, resulting in + the code above causing every row between the old and new rows to be fetched. + + Using QContiguousCache::lastIndex() and QContiguousCache::firstIndex() allows + the example to determine what part of the list the cache is currently caching. + These values don't represent the indexes into the cache's own memory, but rather + a virtual infinite array that the cache represents. + + By using QContiguousCache::append() and QContiguousCache::prepend() the code ensures + that items that may be still on the screen are not lost when the requested row + has not moved far from the current cache range. QContiguousCache::insert() can + potentially remove more than one item from the cache as QContiguousCache does not + allow for gaps. If your cache needs to quickly jump back and forth between + rows with significant gaps between them consider using QCache instead. + + And thats it. A perfectly reasonable cache, using minimal memory for a very large + list. In this case the accessor for getting the words into the cache + generates random information rather than fixed information. This allows you + to see how the cache range is kept for a local number of rows when running the + example. + + \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 + or using a QTimer to incrementally expand the range of the cache prior to + rows being requested out of the current cache range. +*/ diff --git a/examples/corelib/tools/doc/src/customtype.qdoc b/examples/corelib/tools/doc/src/customtype.qdoc new file mode 100644 index 0000000000..f03fafec30 --- /dev/null +++ b/examples/corelib/tools/doc/src/customtype.qdoc @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example tools/customtype + \title Custom Type Example + + \brief The Custom Type example shows how to integrate a custom type into Qt's + meta-object system. + + Contents: + + \tableofcontents + + \section1 Overview + + Qt provides a range of standard value types that are used to provide + rich and meaningful APIs. These types are integrated with the meta-object + system, enabling them to be stored in QVariant objects, written out in + debugging information and sent between components in signal-slot + communication. + + Custom types can also be integrated with the meta-object system as long as + they are written to conform to some simple guidelines. In this example, we + introduce a simple \c Message class, we describe how we make it work with + QVariant, and we show how it can be extended to generate a printable + representation of itself for use in debugging output. + + \section1 The Message Class Definition + + The \c Message class is a simple value class that contains two pieces + of information (a QString and a QStringList), each of which can be read + using trivial getter functions: + + \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 + meta-object system. Other than this, we are free to implement whatever we + need to make the type do what we want, so we also include a constructor + that lets us set the type's data members. + + To enable the type to be used with QVariant, we declare it using the + Q_DECLARE_METATYPE() macro: + + \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 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. + + \section1 The Message Class Implementation + + The implementation of the default constructor, copy constructor and destructor + are straightforward for the \c Message class: + + \snippet tools/customtype/message.cpp Message class implementation + + The streaming operator is implemented in the following way: + + \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 + operator and return the QDebug object obtained from its maybeSpace() member + function; this is described in more detail in the + \l{Creating Custom Qt Types#Making the Type Printable}{Creating Custom Qt Types} + document. + + We include the code for the getter functions for completeness: + + \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. + + \section1 Using the Message + + 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 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 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 + functions. + + The value can be retrieved using the QVariant::value() member template + function: + + \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. + + \section1 Further Reading + + The custom \c Message type can also be used with direct signal-slot + connections. + + To register a custom type for use with queued signals and slots, such as + those used in cross-thread communication, see the + \l{Queued Custom Type Example}. + + More information on using custom types with Qt can be found in the + \l{Creating Custom Qt Types} document. +*/ diff --git a/examples/corelib/tools/tools.pro b/examples/corelib/tools/tools.pro new file mode 100644 index 0000000000..36fa776980 --- /dev/null +++ b/examples/corelib/tools/tools.pro @@ -0,0 +1,7 @@ +requires(qtHaveModule(widgets)) + +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = contiguouscache \ + customtype \ + customtypesending -- cgit v1.2.3