diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2009-08-25 06:18:02 (GMT) |
---|---|---|
committer | Kai Koehne <kai.koehne@nokia.com> | 2009-08-25 06:18:02 (GMT) |
commit | ab4269502cda34abef9fb52161405bd1f6172791 (patch) | |
tree | 764717934171fec0f1c49f45e9449e0d34d6ba7b | |
parent | d4c67f5293c0a6c7d7b586a401e1972b964d0c16 (diff) | |
parent | 8d5bd63dcbfc610128166f6d277680c9385aa665 (diff) | |
download | Qt-ab4269502cda34abef9fb52161405bd1f6172791.zip Qt-ab4269502cda34abef9fb52161405bd1f6172791.tar.gz Qt-ab4269502cda34abef9fb52161405bd1f6172791.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
55 files changed, 735 insertions, 373 deletions
diff --git a/demos/declarative/flickr/content/ImageDetails.qml b/demos/declarative/flickr/common/ImageDetails.qml index 8098273..8098273 100644 --- a/demos/declarative/flickr/content/ImageDetails.qml +++ b/demos/declarative/flickr/common/ImageDetails.qml diff --git a/demos/declarative/flickr/content/LikeOMeter.qml b/demos/declarative/flickr/common/LikeOMeter.qml index 754dbb1..754dbb1 100644 --- a/demos/declarative/flickr/content/LikeOMeter.qml +++ b/demos/declarative/flickr/common/LikeOMeter.qml diff --git a/demos/declarative/flickr/content/Loading.qml b/demos/declarative/flickr/common/Loading.qml index ff2c829..ff2c829 100644 --- a/demos/declarative/flickr/content/Loading.qml +++ b/demos/declarative/flickr/common/Loading.qml diff --git a/demos/declarative/flickr/content/MediaButton.qml b/demos/declarative/flickr/common/MediaButton.qml index 0ffd596..0ffd596 100644 --- a/demos/declarative/flickr/content/MediaButton.qml +++ b/demos/declarative/flickr/common/MediaButton.qml diff --git a/demos/declarative/flickr/content/MediaLineEdit.qml b/demos/declarative/flickr/common/MediaLineEdit.qml index 500a402..500a402 100644 --- a/demos/declarative/flickr/content/MediaLineEdit.qml +++ b/demos/declarative/flickr/common/MediaLineEdit.qml diff --git a/demos/declarative/flickr/content/Progress.qml b/demos/declarative/flickr/common/Progress.qml index 00ef901..00ef901 100644 --- a/demos/declarative/flickr/content/Progress.qml +++ b/demos/declarative/flickr/common/Progress.qml diff --git a/demos/declarative/flickr/common/RssModel.qml b/demos/declarative/flickr/common/RssModel.qml new file mode 100644 index 0000000..ed9fd5c --- /dev/null +++ b/demos/declarative/flickr/common/RssModel.qml @@ -0,0 +1,20 @@ +import Qt 4.6 + +XmlListModel { + property string tags : "" + + source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2" + query: "/rss/channel/item" + namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" + + XmlRole { name: "title"; query: "title/string()" } + XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } + XmlRole { name: "url"; query: "media:content/@url/string()" } + XmlRole { name: "description"; query: "description/string()" } + XmlRole { name: "tags"; query: "media:category/string()" } + XmlRole { name: "photoWidth"; query: "media:content/@width/string()" } + XmlRole { name: "photoHeight"; query: "media:content/@height/string()" } + XmlRole { name: "photoType"; query: "media:content/@type/string()" } + XmlRole { name: "photoAuthor"; query: "author/string()" } + XmlRole { name: "photoDate"; query: "pubDate/string()" } +} diff --git a/demos/declarative/flickr/content/ScrollBar.qml b/demos/declarative/flickr/common/ScrollBar.qml index 89d51e2..89d51e2 100644 --- a/demos/declarative/flickr/content/ScrollBar.qml +++ b/demos/declarative/flickr/common/ScrollBar.qml diff --git a/demos/declarative/flickr/content/Slider.qml b/demos/declarative/flickr/common/Slider.qml index b88636d..b88636d 100644 --- a/demos/declarative/flickr/content/Slider.qml +++ b/demos/declarative/flickr/common/Slider.qml diff --git a/demos/declarative/flickr/content/Star.qml b/demos/declarative/flickr/common/Star.qml index 006e86ad..006e86ad 100644 --- a/demos/declarative/flickr/content/Star.qml +++ b/demos/declarative/flickr/common/Star.qml diff --git a/demos/declarative/flickr/content/pics/background.png b/demos/declarative/flickr/common/pics/background.png Binary files differindex 5b37072..5b37072 100644 --- a/demos/declarative/flickr/content/pics/background.png +++ b/demos/declarative/flickr/common/pics/background.png diff --git a/demos/declarative/flickr/content/pics/button-pressed.png b/demos/declarative/flickr/common/pics/button-pressed.png Binary files differindex e434d32..e434d32 100644 --- a/demos/declarative/flickr/content/pics/button-pressed.png +++ b/demos/declarative/flickr/common/pics/button-pressed.png diff --git a/demos/declarative/flickr/content/pics/button-pressed.sci b/demos/declarative/flickr/common/pics/button-pressed.sci index d3b16e2..d3b16e2 100644 --- a/demos/declarative/flickr/content/pics/button-pressed.sci +++ b/demos/declarative/flickr/common/pics/button-pressed.sci diff --git a/demos/declarative/flickr/content/pics/button.png b/demos/declarative/flickr/common/pics/button.png Binary files differindex 56a63ce..56a63ce 100644 --- a/demos/declarative/flickr/content/pics/button.png +++ b/demos/declarative/flickr/common/pics/button.png diff --git a/demos/declarative/flickr/content/pics/button.sci b/demos/declarative/flickr/common/pics/button.sci index d3b16e2..d3b16e2 100644 --- a/demos/declarative/flickr/content/pics/button.sci +++ b/demos/declarative/flickr/common/pics/button.sci diff --git a/demos/declarative/flickr/content/pics/ghns_star.png b/demos/declarative/flickr/common/pics/ghns_star.png Binary files differindex 4ad43cc..4ad43cc 100644 --- a/demos/declarative/flickr/content/pics/ghns_star.png +++ b/demos/declarative/flickr/common/pics/ghns_star.png diff --git a/demos/declarative/flickr/content/pics/loading.png b/demos/declarative/flickr/common/pics/loading.png Binary files differindex 47a1589..47a1589 100644 --- a/demos/declarative/flickr/content/pics/loading.png +++ b/demos/declarative/flickr/common/pics/loading.png diff --git a/demos/declarative/flickr/content/pics/reflection.png b/demos/declarative/flickr/common/pics/reflection.png Binary files differindex c143a48..c143a48 100644 --- a/demos/declarative/flickr/content/pics/reflection.png +++ b/demos/declarative/flickr/common/pics/reflection.png diff --git a/demos/declarative/flickr/content/pics/shadow-bottom.png b/demos/declarative/flickr/common/pics/shadow-bottom.png Binary files differindex 523f6e7..523f6e7 100644 --- a/demos/declarative/flickr/content/pics/shadow-bottom.png +++ b/demos/declarative/flickr/common/pics/shadow-bottom.png diff --git a/demos/declarative/flickr/content/pics/shadow-corner.png b/demos/declarative/flickr/common/pics/shadow-corner.png Binary files differindex ef8c856..ef8c856 100644 --- a/demos/declarative/flickr/content/pics/shadow-corner.png +++ b/demos/declarative/flickr/common/pics/shadow-corner.png diff --git a/demos/declarative/flickr/content/pics/shadow-right-screen.png b/demos/declarative/flickr/common/pics/shadow-right-screen.png Binary files differindex 9856c4f..9856c4f 100644 --- a/demos/declarative/flickr/content/pics/shadow-right-screen.png +++ b/demos/declarative/flickr/common/pics/shadow-right-screen.png diff --git a/demos/declarative/flickr/content/pics/shadow-right.png b/demos/declarative/flickr/common/pics/shadow-right.png Binary files differindex f534a35..f534a35 100644 --- a/demos/declarative/flickr/content/pics/shadow-right.png +++ b/demos/declarative/flickr/common/pics/shadow-right.png diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr-desktop.qml index d8a27d5..5effc42 100644 --- a/demos/declarative/flickr/flickr.qml +++ b/demos/declarative/flickr/flickr-desktop.qml @@ -1,6 +1,6 @@ import Qt 4.6 -import "content" +import "common" Item { id: MainWindow; width: 800; height: 450 @@ -8,25 +8,6 @@ Item { property bool showPathView : false resources: [ - XmlListModel { - id: FeedModel - property string tags : TagsEdit.text - source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2" - query: "/rss/channel/item" - namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" - - XmlRole { name: "title"; query: "title/string()" } - XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } - XmlRole { name: "url"; query: "media:content/@url/string()" } - XmlRole { name: "description"; query: "description/string()" } - XmlRole { name: "tags"; query: "media:category/string()" } - XmlRole { name: "photoWidth"; query: "media:content/@width/string()" } - XmlRole { name: "photoHeight"; query: "media:content/@height/string()" } - XmlRole { name: "photoType"; query: "media:content/@type/string()" } - XmlRole { name: "photoAuthor"; query: "author/string()" } - XmlRole { name: "photoDate"; query: "pubDate/string()" } - }, - Component { id: PhotoDelegate Item { @@ -72,9 +53,9 @@ Item { Item { id: Shadows - Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height } - Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width } - Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height } + Image { source: "common/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height } + Image { source: "common/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width } + Image { id: Corner; source: "common/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height } } } @@ -123,17 +104,17 @@ Item { anchors.fill: parent - Image { source: "content/pics/background.png"; anchors.fill: parent } - - Loading { anchors.centerIn: parent; visible: FeedModel.status } + Image { source: "common/pics/background.png"; anchors.fill: parent } + RssModel { id: RssModel; tags : TagsEdit.text } + Loading { anchors.centerIn: parent; visible: RssModel.status } GridView { - id: PhotoGridView; model: FeedModel; delegate: PhotoDelegate; cacheBuffer: 100 + id: PhotoGridView; model: RssModel; delegate: PhotoDelegate; cacheBuffer: 100 cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1 } PathView { - id: PhotoPathView; model: FeedModel; delegate: PhotoDelegate + id: PhotoPathView; model: RssModel; delegate: PhotoDelegate y: -380; width: 800; height: 330; pathItemCount: 10; z: 1 path: Path { startX: -50; startY: 40; @@ -175,7 +156,7 @@ Item { text: "Update" anchors.right: ViewModeButton.left; anchors.rightMargin: 5 anchors.top: ViewModeButton.top - onClicked: { FeedModel.reload(); } + onClicked: { RssModel.reload(); } } MediaLineEdit { @@ -205,7 +186,7 @@ Item { Text { id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15; text: "Flickr - " + - (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags) + (RssModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + RssModel.tags) font.pointSize: 20; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" } } diff --git a/demos/declarative/flickr/flickr-mobile.qml b/demos/declarative/flickr/flickr-mobile.qml new file mode 100644 index 0000000..a4692a3 --- /dev/null +++ b/demos/declarative/flickr/flickr-mobile.qml @@ -0,0 +1,51 @@ +import Qt 4.6 +import "common" as Common +import "mobile" as Mobile + +Item { + id: Screen; width: 320; height: 480 + property bool inListView : false + + Rectangle { + id: Background + anchors.fill: parent; color: "#343434"; + + Image { source: "mobile/images/stripes.png"; fillMode: "Tile"; anchors.fill: parent; opacity: 0.3 } + + Common.RssModel { id: RssModel } + Common.Loading { anchors.centerIn: parent; visible: RssModel.status } + + Item { + id: Views + x: 2; width: parent.width - 4 + anchors.top: TitleBar.bottom; anchors.bottom: ToolBar.top + + Mobile.GridDelegate { id: GridDelegate } + GridView { + id: PhotoGridView; model: RssModel; delegate: GridDelegate; cacheBuffer: 100 + cellWidth: 79; cellHeight: 79; width: parent.width; height: parent.height - 1 + } + + Mobile.ListDelegate { id: ListDelegate } + ListView { + id: PhotoListView; model: RssModel; delegate: ListDelegate + width: parent.width; height: parent.height; x: -(parent.width * 1.5); cacheBuffer: 100; + } + } + + Common.ImageDetails { id: ImageDetails; width: parent.width; x: parent.width; height: parent.height } + Mobile.TitleBar { id: TitleBar; width: parent.width; height: 40; opacity: 0.9 } + Mobile.ToolBar { id: ToolBar; height: 40; anchors.bottom: parent.bottom; width: parent.width; opacity: 0.9 } + + states: [ + State { + name: "ListView"; when: Screen.inListView == true + PropertyChanges { target: PhotoListView; x: 0 } + PropertyChanges { target: PhotoGridView; x: -(parent.width * 1.5) } + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x"; duration: 500; easing: "easeInOutQuad" } } + ] + } +} diff --git a/demos/declarative/flickr/flickr2.qml b/demos/declarative/flickr/flickr2.qml deleted file mode 100644 index d9b1f60..0000000 --- a/demos/declarative/flickr/flickr2.qml +++ /dev/null @@ -1,261 +0,0 @@ -import Qt 4.6 - -import "content" - -Item { - id: MainWindow; width: 800; height: 450 - - property bool showPathView : false - - VisualModel { - id: MyVisualModel - model: - XmlListModel { - id: FeedModel - property string tags : TagsEdit.text - source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2" - query: "/rss/channel/item" - namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";" - - XmlRole { name: "title"; query: "title/string()" } - XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" } - XmlRole { name: "url"; query: "media:content/@url/string()" } - XmlRole { name: "description"; query: "description/string()" } - XmlRole { name: "tags"; query: "media:category/string()" } - XmlRole { name: "photoWidth"; query: "media:content/@width/string()" } - XmlRole { name: "photoHeight"; query: "media:content/@height/string()" } - XmlRole { name: "photoType"; query: "media:content/@type/string()" } - XmlRole { name: "photoAuthor"; query: "author/string()" } - XmlRole { name: "photoDate"; query: "pubDate/string()" } - } - - delegate: Package { - Item { - id: Wrapper; width: 85; height: 85; scale: {1.0} - z: PathViewPackage.PathView.z - property real angle: 0 * 0 - - transform: [ - Rotation { - id: Rotation; origin.x: 30; axis.x: 30; axis.y: 60; axis.z: 0 - angle: Wrapper.angle - } - ] - - Connection { - sender: Background.imageDetails; signal: "closed()" - script: { if (Wrapper.state == 'Details') Wrapper.state = '' } - } - - Script { - function photoClicked() { - Background.imageDetails.photoTitle = title; - Background.imageDetails.photoDescription = description; - Background.imageDetails.photoTags = tags; - Background.imageDetails.photoWidth = photoWidth; - Background.imageDetails.photoHeight = photoHeight; - Background.imageDetails.photoType = photoType; - Background.imageDetails.photoAuthor = photoAuthor; - Background.imageDetails.photoDate = photoDate; - Background.imageDetails.photoUrl = url; - Background.imageDetails.rating = 0; - Wrapper.state = "Details"; - } - } - - Rectangle { - id: WhiteRect; anchors.fill: parent; color: "white"; radius: 5 - - Loading { x: 26; y: 26; visible: Thumb.status!=1 } - Image { id: Thumb; source: imagePath; x: 5; y: 5 } - - Item { - id: Shadows - Image { source: "content/pics/shadow-right.png"; x: WhiteRect.width; height: WhiteRect.height } - Image { source: "content/pics/shadow-bottom.png"; y: WhiteRect.height; width: WhiteRect.width } - Image { id: Corner; source: "content/pics/shadow-corner.png"; x: WhiteRect.width; y: WhiteRect.height } - } - } - - MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } } - - states: [ - State { - name: "Details" - PropertyChanges { target: Background.imageDetails; z: 2 } - ParentChange { target: Wrapper; parent: Background.imageDetails.frontContainer } - PropertyChanges { target: Wrapper; x: 45; y: 35; scale: 1; z: 1000 } - PropertyChanges { target: Rotation; angle: 0 } - PropertyChanges { target: Shadows; opacity: 0 } - PropertyChanges { target: Background.imageDetails; y: 20 } - PropertyChanges { target: PhotoGridView; y: "-480" } - PropertyChanges { target: PhotoPathView; y: "-480" } - PropertyChanges { target: ViewModeButton; opacity: 0 } - PropertyChanges { target: TagsEdit; opacity: 0 } - PropertyChanges { target: FetchButton; opacity: 0 } - PropertyChanges { target: CategoryText; y: "-50" } - } - ] - - transitions: [ - Transition { - from: "*"; to: "Details" - ParentAction { } - NumberAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } - }, - Transition { - from: "Details"; to: "*" - SequentialAnimation { - ParentAction { } - NumberAnimation { properties: "x,y,scale,opacity,angle"; duration: 500; easing: "easeInOutQuad" } - PropertyAction { target: Wrapper; properties: "z" } - } - } - ] - } - - Item { - Package.name: "pathView" - id: PathViewPackage; width: 85; height: 85 - } - - Item { - Package.name: "gridView" - id: GridViewPackage; width: 85; height: 85 - } - - Item { - id: MyItem - state: MainWindow.showPathView ? "pathView" : "gridView" - states: [ - State { - name: "gridView" - PropertyChanges { target: Wrapper; explicit: true; property: "moveToParent"; value: GridViewPackage } - }, - State { - name: "pathView" - PropertyChanges { target: Wrapper; scale: PathViewPackage.PathView.scale; angle: PathViewPackage.PathView.angle; } - PropertyChanges { target: Wrapper; explicit: true; moveToParent: PathViewPackage } - } - ] - transitions: [ - Transition { - to: "pathView" - SequentialAnimation { - PropertyAction { target: Wrapper; property: "moveToParent" } - ParallelAnimation { - NumberAnimation { - target: Wrapper - properties: "x,y" - to: 0 - easing: "easeOutQuad" - duration: 350 - } - NumberAnimation { target: Wrapper; properties: "scale,angle"; duration: 350 } - } - } - }, - Transition { - to: "gridView" - SequentialAnimation { - PauseAnimation { duration: Math.floor(index/7)*100 } - PropertyAction { target: Wrapper; property: "moveToParent" } - ParallelAnimation { - NumberAnimation { - target: Wrapper - properties: "x,y" - to: 0 - easing: "easeOutQuad" - duration: 250 - } - NumberAnimation { target: Wrapper; properties: "scale,angle"; duration: 250 } - } - } - } - ] - } - } - } - - - Item { - id: Background - property var imageDetails: ImageDetails - - Image { source: "content/pics/background.png" } - - GridView { - id: PhotoGridView; model: MyVisualModel.parts.gridView - cellWidth: 105; cellHeight: 105; x:32; y: 80; width: 800; height: 330; z: 1 - cacheBuffer: 100 - } - - PathView { - id: PhotoPathView; model: MyVisualModel.parts.pathView - y: 80; width: 800; height: 330; z: 1 - pathItemCount: 10; snapPosition: 0.001 - path: Path { - startX: -150; startY: 40; - - PathAttribute { name: "scale"; value: 0.9 } - PathAttribute { name: "angle"; value: -45 } - PathPercent { value: 0 } - PathLine { x: -50; y: 40 } - - PathPercent { value: 0.001 } - - PathCubic { - x: 400; y: 220 - control1X: 140; control1Y: 40 - control2X: 210; control2Y: 220 - } - - PathAttribute { name: "scale"; value: 1.2 } - PathAttribute { name: "z"; value: 1 } - PathAttribute { name: "angle"; value: 0 } - - PathCubic { - x: 850; y: 40 - control2X: 660; control2Y: 40 - control1X: 590; control1Y: 220 - } - - PathPercent { value: 0.999 } - PathLine { x: 950; y: 40 } - PathPercent { value: 1.0 } - PathAttribute { name: "scale"; value: 0.9 } - PathAttribute { name: "angle"; value: 45 } - } - } - - ImageDetails { id: ImageDetails; width: 750; x: 25; y: 500; height: 410 } - - MediaButton { - id: ViewModeButton; x: 680; y: 410; text: "View Mode" - onClicked: { if (MainWindow.showPathView == true) MainWindow.showPathView = false; else MainWindow.showPathView = true } - } - - MediaButton { - id: FetchButton - text: "Update" - anchors.right: ViewModeButton.left; anchors.rightMargin: 5 - anchors.top: ViewModeButton.top - onClicked: { FeedModel.reload(); } - } - - MediaLineEdit { - id: TagsEdit; - label: "Tags" - anchors.right: FetchButton.left; anchors.rightMargin: 5 - anchors.top: ViewModeButton.top - } - - } - - Text { - id: CategoryText; anchors.horizontalCenter: parent.horizontalCenter; y: 15; - text: "Flickr - " + - (FeedModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + FeedModel.tags) - font.pointSize: 16; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" - } -} diff --git a/demos/declarative/flickr/mobile/Button.qml b/demos/declarative/flickr/mobile/Button.qml new file mode 100644 index 0000000..275408c --- /dev/null +++ b/demos/declarative/flickr/mobile/Button.qml @@ -0,0 +1,41 @@ +import Qt 4.6 + +Item { + id: Container + + signal clicked + + property string text + + BorderImage { + id: Image + source: "images/toolbutton2.sci" + width: Container.width; height: Container.height + } + BorderImage { + id: Pressed + opacity: 0 + source: "images/toolbutton2.sci" + width: Container.width; height: Container.height + } + MouseRegion { + id: MouseRegion + anchors.fill: Image + onClicked: { Container.clicked(); } + } + Text { + color: "white" + anchors.centerIn: Image; font.bold: true + text: Container.text; style: "Raised"; styleColor: "black" + } + states: [ + State { + name: "Pressed" + when: MouseRegion.pressed == true + PropertyChanges { + target: Pressed + opacity: 1 + } + } + ] +} diff --git a/demos/declarative/flickr/mobile/GridDelegate.qml b/demos/declarative/flickr/mobile/GridDelegate.qml new file mode 100644 index 0000000..8090cd4 --- /dev/null +++ b/demos/declarative/flickr/mobile/GridDelegate.qml @@ -0,0 +1,74 @@ + import Qt 4.6 + + Component { + id: PhotoDelegate + Item { + id: Wrapper; width: 79; height: 79 + + Script { + function photoClicked() { + ImageDetails.photoTitle = title; + ImageDetails.photoDescription = description; + ImageDetails.photoTags = tags; + ImageDetails.photoWidth = photoWidth; + ImageDetails.photoHeight = photoHeight; + ImageDetails.photoType = photoType; + ImageDetails.photoAuthor = photoAuthor; + ImageDetails.photoDate = photoDate; + ImageDetails.photoUrl = url; + ImageDetails.rating = 0; + ScaleMe.state = "Details"; + } + } + + Item { + anchors.centerIn: parent + scale: 0.0 + scale: Behavior { NumberAnimation { easing: "easeInOutQuad"} } + id: ScaleMe + + Rectangle { height: 79; width: 79; id: BlackRect; anchors.centerIn: parent; color: "black"; smooth: true } + Rectangle { + id: WhiteRect; width: 77; height: 77; anchors.centerIn: parent; color: "#dddddd"; smooth: true + Image { id: Thumb; source: imagePath; x: 1; y: 1; smooth: true} + Image { source: "mobile/images/gloss.png"; smooth: true} + } + + Connection { + sender: ToolBar.button2; signal: "clicked()" + script: if (ScaleMe.state == 'Details' ) ScaleMe.state = 'Show'; + } + + states: [ + State { + name: "Show"; when: Thumb.status == 1 + PropertyChanges { target: ScaleMe; scale: 1 } + }, + State { + name: "Details"; extend: "Show" + ParentChange { target: Wrapper; parent: ImageDetails.frontContainer } + PropertyChanges { target: Wrapper; x: 20; y: 60 } + PropertyChanges { target: ImageDetails; x: 0 } + PropertyChanges { target: Views; x: -parent.width } + PropertyChanges { target: ToolBar.button2; text: "Back" } + } + ] + transitions: [ + Transition { + from: "Show"; to: "Details" + ParentAction { } + NumberAnimation { properties: "x,y,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + }, + Transition { + from: "Details"; to: "Show" + SequentialAnimation { + ParentAction { } + NumberAnimation { properties: "x,y,opacity,angle"; duration: 500; easing: "easeInOutQuad" } + PropertyAction { target: Wrapper; properties: "z" } + } + } + ] + } + MouseRegion { anchors.fill: Wrapper; onClicked: { photoClicked() } } + } + } diff --git a/demos/declarative/flickr/mobile/ListDelegate.qml b/demos/declarative/flickr/mobile/ListDelegate.qml new file mode 100644 index 0000000..b9ec7f2 --- /dev/null +++ b/demos/declarative/flickr/mobile/ListDelegate.qml @@ -0,0 +1,24 @@ +import Qt 4.6 + +Component { + id: ListDelegate + Item { + id: Wrapper; width: Wrapper.ListView.view.width; height: 86 + Item { + id: MoveMe + Rectangle { color: "black"; opacity: Wrapper.ListView.index % 2 ? 0.2 : 0.3; height: 84; width: Wrapper.width; y: 1 } + Rectangle { + id: WhiteRect; x: 6; y: 4; width: 77; height: 77; color: "white"; smooth: true + + Image { id: Thumb; source: imagePath; x: 1; y: 1 } + Image { source: "images/gloss.png" } + } + Column { + x: 92; width: Wrapper.ListView.view.width - 95; y: 15; spacing: 2 + Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: "ElideRight"; style: "Raised"; styleColor: "black" } + Text { text: photoAuthor; color: "white"; width: parent.width; elide: "ElideLeft"; color: "#cccccc"; style: "Raised"; styleColor: "black" } + Text { text: photoDate; color: "white"; width: parent.width; elide: "ElideRight"; color: "#cccccc"; style: "Raised"; styleColor: "black" } + } + } + } +} diff --git a/demos/declarative/flickr/mobile/TitleBar.qml b/demos/declarative/flickr/mobile/TitleBar.qml new file mode 100644 index 0000000..59b8365 --- /dev/null +++ b/demos/declarative/flickr/mobile/TitleBar.qml @@ -0,0 +1,74 @@ +import Qt 4.6 + +Item { + id: TitleBar + + BorderImage { source: "images/titlebar2.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Item { + id: Container + width: (parent.width * 2) - 55 ; height: parent.height + + Script { + function accept() { + RssModel.tags = Editor.text + TitleBar.state = "" + } + } + + Text { + id: CategoryText + anchors.left: parent.left; anchors.right: TagButton.left + anchors.leftMargin: 10; anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + elide: "ElideLeft" + text: (RssModel.tags=="" ? "Uploads from everyone" : "Recent Uploads tagged " + RssModel.tags) + font.pointSize: 10; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + } + + Button { + id: TagButton; x: TitleBar.width - 50; y: 3; width: 45; height: 32; text: "..." + onClicked: if (TitleBar.state == "Tags") accept(); else TitleBar.state = "Tags" + } + + Item { + id: LineEdit + anchors.left: TagButton.right; anchors.leftMargin: 5; y: 4 + anchors.right: parent.right; anchors.rightMargin: 5; height: parent.height - 9 + BorderImage { source: "images/lineedit.sci"; anchors.fill: parent } + + TextInput { + id: Editor + anchors.left: parent.left; anchors.right: parent.right + anchors.leftMargin: 10; anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + cursorVisible: true; font.bold: true + color: "#151515"; highlightColor: "green" + } + KeyProxy { + id: Proxy + anchors.fill: parent + targets: [(ReturnKey), (Editor)] + } + Item { + id: ReturnKey + Keys.onReturnPressed: accept() + Keys.onEscapePressed: TitleBar.state = "" + } + } + } + states: [ + State { + name: "Tags" + PropertyChanges { target: Container; x: -TagButton.x + 5 } + PropertyChanges { target: TagButton; text: "OK" } + PropertyChanges { target: Proxy; focus: true } + } + ] + transitions: [ + Transition { + from: "*"; to: "*" + NumberAnimation { properties: "x"; easing: "easeInOutQuad" } + } + ] +} diff --git a/demos/declarative/flickr/mobile/ToolBar.qml b/demos/declarative/flickr/mobile/ToolBar.qml new file mode 100644 index 0000000..aa78c52 --- /dev/null +++ b/demos/declarative/flickr/mobile/ToolBar.qml @@ -0,0 +1,23 @@ +import Qt 4.6 + +Item { + id: Toolbar + property var button2: Button2 + + BorderImage { source: "images/titlebar2.sci"; width: parent.width; height: parent.height + 14; y: -7 } + + Button { anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32; text: "Update"; onClicked: RssModel.reload() } + + Button { + id: Button2 + anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32; text: "View mode" + onClicked: { + if (Button2.text == "View mode") { + if (Screen.inListView == true) + Screen.inListView = false; + else + Screen.inListView = true + } + } + } +} diff --git a/demos/declarative/flickr/mobile/images/gloss.png b/demos/declarative/flickr/mobile/images/gloss.png Binary files differnew file mode 100644 index 0000000..5d370cd --- /dev/null +++ b/demos/declarative/flickr/mobile/images/gloss.png diff --git a/demos/declarative/flickr/mobile/images/lineedit.png b/demos/declarative/flickr/mobile/images/lineedit.png Binary files differnew file mode 100644 index 0000000..2cc38dc --- /dev/null +++ b/demos/declarative/flickr/mobile/images/lineedit.png diff --git a/demos/declarative/flickr/mobile/images/lineedit.sci b/demos/declarative/flickr/mobile/images/lineedit.sci new file mode 100644 index 0000000..7c5ec6c --- /dev/null +++ b/demos/declarative/flickr/mobile/images/lineedit.sci @@ -0,0 +1,5 @@ +gridLeft: 10 +gridTop: 10 +gridBottom: 10 +gridRight: 10 +imageFile: lineedit.png diff --git a/demos/declarative/flickr/mobile/images/stripes.png b/demos/declarative/flickr/mobile/images/stripes.png Binary files differnew file mode 100644 index 0000000..9f36727 --- /dev/null +++ b/demos/declarative/flickr/mobile/images/stripes.png diff --git a/demos/declarative/flickr/mobile/images/titlebar2.png b/demos/declarative/flickr/mobile/images/titlebar2.png Binary files differnew file mode 100644 index 0000000..51c9008 --- /dev/null +++ b/demos/declarative/flickr/mobile/images/titlebar2.png diff --git a/demos/declarative/flickr/mobile/images/titlebar2.sci b/demos/declarative/flickr/mobile/images/titlebar2.sci new file mode 100644 index 0000000..e8fc2d1 --- /dev/null +++ b/demos/declarative/flickr/mobile/images/titlebar2.sci @@ -0,0 +1,5 @@ +gridLeft: 22 +gridTop: 10 +gridBottom: 10 +gridRight: 22 +imageFile: titlebar2.png diff --git a/demos/declarative/flickr/mobile/images/toolbutton2.png b/demos/declarative/flickr/mobile/images/toolbutton2.png Binary files differnew file mode 100644 index 0000000..8862898 --- /dev/null +++ b/demos/declarative/flickr/mobile/images/toolbutton2.png diff --git a/demos/declarative/flickr/mobile/images/toolbutton2.sci b/demos/declarative/flickr/mobile/images/toolbutton2.sci new file mode 100644 index 0000000..e3118b0 --- /dev/null +++ b/demos/declarative/flickr/mobile/images/toolbutton2.sci @@ -0,0 +1,5 @@ +gridLeft: 15 +gridTop: 4 +gridBottom: 4 +gridRight: 15 +imageFile: toolbutton2.png diff --git a/demos/declarative/samegame/SameGame.qml b/demos/declarative/samegame/SameGame.qml index d476e8b..0da5679 100644 --- a/demos/declarative/samegame/SameGame.qml +++ b/demos/declarative/samegame/SameGame.qml @@ -1,34 +1,57 @@ import Qt 4.6 - import "content" Rectangle { - id: page; width: 460; height: 700; color: activePalette.window + id: Screen + width: 490; height: 720 + Script { source: "content/samegame.js" } + SystemPalette { id: activePalette; colorGroup: Qt.Active } - Rectangle { - id: gameCanvas - property int score: 0 - z:20; y:20; color: "white"; border.width: 1 - width:parent.width - tileSize - (parent.width % tileSize); - height:parent.height - tileSize - (parent.height % tileSize); - anchors.horizontalCenter: parent.horizontalCenter - Image { id:background; - source: "content/pics/background.png" - anchors.fill: parent + + Item { + width: parent.width; anchors.top: parent.top; anchors.bottom: ToolBar.top + + Image { + id: background + anchors.fill: parent; source: "content/pics/background.png" + fillMode: "PreserveAspectCrop" } - MouseRegion { id: gameMR - anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y); + + Item { + id: gameCanvas + property int score: 0 + + z: 20; anchors.centerIn: parent + width: parent.width - (parent.width % tileSize); + height: parent.height - (parent.height % tileSize); + + MouseRegion { + id: gameMR + anchors.fill: parent; onClicked: handleClick(mouse.x,mouse.y); + } } } - Dialog { id: dialog; anchors.centerIn: parent; z: 21} - Button { - id: btnA; text: "New Game"; onClicked: {initBoard();} - anchors.top: gameCanvas.bottom; anchors.topMargin: 4; anchors.left: gameCanvas.left; - } - Text { - text: "Score: " + gameCanvas.score; width:100; font.pointSize:14 - anchors.top: gameCanvas.bottom; anchors.topMargin: 4; anchors.right: gameCanvas.right; + Dialog { id: dialog; anchors.centerIn: parent; z: 21 } + + Rectangle { + id: ToolBar + color: activePalette.window + height: 32; width: parent.width + anchors.bottom: Screen.bottom + + Button { + id: btnA; text: "New Game"; onClicked: {initBoard();} + anchors.left: parent.left; anchors.leftMargin: 3 + anchors.verticalCenter: parent.verticalCenter + } + + Text { + id: Score + text: "Score: " + gameCanvas.score; font.bold: true + anchors.right: parent.right; anchors.rightMargin: 3 + anchors.verticalCenter: parent.verticalCenter + } } } diff --git a/demos/declarative/samegame/content/Button.qml b/demos/declarative/samegame/content/Button.qml index 70b175c..2354218 100644 --- a/demos/declarative/samegame/content/Button.qml +++ b/demos/declarative/samegame/content/Button.qml @@ -1,18 +1,25 @@ import Qt 4.6 -Rectangle { - id: page; color: activePalette.button; width: txtItem.width+20; height: txtItem.height+4 - border.width: 1; border.color: activePalette.mid; radius: 10; +Rectangle { + id: Container + signal clicked property string text: "Button" - gradient: Gradient { - GradientStop { id:topGrad; position: 0.0; - color: if(mr.pressed){activePalette.dark;}else{activePalette.light;}} + + color: activePalette.button; smooth: true + width: txtItem.width + 20; height: txtItem.height + 6 + border.width: 1; border.color: activePalette.darker(activePalette.button); radius: 8; + + gradient: Gradient { + GradientStop { + id: topGrad; position: 0.0 + color: if (mr.pressed) { activePalette.dark } else { activePalette.light } } GradientStop { position: 1.0; color: activePalette.button } } - MouseRegion { id:mr; anchors.fill: parent; onClicked: page.clicked() } + + MouseRegion { id: mr; anchors.fill: parent; onClicked: Container.clicked() } + Text { - id: txtItem; text: page.text; anchors.centerIn: page; color: activePalette.buttonText - font.pointSize: 14; + id: txtItem; text: Container.text; anchors.centerIn: Container; color: activePalette.buttonText } } diff --git a/demos/declarative/samegame/content/Dialog.qml b/demos/declarative/samegame/content/Dialog.qml index a3c5f33..72c7900 100644 --- a/demos/declarative/samegame/content/Dialog.qml +++ b/demos/declarative/samegame/content/Dialog.qml @@ -2,7 +2,7 @@ import Qt 4.6 Rectangle { id: page - color: "white"; border.width: 1; width: 200; height: 60; + color: "white"; border.width: 1; width: MyText.width + 20; height: 60; property string text: "Hello World!" opacity: 0 opacity: Behavior { @@ -11,5 +11,5 @@ Rectangle { NumberAnimation {property: "opacity"; to: 0; duration: 1500 } } } - Text { anchors.centerIn: parent; text: parent.text } + Text { id: MyText; anchors.centerIn: parent; text: parent.text } } diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index feb4e8c..7938dc9 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -299,6 +299,229 @@ void QFxContents::setItem(QFxItem *item) calcWidth(); } +/* + Key filters can be installed on a QFxItem, but not removed. Currently they + are only used by attached objects (which are only destroyed on Item + destruction), so this isn't a problem. If in future this becomes any form + of public API, they will have to support removal too. +*/ +class QFxItemKeyFilter +{ +public: + QFxItemKeyFilter(QFxItem * = 0); + virtual ~QFxItemKeyFilter(); + + virtual void keyPressed(QKeyEvent *event); + virtual void keyReleased(QKeyEvent *event); + +private: + QFxItemKeyFilter *m_next; +}; + +QFxItemKeyFilter::QFxItemKeyFilter(QFxItem *item) +: m_next(0) +{ + QFxItemPrivate *p = + item?static_cast<QFxItemPrivate *>(QGraphicsItemPrivate::get(item)):0; + if (p) { + m_next = p->keyHandler; + p->keyHandler = this; + } +} + +QFxItemKeyFilter::~QFxItemKeyFilter() +{ +} + +void QFxItemKeyFilter::keyPressed(QKeyEvent *event) +{ + if (m_next) m_next->keyPressed(event); +} + +void QFxItemKeyFilter::keyReleased(QKeyEvent *event) +{ + if (m_next) m_next->keyReleased(event); +} + +class QFxKeyNavigationAttachedPrivate : public QObjectPrivate +{ +public: + QFxKeyNavigationAttachedPrivate() + : QObjectPrivate(), left(0), right(0), up(0), down(0) {} + + QFxItem *left; + QFxItem *right; + QFxItem *up; + QFxItem *down; +}; + +class QFxKeyNavigationAttached : public QObject, public QFxItemKeyFilter +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QFxKeyNavigationAttached); + + Q_PROPERTY(QFxItem *left READ left WRITE setLeft NOTIFY changed); + Q_PROPERTY(QFxItem *right READ right WRITE setRight NOTIFY changed); + Q_PROPERTY(QFxItem *up READ up WRITE setUp NOTIFY changed); + Q_PROPERTY(QFxItem *down READ down WRITE setDown NOTIFY changed); +public: + QFxKeyNavigationAttached(QObject * = 0); + + QFxItem *left() const; + void setLeft(QFxItem *); + QFxItem *right() const; + void setRight(QFxItem *); + QFxItem *up() const; + void setUp(QFxItem *); + QFxItem *down() const; + void setDown(QFxItem *); + + static QFxKeyNavigationAttached *qmlAttachedProperties(QObject *); + +signals: + void changed(); + +private: + virtual void keyPressed(QKeyEvent *event); + virtual void keyReleased(QKeyEvent *event); +}; + +QFxKeyNavigationAttached::QFxKeyNavigationAttached(QObject *parent) +: QObject(*(new QFxKeyNavigationAttachedPrivate), parent), + QFxItemKeyFilter(qobject_cast<QFxItem*>(parent)) +{ +} + +QFxKeyNavigationAttached * +QFxKeyNavigationAttached::qmlAttachedProperties(QObject *obj) +{ + return new QFxKeyNavigationAttached(obj); +} + +QFxItem *QFxKeyNavigationAttached::left() const +{ + Q_D(const QFxKeyNavigationAttached); + return d->left; +} + +void QFxKeyNavigationAttached::setLeft(QFxItem *i) +{ + Q_D(QFxKeyNavigationAttached); + d->left = i; + emit changed(); +} + +QFxItem *QFxKeyNavigationAttached::right() const +{ + Q_D(const QFxKeyNavigationAttached); + return d->right; +} + +void QFxKeyNavigationAttached::setRight(QFxItem *i) +{ + Q_D(QFxKeyNavigationAttached); + d->right = i; + emit changed(); +} + +QFxItem *QFxKeyNavigationAttached::up() const +{ + Q_D(const QFxKeyNavigationAttached); + return d->up; +} + +void QFxKeyNavigationAttached::setUp(QFxItem *i) +{ + Q_D(QFxKeyNavigationAttached); + d->up = i; + emit changed(); +} + +QFxItem *QFxKeyNavigationAttached::down() const +{ + Q_D(const QFxKeyNavigationAttached); + return d->down; +} + +void QFxKeyNavigationAttached::setDown(QFxItem *i) +{ + Q_D(QFxKeyNavigationAttached); + d->down = i; + emit changed(); +} + +void QFxKeyNavigationAttached::keyPressed(QKeyEvent *event) +{ + Q_D(QFxKeyNavigationAttached); + + event->ignore(); + + switch(event->key()) { + case Qt::Key_Left: + if (d->left) { + d->left->setFocus(true); + event->accept(); + } + break; + case Qt::Key_Right: + if (d->right) { + d->right->setFocus(true); + event->accept(); + } + break; + case Qt::Key_Up: + if (d->up) { + d->up->setFocus(true); + event->accept(); + } + break; + case Qt::Key_Down: + if (d->down) { + d->down->setFocus(true); + event->accept(); + } + break; + default: + break; + } + + if (!event->isAccepted()) QFxItemKeyFilter::keyPressed(event); +} + +void QFxKeyNavigationAttached::keyReleased(QKeyEvent *event) +{ + Q_D(QFxKeyNavigationAttached); + + event->ignore(); + + switch(event->key()) { + case Qt::Key_Left: + if (d->left) { + event->accept(); + } + break; + case Qt::Key_Right: + if (d->right) { + event->accept(); + } + break; + case Qt::Key_Up: + if (d->up) { + event->accept(); + } + break; + case Qt::Key_Down: + if (d->down) { + event->accept(); + } + break; + default: + break; + } + + if (!event->isAccepted()) QFxItemKeyFilter::keyReleased(event); +} + /*! \qmlclass Keys \brief The Keys attached property provides key handling to Items. @@ -616,7 +839,7 @@ public: bool enabled; }; -class QFxKeysAttached : public QObject +class QFxKeysAttached : public QObject, public QFxItemKeyFilter { Q_OBJECT Q_DECLARE_PRIVATE(QFxKeysAttached); @@ -681,8 +904,8 @@ signals: void volumeDownPressed(QFxKeyEvent *event); private: - void keyPressed(QKeyEvent *event); - void keyReleased(QKeyEvent *event); + virtual void keyPressed(QKeyEvent *event); + virtual void keyReleased(QKeyEvent *event); const char *keyToSignal(int key) { QByteArray keySignal; @@ -704,8 +927,6 @@ private: }; static const SigMap sigMap[]; - static QHash<QObject*, QFxKeysAttached*> attachedProperties; - friend class QFxItem; }; const QFxKeysAttached::SigMap QFxKeysAttached::sigMap[] = { @@ -738,24 +959,19 @@ const QFxKeysAttached::SigMap QFxKeysAttached::sigMap[] = { { 0, 0 } }; -QHash<QObject*, QFxKeysAttached*> QFxKeysAttached::attachedProperties; - bool QFxKeysAttachedPrivate::isConnected(const char *signalName) { return isSignalConnected(signalIndex(signalName)); } QFxKeysAttached::QFxKeysAttached(QObject *parent) - : QObject(*(new QFxKeysAttachedPrivate), parent) +: QObject(*(new QFxKeysAttachedPrivate), parent), + QFxItemKeyFilter(qobject_cast<QFxItem*>(parent)) { - if (QFxItem *item = qobject_cast<QFxItem*>(parent)) - item->setKeyHandler(this); } QFxKeysAttached::~QFxKeysAttached() { - if (QFxItem *item = qobject_cast<QFxItem*>(parent())) - item->setKeyHandler(0); } void QFxKeysAttached::keyPressed(QKeyEvent *event) @@ -780,6 +996,8 @@ void QFxKeysAttached::keyPressed(QKeyEvent *event) if (!ke.isAccepted()) emit pressed(&ke); event->setAccepted(ke.isAccepted()); + + if (!event->isAccepted()) QFxItemKeyFilter::keyPressed(event); } void QFxKeysAttached::keyReleased(QKeyEvent *event) @@ -792,19 +1010,15 @@ void QFxKeysAttached::keyReleased(QKeyEvent *event) QFxKeyEvent ke(*event); emit released(&ke); event->setAccepted(ke.isAccepted()); + + if (!event->isAccepted()) QFxItemKeyFilter::keyReleased(event); } QFxKeysAttached *QFxKeysAttached::qmlAttachedProperties(QObject *obj) { - QFxKeysAttached *rv = attachedProperties.value(obj); - if (!rv) { - rv = new QFxKeysAttached(obj); - attachedProperties.insert(obj, rv); - } - return rv; + return new QFxKeysAttached(obj); } - /*! \qmlclass Item QFxItem \brief The Item is the most basic of all visual items in QML. @@ -1423,12 +1637,6 @@ void QFxItem::geometryChanged(const QRectF &newGeometry, } } -void QFxItem::setKeyHandler(QFxKeysAttached *handler) -{ - Q_D(QFxItem); - d->keyHandler = handler; -} - /*! \reimp */ @@ -2438,6 +2646,8 @@ QT_END_NAMESPACE QML_DECLARE_TYPE(QFxKeysAttached) QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Keys,QFxKeysAttached) +QML_DECLARE_TYPE(QFxKeyNavigationAttached) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,KeyNavigation,QFxKeyNavigationAttached) #include "moc_qfxitem.cpp" #include "qfxitem.moc" diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 89c2cf1..cb2d97a 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -63,7 +63,6 @@ class QmlTransition; class QFxKeyEvent; class QFxAnchors; class QFxItemPrivate; -class QFxKeysAttached; class Q_DECLARATIVE_EXPORT QFxItem : public QGraphicsObject, public QmlParserStatus { Q_OBJECT @@ -197,11 +196,8 @@ private: QFxAnchorLine verticalCenter() const; QFxAnchorLine baseline() const; - void setKeyHandler(QFxKeysAttached *); - friend class QmlStatePrivate; friend class QFxAnchors; - friend class QFxKeysAttached; Q_DISABLE_COPY(QFxItem) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QFxItem) }; diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h index 1d4bef3..d30e324 100644 --- a/src/declarative/fx/qfxitem_p.h +++ b/src/declarative/fx/qfxitem_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE class QNetworkReply; -class QFxKeysAttached; +class QFxItemKeyFilter; //### merge into private? class QFxContents : public QObject @@ -209,7 +209,7 @@ public: bool _keepMouse:1; bool smooth:1; - QFxKeysAttached *keyHandler; + QFxItemKeyFilter *keyHandler; qreal width; qreal height; diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 8dfe171..4b28462 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -59,7 +59,7 @@ public: attachedProperties.remove(parent()); } - Q_PROPERTY(QFxListView *view READ view) + Q_PROPERTY(QFxListView *view READ view CONSTANT) QFxListView *view() { return m_view; } Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged) @@ -212,8 +212,11 @@ public: qreal startPosition() const { qreal pos = 0; - if (!visibleItems.isEmpty()) - pos = visibleItems.first()->position() - visibleIndex * (averageSize + spacing); + if (!visibleItems.isEmpty()) { + pos = visibleItems.first()->position(); + if (visibleIndex > 0) + pos -= visibleIndex * (averageSize + spacing) - spacing; + } return pos; } diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index e1f4a90..e4ca358 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -64,6 +64,11 @@ QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx, QmlAbstractExpression::setContext(context); } +QmlBinding_Id::~QmlBinding_Id() +{ + removeFromContext(); +} + void QmlBinding_Id::setEnabled(bool e) { if (e) { @@ -103,7 +108,7 @@ void QmlBinding_Id::update() } } -void QmlBinding_Id::reset() +void QmlBinding_Id::removeFromContext() { if (m_prev) { *m_prev = m_next; @@ -111,6 +116,11 @@ void QmlBinding_Id::reset() m_next = 0; m_prev = 0; } +} + +void QmlBinding_Id::reset() +{ + removeFromContext(); QObject *o = 0; void *a[] = { &o, 0 }; diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index 2d2ffec..ab264c7 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -65,7 +65,8 @@ class QmlBinding_Id : public QmlAbstractExpression, { public: QmlBinding_Id(QObject *object, int propertyIdx, - QmlContext *context, int id); + QmlContext *context, int id); + virtual ~QmlBinding_Id(); // Inherited from QmlAbstractBinding virtual void setEnabled(bool); @@ -75,6 +76,8 @@ public: void reset(); private: + void removeFromContext(); + QmlBinding_Id **m_prev; QmlBinding_Id *m_next; diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 1771cb4..3dcc448 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1176,11 +1176,19 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, } QmlType *type = 0; - QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name, &type, 0); - // 0: attached properties not supported in QML component files - - if (!type || !type->attachedPropertiesType()) + QmlEnginePrivate::ImportedNamespace *typeNamespace = 0; + QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name, + &type, 0, &typeNamespace); + + if (typeNamespace) { + // ### We might need to indicate that this property is a namespace + // for the DOM API + COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, + ctxt)); + return true; + } else if (!type || !type->attachedPropertiesType()) { COMPILE_EXCEPTION(prop, "Non-existant attached object"); + } if (!prop->value) COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); @@ -1265,6 +1273,40 @@ bool QmlCompiler::buildProperty(QmlParser::Property *prop, return true; } +bool +QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, + QmlParser::Property *nsProp, + QmlParser::Object *obj, + const BindingContext &ctxt) +{ + if (!nsProp->value) + COMPILE_EXCEPTION(nsProp, "Invalid use of namespace"); + + foreach (Property *prop, nsProp->value->properties) { + + if (!isAttachedPropertyName(prop->name)) + COMPILE_EXCEPTION(prop, "Not an attached property name"); + + // Setup attached property data + + QmlType *type = 0; + QmlEnginePrivate::get(engine)->resolveTypeInNamespace(ns, prop->name, + &type, 0); + + if (!type || !type->attachedPropertiesType()) + COMPILE_EXCEPTION(prop, "Non-existant attached object"); + + if (!prop->value) + COMPILE_EXCEPTION(prop, "Invalid attached object assignment"); + + Q_ASSERT(type->attachedPropertiesFunction()); + prop->index = type->index(); + prop->value->metatype = type->attachedPropertiesType(); + + COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt)); + } +} + void QmlCompiler::genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj) { @@ -1407,11 +1449,19 @@ bool QmlCompiler::buildIdProperty(QmlParser::Property *prop, prop->values.at(0)->object) COMPILE_EXCEPTION(prop, "Invalid use of id property"); - QString val = prop->values.at(0)->primitive(); + QmlParser::Value *idValue = prop->values.at(0); + QString val = idValue->primitive(); if (!isValidId(val)) COMPILE_EXCEPTION(prop, val << "is not a valid object id"); + // We disallow id's that conflict with import prefixes + QmlEnginePrivate::ImportedNamespace *ns = 0; + QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(), + 0, 0, &ns); + if (ns) + COMPILE_EXCEPTION(idValue, "id conflicts with namespace prefix"); + if (compileState.ids.contains(val)) COMPILE_EXCEPTION(prop, "id is not unique"); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 58279c4..c42c2d9 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -60,6 +60,7 @@ #include <private/qmlinstruction_p.h> #include <private/qmlcompositetypemanager_p.h> #include <private/qmlparser_p.h> +#include <private/qmlengine_p.h> QT_BEGIN_NAMESPACE @@ -165,6 +166,10 @@ private: const BindingContext &); bool buildProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &); + bool buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns, + QmlParser::Property *prop, + QmlParser::Object *obj, + const BindingContext &); bool buildIdProperty(QmlParser::Property *prop, QmlParser::Object *obj); bool buildAttachedProperty(QmlParser::Property *prop, QmlParser::Object *obj, diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index c84b3b5..18e3765 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -209,10 +209,14 @@ public: bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; - bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, ImportedNamespace** ns_return=0) const; - - void resolveNamespace(const Imports& imports, const QByteArray &type, ImportedNamespace **s, QByteArray *unqualifiedType) const; - bool resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, QmlType** type_return, QUrl* url_return ) const; + bool resolveType(const Imports&, const QByteArray& type, + QmlType** type_return, QUrl* url_return, + ImportedNamespace** ns_return=0) const; + void resolveNamespace(const Imports& imports, const QByteArray &type, + ImportedNamespace **s, + QByteArray *unqualifiedType) const; + bool resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type, + QmlType** type_return, QUrl* url_return ) const; static QScriptValue qmlScriptObject(QObject*, QmlEngine*); diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index d15bd4a..0b48449 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -81,7 +81,7 @@ public: void deleteFromBinding(); }; -class ActionEvent +class ActionEvent { public: virtual ~ActionEvent(); @@ -126,7 +126,7 @@ class Q_DECLARATIVE_EXPORT QmlState : public QObject Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QmlBinding *when READ when WRITE setWhen) - Q_PROPERTY(QString extends READ extends WRITE setExtends) + Q_PROPERTY(QString extend READ extends WRITE setExtends) Q_PROPERTY(QmlList<QmlStateOperation *>* changes READ changes) Q_CLASSINFO("DefaultProperty", "changes") @@ -137,7 +137,7 @@ public: QString name() const; void setName(const QString &); - /*'when' is a QmlBinding to limit state changes oscillation + /*'when' is a QmlBinding to limit state changes oscillation due to the unpredictable order of evaluation of bound expressions*/ bool isWhenKnown() const; QmlBinding *when() const; diff --git a/tests/auto/declarative/qmlparser/failingComponent.errors.txt b/tests/auto/declarative/qmlparser/failingComponent.errors.txt index 388fa76..190a649 100644 --- a/tests/auto/declarative/qmlparser/failingComponent.errors.txt +++ b/tests/auto/declarative/qmlparser/failingComponent.errors.txt @@ -1,2 +1,2 @@ --1:-1:Unable to create type FailingComponent +3:5:Unable to create type FailingComponent 4:5:Cannot assign to non-existant property "a" diff --git a/tests/auto/declarative/qmlparser/invalidID.5.errors.txt b/tests/auto/declarative/qmlparser/invalidID.5.errors.txt new file mode 100644 index 0000000..b0a63a0 --- /dev/null +++ b/tests/auto/declarative/qmlparser/invalidID.5.errors.txt @@ -0,0 +1 @@ +4:9:id conflicts with namespace prefix diff --git a/tests/auto/declarative/qmlparser/invalidID.5.qml b/tests/auto/declarative/qmlparser/invalidID.5.qml new file mode 100644 index 0000000..0545b0d --- /dev/null +++ b/tests/auto/declarative/qmlparser/invalidID.5.qml @@ -0,0 +1,6 @@ +import Test 1.0 +import Test 1.0 as Hello +MyQmlObject { + id: Hello +} + diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp index a9c4351..3047bb0 100644 --- a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp +++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp @@ -135,6 +135,8 @@ void tst_qmlparser::errors_data() QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false; QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false; QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false; + QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false; + QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false; QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true; |