aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-07-02 14:52:52 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-07-02 14:52:52 +0200
commit7238de11c5028e6f9aeaed74295049b1e172294c (patch)
tree370099640c8018d85e8613366d1e2276ab3f5ef1 /examples
parentd1af0a90e6663d49c3e78ac674b0a1ae040c2085 (diff)
parent41e924eb6e1c690bc81d095fc5e8f57244aae964 (diff)
Merge "Merge remote-tracking branch 'origin/5.3' into dev" into refs/staging/dev
Diffstat (limited to 'examples')
-rw-r--r--examples/quick/demos/demos.pro5
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpgbin0 -> 25541 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpgbin0 -> 79678 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpgbin0 -> 27911 bytes
-rw-r--r--examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpgbin0 -> 59198 bytes
-rw-r--r--examples/quick/demos/maroon/doc/src/maroon.qdoc855
-rw-r--r--examples/quick/demos/rssnews/content/BusyIndicator.qml73
-rw-r--r--examples/quick/demos/rssnews/content/CategoryDelegate.qml147
-rw-r--r--examples/quick/demos/rssnews/content/NewsDelegate.qml146
-rw-r--r--examples/quick/demos/rssnews/content/RssFeeds.qml91
-rw-r--r--examples/quick/demos/rssnews/content/ScrollBar.qml79
-rw-r--r--examples/quick/demos/rssnews/content/images/Asia.jpgbin0 -> 10578 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Business.jpgbin0 -> 17276 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Entertainment.jpgbin0 -> 15433 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Europe.jpgbin0 -> 15872 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Health.jpgbin0 -> 16015 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Politics.jpgbin0 -> 16401 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Science.jpgbin0 -> 9496 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Sports.jpgbin0 -> 9281 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/Technology.jpgbin0 -> 22290 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/TopStories.jpgbin0 -> 8067 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/USNational.jpgbin0 -> 9635 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/World.jpgbin0 -> 15128 bytes
-rw-r--r--examples/quick/demos/rssnews/content/images/btn_close.pngbin0 -> 1267 bytes
-rw-r--r--examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.pngbin43372 -> 56864 bytes
-rw-r--r--examples/quick/demos/rssnews/main.cpp41
-rw-r--r--examples/quick/demos/rssnews/rssnews.pro13
-rw-r--r--examples/quick/demos/rssnews/rssnews.qml197
-rw-r--r--examples/quick/demos/rssnews/rssnews.qrc25
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp273
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/fbitem.h136
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/logo.cpp141
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/logo.h65
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/main.cpp56
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp216
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h80
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro17
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc5
-rw-r--r--examples/quick/quickwidgets/qquickviewcomparison/test.qml210
-rw-r--r--examples/quick/quickwidgets/quickwidgets.pro3
-rw-r--r--examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc113
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.cpp74
-rw-r--r--examples/quick/scenegraph/openglunderqml/squircle.h33
43 files changed, 2694 insertions, 400 deletions
diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro
index ac15cc3c1f..9aac7bf6f7 100644
--- a/examples/quick/demos/demos.pro
+++ b/examples/quick/demos/demos.pro
@@ -7,6 +7,7 @@ SUBDIRS = samegame \
photosurface \
stocqt
+qtHaveModule(xmlpatterns): SUBDIRS += rssnews
+
EXAMPLE_FILES = \
- photoviewer \
- rssnews
+ photoviewer
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg
new file mode 100644
index 0000000000..a83e282d5f
--- /dev/null
+++ b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-3.jpg
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg
new file mode 100644
index 0000000000..8a6063b7c7
--- /dev/null
+++ b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-4.jpg
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg
new file mode 100644
index 0000000000..e3e4a2ec89
--- /dev/null
+++ b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-5.jpg
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg
new file mode 100644
index 0000000000..ad6b4bf156
--- /dev/null
+++ b/examples/quick/demos/maroon/doc/images/qtquick-demo-maroon-med-6.jpg
Binary files differ
diff --git a/examples/quick/demos/maroon/doc/src/maroon.qdoc b/examples/quick/demos/maroon/doc/src/maroon.qdoc
index 59f6397dcf..4b364397c1 100644
--- a/examples/quick/demos/maroon/doc/src/maroon.qdoc
+++ b/examples/quick/demos/maroon/doc/src/maroon.qdoc
@@ -29,14 +29,861 @@
\title Qt Quick Demo - Maroon in Trouble
\ingroup qtquickdemos
\example demos/maroon
- \brief A cute game designed for touchscreens.
- \image qtquick-demo-maroon-med-1.png
+ \brief A Qt Quick game for touch devices that uses SpriteSequence,
+ ParticleSystem, Emitter, and Wander types to animate objects and the SoundEffect type to
+ play sound effects.
+
\image qtquick-demo-maroon-med-2.png
- \e{Maroon in Trouble} demonstrates various QML and \l{Qt Quick} features
- such as displaying custom components and playing sound effects.
+ \e{Maroon in Trouble} demonstrates QML features that are useful when
+ developing games:
+
+ \list
+ \li Using custom QML types to create different screens for
+ different stages of the game.
+ \li Using the \l Item and \l Image types to construct a game background.
+ \li Using the SequentialAnimation, NumberAnimation, ParticleSystem,
+ \l Emitter, and \l Wander types to animate background objects.
+ \li Using the \l Timer and \l Repeater types to display a countdown
+ sequence before starting the game.
+ \li Using a custom QML type with custom properties to construct a game
+ board.
+ \li Using the SpriteSequence and \l Sprite types to add animated objects
+ to the game board.
+ \li Using a custom QML type that uses the \l Image type with some custom
+ properties to add a menu where the players can buy objects.
+ \li Using custom properties with private functions to keep track of game
+ statistics and a custom QML type to display them to the players.
+ \li Using the \l State type with JavaScript functions to manage game
+ states.
+ \li Using the \l SoundEffect type to play individual sound effects
+ depending on the object type and the action applied to the object.
+ \li Using signal handlers to specify keyboard shortcuts for some game
+ actions.
+ \li Using resource files to package game resources for deployment and
+ delivery.
+ \endlist
\include examples-run.qdocinc
+ \section1 Adding Screens
+
+ In the Maroon in Trouble app, we use the following custom types that
+ are each defined in a separate .qml file to create the game screens:
+
+ \list
+ \li NewGameScreen.qml
+ \li GameCanvas.qml
+ \li GameOverScreen.qml
+ \endlist
+
+ To use the custom types, we add an import statement to the main QML file,
+ maroon.qml that imports the folder called \c content where the types are
+ located:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto content
+ \printuntil "
+
+ We use the screen types at different stages of the game. The NewGameScreen
+ type is used to create the screen that appears when the players start the
+ app. In NewGameScreen.qml, we use an \l{Image} type to create a New Game
+ button that the players can press to start a new game.
+
+ \image qtquick-demo-maroon-med-1.png
+
+ Tapping the button initiates a countdown timer that triggers the creation
+ of the game canvas by using the GameCanvas type. Another \l{Timer} type
+ spawns mobs of fish inside bubbles that the players must free before they
+ reach the surface. The players can tap on the screen to open a menu where
+ they can buy different types of weapons (melee, ranged, and bombs) to burst
+ the bubbles.
+
+ \image qtquick-demo-maroon-med-2.png
+
+ When the game finishes, a screen created by using the GameOverScreen type
+ appears. On this screen, the players can see their score and start a new
+ game.
+
+ \image qtquick-demo-maroon-med-3.jpg
+
+ The screens are all created on the same background and use some of the same
+ images and animations.
+
+ \section1 Constructing the Background
+
+ In the maroon.qml file, we use an \l{Item} type with the id \c root and a
+ fixed width and height to create a main window for the game:
+
+ \skipto Item
+ \printuntil passedSplash
+
+ We declare two custom properties for the root item, \c gameState and
+ \c passedSplash that we will use later to manage game states.
+
+ We use an \l{Image} item to display the game background image:
+
+ \printuntil anchors.bottom
+
+ We want to be able to load the background image only once at app startup
+ and still use different scenes for the game screens. Therefore,
+ background.png is three times the length of the root item and displays a
+ scene that stretches from the bottom of sea to the sky above the horizon.
+
+ We use the \c anchors.bottom property to anchor the background image to the
+ bottom of the \l{Column} layout that we use to position the screens:
+
+ \skipto Column
+ \printuntil GameOverScreen
+
+ We set a negative value for the \c y property to set the first scene at the
+ bottom of the sea. We calculate the position by subtracting the height of
+ a screen from the \c height property.
+
+ Within the column layout, we use an \l{Item} type to add objects to the
+ background. Within the item, we use \l{Row} layout objects to position
+ \l{Image} objects that display waves on the game canvas and the game over
+ screen:
+
+ \printuntil }
+ \printuntil }
+ \dots
+ \skipto Row
+ \printuntil }
+ \printuntil }
+
+ The second row of waves is positioned on the y axis with a slight offset to
+ the first row. We also use the \c opacity property to make the waves appear
+ lighter in color than the first two waves, which gives the background some
+ depth.
+
+ We use \l{Image} objects to also display sunlight on the new game screen and
+ on the game canvas:
+
+ \skipto Image
+ \printuntil anchors
+ \dots
+ \skipto Image
+ \printuntil anchors
+
+ We set the \c opacity property of the images to \c 0.02 and \c 0.04 to give
+ some depth to the rays of sunshine. We use the \c y property to position the
+ images at fixed locations on the y axis and the
+ \c {anchors.horizontalCenter} property to center them horizontally in
+ relation to their parent.
+
+ We use an \l {Image} type to display an image that adds a deepening shadow
+ to the background:
+
+ \skipto Image
+ \printuntil }
+
+ We set the \c opacity property of the image to \c 0.5 to make the background
+ visible behind the shadow.
+
+ To make the background more interesting, we animate some of the objects we
+ added to it.
+
+ \section1 Animating Background Objects
+
+ We use NumberAnimation to move the waves horizontally across the screen in
+ opposite directions and SequentialAnimation with NumberAnimation to move
+ them up and down.
+
+ We apply the number animation to the \c x property of \c wave as a property
+ value source to animate the x value from its current value to the
+ \c -(wave.width), over 16 seconds. We set the \c loops property to
+ \c {Animation.Infinite} to repeat the animation indefinitely:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto wave.width
+ \printuntil }
+
+ We apply the sequential animation to the \c y property of the image as a
+ property value source to animate the y value. We use one number animation
+ to animate the image from the y position of two below the value of y to two
+ above it, over 1600 milliseconds. We use another number animation to
+ subsequently animate the image in the opposite direction, again over 1600
+ milliseconds. The animation is repeated indefinitely:
+
+ \skipto SequentialAnimation
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ We use the easing curve of the type \c {Easing.InOutQuad} for a quintic
+ (t^5) function to accelerate the motion until halfway and then decelerate
+ it.
+
+ We use sequential animation and number animation to animate \c wave2
+ similarly to \c wave, but in the opposite direction:
+
+ \skipto SequentialAnimation
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ We use sequential animation to rotate the rays of sunlight in degrees
+ clockwise around an origin point that we set to \c {Item.Top} in the
+ \c transformOrigin property. The animation is repeated indefinitely:
+
+ \skipto transformOrigin
+ \printuntil to: -10
+ \printuntil }
+
+ We use one number animation to rotate the image from \c -10 degrees to
+ \c 10 degrees over 8 seconds and another to subsequently rotate it from
+ \c 10 degrees to \c -10 degrees over the same duration.
+
+ We use the easing curve of the type \c {Easing.InOutSine} for a sinusoidal
+ (sin(t)) function to accelerate the motion until halfway and then decelerate
+ it.
+
+ We use sequential animation and number animation to animate another
+ sunlight.png image similarly, but in the opposite direction:
+
+ \skipto transformOrigin
+ \printuntil to: 10
+ \printuntil }
+
+ For examples of using SequentialAnimation and NumberAnimation on the \c x
+ and \c y properties and the \c width and \c height properties, see
+ NewGameScreen.qml.
+
+ \section1 Emitting Particles
+
+ In addition to animation, we use particles to generate motion on the game
+ screens. We use the ParticleSystem QML type in maroon.qml to make bubbles
+ appear at the bottom of the new game screen and game canvas and slowly float
+ towards the top on varying trajectories.
+
+ To use the ParticleSystem type, we must import \l{Qt Quick Particles}:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto Particles
+ \printuntil 0
+
+ To have the particles appear on the game background, we place the
+ ParticleSystem type within the \l{Image} type that displays the game
+ background:
+
+ \skipto Image
+ \printuntil anchors.fill
+
+ In the ParticleSystem, we use an \l{Emitter} type to emit particles from the
+ location of the emitter at the rate of two per second with the life span of
+ 15 seconds:
+
+ \skipto Emitter
+ \printuntil sizeVariation
+ \printuntil }
+
+ The \c acceleration property uses the PointDirection type to
+ specify random variation of the x and y coordinates, so that the bubbles
+ appear inside a rectangular area around the emitter that is anchored to the
+ bottom of the image.
+
+ The \c size property sets the base size of the particles at the beginning of
+ their life to 24 pixels and the \c sizeVariation property randomly increases
+ or decreases the particle size by up to 16 pixels, so that we get bubbles in
+ different sizes.
+
+ As emitters have no visualization, we use the ImageParticle type to render
+ the catch.png image at the particle location:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto ImageParticle
+ \printuntil }
+
+ A \l{Wander} type applies a random trajectory to the particles, so that the
+ bubbles follow random routes from the bottom to the top.
+
+ \printuntil }
+
+ For another example of using the ParticleSystem type, see the
+ GameOverScreen.qml file, where an ImageParticle type is used to make clouds
+ move across the sky.
+
+ \section1 Using Timers
+
+ \image qtquick-demo-maroon-med-4.jpg
+
+ In maroon.qml, we use the \l{Timer} type with a \l{Repeater} type to display
+ a countdown sequence before using another timer to start a new game. Both
+ timers are started simultaneously in the \c "gameOn" state, that is when the
+ players tap the New Game button and \c passedSplash is \c true. This is
+ explained in more detail in \l{Managing Game States}.
+
+ We use the \c countdownTimer to display the countdown sequence:
+
+ \skipto Timer
+ \printuntil }
+
+ The \c onTriggered signal handler is called when the timer is triggered to
+ increment the value of the the \c countdown custom property.
+
+ We set the \c repeat property to \c true to specify that the timer is
+ triggered at the interval of 1 second as long as the value of \c countdown
+ is less than 5.
+
+ The \c countdown property is defined in the root item with an initial value
+ of \c 10, so that \c countdownTimer is not running by default:
+
+ \skipto countdown:
+ \printuntil 10
+
+ Each time the timer is triggered, an image from the countdown sequence is
+ displayed. We use a \l{Repeater} type to instantiate the \l{Image} delegate
+ in the context of the repeater's parent, \c canvasArea item, seeded with
+ data from the \c model:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto Repeater
+ \printuntil scale
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ We scale the images from \c 0.0 to \c 1.0 and use the \c visible property to
+ hide the images for the previous steps as the countdown progresses. We also
+ raise the opacity of the image that matches the current countdown step,
+ keeping the others nearly transparent.
+
+ By animating the changes in the \c opacity and \c scale properties using a
+ \l Behavior type, we achieve a countdown sequence where numbers zoom in
+ towards the players.
+
+ \section1 Constructing the Game Board
+
+ To construct the game board, we use the GameCanvas custom type that is
+ defined in GameCanvas.qml.
+
+ In maroon.qml, we use the GameCanvas type to display the game canvas
+ at the position of 32 on the x axis and 20 pixels from the bottom of
+ its parent item, \c canvasArea:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto GameCanvas
+ \printuntil }
+
+ We set the \c focus property to \c true to give \c canvas active focus on
+ startup.
+
+ In GameCanvas.qml, we use an \l Item type and define custom properties for
+ it to create a grid of equally sized squares divided to 4 columns on 6 rows:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto Item
+ \printuntil canvas
+
+ We use the custom properties to set the \c width and \c height of the
+ \c grid item as the amount of columns and rows multiplied by square size:
+
+ \skipto width
+ \printuntil height
+
+ We use an \l{Image} type with a MouseArea type to display a help button
+ that the players can tap to view an image that contains instructions for
+ playing the game:
+
+ \skipuntil endGame
+ \skipto Image
+ \printuntil bottomMargin
+ \printuntil }
+
+ We declare the \c goAway() private function to disable the mouse area and
+ make the image fully transparent and a \c comeBack() function to enable the
+ mouse area and make the button fully opaque. We use a \l {Behavior} type on
+ the \c opacity property to apply the default number animation when the value
+ of \c opacity changes.
+
+ When the players tap the help button, the \c onClicked signal handler is
+ called to hide the help button by setting the \c {helpButton.visible}
+ property to \c false and to show the help image by setting the
+ \c {helpImage.visible} property to \c false.
+
+ \image qtquick-demo-maroon-med-6.jpg
+
+ We use anchoring to position the help button at the bottom center of the
+ game canvas.
+
+ We use another \l{Image} type to to display the help image:
+
+ \printuntil }
+ \printuntil }
+
+ To hide the help image when the players tap it, the \c onClicked signal
+ handler within the MouseArea type is called to set the \c{helpImage.visible}
+ property to \c true.
+
+ To ensure that the images are placed on top when they are visible, we set
+ a high value for their \c z property.
+
+ The following sections describe how to use timers to add animated objects to
+ the game board and how to create a menu dialog from which the players can
+ add more objects to it.
+
+ \section1 Animating Objects on the Game Board
+
+ We use sprite animation to animate objects on the game board. The Qt Quick
+ \l{Sprite Animations}{sprite engine} is a stochastic state machine combined
+ with the ability to chop up images containing multiple frames of an
+ animation.
+
+ \section2 Spawning Fish
+
+ We use a \l{Timer} element with the \c tick() function in GameCanvas.qml to
+ spawn mobs of fish in waves at an increasing rate, starting at 16
+ milliseconds:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto Timer
+ \printuntil }
+
+ We use the MobBase custom type that is defined in MobBase.qml to
+ animate mobs of fish that swim inside bubbles. We use an \l{Item} type with
+ custom properties and private functions to create the fish and the bubbles
+ and to define the actions that can be applied to them:
+
+ \quotefromfile demos/maroon/content/mobs/MobBase.qml
+ \skipto Item
+ \printuntil }
+ \dots
+
+ We use a SpriteSequence type to animate the fish:
+
+ \skipto SpriteSequence
+ \printuntil goalSprite
+
+ The SpriteSequence type renders and controls a list of animations
+ defined by \l{Sprite} types:
+
+ \skipto Sprite {
+ \printuntil name: "right"
+ \printuntil }
+ \printuntil }
+
+ In the \c fishSprite sprite sequence, each sprite defines one frame within
+ the mob-idle.png file, which shows a fish facing right, front, and left:
+
+ \image ../../content/gfx/mob-idle.png
+
+ We use the \c frameWidth, \c frameHeight, and \c frameX properties to
+ determine that the first 64x64-pixel square of the image is framed in the
+ \c "left" sprite, the second in the \c "front" sprite, and the third in the
+ \c "right" sprite. For each sprite, the \c frameCount property is set to
+ \c 1 to specify that the sprite contains one frame.
+
+ We use the \c frameDuration and \c frameDurationVariation properties to
+ specify that the duration of an animation can vary from \c 400 to \c 1200
+ milliseconds.
+
+ The \c to property specifies that the sprites have weighted transitions to
+ other sprites. The \c "left" and \c "right" sprites always transfer to the
+ \c "front" sprite. When the \c "front" animation finishes, the sprite engine
+ chooses \c "left" or \c "right" randomly, but at roughly equal proportions,
+ because they both have the weight \c 1.
+
+ When the fish are set free, we want them to swim away in the direction they
+ are facing until they get off the screen. If they were facing front, we use
+ the \c jumpTo method with the JavaScript \c {Math.random()} method in the
+ \c die() private function to randomly jump to the \c "left" or \c "right"
+ sprite:
+
+ \quotefromfile demos/maroon/content/mobs/MobBase.qml
+ \skipto die()
+ \printuntil }
+
+ We then use the \c start() function to run a NumberAnimation that applies a
+ number animation to the x value from its current value to \c -360 or \c 360,
+ depending on whether the \c goingLeft custom property is \c true, in 300
+ milliseconds:
+
+ \skipto NumberAnimation
+ \printuntil }
+
+ \section2 Bursting Bubbles
+
+ We use another SpriteSequence to animate the bubbles so that they
+ become smaller and finally burst when they are attacked by a shooter or
+ a melee. For this effect, we set the value of the \c scale property to
+ decrease by \c 0.2 each time the custom \c hp property changes:
+
+ \skipto SpriteSequence
+ \printuntil goalSprite
+
+ We use a \l{Behavior} type to apply a NumberAnimation when the value of
+ \c scale changes. We use the \c{Easing.OutBack} easing type for a back
+ (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out curve that
+ decelerates the motion to zero velocity in 150 milliseconds:
+
+ \skipto Behavior
+ \printuntil }
+ \printuntil }
+
+ The SpriteSequence consist of two sprites that display different images. The
+ first sprite, \c "big", uses the catch.png image to display an empty bubble:
+
+ \skipto Sprite
+ \printuntil }
+ \printuntil }
+
+ We set the \c to property to \c "burst" with the weight \c 0 to make the
+ second sprite, \c "burst", a valid goal for the \c jumpTo method that we use
+ in the \c die() private function to jump directly to the \c "burst" sprite
+ without playing the first sprite.
+
+ In the \c "burst" sprite, we set the \c frameCount property to \c 3 and the
+ \c frameX property to \c 64 to specify that the animation starts at pixel
+ location 64 and loads each frame for the duration of 200 milliseconds.
+
+ \skipto Sprite
+ \printuntil }
+
+ Within the SpriteSequence, we use SequentialAnimation with NumberAnimation
+ to animate the transitions between the frames. To create a pulsating effect
+ on the bubbles, we apply a sequential animation on the \c width property
+ with two number animations to first increase the bubble width from
+ \c{* 1} to \c{* 1.1} over 800 milliseconds and then bring it back over 1
+ second:
+
+ \skipto SequentialAnimation
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ Similarly, we increase the bubble height from \c{* 1} to \c{* 1.15} over
+ 1200 milliseconds and then bring it back over 1 second:
+
+ \skipto SequentialAnimation
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ We use yet another SpriteSequence to display the effect of squid ink on the
+ bubbles. For more examples of using sprite sequences, see the QML files in
+ the \c towers directory.
+
+ \section1 Adding Dialogs
+
+ \image qtquick-demo-maroon-med-5.jpg
+
+ In GameCanvas.qml, we use an \l{Image} type with some custom properties to
+ create a menu where the players can buy tower objects:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto Image
+ \printuntil towerExists
+
+ We set the \c visible property to \c false to hide the menu by default. The
+ \c z property is set to 1500 to ensure that the menu is displayed in front
+ of all other items when it is visible.
+
+ We use a MouseArea type to open or close the menu when players tap on the
+ canvas:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto MouseArea
+ \printuntil }
+ \printuntil }
+
+ We set the \c anchors.fill property to \c parent to allow the players to tap
+ anywhere on the game canvas. We use a condition in the \c onClicked
+ signal handler to call the \c {finish()} function if the menu is visible
+ and the \c {open()} function otherwise.
+
+ The \c {finish()} function hides the menu by setting the \c shown custom
+ property to \c false:
+
+ \skipto finish
+ \printuntil }
+
+ The \c {open()} function displays the menu at the x and y position of the
+ mouse pointer:
+
+ \printuntil }
+
+ If \c gameRunning is \c true, we call the JavaScript \c row() function to
+ calculate the value of the \c targetRow custom property and the \c col()
+ function to calculate the value of the \c targetCol custom property. If
+ the value of \c targetRow equals \c 0, the y position is set to one square
+ above the mouse pointer. Otherwise, it is set to one square below the mouse
+ pointer.
+
+ We use the \c towerIdx() function to set the value of the \c towerExists
+ custom property.
+
+ We set the \c shown custom property to \c true to show the menu and call the
+ \c {helpButton.goAway()} function to hide the help button when the menu
+ opens.
+
+ We use states and transitions to display the menu when the \c shown
+ property is \c true and the \c gameOver property is \c false:
+
+ \printuntil OutElastic
+ \printuntil }
+
+ To set the visibility of the menu to \c "visible" without animating the
+ property change, we use a PropertyAction type. We do want to animate the
+ changes in opacity and scale, though, so we use number animation to
+ animate the value of the \c scale property from \c 0.9 to \c 1 and the
+ value of \c opacity property from \c 0.7 to \c 1, over 500 milliseconds.
+ We use the \c {Easing.outElastic} easing type for an elastic (exponentially
+ decaying sine wave) function easing curve that decelerates from zero
+ velocity.
+
+ To construct the menu, we use a BuildButton custom type that is defined in
+ BuildButton.qml. In GameCanvas.qml, we create one build button for each
+ tower object that the players can buy and position them in a \l{Row} layout
+ in front of the menu background image, dialog.png:
+
+ \printuntil dialog-factory.png
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ For each build button, we set the values of \c towerType and \c index custom
+ properties that we define in BuildButton.qml.
+
+ We use the \c canBuild custom property to prevent players from adding tower
+ objects in locations where tower objects already exist.
+
+ We use the \c source property to display the image for the tower type.
+
+ The \c onClicked signal handler is called to execute the \c finish()
+ function that closes the menu when the players tap an enabled build button.
+
+ Build buttons are enabled when the players have enough coins to buy the
+ tower objects. We use an \l {Image} type in BuildButton.qml to display
+ images on the buttons:
+
+ \quotefromfile demos/maroon/content/BuildButton.qml
+ \skipto Image
+ \printuntil }
+
+ We use the \c opacity property to make the buttons appear enabled. If
+ \c canBuild is \c true and the value of the \c gameCanvas.coins property
+ is larger than or equal to the cost of a tower object, the images are fully
+ opaque, otherwise their opacity is set to \c 0.4.
+
+ We use a \l{Text} type to display the cost of each tower item, as specified
+ by the the \c towerData variable, depending on \c towerType:
+
+ \skipto Text
+ \printuntil }
+
+ To display a pointer on the screen at the position where the tower object
+ will be added, we use the \l {Image} type. We use the \c visible property
+ to determine whether the dialog-pointer.png image should be positioned below
+ or above the menu. When the value of the \c col property equals the \c index
+ and the value or the \c row property is not \c 0, we anchor the image to the
+ bottom of its parent, BuildButton.
+
+ When the value or the \c row property is \c 0, we anchor the image to the
+ top of BuildButton to position the pointer above the menu and use the
+ \c rotation property to rotate it by 180 degrees, so that it points upwards:
+
+ \skipto Image
+ \printuntil }
+ \printuntil }
+
+ \section1 Keeping Track of Game Statistics
+
+ To keep track of the game statistics, we use the InfoBar custom type (that
+ is defined in InfoBar.qml) in maroon.qml:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto InfoBar
+ \printuntil }
+
+ We use the \c {anchors.bottom} and \c {anchors.bottomMargin} properties to
+ position the info bar at 6 points from the top of the game canvas. We bind
+ the \c width property of the info bar to that of its parent.
+
+ In InfoBar.qml, we use an \l{Item} type to create the info bar. Within it,
+ we use a \l{Row} layout type to display the number of lives the players have
+ left, the number of fish that have been saved, and the amount of coins that
+ are available for use.
+
+ We use the \c anchors property to position the rows in relationship to their
+ parent and to each other. In the first \l{Row} object, we use the
+ \c {anchors.left} and \c {anchors.leftMargin} properties to position the
+ heart icons at 10 points from the left border of the parent item:
+
+ \quotefromfile demos/maroon/content/InfoBar.qml
+ \skipto Item
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ We use a \l{Repeater} type with a \c model and a \c delegate to display as
+ many hearts as the players have lives left. We use the \c spacing property
+ to leave 5 pixels between the displayed icons.
+
+ In the second \l{Row} object, we use the \c {anchors.right} and
+ \c {anchors.rightMargin} properties to position the number of fish saved at
+ 20 points left of the third \l{Row} object that displays the number of coins
+ available (and has the id \c points):
+
+ \skipto Row
+ \printuntil /^\}/
+
+ In these objects, we set spacing to 5 pixels to separate the icons from the
+ numbers that we display by using a \l{Text} type.
+
+ In GameCanvas.qml, we define custom properties to hold the game statistics:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto score
+ \printuntil lives
+
+ We declare the \c freshState() function to set the initial game statistics
+ when a new game starts:
+
+ \skipto freshState()
+ \printuntil }
+
+ We use the \c {Logic.gameState.score} variable in the \c die() function
+ that we declare in MobBase.qml to increase the score by one when the players
+ set a fish free:
+
+ \quotefromfile demos/maroon/content/mobs/MobBase.qml
+ \skipto score
+ \printuntil ;
+
+ \section1 Managing Game States
+
+ In maroon.qml, we use a \l{State} type and JavaScript to switch between
+ screens according to the game state. The logic.js file contains definitions
+ for the functions. To use the functions in a QML file, we import logic.js as
+ the \c Logic namespace in that file:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto logic.js
+ \printuntil Logic
+
+ The base state displays the new game screen when the application starts.
+ In addition, we call the Component.onCompleted signal handler to initialize
+ a new game:
+
+ \skipto newGameState
+ \printuntil ;
+
+ In NewGameScreen.qml we use the \c onClicked signal handler to emit the
+ \c startButtonClicked() signal when the players tap the New Game button:
+
+ \quotefromfile demos/maroon/content/NewGameScreen.qml
+ \skipto to: 150
+ \skipto Image
+ \printuntil }
+
+ In maroon.qml, we use the \c onStartButtonClicked signal handler to set the
+ \c passedSplash property of the \c root item to \c true:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto NewGameScreen
+ \printuntil }
+
+ We then use the \c passedSplash property in the \c when property of the
+ \c gameOn state to trigger the \c gameStarter timer:
+
+ \skipto State {
+ \printuntil gameStarter
+ \printuntil }
+
+ We also switch to the \c "gameOn" state and move to the y position
+ \c {-(height - 960)} to display the game canvas.
+
+ In the \c gameStarter \l{Timer} object we use the \c onTriggered signal
+ handler to call the \c startGame() function that starts a new game:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto property int
+ \skipto Timer
+ \printuntil }
+
+ The game continues until \c gameState.gameOver is set to \c true and
+ \c gameState.gameRunning is set to \c false by calling the \c endGame()
+ function when the value of the \c gameState.lives property becomes less
+ than or equal to \c 0.
+
+ In GameOverScreen.qml, we use a MouseArea type and an \c onClicked signal
+ handler within an \l{Image} type to return to the game canvas when the
+ players tap the New Game button:
+
+ \quotefromfile demos/maroon/content/GameOverScreen.qml
+ \skipto opacity: 0.5
+ \skipto Image
+ \printuntil }
+ \printuntil }
+
+ The \c onClicked signal handler triggers a state change in maroon.qml to
+ display the game canvas:
+
+ \quotefromfile demos/maroon/maroon.qml
+ \skipto target: gameStarter
+ \skipto State
+ \printuntil }
+ \printuntil }
+
+ \section1 Playing Sound Effects
+
+ The app can play sound effects if the \l{Qt Multimedia} module is installed.
+ In the SoundEffect.qml file, we proxy a SoundEffect type:
+
+ \quotefromfile demos/maroon/content/SoundEffect.qml
+ \skipto Item
+ \printuntil }
+ \printuntil }
+
+ We add the \c qtHaveModule() qmake command to the app .pro file, maroon.pro,
+ to check whether the \l{Qt Multimedia} module is present:
+
+ \quotefromfile demos/maroon/maroon.pro
+ \skipto QT
+ \printuntil multimedia
+
+ In each QML file that defines a custom type used on the game canvas, we
+ use a SoundEffect type to specify the audio file to play for that type
+ of objects. For example, in Bomb.qml, we specify the sound that a bomb
+ makes when it explodes:
+
+ \quotefromfile demos/maroon/content/towers/Bomb.qml
+ \skipto SoundEffect
+ \printuntil }
+
+ To play the sound effect when a bomb explodes, we call the \c sound.play()
+ function that we declare as a member of the private \c fire() function
+ within the TowerBase custom type:
+
+ \quotefromfile demos/maroon/content/towers/Bomb.qml
+ \skipto fire()
+ \printuntil }
+
+ For more examples of playing sound effects, see the QML files in the
+ \c towers directory and MobBase.qml.
+
+ \section1 Adding Keyboard Shortcuts
+
+ This is a touch example, so you should not really need to handle key
+ presses. However, we do not want you to have to spend more time playing the
+ game than you want to while testing it, so we use the \c {Keys.onPressed}
+ signal handler to specify keyboard shortcuts. You can press Shift+Up to
+ increment the values of the \c coins property to add coins, Shift+Left to
+ increment the value of \c lives, Shift+Down to increment the value of the
+ \c waveProgress property to spawn mobs of fish faster, and Shift+Right to
+ call the \c endGame() function to quit the game:
+
+ \quotefromfile demos/maroon/content/GameCanvas.qml
+ \skipto Keys
+ \printuntil }
+
+ \section1 Packaging Resources for Deployment
+
+ To be able to run the app on mobile devices, we package all QML, JavaScript,
+ image, and sound files into a Qt resource file (.qrc). For more information,
+ see \l{The Qt Resource System}.
+
\sa {QML Applications}
*/
diff --git a/examples/quick/demos/rssnews/content/BusyIndicator.qml b/examples/quick/demos/rssnews/content/BusyIndicator.qml
index c16f582c40..e6cd15847a 100644
--- a/examples/quick/demos/rssnews/content/BusyIndicator.qml
+++ b/examples/quick/demos/rssnews/content/BusyIndicator.qml
@@ -1,53 +1,54 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
Image {
id: container
- property bool on: false
- source: "images/busy.png"; visible: container.on
+ source: "images/busy.png";
NumberAnimation on rotation {
- running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200
+ running: container.visible
+ from: 0; to: 360;
+ loops: Animation.Infinite;
+ duration: 1200
}
}
diff --git a/examples/quick/demos/rssnews/content/CategoryDelegate.qml b/examples/quick/demos/rssnews/content/CategoryDelegate.qml
index 31dd9c0d3b..cb48715609 100644
--- a/examples/quick/demos/rssnews/content/CategoryDelegate.qml
+++ b/examples/quick/demos/rssnews/content/CategoryDelegate.qml
@@ -1,82 +1,125 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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.
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** "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.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
+import QtGraphicalEffects 1.0
-Item {
+Rectangle {
id: delegate
- width: delegate.ListView.view.width; height: 60
+ property bool selected: ListView.isCurrentItem
+ property real itemSize
+ width: itemSize
+ height: itemSize
- Text {
- text: name
- color: delegate.ListView.isCurrentItem ? "white" : "black"
- font { family: "Helvetica"; pixelSize: 16; bold: true }
- anchors {
- left: parent.left; leftMargin: 15
- verticalCenter: parent.verticalCenter
- }
+ Image {
+ anchors.centerIn: parent
+ source: image
}
- BusyIndicator {
- scale: 0.6
- on: delegate.ListView.isCurrentItem && window.loading
- anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter }
- }
+ Item {
+ id: title
+ anchors.fill: parent
+
+ Text {
+ id: titleText
+
+ anchors {
+ left: parent.left; leftMargin: 20
+ right: parent.right; rightMargin: 20
+ top: parent.top; topMargin: 20
+ }
+ font { pixelSize: 18; bold: true }
+ text: name
+ color: selected ? "#ffffff" : "#ebebdd"
+ Behavior on color { ColorAnimation { duration: 150 } }
+ }
- Rectangle {
- width: delegate.width; height: 1; color: "#cccccc"
- anchors.bottom: delegate.bottom
- visible: delegate.ListView.isCurrentItem ? false : true
+ DropShadow {
+ source: titleText
+ anchors.fill: titleText
+ horizontalOffset: selected ? 3 : 1
+ verticalOffset: selected ? 3 : 1
+ radius: 4
+ color: "#2f1000"
+ samples: 8
+
+ Behavior on horizontalOffset { NumberAnimation { duration: 300 } }
+ Behavior on verticalOffset { NumberAnimation { duration: 300 } }
+ }
+
+ states: [
+ State {
+ name: "selected"
+ when: selected
+ PropertyChanges { target: title; scale: "1.1" }
+ }]
+
+ transitions: [
+ Transition {
+ to: "selected"
+ SequentialAnimation {
+ id: titleAnimation
+ PropertyAnimation { target: title; property: "scale"; duration: 300 }
+ }
+ },
+ Transition {
+ to: ""
+ animations: titleAnimation
+ }]
}
- Rectangle {
- width: delegate.width; height: 1; color: "white"
- visible: delegate.ListView.isCurrentItem ? false : true
+
+ BusyIndicator {
+ scale: 0.8
+ visible: delegate.ListView.isCurrentItem && window.loading
+ anchors.centerIn: parent
}
MouseArea {
anchors.fill: delegate
onClicked: {
delegate.ListView.view.currentIndex = index
- window.currentFeed = feed
+ if (window.currentFeed == feed)
+ feedModel.reload()
+ else
+ window.currentFeed = feed
}
}
}
diff --git a/examples/quick/demos/rssnews/content/NewsDelegate.qml b/examples/quick/demos/rssnews/content/NewsDelegate.qml
index ec39510eba..fee1119b08 100644
--- a/examples/quick/demos/rssnews/content/NewsDelegate.qml
+++ b/examples/quick/demos/rssnews/content/NewsDelegate.qml
@@ -1,71 +1,129 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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.
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** "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.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
+import QtQuick.Layouts 1.1
-Item {
+ColumnLayout {
id: delegate
- height: column.height + 40
width: delegate.ListView.view.width
- Column {
- id: column
- x: 20; y: 20
- width: parent.width - 40
+ // Returns a string representing how long ago an event occurred
+ function timeSinceEvent(pubDate) {
+ var result = pubDate;
+
+ // We need to modify the pubDate read from the RSS feed
+ // so the JavaScript Date object can interpret it
+ var d = pubDate.replace(',','').split(' ');
+ if (d.length != 6)
+ return result;
+
+ var date = new Date([d[0], d[2], d[1], d[3], d[4], 'GMT' + d[5]].join(' '));
+
+ if (!isNaN(date.getDate())) {
+ var age = new Date() - date;
+ var minutes = Math.floor(Number(age) / 60000);
+ if (minutes < 1440) {
+ if (minutes < 2)
+ result = qsTr("Just now");
+ else if (minutes < 60)
+ result = '' + minutes + ' ' + qsTr("minutes ago")
+ else if (minutes < 120)
+ result = qsTr("1 hour ago");
+ else
+ result = '' + Math.floor(minutes/60) + ' ' + qsTr("hours ago");
+ }
+ else {
+ result = date.toDateString();
+ }
+ }
+ return result;
+ }
+
+ RowLayout {
+ Layout.maximumWidth: parent.width
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignTop
+
+ Item {
+ height: titleText.font.pixelSize / 4
+ }
+
+ Image {
+ id: titleImage
+ source: image
+ }
+ }
Text {
id: titleText
- text: title; width: parent.width; wrapMode: Text.WordWrap
- font { bold: true; family: "Helvetica"; pointSize: 16 }
+
+ text: title
+ Layout.maximumWidth: delegate.width - titleImage.width
+ wrapMode: Text.WordWrap
+ font.pixelSize: 26
+ font.bold: true
}
+ }
- Text {
- id: descriptionText
- width: parent.width; text: description
- wrapMode: Text.WordWrap; font.family: "Helvetica"
+ Text {
+ Layout.maximumWidth: delegate.width
+ font.pixelSize: 12
+ textFormat: Text.RichText
+ font.italic: true
+ Layout.alignment: Qt.AlignLeft
+ text: timeSinceEvent(pubDate) + " (<a href=\"" + link + "\">Link</a>)"
+ onLinkActivated: {
+ Qt.openUrlExternally(link)
}
}
- Rectangle {
- width: parent.width; height: 1; color: "#cccccc"
- anchors.bottom: parent.bottom
+ Text {
+ id: descriptionText
+
+ text: description
+ Layout.maximumWidth: parent.width
+ wrapMode: Text.WordWrap
+ font.pixelSize: 14
+ textFormat: Text.StyledText
+ horizontalAlignment: Qt.AlignLeft
}
}
diff --git a/examples/quick/demos/rssnews/content/RssFeeds.qml b/examples/quick/demos/rssnews/content/RssFeeds.qml
index 50bc771192..3ae3b23921 100644
--- a/examples/quick/demos/rssnews/content/RssFeeds.qml
+++ b/examples/quick/demos/rssnews/content/RssFeeds.qml
@@ -1,59 +1,56 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
ListModel {
- id: rssFeeds
-
- ListElement { name: "Top Stories"; feed: "rss.news.yahoo.com/rss/topstories" }
- ListElement { name: "World"; feed: "rss.news.yahoo.com/rss/world" }
- ListElement { name: "Europe"; feed: "rss.news.yahoo.com/rss/europe" }
- ListElement { name: "Oceania"; feed: "rss.news.yahoo.com/rss/oceania" }
- ListElement { name: "U.S. National"; feed: "rss.news.yahoo.com/rss/us" }
- ListElement { name: "Politics"; feed: "rss.news.yahoo.com/rss/politics" }
- ListElement { name: "Business"; feed: "rss.news.yahoo.com/rss/business" }
- ListElement { name: "Technology"; feed: "rss.news.yahoo.com/rss/tech" }
- ListElement { name: "Entertainment"; feed: "rss.news.yahoo.com/rss/entertainment" }
- ListElement { name: "Health"; feed: "rss.news.yahoo.com/rss/health" }
- ListElement { name: "Science"; feed: "rss.news.yahoo.com/rss/science" }
- ListElement { name: "Sports"; feed: "rss.news.yahoo.com/rss/sports" }
+ ListElement { name: "Top Stories"; feed: "news.yahoo.com/rss/topstories"; image: "images/TopStories.jpg" }
+ ListElement { name: "World"; feed: "news.yahoo.com/rss/world"; image: "images/World.jpg" }
+ ListElement { name: "Europe"; feed: "news.yahoo.com/rss/europe"; image: "images/Europe.jpg" }
+ ListElement { name: "Asia"; feed: "news.yahoo.com/rss/asia"; image: "images/Asia.jpg" }
+ ListElement { name: "U.S. National"; feed: "news.yahoo.com/rss/us"; image: "images/USNational.jpg" }
+ ListElement { name: "Politics"; feed: "news.yahoo.com/rss/politics"; image: "images/Politics.jpg" }
+ ListElement { name: "Business"; feed: "news.yahoo.com/rss/business"; image: "images/Business.jpg" }
+ ListElement { name: "Technology"; feed: "news.yahoo.com/rss/tech"; image: "images/Technology.jpg" }
+ ListElement { name: "Entertainment"; feed: "news.yahoo.com/rss/entertainment"; image: "images/Entertainment.jpg" }
+ ListElement { name: "Health"; feed: "news.yahoo.com/rss/health"; image: "images/Health.jpg" }
+ ListElement { name: "Science"; feed: "news.yahoo.com/rss/science"; image: "images/Science.jpg" }
+ ListElement { name: "Sports"; feed: "news.yahoo.com/rss/sports"; image: "images/Sports.jpg" }
}
diff --git a/examples/quick/demos/rssnews/content/ScrollBar.qml b/examples/quick/demos/rssnews/content/ScrollBar.qml
index d3cf4a6851..606f2e4259 100644
--- a/examples/quick/demos/rssnews/content/ScrollBar.qml
+++ b/examples/quick/demos/rssnews/content/ScrollBar.qml
@@ -1,51 +1,50 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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.
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** "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.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
Item {
id: container
property variant scrollArea
- property variant orientation: Qt.Vertical
+ property int orientation: Qt.Vertical
opacity: 0
@@ -56,7 +55,11 @@ Item {
ny = scrollArea.visibleArea.yPosition * container.height;
else
ny = scrollArea.visibleArea.xPosition * container.width;
- if (ny > 2) return ny; else return 2;
+
+ if (ny > 2)
+ return ny;
+ else
+ return 2;
}
function size()
@@ -79,8 +82,12 @@ Item {
t = Math.ceil(container.height - 3 - ny);
else
t = Math.ceil(container.width - 3 - ny);
- if (nh > t) return t; else return nh;
- } else return nh + ny;
+ if (nh > t)
+ return t;
+ else
+ return nh;
+ } else
+ return nh + ny;
}
Rectangle { anchors.fill: parent; color: "Black"; opacity: 0.3 }
@@ -89,14 +96,16 @@ Item {
source: "images/scrollbar.png"
border { left: 1; right: 1; top: 1; bottom: 1 }
x: container.orientation == Qt.Vertical ? 2 : position()
- width: container.orientation == Qt.Vertical ? container.width - 4 : size()
y: container.orientation == Qt.Vertical ? position() : 2
+ width: container.orientation == Qt.Vertical ? container.width - 4 : size()
height: container.orientation == Qt.Vertical ? size() : container.height - 4
}
states: State {
name: "visible"
- when: container.orientation == Qt.Vertical ? scrollArea.movingVertically : scrollArea.movingHorizontally
+ when: container.orientation == Qt.Vertical ?
+ scrollArea.movingVertically :
+ scrollArea.movingHorizontally
PropertyChanges { target: container; opacity: 1.0 }
}
diff --git a/examples/quick/demos/rssnews/content/images/Asia.jpg b/examples/quick/demos/rssnews/content/images/Asia.jpg
new file mode 100644
index 0000000000..a609557a08
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Asia.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Business.jpg b/examples/quick/demos/rssnews/content/images/Business.jpg
new file mode 100644
index 0000000000..b2c1d92138
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Business.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Entertainment.jpg b/examples/quick/demos/rssnews/content/images/Entertainment.jpg
new file mode 100644
index 0000000000..2c69fc04d7
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Entertainment.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Europe.jpg b/examples/quick/demos/rssnews/content/images/Europe.jpg
new file mode 100644
index 0000000000..bf524e13d0
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Europe.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Health.jpg b/examples/quick/demos/rssnews/content/images/Health.jpg
new file mode 100644
index 0000000000..0e8c71f0c9
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Health.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Politics.jpg b/examples/quick/demos/rssnews/content/images/Politics.jpg
new file mode 100644
index 0000000000..0b1800c97e
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Politics.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Science.jpg b/examples/quick/demos/rssnews/content/images/Science.jpg
new file mode 100644
index 0000000000..7faccbbb97
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Science.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Sports.jpg b/examples/quick/demos/rssnews/content/images/Sports.jpg
new file mode 100644
index 0000000000..0ab3bd3ce7
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Sports.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/Technology.jpg b/examples/quick/demos/rssnews/content/images/Technology.jpg
new file mode 100644
index 0000000000..db553028fb
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/Technology.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/TopStories.jpg b/examples/quick/demos/rssnews/content/images/TopStories.jpg
new file mode 100644
index 0000000000..e35bd67f20
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/TopStories.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/USNational.jpg b/examples/quick/demos/rssnews/content/images/USNational.jpg
new file mode 100644
index 0000000000..82c78228c1
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/USNational.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/World.jpg b/examples/quick/demos/rssnews/content/images/World.jpg
new file mode 100644
index 0000000000..7a0a806fd4
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/World.jpg
Binary files differ
diff --git a/examples/quick/demos/rssnews/content/images/btn_close.png b/examples/quick/demos/rssnews/content/images/btn_close.png
new file mode 100644
index 0000000000..6d635375eb
--- /dev/null
+++ b/examples/quick/demos/rssnews/content/images/btn_close.png
Binary files differ
diff --git a/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png b/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png
index 0ad6c02251..ffef99ee5c 100644
--- a/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png
+++ b/examples/quick/demos/rssnews/doc/images/qtquick-demo-rssnews-small.png
Binary files differ
diff --git a/examples/quick/demos/rssnews/main.cpp b/examples/quick/demos/rssnews/main.cpp
new file mode 100644
index 0000000000..0064412f39
--- /dev/null
+++ b/examples/quick/demos/rssnews/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(demos/rssnews/rssnews)
diff --git a/examples/quick/demos/rssnews/rssnews.pro b/examples/quick/demos/rssnews/rssnews.pro
new file mode 100644
index 0000000000..c67c5a6558
--- /dev/null
+++ b/examples/quick/demos/rssnews/rssnews.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+
+QT += quick qml xml xmlpatterns
+SOURCES += main.cpp
+RESOURCES += rssnews.qrc
+
+OTHER_FILES = rssnews.qml \
+ content/*.qml \
+ content/*.js \
+ content/images/*
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/rssnews
+INSTALLS += target
diff --git a/examples/quick/demos/rssnews/rssnews.qml b/examples/quick/demos/rssnews/rssnews.qml
index a367490ef7..cb9734208d 100644
--- a/examples/quick/demos/rssnews/rssnews.qml
+++ b/examples/quick/demos/rssnews/rssnews.qml
@@ -1,112 +1,159 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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.
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** "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.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
+** 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$
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.2
import QtQuick.XmlListModel 2.0
-import "content"
+import QtQuick.Window 2.1
+import "./content"
Rectangle {
id: window
- width: 800; height: 480
- property string currentFeed: "rss.news.yahoo.com/rss/topstories"
- property bool loading: feedModel.status == XmlListModel.Loading
+ width: 800
+ height: 480
+
+ property string currentFeed: rssFeeds.get(0).feed
+ property bool loading: feedModel.status === XmlListModel.Loading
+ property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation
+
+ onLoadingChanged: {
+ if (feedModel.status == XmlListModel.Ready)
+ list.positionViewAtBeginning()
+ }
RssFeeds { id: rssFeeds }
XmlListModel {
id: feedModel
+
source: "http://" + window.currentFeed
- query: "/rss/channel/item"
+ query: "/rss/channel/item[child::media:content]"
+ namespaceDeclarations: "declare namespace media = 'http://search.yahoo.com/mrss/';"
XmlRole { name: "title"; query: "title/string()" }
+ // Remove any links from the description
+ XmlRole { name: "description"; query: "fn:replace(description/string(), '\&lt;a href=.*\/a\&gt;', '')" }
+ XmlRole { name: "image"; query: "media:content/@url/string()" }
XmlRole { name: "link"; query: "link/string()" }
- XmlRole { name: "description"; query: "description/string()" }
+ XmlRole { name: "pubDate"; query: "pubDate/string()" }
}
- Row {
- Rectangle {
- width: 220; height: window.height
- color: "#efefef"
-
- ListView {
- focus: true
- id: categories
- anchors.fill: parent
- model: rssFeeds
- footer: quitButtonDelegate
- delegate: CategoryDelegate {}
- highlight: Rectangle { color: "steelblue" }
- highlightMoveVelocity: 9999999
- }
- ScrollBar {
- scrollArea: categories; height: categories.height; width: 8
- anchors.right: categories.right
- }
- }
- ListView {
- id: list
- width: window.width - 220; height: window.height
- model: feedModel
- delegate: NewsDelegate {}
- }
+ ListView {
+ id: categories
+ property int itemWidth: 190
+
+ width: isPortrait ? parent.width : itemWidth
+ height: isPortrait ? itemWidth : parent.height
+ orientation: isPortrait ? ListView.Horizontal : ListView.Vertical
+ anchors.top: parent.top
+ model: rssFeeds
+ delegate: CategoryDelegate { itemSize: categories.itemWidth }
+ spacing: 3
+ }
+
+ ScrollBar {
+ id: listScrollBar
+
+ orientation: isPortrait ? Qt.Horizontal : Qt.Vertical
+ height: isPortrait ? 8 : categories.height;
+ width: isPortrait ? categories.width : 8
+ scrollArea: categories;
+ anchors.right: categories.right
}
+
+ ListView {
+ id: list
+
+ anchors.left: isPortrait ? window.left : categories.right
+ anchors.right: closeButton.left
+ anchors.top: isPortrait ? categories.bottom : window.top
+ anchors.bottom: window.bottom
+ anchors.leftMargin: 30
+ anchors.rightMargin: 4
+ clip: isPortrait
+ model: feedModel
+ footer: footerText
+ delegate: NewsDelegate {}
+ }
+
+ ScrollBar {
+ scrollArea: list
+ width: 8
+ anchors.right: window.right
+ anchors.top: isPortrait ? categories.bottom : window.top
+ anchors.bottom: window.bottom
+ }
+
Component {
- id: quitButtonDelegate
- Item {
- width: categories.width; height: 60
+ id: footerText
+
+ Rectangle {
+ width: parent.width
+ height: closeButton.height
+ color: "lightgray"
+
Text {
- text: "Quit"
- font { family: "Helvetica"; pixelSize: 16; bold: true }
- anchors {
- left: parent.left; leftMargin: 15
- verticalCenter: parent.verticalCenter
- }
+ text: "RSS Feed from Yahoo News"
+ anchors.centerIn: parent
+ font.pixelSize: 14
}
- MouseArea {
- anchors.fill: parent
- onClicked: Qt.quit()
+ }
+ }
+
+ Image {
+ id: closeButton
+ source: "content/images/btn_close.png"
+ scale: 0.8
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.margins: 4
+ opacity: (isPortrait && categories.moving) ? 0.2 : 1.0
+ Behavior on opacity {
+ NumberAnimation { duration: 300; easing.type: Easing.OutSine }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ Qt.quit()
}
}
}
- ScrollBar { scrollArea: list; height: list.height; width: 8; anchors.right: window.right }
- Rectangle { x: 220; height: window.height; width: 1; color: "#cccccc" }
}
diff --git a/examples/quick/demos/rssnews/rssnews.qrc b/examples/quick/demos/rssnews/rssnews.qrc
new file mode 100644
index 0000000000..1208d44fd7
--- /dev/null
+++ b/examples/quick/demos/rssnews/rssnews.qrc
@@ -0,0 +1,25 @@
+<RCC>
+ <qresource prefix="/demos/rssnews">
+ <file>rssnews.qml</file>
+ <file>content/BusyIndicator.qml</file>
+ <file>content/CategoryDelegate.qml</file>
+ <file>content/NewsDelegate.qml</file>
+ <file>content/RssFeeds.qml</file>
+ <file>content/ScrollBar.qml</file>
+ <file>content/images/btn_close.png</file>
+ <file>content/images/Business.jpg</file>
+ <file>content/images/busy.png</file>
+ <file>content/images/Entertainment.jpg</file>
+ <file>content/images/Europe.jpg</file>
+ <file>content/images/Health.jpg</file>
+ <file>content/images/Asia.jpg</file>
+ <file>content/images/Politics.jpg</file>
+ <file>content/images/Science.jpg</file>
+ <file>content/images/scrollbar.png</file>
+ <file>content/images/Sports.jpg</file>
+ <file>content/images/Technology.jpg</file>
+ <file>content/images/TopStories.jpg</file>
+ <file>content/images/USNational.jpg</file>
+ <file>content/images/World.jpg</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp
new file mode 100644
index 0000000000..3b9f2e97f3
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "fbitem.h"
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFunctions>
+#include <QMatrix4x4>
+
+FbItem::FbItem(QQuickItem *parent)
+ : QQuickFramebufferObject(parent),
+ m_target(0, 0, -1),
+ m_syncState(AllNeedsSync),
+ m_multisample(false)
+{
+}
+
+QQuickFramebufferObject::Renderer *FbItem::createRenderer() const
+{
+ return new FbItemRenderer(m_multisample);
+}
+
+void FbItem::setEye(const QVector3D &v)
+{
+ if (m_eye != v) {
+ m_eye = v;
+ m_syncState |= CameraNeedsSync;
+ update();
+ }
+}
+
+void FbItem::setTarget(const QVector3D &v)
+{
+ if (m_target != v) {
+ m_target = v;
+ m_syncState |= CameraNeedsSync;
+ update();
+ }
+}
+
+void FbItem::setRotation(const QVector3D &v)
+{
+ if (m_rotation != v) {
+ m_rotation = v;
+ m_syncState |= RotationNeedsSync;
+ update();
+ }
+}
+
+int FbItem::swapSyncState()
+{
+ int s = m_syncState;
+ m_syncState = 0;
+ return s;
+}
+
+FbItemRenderer::FbItemRenderer(bool multisample)
+ : m_inited(false),
+ m_multisample(multisample),
+ m_dirty(DirtyAll)
+{
+ m_camera.setToIdentity();
+ m_baseWorld.setToIdentity();
+ m_baseWorld.translate(0, 0, -1);
+ m_world = m_baseWorld;
+}
+
+void FbItemRenderer::synchronize(QQuickFramebufferObject *qfbitem)
+{
+ FbItem *item = static_cast<FbItem *>(qfbitem);
+ int syncState = item->swapSyncState();
+ if (syncState & FbItem::CameraNeedsSync) {
+ m_camera.setToIdentity();
+ m_camera.lookAt(item->eye(), item->eye() + item->target(), QVector3D(0, 1, 0));
+ m_dirty |= DirtyCamera;
+ }
+ if (syncState & FbItem::RotationNeedsSync) {
+ m_rotation = item->rotation();
+ m_dirty |= DirtyWorld;
+ }
+}
+
+struct StateBinder
+{
+ StateBinder(FbItemRenderer *r)
+ : m_r(r) {
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glEnable(GL_DEPTH_TEST);
+ f->glEnable(GL_CULL_FACE);
+ f->glDepthMask(GL_TRUE);
+ f->glDepthFunc(GL_LESS);
+ f->glFrontFace(GL_CCW);
+ f->glCullFace(GL_BACK);
+ m_r->m_program->bind();
+ }
+ ~StateBinder() {
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ m_r->m_program->release();
+ f->glDisable(GL_CULL_FACE);
+ f->glDisable(GL_DEPTH_TEST);
+ }
+ FbItemRenderer *m_r;
+};
+
+void FbItemRenderer::updateDirtyUniforms()
+{
+ if (m_dirty & DirtyProjection)
+ m_program->setUniformValue(m_projMatrixLoc, m_proj);
+
+ if (m_dirty & DirtyCamera)
+ m_program->setUniformValue(m_camMatrixLoc, m_camera);
+
+ if (m_dirty & DirtyWorld) {
+ m_program->setUniformValue(m_worldMatrixLoc, m_world);
+ QMatrix3x3 normalMatrix = m_world.normalMatrix();
+ m_program->setUniformValue(m_normalMatrixLoc, normalMatrix);
+ }
+
+ if (m_dirty & DirtyLight)
+ m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70));
+
+ m_dirty = 0;
+}
+
+void FbItemRenderer::render()
+{
+ ensureInit();
+
+ QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
+ if (!m_vao.isCreated())
+ setupVertexAttribs();
+
+ StateBinder state(this);
+
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glClearColor(0, 0, 0, 0);
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (m_dirty & DirtyWorld) {
+ m_world = m_baseWorld;
+ m_world.rotate(m_rotation.x(), 1, 0, 0);
+ m_world.rotate(m_rotation.y(), 0, 1, 0);
+ m_world.rotate(m_rotation.z(), 0, 0, 1);
+ }
+
+ updateDirtyUniforms();
+
+ f->glDrawArrays(GL_TRIANGLES, 0, m_logo.vertexCount());
+}
+
+QOpenGLFramebufferObject *FbItemRenderer::createFramebufferObject(const QSize &size)
+{
+ m_dirty |= DirtyProjection;
+ m_proj.setToIdentity();
+ m_proj.perspective(45.0f, GLfloat(size.width()) / size.height(), 0.01f, 100.0f);
+
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(m_multisample ? 4 : 0);
+ return new QOpenGLFramebufferObject(size, format);
+}
+
+void FbItemRenderer::ensureInit()
+{
+ if (m_inited)
+ return;
+
+ m_inited = true;
+
+ initBuf();
+ initProgram();
+}
+
+void FbItemRenderer::initBuf()
+{
+ m_vao.create();
+ QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
+
+ m_logoVbo.create();
+ m_logoVbo.bind();
+ m_logoVbo.allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat));
+
+ setupVertexAttribs();
+}
+
+void FbItemRenderer::setupVertexAttribs()
+{
+ m_logoVbo.bind();
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ f->glEnableVertexAttribArray(0);
+ f->glEnableVertexAttribArray(1);
+ f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
+ f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
+ m_logoVbo.release();
+}
+
+static const char *vertexShaderSource =
+ "attribute vec4 vertex;\n"
+ "attribute vec3 normal;\n"
+ "varying vec3 vert;\n"
+ "varying vec3 vertNormal;\n"
+ "uniform mat4 projMatrix;\n"
+ "uniform mat4 camMatrix;\n"
+ "uniform mat4 worldMatrix;\n"
+ "uniform mat3 normalMatrix;\n"
+ "void main() {\n"
+ " vert = vertex.xyz;\n"
+ " vertNormal = normalMatrix * normal;\n"
+ " gl_Position = projMatrix * camMatrix * worldMatrix * vertex;\n"
+ "}\n";
+
+static const char *fragmentShaderSource =
+ "varying highp vec3 vert;\n"
+ "varying highp vec3 vertNormal;\n"
+ "uniform highp vec3 lightPos;\n"
+ "void main() {\n"
+ " highp vec3 L = normalize(lightPos - vert);\n"
+ " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
+ " highp vec3 color = vec3(0.39, 1.0, 0.0);\n"
+ " highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
+ " gl_FragColor = vec4(col, 1.0);\n"
+ "}\n";
+
+void FbItemRenderer::initProgram()
+{
+ m_program.reset(new QOpenGLShaderProgram);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
+ m_program->bindAttributeLocation("vertex", 0);
+ m_program->bindAttributeLocation("normal", 1);
+ m_program->link();
+ m_projMatrixLoc = m_program->uniformLocation("projMatrix");
+ m_camMatrixLoc = m_program->uniformLocation("camMatrix");
+ m_worldMatrixLoc = m_program->uniformLocation("worldMatrix");
+ m_normalMatrixLoc = m_program->uniformLocation("normalMatrix");
+ m_lightPosLoc = m_program->uniformLocation("lightPos");
+}
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
new file mode 100644
index 0000000000..b29998c253
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 FBITEM_H
+#define FBITEM_H
+
+#include <QQuickFramebufferObject>
+#include <QOpenGLVertexArrayObject>
+#include <QOpenGLBuffer>
+#include <QOpenGLShaderProgram>
+#include <QVector3D>
+#include "logo.h"
+
+struct StateBinder;
+
+class FbItemRenderer : public QQuickFramebufferObject::Renderer
+{
+public:
+ FbItemRenderer(bool multisample);
+ void synchronize(QQuickFramebufferObject *item) Q_DECL_OVERRIDE;
+ void render() Q_DECL_OVERRIDE;
+ QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) Q_DECL_OVERRIDE;
+
+private:
+ void ensureInit();
+ void initBuf();
+ void setupVertexAttribs();
+ void initProgram();
+ void updateDirtyUniforms();
+
+ bool m_inited;
+ bool m_multisample;
+ QMatrix4x4 m_proj;
+ QMatrix4x4 m_camera;
+ QMatrix4x4 m_baseWorld;
+ QMatrix4x4 m_world;
+ QOpenGLVertexArrayObject m_vao;
+ QOpenGLBuffer m_logoVbo;
+ Logo m_logo;
+ QScopedPointer<QOpenGLShaderProgram> m_program;
+ int m_projMatrixLoc;
+ int m_camMatrixLoc;
+ int m_worldMatrixLoc;
+ int m_normalMatrixLoc;
+ int m_lightPosLoc;
+ QVector3D m_rotation;
+
+ enum Dirty {
+ DirtyProjection = 0x01,
+ DirtyCamera = 0x02,
+ DirtyWorld = 0x04,
+ DirtyLight = 0x08,
+ DirtyAll = 0xFF
+ };
+ int m_dirty;
+
+ friend struct StateBinder;
+};
+
+class FbItem : public QQuickFramebufferObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector3D eye READ eye WRITE setEye)
+ Q_PROPERTY(QVector3D target READ target WRITE setTarget)
+ Q_PROPERTY(QVector3D rotation READ rotation WRITE setRotation)
+ Q_PROPERTY(bool multisample READ multisample WRITE setMultisample)
+
+public:
+ explicit FbItem(QQuickItem *parent = 0);
+
+ QQuickFramebufferObject::Renderer *createRenderer() const Q_DECL_OVERRIDE;
+
+ QVector3D eye() const { return m_eye; }
+ void setEye(const QVector3D &v);
+ QVector3D target() const { return m_target; }
+ void setTarget(const QVector3D &v);
+
+ QVector3D rotation() const { return m_rotation; }
+ void setRotation(const QVector3D &v);
+
+ enum SyncState {
+ CameraNeedsSync = 0x01,
+ RotationNeedsSync = 0x02,
+ AllNeedsSync = 0xFF
+ };
+ int swapSyncState();
+
+ bool multisample() const { return m_multisample; }
+ void setMultisample(bool m) { m_multisample = m; }
+
+private:
+ QVector3D m_eye;
+ QVector3D m_target;
+ QVector3D m_rotation;
+ int m_syncState;
+ bool m_multisample;
+};
+
+#endif // FBITEM_H
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/logo.cpp b/examples/quick/quickwidgets/qquickviewcomparison/logo.cpp
new file mode 100644
index 0000000000..1ba47ddfb5
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/logo.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "logo.h"
+#include <qmath.h>
+
+Logo::Logo()
+ : m_count(0)
+{
+ m_data.resize(2500 * 6);
+
+ const GLfloat x1 = +0.06f;
+ const GLfloat y1 = -0.14f;
+ const GLfloat x2 = +0.14f;
+ const GLfloat y2 = -0.06f;
+ const GLfloat x3 = +0.08f;
+ const GLfloat y3 = +0.00f;
+ const GLfloat x4 = +0.30f;
+ const GLfloat y4 = +0.22f;
+
+ quad(x1, y1, x2, y2, y2, x2, y1, x1);
+ quad(x3, y3, x4, y4, y4, x4, y3, x3);
+
+ extrude(x1, y1, x2, y2);
+ extrude(x2, y2, y2, x2);
+ extrude(y2, x2, y1, x1);
+ extrude(y1, x1, x1, y1);
+ extrude(x3, y3, x4, y4);
+ extrude(x4, y4, y4, x4);
+ extrude(y4, x4, y3, x3);
+
+ const int NumSectors = 100;
+
+ for (int i = 0; i < NumSectors; ++i) {
+ GLfloat angle = (i * 2 * M_PI) / NumSectors;
+ GLfloat angleSin = qSin(angle);
+ GLfloat angleCos = qCos(angle);
+ const GLfloat x5 = 0.30f * angleSin;
+ const GLfloat y5 = 0.30f * angleCos;
+ const GLfloat x6 = 0.20f * angleSin;
+ const GLfloat y6 = 0.20f * angleCos;
+
+ angle = ((i + 1) * 2 * M_PI) / NumSectors;
+ angleSin = qSin(angle);
+ angleCos = qCos(angle);
+ const GLfloat x7 = 0.20f * angleSin;
+ const GLfloat y7 = 0.20f * angleCos;
+ const GLfloat x8 = 0.30f * angleSin;
+ const GLfloat y8 = 0.30f * angleCos;
+
+ quad(x5, y5, x6, y6, x7, y7, x8, y8);
+
+ extrude(x6, y6, x7, y7);
+ extrude(x8, y8, x5, y5);
+ }
+}
+
+void Logo::add(const QVector3D &v, const QVector3D &n)
+{
+ GLfloat *p = m_data.data() + m_count;
+ *p++ = v.x();
+ *p++ = v.y();
+ *p++ = v.z();
+ *p++ = n.x();
+ *p++ = n.y();
+ *p++ = n.z();
+ m_count += 6;
+}
+
+void Logo::quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4)
+{
+ QVector3D n = QVector3D::normal(QVector3D(x4 - x1, y4 - y1, 0.0f), QVector3D(x2 - x1, y2 - y1, 0.0f));
+
+ add(QVector3D(x1, y1, -0.05f), n);
+ add(QVector3D(x4, y4, -0.05f), n);
+ add(QVector3D(x2, y2, -0.05f), n);
+
+ add(QVector3D(x3, y3, -0.05f), n);
+ add(QVector3D(x2, y2, -0.05f), n);
+ add(QVector3D(x4, y4, -0.05f), n);
+
+ n = QVector3D::normal(QVector3D(x1 - x4, y1 - y4, 0.0f), QVector3D(x2 - x4, y2 - y4, 0.0f));
+
+ add(QVector3D(x4, y4, 0.05f), n);
+ add(QVector3D(x1, y1, 0.05f), n);
+ add(QVector3D(x2, y2, 0.05f), n);
+
+ add(QVector3D(x2, y2, 0.05f), n);
+ add(QVector3D(x3, y3, 0.05f), n);
+ add(QVector3D(x4, y4, 0.05f), n);
+}
+
+void Logo::extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+ QVector3D n = QVector3D::normal(QVector3D(0.0f, 0.0f, -0.1f), QVector3D(x2 - x1, y2 - y1, 0.0f));
+
+ add(QVector3D(x1, y1, +0.05f), n);
+ add(QVector3D(x1, y1, -0.05f), n);
+ add(QVector3D(x2, y2, +0.05f), n);
+
+ add(QVector3D(x2, y2, -0.05f), n);
+ add(QVector3D(x2, y2, +0.05f), n);
+ add(QVector3D(x1, y1, -0.05f), n);
+}
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/logo.h b/examples/quick/quickwidgets/qquickviewcomparison/logo.h
new file mode 100644
index 0000000000..29bb7fa241
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/logo.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 LOGO_H
+#define LOGO_H
+
+#include <qopengl.h>
+#include <QVector>
+#include <QVector3D>
+
+class Logo
+{
+public:
+ Logo();
+ const GLfloat *constData() const { return m_data.constData(); }
+ int count() const { return m_count; }
+ int vertexCount() const { return m_count / 6; }
+
+private:
+ void quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4);
+ void extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+ void add(const QVector3D &v, const QVector3D &n);
+
+ QVector<GLfloat> m_data;
+ int m_count;
+};
+
+#endif // LOGO_H
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/main.cpp b/examples/quick/quickwidgets/qquickviewcomparison/main.cpp
new file mode 100644
index 0000000000..5f006c3fb6
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 <QApplication>
+
+#include "mainwindow.h"
+
+int main(int argc, char **argv)
+{
+ qputenv("QML_BAD_GUI_RENDER_LOOP", "1"); // QTBUG-39507
+
+ QApplication app(argc, argv);
+
+ MainWindow widgetWindow;
+ widgetWindow.resize(1024, 768);
+ widgetWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
new file mode 100644
index 0000000000..dbf4121518
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "mainwindow.h"
+#include "fbitem.h"
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QRadioButton>
+#include <QCheckBox>
+#include <QLabel>
+#include <QQuickItem>
+
+MainWindow::MainWindow()
+ : m_currentView(0),
+ m_currentRootObject(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+
+ QGroupBox *groupBox = new QGroupBox(tr("Type"));
+ QVBoxLayout *vbox = new QVBoxLayout;
+ m_radioView = new QRadioButton(tr("QQuickView in a window container (direct)"));
+ m_radioWidget = new QRadioButton(tr("QQuickWidget (indirect through framebuffer objects)"));
+ vbox->addWidget(m_radioView);
+ vbox->addWidget(m_radioWidget);
+ m_radioView->setChecked(true);
+ connect(m_radioView, &QRadioButton::toggled, this, &MainWindow::updateView);
+ connect(m_radioWidget, &QRadioButton::toggled, this, &MainWindow::updateView);
+ groupBox->setLayout(vbox);
+
+ layout->addWidget(groupBox);
+
+ m_checkboxMultiSample = new QCheckBox(tr("Multisample (4x)"));
+ connect(m_checkboxMultiSample, &QCheckBox::toggled, this, &MainWindow::updateView);
+ layout->addWidget(m_checkboxMultiSample);
+
+ m_labelStatus = new QLabel;
+ layout->addWidget(m_labelStatus);
+
+ qmlRegisterType<FbItem>("fbitem", 1, 0, "FbItem");
+
+ QWidget *quickContainer = new QWidget;
+ layout->addWidget(quickContainer);
+ layout->setStretchFactor(quickContainer, 8);
+ m_containerLayout = new QVBoxLayout;
+ quickContainer->setLayout(m_containerLayout);
+
+ // Add an overlay widget to demonstrate that it will _not_ work with
+ // QQuickView, whereas it is perfectly fine with QQuickWidget.
+ QPalette semiTransparent(QColor(255,0,0,128));
+ semiTransparent.setBrush(QPalette::Text, Qt::white);
+ semiTransparent.setBrush(QPalette::WindowText, Qt::white);
+
+ m_overlayLabel = new QLabel("This is a\nsemi-transparent\n overlay widget\nwhich is placed\non top\n of the Quick\ncontent.", this);
+ m_overlayLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
+ m_overlayLabel->setAutoFillBackground(true);
+ m_overlayLabel->setPalette(semiTransparent);
+ QFont f = font();
+ f.setPixelSize(QFontInfo(f).pixelSize()*2);
+ f.setWeight(QFont::Bold);
+ m_overlayLabel->setFont(f);
+ m_overlayLabel->hide();
+
+ m_checkboxOverlayVisible = new QCheckBox(tr("Show widget overlay"));
+ connect(m_checkboxOverlayVisible, &QCheckBox::toggled, m_overlayLabel, &QWidget::setVisible);
+ layout->addWidget(m_checkboxOverlayVisible);
+
+ setLayout(layout);
+
+ updateView();
+}
+
+void MainWindow::resizeEvent(QResizeEvent*)
+{
+ int margin = width() / 10;
+ int top = m_checkboxMultiSample->y();
+ int bottom = m_checkboxOverlayVisible->geometry().bottom();
+ m_overlayLabel->setGeometry(margin, top, width() - 2 * margin, bottom - top);
+}
+
+void MainWindow::switchTo(QWidget *view)
+{
+ if (m_containerLayout->count())
+ m_containerLayout->takeAt(0);
+
+ delete m_currentView;
+ m_currentView = view;
+ m_containerLayout->addWidget(m_currentView);
+ m_currentView->setFocus();
+}
+
+void MainWindow::updateView()
+{
+ QString text = m_currentRootObject
+ ? m_currentRootObject->property("currentText").toString()
+ : QStringLiteral("Hello Qt");
+
+ QUrl source("qrc:qquickviewcomparison/test.qml");
+ QSurfaceFormat format;
+ format.setDepthBufferSize(16);
+ format.setStencilBufferSize(8);
+ if (m_checkboxMultiSample->isChecked())
+ format.setSamples(4);
+
+ if (m_radioView->isChecked()) {
+ QQuickView *quickView = new QQuickView;
+ quickView->setFormat(format);
+ quickView->setResizeMode(QQuickView::SizeRootObjectToView);
+ connect(quickView, &QQuickView::statusChanged, this, &MainWindow::onStatusChangedView);
+ connect(quickView, &QQuickView::sceneGraphError, this, &MainWindow::onSceneGraphError);
+ quickView->setSource(source);
+ m_currentRootObject = quickView->rootObject();
+ switchTo(QWidget::createWindowContainer(quickView));
+ } else {
+ QQuickWidget *quickWidget = new QQuickWidget;
+ quickWidget->setFormat(format);
+ quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ connect(quickWidget, &QQuickWidget::statusChanged, this, &MainWindow::onStatusChangedWidget);
+ connect(quickWidget, &QQuickWidget::sceneGraphError, this, &MainWindow::onSceneGraphError);
+ quickWidget->setSource(source);
+ m_currentRootObject = quickWidget->rootObject();
+ switchTo(quickWidget);
+ }
+
+ m_currentRootObject->setProperty("currentText", text);
+ m_currentRootObject->setProperty("multisample", m_checkboxMultiSample->isChecked());
+
+ m_overlayLabel->raise();
+}
+
+void MainWindow::onStatusChangedView(QQuickView::Status status)
+{
+ QString s;
+ switch (status) {
+ case QQuickView::Null:
+ s = tr("Null");
+ break;
+ case QQuickView::Ready:
+ s = tr("Ready");
+ break;
+ case QQuickView::Loading:
+ s = tr("Loading");
+ break;
+ case QQuickView::Error:
+ s = tr("Error");
+ break;
+ default:
+ s = tr("Unknown");
+ break;
+ }
+ m_labelStatus->setText(tr("QQuickView status: %1").arg(s));
+}
+
+void MainWindow::onStatusChangedWidget(QQuickWidget::Status status)
+{
+ QString s;
+ switch (status) {
+ case QQuickWidget::Null:
+ s = tr("Null");
+ break;
+ case QQuickWidget::Ready:
+ s = tr("Ready");
+ break;
+ case QQuickWidget::Loading:
+ s = tr("Loading");
+ break;
+ case QQuickWidget::Error:
+ s = tr("Error");
+ break;
+ default:
+ s = tr("Unknown");
+ break;
+ }
+ m_labelStatus->setText(tr("QQuickWidget status: %1").arg(s));
+}
+
+void MainWindow::onSceneGraphError(QQuickWindow::SceneGraphError error, const QString &message)
+{
+ m_labelStatus->setText(tr("Scenegraph error %1: %2").arg(error).arg(message));
+}
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h
new file mode 100644
index 0000000000..c7bd514d81
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+#include <QQuickWidget>
+#include <QQuickView>
+
+QT_FORWARD_DECLARE_CLASS(QRadioButton)
+QT_FORWARD_DECLARE_CLASS(QCheckBox)
+QT_FORWARD_DECLARE_CLASS(QLabel)
+QT_FORWARD_DECLARE_CLASS(QLayout)
+
+class MainWindow : public QWidget
+{
+public:
+ MainWindow();
+
+protected:
+ void resizeEvent(QResizeEvent*);
+private slots:
+ void updateView();
+ void onStatusChangedView(QQuickView::Status status);
+ void onStatusChangedWidget(QQuickWidget::Status status);
+ void onSceneGraphError(QQuickWindow::SceneGraphError error, const QString &message);
+
+private:
+ void switchTo(QWidget *view);
+
+ QRadioButton *m_radioView;
+ QRadioButton *m_radioWidget;
+ QCheckBox *m_checkboxMultiSample;
+ QLabel *m_labelStatus;
+ QLayout *m_containerLayout;
+ QWidget *m_currentView;
+ QObject *m_currentRootObject;
+ QLabel *m_overlayLabel;
+ QCheckBox *m_checkboxOverlayVisible;
+};
+
+#endif
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro b/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro
new file mode 100644
index 0000000000..9d70f7aa5a
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro
@@ -0,0 +1,17 @@
+TEMPLATE = app
+TARGET = qquickviewcomparison
+
+QT += quick widgets quickwidgets
+
+SOURCES += main.cpp \
+ mainwindow.cpp \
+ logo.cpp \
+ fbitem.cpp
+
+HEADERS += mainwindow.h \
+ logo.h \
+ fbitem.h
+
+RESOURCES += qquickviewcomparison.qrc
+
+OTHER_FILES += test.qml
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc b/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc
new file mode 100644
index 0000000000..2b259fdeec
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qquickviewcomparison">
+ <file>test.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/test.qml b/examples/quick/quickwidgets/qquickviewcomparison/test.qml
new file mode 100644
index 0000000000..2e8c83024a
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickviewcomparison/test.qml
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtQuick.Particles 2.0
+import fbitem 1.0
+
+Rectangle {
+ id: root
+ color: "lightBlue"
+ property alias currentText: edit.text
+ property alias multisample: fbitem.multisample
+
+ ParticleSystem {
+ anchors.fill: parent
+ running: true
+
+ ImageParticle {
+ source: "qrc:///particleresources/glowdot.png"
+ alpha: 0
+ colorVariation: 1
+ }
+
+ Emitter {
+ anchors.fill: parent
+ lifeSpan: 3000
+ emitRate: 30
+ size: 50
+ sizeVariation: 10
+ velocity: PointDirection { xVariation: 10; yVariation: 10; }
+ acceleration: PointDirection {
+ y: -10
+ xVariation: 5
+ yVariation: 5
+ }
+ }
+ }
+
+ Rectangle {
+ y: 10
+ width: parent.width / 2
+ height: edit.contentHeight + 4
+ anchors.horizontalCenter: parent.horizontalCenter
+ border.color: "gray"
+ border.width: 2
+ radius: 8
+ color: "lightGray"
+ clip: true
+ TextInput {
+ id: edit
+ anchors.horizontalCenter: parent.horizontalCenter
+ maximumLength: 30
+ focus: true
+ font.pointSize: 20
+ }
+ }
+
+ Rectangle {
+ width: 300
+ height: 300
+ anchors.centerIn: parent
+ color: "red"
+ NumberAnimation on rotation { from: 0; to: 360; duration: 20000; loops: Animation.Infinite; }
+ }
+
+ FbItem {
+ id: fbitem
+ anchors.fill: parent
+ SequentialAnimation on eye.y {
+ loops: Animation.Infinite
+ NumberAnimation {
+ from: 0
+ to: 0.15
+ duration: 1000
+ }
+ NumberAnimation {
+ from: 0.15
+ to: 0
+ duration: 2000
+ }
+ }
+ SequentialAnimation on eye.x {
+ loops: Animation.Infinite
+ NumberAnimation {
+ from: 0
+ to: -0.5
+ duration: 3000
+ }
+ NumberAnimation {
+ from: -0.5
+ to: 0.5
+ duration: 3000
+ easing.type: Easing.OutQuad
+ }
+ NumberAnimation {
+ from: 0.5
+ to: 0
+ duration: 1000
+ }
+ }
+ SequentialAnimation on rotation.y {
+ loops: Animation.Infinite
+ NumberAnimation {
+ from: 0
+ to: 360
+ duration: 5000
+ }
+ NumberAnimation {
+ from: 360
+ to: 0
+ duration: 2500
+ }
+ }
+ SequentialAnimation on rotation.x {
+ loops: Animation.Infinite
+ NumberAnimation {
+ from: 0
+ to: 360
+ duration: 6000
+ }
+ NumberAnimation {
+ from: 360
+ to: 0
+ duration: 3000
+ }
+ }
+ }
+
+ Text {
+ id: effText
+ text: edit.text
+ anchors.centerIn: parent
+ font.pointSize: 60
+ style: Text.Outline
+ styleColor: "green"
+ }
+
+ ShaderEffectSource {
+ id: effSource
+ sourceItem: effText
+ hideSource: true
+ }
+
+ ShaderEffect {
+ SequentialAnimation on scale {
+ loops: Animation.Infinite
+ NumberAnimation { from: 1.0; to: 2.0; duration: 1000; easing.type: Easing.InCirc }
+ PauseAnimation { duration: 1000 }
+ NumberAnimation { from: 2.0; to: 0.5; duration: 1000; easing.type: Easing.OutExpo }
+ NumberAnimation { from: 0.5; to: 1.0; duration: 500 }
+ PauseAnimation { duration: 1000 }
+ }
+ width: effText.width
+ height: effText.height
+ anchors.centerIn: parent
+ property variant source: effSource
+ property real amplitude: 0.002
+ property real frequency: 10
+ property real time: 0
+ NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 1000 }
+ fragmentShader:
+ "uniform lowp float qt_Opacity;" +
+ "uniform highp float amplitude;" +
+ "uniform highp float frequency;" +
+ "uniform highp float time;" +
+ "uniform sampler2D source;" +
+ "varying highp vec2 qt_TexCoord0;" +
+ "void main() {" +
+ " highp vec2 p = sin(time + frequency * qt_TexCoord0);" +
+ " gl_FragColor = texture2D(source, qt_TexCoord0 + amplitude * vec2(p.y, -p.x)) * qt_Opacity;" +
+ "}"
+ }
+}
diff --git a/examples/quick/quickwidgets/quickwidgets.pro b/examples/quick/quickwidgets/quickwidgets.pro
index 07192b6696..be932f33d0 100644
--- a/examples/quick/quickwidgets/quickwidgets.pro
+++ b/examples/quick/quickwidgets/quickwidgets.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = quickwidget
+SUBDIRS = quickwidget \
+ qquickviewcomparison
diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
index 1f87412aa4..de023ff95c 100644
--- a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
+++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc
@@ -50,54 +50,40 @@
in the QML file and this value is used by the OpenGL shader
program that draws the squircles.
+ \snippet scenegraph/openglunderqml/squircle.h 2
+
+ First of all, we need an object we can expose to QML. This is a
+ subclass of QQuickItem so we can easily access \l QQuickItem::window().
+
\snippet scenegraph/openglunderqml/squircle.h 1
- First of all, we need a QObject with a slot to connect the signals
- to. We subclass QQuickItem in order to use the \l
- QQuickItem::window() which holds the window instance we want to
- connect to.
-
- We use two values of \c t. The variable \c m_t is the property
- value as it exists in the GUI thread. The \c m_thread_t value is a
- copy of \c m_t for use in the rendering thread. We need an
- explicit copy because the scene graph can render in one thread
- while updating properties on the GUI thread in preparation for the
- next frame. If we had used only one value, the animation could
- have updated the value to that of the next frame before we got a
- chance to render it.
-
- \note In this example, a wrong value for \c t will have minimal
- consequences, but we emphasize that rendering and GUI thread
- objects and values must stay separate to avoid race conditions,
- undesired behavior and in the worst case, crashes.
+ Then we need an object to take care of the rendering. This
+ instance needs to be separated from the QQuickItem because the
+ item lives in the GUI thread and the rendering potentially happens
+ on the render thread. Since we want to connect to \l
+ QQuickWindow::beforeRendering(), we make the renderer a QObject.
+ The renderer contains a copy of all the state it needs,
+ independent of the GUI thread.
+
+ \note Don't be tempted to merge the two objects into
+ one. QQuickItems may be deleted on the GUI thread while the render
+ thread is rendering.
Lets move on to the implementation.
\snippet scenegraph/openglunderqml/squircle.cpp 7
The constructor of the \c Squircle class simply initializes the
- values. The shader program will be initialized during rendering
- later.
-
- \snippet scenegraph/openglunderqml/squircle.cpp 8
-
- The property setter checks that the value has indeed changed
- before updating its internal variable. It then calls \l
- QQuickWindow::update() which will trigger another frame to be
- rendered. Note that the setter might be called during
- initialization, before the object has been entered into the scene
- and before it has a window.
+ values and connects to the window changed signal which we will use
+ to prepare our renderer.
\snippet scenegraph/openglunderqml/squircle.cpp 1
- \snippet scenegraph/openglunderqml/squircle.cpp 2
- For our paint function to be called, we need to connect to the
- window's signals. When Squircle object is populated into the
- scene, the windowChanged signal is emitted. In our handler,
- we connect \l QQuickWindow::beforeRendering() to
- \c paint() to do the rendering, and \l
- QQuickWindow::beforeSynchronizing() to \c sync() to copy the state
- of the \c t property for the upcoming frame.
+ Once we have a window, we attach to the \l
+ QQuickWindow::beforeSynchronizing() signal which we will use to
+ create the renderer and to copy state into it safely. We also
+ connect to the \l QQuickWindow::sceneGraphInvalidated() signal to
+ handle the cleanup of the renderer.
\note Since the Squircle object has affinity to the GUI thread and
the signals are emitted from the rendering thread, it is crucial
@@ -113,18 +99,35 @@
graph, we need to turn this clearing off. This means that we need
to clear ourselves in the \c paint() function.
- \snippet scenegraph/openglunderqml/squircle.cpp 4
+ \snippet scenegraph/openglunderqml/squircle.cpp 9
+
+ We use the \c sync() function to initialize the renderer and to
+ copy the state in our item into the renderer. When the renderer is
+ created, we also connect the \l QQuickWindow::beforeRendering() to
+ the renderer's \c paint() slot.
- The first thing we do in the \c paint() function is to
- initialize the shader program. By initializing the shader program
- here, we make sure that the OpenGL context is bound and that we
- are on the correct thread.
+ \note The \l QQuickWindow::beforeSynchronizing() signal is emitted
+ on the rendering thread while the GUI thread is blocked, so it is
+ safe to simply copy the value without any additional protection.
- We also connect to the QOpenGLContext::aboutToBeDestroyed()
- signal, so that we can clean up the shader program when the
- context is destroyed. Again, this is a \l Qt::DirectConnection as
- all rendering related operations must happen on the rendering
- thread.
+ \snippet scenegraph/openglunderqml/squircle.cpp 6
+
+ In the \c cleanup() function we delete the renderer which in turn
+ cleans up its own resources.
+
+ \snippet scenegraph/openglunderqml/squircle.cpp 8
+
+ When the value of \c t changes, we call \l QQuickWindow::update()
+ rather than \l QQuickItem::update() because the former will force
+ the entire window to be redrawn, even when the scene graph has not
+ changed since the last frame.
+
+ \snippet scenegraph/openglunderqml/squircle.cpp 4
+
+ In the SquircleRenderer's \c paint() function we start by
+ initializing the shader program. By initializing the shader
+ program here, we make sure that the OpenGL context is bound and
+ that we are on the correct thread.
\snippet scenegraph/openglunderqml/squircle.cpp 5
@@ -133,18 +136,10 @@
attributes we used so that the OpenGL context is in a "clean"
state for the scene graph to pick it up.
- \snippet scenegraph/openglunderqml/squircle.cpp 6
-
- In the \c cleanup() function we delete the program.
-
- \snippet scenegraph/openglunderqml/squircle.cpp 9
-
- We use the \c sync() function to copy the state of the
- object in the GUI thread into the rendering thread.
-
- The signal is emitted on the rendering thread while the GUI
- thread is blocked, so it is safe to simply copy the value without
- any additional protection.
+ \note If tracking the changes in the OpenGL context's state is not
+ feasible, one can use the function \l
+ QQuickWindow::resetOpenGLState() which will reset all state that
+ the scene graph relies on.
\snippet scenegraph/openglunderqml/main.cpp 1
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp
index 5be12e6b62..9f8a27ac12 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.cpp
+++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp
@@ -47,9 +47,8 @@
//! [7]
Squircle::Squircle()
- : m_program(0)
- , m_t(0)
- , m_thread_t(0)
+ : m_t(0)
+ , m_renderer(0)
{
connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
}
@@ -71,24 +70,46 @@ void Squircle::setT(qreal t)
void Squircle::handleWindowChanged(QQuickWindow *win)
{
if (win) {
-//! [1]
- // Connect the beforeRendering signal to our paint function.
- // Since this call is executed on the rendering thread it must be
- // a Qt::DirectConnection
-//! [2]
- connect(win, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
-//! [2]
-
+ connect(win, SIGNAL(sceneGraphInvalidated()), this, SLOT(cleanup()), Qt::DirectConnection);
+//! [1]
// If we allow QML to do the clearing, they would clear what we paint
// and nothing would show.
//! [3]
win->setClearBeforeRendering(false);
}
}
+//! [3]
+
+//! [6]
+void Squircle::cleanup()
+{
+ if (m_renderer) {
+ delete m_renderer;
+ m_renderer = 0;
+ }
+}
-//! [3] //! [4]
-void Squircle::paint()
+SquircleRenderer::~SquircleRenderer()
+{
+ delete m_program;
+}
+//! [6]
+
+//! [9]
+void Squircle::sync()
+{
+ if (!m_renderer) {
+ m_renderer = new SquircleRenderer();
+ connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
+ }
+ m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
+ m_renderer->setT(m_t);
+}
+//! [9]
+
+//! [4]
+void SquircleRenderer::paint()
{
if (!m_program) {
initializeOpenGLFunctions();
@@ -114,8 +135,6 @@ void Squircle::paint()
m_program->bindAttributeLocation("vertices", 0);
m_program->link();
- connect(window()->openglContext(), SIGNAL(aboutToBeDestroyed()),
- this, SLOT(cleanup()), Qt::DirectConnection);
}
//! [4] //! [5]
m_program->bind();
@@ -129,12 +148,9 @@ void Squircle::paint()
1, 1
};
m_program->setAttributeArray(0, GL_FLOAT, values, 2);
- m_program->setUniformValue("t", (float) m_thread_t);
+ m_program->setUniformValue("t", (float) m_t);
- qreal ratio = window()->devicePixelRatio();
- int w = int(ratio * window()->width());
- int h = int(ratio * window()->height());
- glViewport(0, 0, w, h);
+ glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());
glDisable(GL_DEPTH_TEST);
@@ -150,21 +166,3 @@ void Squircle::paint()
m_program->release();
}
//! [5]
-
-//! [6]
-void Squircle::cleanup()
-{
- if (m_program) {
- delete m_program;
- m_program = 0;
- }
-}
-//! [6]
-
-//! [9]
-void Squircle::sync()
-{
- m_thread_t = m_t;
-}
-//! [9]
-
diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h
index 203a174f3c..d557339155 100644
--- a/examples/quick/scenegraph/openglunderqml/squircle.h
+++ b/examples/quick/scenegraph/openglunderqml/squircle.h
@@ -46,11 +46,33 @@
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLFunctions>
+
+
//! [1]
-class Squircle : public QQuickItem, protected QOpenGLFunctions
+class SquircleRenderer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
+public:
+ SquircleRenderer() : m_t(0), m_program(0) { }
+ ~SquircleRenderer();
+ void setT(qreal t) { m_t = t; }
+ void setViewportSize(const QSize &size) { m_viewportSize = size; }
+
+public slots:
+ void paint();
+
+private:
+ QSize m_viewportSize;
+ qreal m_t;
+ QOpenGLShaderProgram *m_program;
+};
+//! [1]
+
+//! [2]
+class Squircle : public QQuickItem
+{
+ Q_OBJECT
Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
public:
@@ -63,19 +85,16 @@ signals:
void tChanged();
public slots:
- void paint();
- void cleanup();
void sync();
+ void cleanup();
private slots:
void handleWindowChanged(QQuickWindow *win);
private:
- QOpenGLShaderProgram *m_program;
-
qreal m_t;
- qreal m_thread_t;
+ SquircleRenderer *m_renderer;
};
-//! [1]
+//! [2]
#endif // SQUIRCLE_H