diff options
49 files changed, 994 insertions, 399 deletions
diff --git a/examples/declarative/minehunt/Description.qml b/demos/declarative/minehunt/Description.qml index df4881c..df4881c 100644 --- a/examples/declarative/minehunt/Description.qml +++ b/demos/declarative/minehunt/Description.qml diff --git a/examples/declarative/minehunt/Explosion.qml b/demos/declarative/minehunt/Explosion.qml index 9b8bd6e..a997048 100644 --- a/examples/declarative/minehunt/Explosion.qml +++ b/demos/declarative/minehunt/Explosion.qml @@ -5,8 +5,8 @@ Item { Particles { id: particles - width: 38 - height: 21 + width: 40 + height: 40 lifeSpan: 1000 lifeSpanDeviation: 0 source: "pics/star.png" diff --git a/examples/declarative/minehunt/main.cpp b/demos/declarative/minehunt/main.cpp index 20f7492..20f7492 100644 --- a/examples/declarative/minehunt/main.cpp +++ b/demos/declarative/minehunt/main.cpp diff --git a/examples/declarative/minehunt/minehunt.pro b/demos/declarative/minehunt/minehunt.pro index 01791b1..01791b1 100644 --- a/examples/declarative/minehunt/minehunt.pro +++ b/demos/declarative/minehunt/minehunt.pro diff --git a/examples/declarative/minehunt/minehunt.qml b/demos/declarative/minehunt/minehunt.qml index 4bae64d..fa169aa 100644 --- a/examples/declarative/minehunt/minehunt.qml +++ b/demos/declarative/minehunt/minehunt.qml @@ -60,9 +60,6 @@ Item { } Explosion { id: expl - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - //explode: modelData.hasMine && modelData.flipped//Doesn't wait for the pause } } states: [ @@ -77,16 +74,20 @@ Item { SequentialAnimation { PauseAnimation { duration: { - var ret = Math.abs(flipable.parent.x-field.clickx) + var ret; + if(flipable.parent != null) + ret = Math.abs(flipable.parent.x-field.clickx) + Math.abs(flipable.parent.y-field.clicky); + else + ret = 0; if (ret > 0) { if (modelData.hasMine && modelData.flipped) { - ret*3 + ret*3; } else { - ret + ret; } } else { - 0 + 0; } } } @@ -95,14 +96,14 @@ Item { properties: "angle" } ScriptAction{ - script: if(modelData.hasMine && modelData.flipped) - {expl.explode = true;} + script: "if(modelData.hasMine && modelData.flipped){expl.explode = true;}" } } } ] MouseRegion { anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton onPressed: { field.clickx = flipable.parent.x; field.clicky = flipable.parent.y; @@ -141,47 +142,54 @@ Item { } } } - Item { + Row { id: gamedata - width: 370 - height: 100 - y: 380 - Text { - color: "white" - font.pointSize: 18 - x: 20 - y: 20 - } - Image { - x: 100 - y: 20 - source: "pics/bomb-color.png" - } - Text { - x: 100 - y: 60 - color: "white" - text: numMines - } - Image { - x: 140 - y: 20 - source: "pics/flag-color.png" - } - Text { - x: 140 - y: 60 - color: "white" - text: numFlags + // width: 370 + // height: 100 + y: 400 + x: 20 + spacing: 20 + Column { + spacing: 2 + width: childrenRect.width + Image { + // x: 100 + // y: 20 + source: "pics/bomb-color.png" + } + Text { + // x: 100 + // y: 60 + anchors.horizontalCenter: parent.horizontalCenter + color: "white" + text: numMines + } } - Image { - x: 280 - y: 10 - source: isPlaying ? 'pics/face-smile.png' : hasWon ? 'pics/face-smile-big.png': 'pics/face-sad.png' - MouseRegion { - anchors.fill: parent - onPressed: { reset() } + Column { + spacing: 2 + width: childrenRect.width + Image { + // x: 140 + // y: 20 + source: "pics/flag-color.png" + } + Text { + // x: 140 + // y: 60 + anchors.horizontalCenter: parent.horizontalCenter + color: "white" + text: numFlags } } } + Image { + y: 390 + anchors.right: field.right + anchors.rightMargin: 20 + source: isPlaying ? 'pics/face-smile.png' : hasWon ? 'pics/face-smile-big.png': 'pics/face-sad.png' + MouseRegion { + anchors.fill: parent + onPressed: { reset() } + } + } } diff --git a/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg b/demos/declarative/minehunt/pics/No-Ones-Laughing-3.jpg Binary files differindex 445567f..445567f 100644 --- a/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg +++ b/demos/declarative/minehunt/pics/No-Ones-Laughing-3.jpg diff --git a/examples/declarative/minehunt/pics/back.png b/demos/declarative/minehunt/pics/back.png Binary files differindex f6b3f0b..f6b3f0b 100644 --- a/examples/declarative/minehunt/pics/back.png +++ b/demos/declarative/minehunt/pics/back.png diff --git a/examples/declarative/minehunt/pics/bomb-color.png b/demos/declarative/minehunt/pics/bomb-color.png Binary files differindex 61ad0a9..61ad0a9 100644 --- a/examples/declarative/minehunt/pics/bomb-color.png +++ b/demos/declarative/minehunt/pics/bomb-color.png diff --git a/examples/declarative/minehunt/pics/bomb.png b/demos/declarative/minehunt/pics/bomb.png Binary files differindex a992575..a992575 100644 --- a/examples/declarative/minehunt/pics/bomb.png +++ b/demos/declarative/minehunt/pics/bomb.png diff --git a/examples/declarative/minehunt/pics/face-sad.png b/demos/declarative/minehunt/pics/face-sad.png Binary files differindex cf00aaf..cf00aaf 100644 --- a/examples/declarative/minehunt/pics/face-sad.png +++ b/demos/declarative/minehunt/pics/face-sad.png diff --git a/examples/declarative/minehunt/pics/face-smile-big.png b/demos/declarative/minehunt/pics/face-smile-big.png Binary files differindex f9c2335..f9c2335 100644 --- a/examples/declarative/minehunt/pics/face-smile-big.png +++ b/demos/declarative/minehunt/pics/face-smile-big.png diff --git a/examples/declarative/minehunt/pics/face-smile.png b/demos/declarative/minehunt/pics/face-smile.png Binary files differindex 3d66d72..3d66d72 100644 --- a/examples/declarative/minehunt/pics/face-smile.png +++ b/demos/declarative/minehunt/pics/face-smile.png diff --git a/examples/declarative/minehunt/pics/flag-color.png b/demos/declarative/minehunt/pics/flag-color.png Binary files differindex aadad0f..aadad0f 100644 --- a/examples/declarative/minehunt/pics/flag-color.png +++ b/demos/declarative/minehunt/pics/flag-color.png diff --git a/examples/declarative/minehunt/pics/flag.png b/demos/declarative/minehunt/pics/flag.png Binary files differindex 39cde4d..39cde4d 100644 --- a/examples/declarative/minehunt/pics/flag.png +++ b/demos/declarative/minehunt/pics/flag.png diff --git a/examples/declarative/minehunt/pics/front.png b/demos/declarative/minehunt/pics/front.png Binary files differindex 834331b..834331b 100644 --- a/examples/declarative/minehunt/pics/front.png +++ b/demos/declarative/minehunt/pics/front.png diff --git a/examples/declarative/minehunt/pics/star.png b/demos/declarative/minehunt/pics/star.png Binary files differindex 3772359..3772359 100644 --- a/examples/declarative/minehunt/pics/star.png +++ b/demos/declarative/minehunt/pics/star.png diff --git a/demos/declarative/twitter/content/AuthView.qml b/demos/declarative/twitter/content/AuthView.qml new file mode 100644 index 0000000..6bd98b9 --- /dev/null +++ b/demos/declarative/twitter/content/AuthView.qml @@ -0,0 +1,92 @@ +import Qt 4.6 +import "../../flickr/common" +import "../../flickr/mobile" + +Item { + id: wrapper + Column { + width: childrenRect.width; height:childrenRect.height; anchors.centerIn: parent + spacing: 20 + Row{ + width: childrenRect.width; height:childrenRect.height; + spacing: 4 + Text { + width: 100 + text: "Screen name:" + font.pointSize: 10; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Qt.AlignRight + } + Item { + width: 160 + height: 28 + BorderImage { source: "../../flickr/mobile/images/lineedit.sci"; anchors.fill: parent } + TextInput{ + id: nameIn + width: parent.width - 8 + height: parent.height - 12 + anchors.centerIn: parent + maximumLength:21 + font.bold: true + color: "#151515"; highlightColor: "green" + KeyProxy { + id: Proxy + targets: [(tabber), (nameIn)] + focus: true + } + Item { + id: tabber + //Note: it's not working yet + Keys.onPressed: {if(event.key == Qt.Key_Tab){print('Tab works!'); passIn.focus = true; accept(); }} + } + } + } + } + Row{ + width: childrenRect.width; height:childrenRect.height; + spacing: 4 + Text { + width: 100 + text: "Password:" + font.pointSize: 10; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Qt.AlignRight + } + Item { + width: 160 + height: 28 + BorderImage { source: "../../flickr/mobile/images/lineedit.sci"; anchors.fill: parent } + TextInput{ + id: passIn + width: parent.width - 8 + height: parent.height - 12 + anchors.centerIn: parent + maximumLength:21 + echoMode: 2 + font.bold: true + color: "#151515"; highlightColor: "green" + } + } + } + Item{ + width: childrenRect.width; anchors.horizontalCenter: parent.horizontalCenter + height: childrenRect.height + Button { + x: 10 + width: 100 + height: 32 + id: login + text: "Log in" + onClicked: {RssModel.authName=nameIn.text; RssModel.authPass=passIn.text; RssModel.tags='my timeline';} + } + Button { + x: 120 + width: 100 + height: 32 + id: guest + text: "Guest" + onClicked: RssModel.authName='inv' + } + } + } +} diff --git a/demos/declarative/twitter/content/FatDelegate.qml b/demos/declarative/twitter/content/FatDelegate.qml new file mode 100644 index 0000000..a2e9c39 --- /dev/null +++ b/demos/declarative/twitter/content/FatDelegate.qml @@ -0,0 +1,47 @@ +import Qt 4.6 +import "../../flickr/common" + +Component { + id: ListDelegate + Item { + id: Wrapper; width: Wrapper.ListView.view.width; height: if(txt.height > 58){txt.height+8}else{58}//50+4+4 + Script { + function handleLink(link){ + if(link.slice(0,3) == 'app'){ + setUser(link.slice(7)); + Screen.setMode(true); + }else if(link.slice(0,4) == 'http'){ + Qt.DesktopServices.openUrl(link); + } + } + function addTags(str){ + ret = str.replace(/@[a-zA-Z0-9_]+/g, '<a href="app://$&">$&</a>');//click to jump to user? + ret2 = ret.replace(/http:\/\/[^ \n\t]+/g, '<a href="$&">$&</a>');//surrounds http links with html link tags + return ret2; + } + } + Item { + id: MoveMe; height: parent.height + Rectangle { + id: BlackRect + color: "black"; opacity: Wrapper.ListView.index % 2 ? 0.2 : 0.3; height: Wrapper.height-2; width: Wrapper.width; y: 1 + } + Rectangle { + id: WhiteRect; x: 6; width: 50; height: 50; color: "white"; smooth: true + anchors.verticalCenter: parent.verticalCenter + + Loading { x: 1; y: 1; width: 48; height: 48; visible: RealImage.status != 1 } + Image { id: RealImage; source: userImage; x: 1; y: 1; width:48; height:48 } + } + Text { id:txt; y:4; x: 56 + text: '<html><style type="text/css">a:link {color:"#aaccaa"}; a:visited {color:"#336633"}</style>' + + '<a href="app://@'+userScreenName+'"><b>'+userScreenName + "</b></a> from " +source + + "<br /><b>" + addTags(statusText) + "</b></html>"; + textFormat: Qt.RichText + color: "white"; color: "#cccccc"; style: "Raised"; styleColor: "black"; wrap: true + anchors.left: WhiteRect.right; anchors.right: BlackRect.right; anchors.leftMargin: 6; anchors.rightMargin: 6 + onLinkActivated: handleLink(link) + } + } + } +} diff --git a/demos/declarative/twitter/content/HomeTitleBar.qml b/demos/declarative/twitter/content/HomeTitleBar.qml new file mode 100644 index 0000000..878a83e --- /dev/null +++ b/demos/declarative/twitter/content/HomeTitleBar.qml @@ -0,0 +1,125 @@ +import Qt 4.6 +import "../../flickr/mobile" +import "../../flickr/common" + +Item { + id: TitleBar + + signal update() + onYChanged: state="" //When switching titlebars + + BorderImage { source: "../../flickr/mobile/images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 } + Item { + id: Container + width: (parent.width * 2) - 55 ; height: parent.height + + Script { + function accept() { + if(RssModel.authName == '' || RssModel.authPass == '') + return false;//Can't login like that + + var postData = "status=" + Editor.text; + var postman = new XMLHttpRequest(); + postman.open("POST", "http://twitter.com/statuses/update.xml", true, RssModel.authName, RssModel.authPass); + postman.onreadystatechange = function() { + if (postman.readyState == postman.DONE) { + TitleBar.update(); + } + } + postman.send(postData); + + TitleBar.state = "" + } + } + + Rectangle { + id: WhiteRect; x: 6; width: 50; height: 50; color: "white"; smooth: true + anchors.verticalCenter: parent.verticalCenter + + UserModel { user: RssModel.authName; id: userModel } + Component { id: imgDelegate; + Item { id: Wrapper + Loading { width:48; height:48; visible: realImage.status != 1 } + Image { source: image; width:48; height:48; id: realImage } + } + } + ListView { model: userModel.model; x:1; y:1; delegate: imgDelegate } + } + + Text { + id: CategoryText + anchors.left: parent.left; anchors.right: TagButton.left + anchors.leftMargin: 58; anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + elide: "ElideLeft" + text: "Timeline for " + RssModel.authName + font.pointSize: 10; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + } + + Button { + id: TagButton; x: TitleBar.width - 90; width: 85; height: 32; text: "New Post..." + anchors.verticalCenter: parent.verticalCenter; + onClicked: if (TitleBar.state == "Posting") accept(); else TitleBar.state = "Posting" + } + + Text { + id: charsLeftText; anchors.horizontalCenter: TagButton.horizontalCenter; + anchors.top: TagButton.bottom; anchors.topMargin: 2 + text: {140 - Editor.text.length;} visible: TitleBar.state == "Posting" + font.pointSize: 10; font.bold: true; color: "white"; style: "Raised"; styleColor: "black" + } + Item { + id: txtEdit; + anchors.left: TagButton.right; anchors.leftMargin: 5; y: 4 + anchors.right: parent.right; anchors.rightMargin: 40; height: parent.height - 9 + BorderImage { source: "../../flickr/mobile/images/lineedit.sci"; anchors.fill: parent } + + Binding {//TODO: Can this be a function, which also resets the cursor? And flashes? + when: Editor.text.length > 140 + target: Editor + property: "text" + value: Editor.text.slice(0,140) + } + TextEdit { + id: Editor + anchors.left: parent.left; + anchors.leftMargin: 8; + anchors.bottom: parent.bottom + anchors.bottomMargin: 4; + cursorVisible: true; font.bold: true + width: parent.width - 12 + height: parent.height - 8 + font.pointSize: 10 + wrap: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: "Posting" + PropertyChanges { target: Container; x: -TagButton.x + 5 } + PropertyChanges { target: TitleBar; height: 80 } + PropertyChanges { target: TagButton; text: "OK" } + PropertyChanges { target: TagButton; width: 28 } + PropertyChanges { target: TagButton; height: 24 } + PropertyChanges { target: Proxy; focus: true } + } + ] + transitions: [ + Transition { + from: "*"; to: "*" + NumberAnimation { properties: "x,y,width,height"; easing: "easeInOutQuad" } + } + ] +} diff --git a/demos/declarative/twitter/content/MultiTitleBar.qml b/demos/declarative/twitter/content/MultiTitleBar.qml new file mode 100644 index 0000000..6a6a28f --- /dev/null +++ b/demos/declarative/twitter/content/MultiTitleBar.qml @@ -0,0 +1,25 @@ +import Qt 4.6 +import "../../flickr/mobile" + +Item { + height: HomeBar.height + HomeTitleBar { id: HomeBar; width: parent.width; height: 60; + onUpdate: RssModel.reload() + } + TitleBar { id: TitleBar; width: parent.width; height: 60; + y: -80 + untaggedString: "Latest tweets from everyone" + taggedString: "Latest tweets from " + } + states: [ + State { + name: "search"; when: Screen.userView + PropertyChanges { target: TitleBar; y: 0 } + PropertyChanges { target: HomeBar; y: -80 } + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x,y"; duration: 500; easing: "easeInOutQuad" } } + ] +} + diff --git a/demos/declarative/twitter/content/RssModel.qml b/demos/declarative/twitter/content/RssModel.qml new file mode 100644 index 0000000..144d7af --- /dev/null +++ b/demos/declarative/twitter/content/RssModel.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Item { id: wrapper + property var model: xmlModel + property string tags : "" + property string authName : "" + property string authPass : "" + property string mode : "everyone" + property int status: xmlModel.status + function reload() { xmlModel.reload(); } +XmlListModel { + id: xmlModel + + source: if (wrapper.authName == ""){ + ""; //Avoid worthless calls to twitter servers + }else if(wrapper.mode == 'user'){ + "https://"+ ((wrapper.authName!="" && wrapper.authPass!="")? (wrapper.authName+":"+wrapper.authPass+"@") : "" )+"twitter.com/statuses/user_timeline.xml?screen_name="+wrapper.tags; + }else if(wrapper.mode == 'self'){ + "https://"+ ((wrapper.authName!="" && wrapper.authPass!="")? (wrapper.authName+":"+wrapper.authPass+"@") : "" )+"twitter.com/statuses/friends_timeline.xml"; + }else{//everyone/public + "http://twitter.com/statuses/public_timeline.xml"; + } + query: "/statuses/status" + + XmlRole { name: "statusText"; query: "text/string()" } + XmlRole { name: "timestamp"; query: "created_at/string()" } + XmlRole { name: "source"; query: "source/string()" } + XmlRole { name: "userName"; query: "user/name/string()" } + XmlRole { name: "userScreenName"; query: "user/screen_name/string()" } + XmlRole { name: "userImage"; query: "user/profile_image_url/string()" } + XmlRole { name: "userLocation"; query: "user/location/string()" } + XmlRole { name: "userDescription"; query: "user/description/string()" } + XmlRole { name: "userFollowers"; query: "user/followers_count/string()" } + XmlRole { name: "userStatuses"; query: "user/statuses_count/string()" } + //TODO: Could also get the user's color scheme, timezone and a few other things +} +Binding { + property: "mode" + target: wrapper + value: {if(wrapper.tags==''){"everyone";}else if(wrapper.tags=='my timeline'){"self";}else{"user";}} +} +} diff --git a/demos/declarative/twitter/content/UserModel.qml b/demos/declarative/twitter/content/UserModel.qml new file mode 100644 index 0000000..c146b84 --- /dev/null +++ b/demos/declarative/twitter/content/UserModel.qml @@ -0,0 +1,26 @@ +import Qt 4.6 + +//This "model" gets the user information about the searched user. Mainly for the icon. +//Copied from RssModel + +Item { id: wrapper + property var model: xmlModel + property string user : "" + property int status: xmlModel.status + function reload() { xmlModel.reload(); } +XmlListModel { + id: xmlModel + + source: {if(user!="") {"http://twitter.com/users/show.xml?screen_name="+user;}else{"";}} + query: "/user" + + XmlRole { name: "name"; query: "name/string()" } + XmlRole { name: "screenName"; query: "screen_name/string()" } + XmlRole { name: "image"; query: "profile_image_url/string()" } + XmlRole { name: "location"; query: "location/string()" } + XmlRole { name: "description"; query: "description/string()" } + XmlRole { name: "followers"; query: "followers_count/string()" } + //XmlRole { name: "protected"; query: "protected/bool()" } + //TODO: Could also get the user's color scheme, timezone and a few other things +} +} diff --git a/demos/declarative/twitter/twitter.qml b/demos/declarative/twitter/twitter.qml new file mode 100644 index 0000000..566832b --- /dev/null +++ b/demos/declarative/twitter/twitter.qml @@ -0,0 +1,87 @@ +import Qt 4.6 +import "content" as Twitter +import "../flickr/common" as Common +import "../flickr/mobile" as Mobile + +Item { + id: Screen; width: 320; height: 480 + property bool userView : false + function setMode(m){ + Screen.userView = m; + if(m == false){ + RssModel.tags='my timeline'; + RssModel.reload(); + ToolBar.button2Label = "View others"; + } else { + ToolBar.button2Label = "Return home"; + } + } + //Workaround for bug 260266 + Timer{ interval: 1; running: false; repeat: false; onTriggered: reallySetUser(); id:hack } + Script{ + var tmpStr; + function setUser(str){hack.running = true; tmpStr = str} + function reallySetUser(){RssModel.tags = tmpStr;} + } + + Rectangle { + id: Background + anchors.fill: parent; color: "#343434"; + + Image { source: "mobile/images/stripes.png"; fillMode: "Tile"; anchors.fill: parent; opacity: 0.3 } + + Twitter.RssModel { id: RssModel } + Common.Loading { anchors.centerIn: parent; visible: RssModel.status && state!='unauthed'} + + Item { + id: Views + x: 2; width: parent.width - 4 + y:60 //Below the title bars + height: 320 + + Twitter.AuthView{ + id: authView + anchors.verticalCenter: parent.verticalCenter + width: parent.width; height: parent.height-60; + x: -(Screen.width * 1.5) + } + + Twitter.FatDelegate { id: FatDelegate } + ListView { + id: MainView; model: RssModel.model; delegate: FatDelegate; + width: parent.width; height: parent.height; x: 0; cacheBuffer: 100; + } + } + + Twitter.MultiTitleBar { id: TitleBar; width: parent.width } + Mobile.ToolBar { id: ToolBar; height: 40; + //anchors.bottom: parent.bottom; + //TODO: Use anchor changes instead of hard coding + y: 440 + width: parent.width; opacity: 0.9 + button1Label: "Update" + button2Label: "View others" + onButton2Clicked: + { + if(Screen.userView == true){ + Screen.setMode(false); + }else{ + Screen.setMode(true); + } + } + } + + states: [ + State { + name: "unauthed"; when: RssModel.authName=="" + PropertyChanges { target: authView; x: 0 } + PropertyChanges { target: MainView; x: -(parent.width * 1.5) } + PropertyChanges { target: TitleBar; y: -80 } + PropertyChanges { target: ToolBar; y: Screen.height + 80 } + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x,y"; duration: 500; easing: "easeInOutQuad" } } + ] + } +} diff --git a/examples/declarative/scrollbar/ScrollBar.qml b/examples/declarative/scrollbar/ScrollBar.qml index c1c4a4f..b42563d 100644 --- a/examples/declarative/scrollbar/ScrollBar.qml +++ b/examples/declarative/scrollbar/ScrollBar.qml @@ -7,8 +7,8 @@ Item { // height of the page, i.e. a pageSize of 0.5 means that you can see 50% // of the height of the view. // orientation can be either 'Vertical' or 'Horizontal' - property var position - property var pageSize + property real position + property real pageSize property var orientation : "Vertical" // A light, semi-transparent background diff --git a/examples/declarative/scrollbar/display.qml b/examples/declarative/scrollbar/display.qml index 48cceb7..0180bda 100644 --- a/examples/declarative/scrollbar/display.qml +++ b/examples/declarative/scrollbar/display.qml @@ -38,22 +38,20 @@ Rectangle { id: SBV opacity: 0 orientation: "Vertical" - position: View.pageYPosition - pageSize: View.pageHeight + position: View.visibleArea.yPosition + pageSize: View.visibleArea.heightRatio width: 12 height: View.height-12 anchors.right: View.right } - /* ScrollBar { id: SBH opacity: 0 orientation: "Horizontal" - position: View.pageXPosition - pageSize: View.pageWidth + position: View.visibleArea.xPosition + pageSize: View.visibleArea.widthRatio height: 12 width: View.width-12 anchors.bottom: View.bottom } - */ } diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index a401a70..b24f6fe 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -48,6 +48,10 @@ Flickable: xVelocity -> horizontalVelocity Flickable: yVelocity -> verticalVelocity Flickable: velocityDecay -> reportedVelocitySmoothing Flickable: locked -> interactive (note reversal of meaning) +Flickable: pageXPosition -> visibleArea.xPosition +Flickable: pageYPosition -> visibleArea.yPosition +Flickable: pageWidth -> visibleArea.widthRatio +Flickable: pageHeight -> visibleArea.heightRatio WebView: idealWidth -> preferredWidth WebView: idealHeight -> preferredHeight WebView: status -> statusText @@ -67,6 +71,7 @@ Column/VerticalPositioner: lost "margins" property Row/HorizontalPositioner: lost "margins" property Grid/Positioner/Layout: lost "margins" property WebView: lost "interactive" property (always true now) +Flickable: removed "dragMode" property Other Changes: Drag: axis becomes an enum with values "XAxis", "YAxis", "XandYAxis" diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp index 0690df1..0ea50b8 100644 --- a/src/declarative/fx/qfxflickable.cpp +++ b/src/declarative/fx/qfxflickable.cpp @@ -48,57 +48,107 @@ QT_BEGIN_NAMESPACE -ElasticValue::ElasticValue(QmlTimeLineValue &val) - : _value(val) +class QFxFlickableVisibleArea : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal xPosition READ xPosition NOTIFY pageChanged) + Q_PROPERTY(qreal yPosition READ yPosition NOTIFY pageChanged) + Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY pageChanged) + Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY pageChanged) + +public: + QFxFlickableVisibleArea(QFxFlickable *parent=0); + + qreal xPosition() const; + qreal widthRatio() const; + qreal yPosition() const; + qreal heightRatio() const; + + void updateVisible(); + +signals: + void pageChanged(); + +private: + QFxFlickable *flickable; + qreal m_xPosition; + qreal m_widthRatio; + qreal m_yPosition; + qreal m_heightRatio; +}; + +QFxFlickableVisibleArea::QFxFlickableVisibleArea(QFxFlickable *parent) + : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.) + , m_yPosition(0.), m_heightRatio(0.) { - _to = _value.value(); - _myValue = _to; - _velocity = 0; } -void ElasticValue::setValue(qreal to) +qreal QFxFlickableVisibleArea::widthRatio() const { - if (_to != to) { - _to = to; - _startTime.start(); - if (state() != Running) - start(); - } + return m_widthRatio; } -void ElasticValue::clear() +qreal QFxFlickableVisibleArea::xPosition() const { - stop(); - _velocity = 0.0; - _myValue = _value.value(); + return m_xPosition; } -void ElasticValue::updateCurrentTime(int) +qreal QFxFlickableVisibleArea::heightRatio() const { - const qreal Tension = 0.1; - int elapsed = _startTime.restart(); - if (!elapsed) - return; - qreal dist = _to - _value.value(); - qreal move = Tension * dist * qAbs(dist); - if (elapsed < 100 && _velocity != 0.0) - move = (elapsed * move + (100 - elapsed) * _velocity) / 100; - _myValue += move * elapsed / 1000; - _value.setValue(qRound(_myValue)); // moving sub-pixel can be ugly. -// _value.setValue(_myValue); - _velocity = move; - if (qAbs(_velocity) < 5.0) - clear(); - emit updated(); + return m_heightRatio; +} + +qreal QFxFlickableVisibleArea::yPosition() const +{ + return m_yPosition; } +void QFxFlickableVisibleArea::updateVisible() +{ + QFxFlickablePrivate *p = static_cast<QFxFlickablePrivate *>(QGraphicsItemPrivate::get(flickable)); + bool pageChange = false; + + // Vertical + const qreal viewheight = flickable->height(); + const qreal maxyextent = -flickable->maxYExtent(); + qreal pagePos = -p->_moveY.value() / (maxyextent + viewheight); + qreal pageSize = viewheight / (maxyextent + viewheight); + + if (pageSize != m_heightRatio) { + m_heightRatio = pageSize; + pageChange = true; + } + if (pagePos != m_yPosition) { + m_yPosition = pagePos; + pageChange = true; + } + + // Horizontal + const qreal viewwidth = flickable->width(); + const qreal maxxextent = -flickable->maxXExtent(); + pagePos = -p->_moveX.value() / (maxxextent + viewwidth); + pageSize = viewwidth / (maxxextent + viewwidth); + + if (pageSize != m_widthRatio) { + m_widthRatio = pageSize; + pageChange = true; + } + if (pagePos != m_xPosition) { + m_xPosition = pagePos; + pageChange = true; + } + if (pageChange) + emit pageChanged(); +} + + QFxFlickablePrivate::QFxFlickablePrivate() - : _flick(new QFxItem), _moveX(_flick, &QFxItem::setX), _moveY(_flick, &QFxItem::setY) + : viewport(new QFxItem), _moveX(viewport, &QFxItem::setX), _moveY(viewport, &QFxItem::setY) , vWidth(-1), vHeight(-1), overShoot(true), flicked(false), moving(false), stealMouse(false) - , pressed(false), maxVelocity(-1), interactive(true), dragMode(QFxFlickable::Hard) - , elasticY(_moveY), elasticX(_moveX), reportedVelocitySmoothing(100), horizontalVelocity(this), verticalVelocity(this) - , vTime(0), atXEnd(false), atXBeginning(true), pageXPosition(0.), pageWidth(0.) - , atYEnd(false), atYBeginning(true), pageYPosition(0.), pageHeight(0.) + , pressed(false), atXEnd(false), atXBeginning(true), atYEnd(false), atYBeginning(true) + , interactive(true), maxVelocity(-1), reportedVelocitySmoothing(100) + , horizontalVelocity(this), verticalVelocity(this), vTime(0), visibleArea(0) { fixupXEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupX>(&_moveX, this); fixupYEvent = QmlTimeLineEvent::timeLineEvent<QFxFlickablePrivate, &QFxFlickablePrivate::fixupY>(&_moveY, this); @@ -107,15 +157,13 @@ QFxFlickablePrivate::QFxFlickablePrivate() void QFxFlickablePrivate::init() { Q_Q(QFxFlickable); - _flick->setParent(q); - QObject::connect(&_tl, SIGNAL(updated()), q, SLOT(ticked())); - QObject::connect(&_tl, SIGNAL(completed()), q, SLOT(movementEnding())); + viewport->setParent(q); + QObject::connect(&timeline, SIGNAL(updated()), q, SLOT(ticked())); + QObject::connect(&timeline, SIGNAL(completed()), q, SLOT(movementEnding())); q->setAcceptedMouseButtons(Qt::LeftButton); q->setFiltersChildEvents(true); - QObject::connect(_flick, SIGNAL(xChanged()), q, SIGNAL(positionXChanged())); - QObject::connect(_flick, SIGNAL(yChanged()), q, SIGNAL(positionYChanged())); - QObject::connect(&elasticX, SIGNAL(updated()), q, SLOT(ticked())); - QObject::connect(&elasticY, SIGNAL(updated()), q, SLOT(ticked())); + QObject::connect(viewport, SIGNAL(xChanged()), q, SIGNAL(positionXChanged())); + QObject::connect(viewport, SIGNAL(yChanged()), q, SIGNAL(positionYChanged())); QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(heightChange())); QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(widthChange())); } @@ -142,16 +190,16 @@ void QFxFlickablePrivate::flickX(qreal velocity) else v = maxVelocity; } - _tl.reset(_moveX); - _tl.accel(_moveX, v, 500, maxDistance); - _tl.execute(fixupXEvent); + timeline.reset(_moveX); + timeline.accel(_moveX, v, 500, maxDistance); + timeline.execute(fixupXEvent); if (!flicked) { flicked = true; emit q->flickingChanged(); emit q->flickStarted(); } } else { - _tl.reset(_moveX); + timeline.reset(_moveX); fixupX(); } } @@ -178,16 +226,16 @@ void QFxFlickablePrivate::flickY(qreal velocity) else v = maxVelocity; } - _tl.reset(_moveY); - _tl.accel(_moveY, v, 500, maxDistance); - _tl.execute(fixupYEvent); + timeline.reset(_moveY); + timeline.accel(_moveY, v, 500, maxDistance); + timeline.execute(fixupYEvent); if (!flicked) { flicked = true; emit q->flickingChanged(); emit q->flickStarted(); } } else { - _tl.reset(_moveY); + timeline.reset(_moveY); fixupY(); } } @@ -198,16 +246,16 @@ void QFxFlickablePrivate::fixupX() if (!q->xflick() || _moveX.timeLine()) return; - vTime = _tl.time(); + vTime = timeline.time(); - if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->maxXExtent())) { - _tl.reset(_moveY); + if (_moveX.value() > q->minXExtent() || (q->maxXExtent() > q->minXExtent())) { + timeline.reset(_moveX); if (_moveX.value() != q->minXExtent()) - _tl.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveX, q->minXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); //emit flickingChanged(); } else if (_moveX.value() < q->maxXExtent()) { - _tl.reset(_moveY); - _tl.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.reset(_moveX); + timeline.move(_moveX, q->maxXExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); //emit flickingChanged(); } else { flicked = false; @@ -220,16 +268,16 @@ void QFxFlickablePrivate::fixupY() if (!q->yflick() || _moveY.timeLine()) return; - vTime = _tl.time(); + vTime = timeline.time(); if (_moveY.value() > q->minYExtent() || (q->maxYExtent() > q->minYExtent())) { - _tl.reset(_moveY); + timeline.reset(_moveY); if (_moveY.value() != q->minYExtent()) - _tl.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.move(_moveY, q->minYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); //emit flickingChanged(); } else if (_moveY.value() < q->maxYExtent()) { - _tl.reset(_moveY); - _tl.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.reset(_moveY); + timeline.move(_moveY, q->maxYExtent(), QEasingCurve(QEasingCurve::InOutQuad), 200); //emit flickingChanged(); } else { flicked = false; @@ -239,26 +287,14 @@ void QFxFlickablePrivate::fixupY() void QFxFlickablePrivate::updateBeginningEnd() { Q_Q(QFxFlickable); - bool pageChange = false; bool atBoundaryChange = false; // Vertical - const int viewheight = q->height(); const int maxyextent = int(-q->maxYExtent()); const qreal ypos = -_moveY.value(); - qreal pagePos = ((ypos * 100.0) / (maxyextent + viewheight)) / 100.0; - qreal pageSize = ((viewheight * 100.0) / (maxyextent + viewheight)) / 100.0; bool atBeginning = (ypos <= 0.0); bool atEnd = (maxyextent <= ypos); - if (pageSize != pageHeight) { - pageHeight = pageSize; - pageChange = true; - } - if (pagePos != pageYPosition) { - pageYPosition = pagePos; - pageChange = true; - } if (atBeginning != atYBeginning) { atYBeginning = atBeginning; atBoundaryChange = true; @@ -269,22 +305,11 @@ void QFxFlickablePrivate::updateBeginningEnd() } // Horizontal - const int viewwidth = q->width(); const int maxxextent = int(-q->maxXExtent()); const qreal xpos = -_moveX.value(); - pagePos = ((xpos * 100.0) / (maxxextent + viewwidth)) / 100.0; - pageSize = ((viewwidth * 100.0) / (maxxextent + viewwidth)) / 100.0; atBeginning = (xpos <= 0.0); atEnd = (maxxextent <= xpos); - if (pageSize != pageWidth) { - pageWidth = pageSize; - pageChange = true; - } - if (pagePos != pageXPosition) { - pageXPosition = pagePos; - pageChange = true; - } if (atBeginning != atXBeginning) { atXBeginning = atBeginning; atBoundaryChange = true; @@ -294,10 +319,11 @@ void QFxFlickablePrivate::updateBeginningEnd() atBoundaryChange = true; } - if (pageChange) - emit q->pageChanged(); if (atBoundaryChange) emit q->isAtBoundaryChanged(); + + if (visibleArea) + visibleArea->updateVisible(); } static const int FlickThreshold = 5; @@ -350,6 +376,27 @@ Flickable { */ +/*! + \qmlproperty real Flickable::visibleArea.xPosition + \qmlproperty real Flickable::visibleArea.widthRatio + \qmlproperty real Flickable::visibleArea.yPosition + \qmlproperty real Flickable::visibleArea.heightRatio + + These properties describe the position and size of the currently viewed area. + The size is defined as the percentage of the full view currently visible, + scaled to 0.0 - 1.0. The page position is in the range 0.0 (beginning) to + size ratio (end), i.e. yPosition is in the range 0.0 - heightRatio. + + These properties are typically used to draw a scrollbar, for example: + \code + Rectangle { + opacity: 0.5; anchors.right: MyListView.right-2; width: 6 + y: MyListView.visibleArea.yPosition * MyListView.height + height: MyListView.visibleArea.heightRatio * MyListView.height + } + \endcode +*/ + QFxFlickable::QFxFlickable(QFxItem *parent) : QFxItem(*(new QFxFlickablePrivate), parent) { @@ -387,7 +434,7 @@ void QFxFlickable::setViewportX(qreal pos) Q_D(QFxFlickable); pos = qRound(pos); if (-pos != d->_moveX.value()) { - d->_tl.reset(d->_moveX); + d->timeline.reset(d->_moveX); d->_moveX.setValue(-pos); viewportMoved(); } @@ -404,7 +451,7 @@ void QFxFlickable::setViewportY(qreal pos) Q_D(QFxFlickable); pos = qRound(pos); if (-pos != d->_moveY.value()) { - d->_tl.reset(d->_moveY); + d->timeline.reset(d->_moveY); d->_moveY.setValue(-pos); viewportMoved(); } @@ -430,7 +477,7 @@ void QFxFlickable::setInteractive(bool interactive) Q_D(QFxFlickable); d->interactive = interactive; if (!interactive && d->flicked) { - d->_tl.clear(); + d->timeline.clear(); d->flicked = false; emit flickingChanged(); emit flickEnded(); @@ -438,28 +485,6 @@ void QFxFlickable::setInteractive(bool interactive) } /*! - \qmlproperty enumeration Flickable::dragMode - This property contains the kind of 'physics' applied when dragging the surface. - - Two modes are supported: - \list - \i Hard - the view follows the user's input exactly. - \i Elastic - the view moves elastically in response to the user's input. - \endlist -*/ -QFxFlickable::DragMode QFxFlickable::dragMode() const -{ - Q_D(const QFxFlickable); - return d->dragMode; -} - -void QFxFlickable::setDragMode(DragMode mode) -{ - Q_D(QFxFlickable); - d->dragMode = mode; -} - -/*! \qmlproperty real Flickable::horizontalVelocity \qmlproperty real Flickable::verticalVelocity \qmlproperty real Flickable::reportedVelocitySmoothing @@ -514,50 +539,6 @@ bool QFxFlickable::isAtYBeginning() const return d->atYBeginning; } -/*! - \qmlproperty real Flickable::pageXPosition - \qmlproperty real Flickable::pageWidth - \qmlproperty real Flickable::pageYPosition - \qmlproperty real Flickable::pageHeight - - These properties describe the position and size of the currently viewed page. - The page size is defined as the percentage of the full view currently visible, - scaled to 0.0 - 1.0. The page position is also in the range 0.0 (beginning) to - 1.0 (end). - - These properties are typically used to draw a scrollbar, for example: - \code - Rectangle { - opacity: 0.5; anchors.right: MyListView.right-2; width: 6 - y: MyListView.pageYPosition * MyListView.height - height: MyListView.pageHeight * MyListView.height - } - \endcode -*/ -qreal QFxFlickable::pageWidth() const -{ - Q_D(const QFxFlickable); - return d->pageWidth; -} - -qreal QFxFlickable::pageXPosition() const -{ - Q_D(const QFxFlickable); - return d->pageXPosition; -} - -qreal QFxFlickable::pageHeight() const -{ - Q_D(const QFxFlickable); - return d->pageHeight; -} - -qreal QFxFlickable::pageYPosition() const -{ - Q_D(const QFxFlickable); - return d->pageYPosition; -} - void QFxFlickable::ticked() { viewportMoved(); @@ -566,7 +547,7 @@ void QFxFlickable::ticked() QFxItem *QFxFlickable::viewport() { Q_D(QFxFlickable); - return d->_flick; + return d->viewport; } qreal QFxFlickable::visibleX() const @@ -581,14 +562,22 @@ qreal QFxFlickable::visibleY() const return -d->_moveY.value(); } +QFxFlickableVisibleArea *QFxFlickable::visibleArea() +{ + Q_D(QFxFlickable); + if (!d->visibleArea) + d->visibleArea = new QFxFlickableVisibleArea(this); + return d->visibleArea; +} + void QFxFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) { - if (interactive && _tl.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10)) + if (interactive && timeline.isActive() && (qAbs(velocityX) > 10 || qAbs(velocityY) > 10)) stealMouse = true; // If we've been flicked then steal the click. else stealMouse = false; pressed = true; - _tl.clear(); + timeline.clear(); velocityX = -1; velocityY = -1; lastPos = QPoint(); @@ -598,10 +587,6 @@ void QFxFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) pressY = _moveY.value(); flicked = false; pressTime.start(); - if (dragMode == QFxFlickable::Elastic) { - elasticX.clear(); - elasticY.clear(); - } velocityTime.start(); } @@ -625,10 +610,7 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) if (newY < maxY && maxY - minY < 0) newY = maxY + (newY - maxY) / 2; if (q->overShoot() || (newY <= minY && newY >= maxY)) { - if (dragMode == QFxFlickable::Hard) - _moveY.setValue(newY); - else - elasticY.setValue(newY); + _moveY.setValue(newY); moved = true; } else if (!q->overShoot()) rejectY = true; @@ -648,10 +630,7 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) if (newX < maxX && maxX - minX < 0) newX = maxX + (newX - maxX) / 2; if (q->overShoot() || (newX <= minX && newX >= maxX)) { - if (dragMode == QFxFlickable::Hard) - _moveX.setValue(newX); - else - elasticX.setValue(newX); + _moveX.setValue(newX); moved = true; } else if (!q->overShoot()) rejectX = true; @@ -693,12 +672,7 @@ void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) if (lastPosTime.isNull()) return; - if (dragMode == QFxFlickable::Elastic) { - elasticY.clear(); - elasticX.clear(); - } - - vTime = _tl.time(); + vTime = timeline.time(); if (qAbs(velocityY) > 10) flickY(velocityY); else @@ -712,7 +686,7 @@ void QFxFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) stealMouse = false; lastPosTime = QTime(); - if (!_tl.isActive()) + if (!timeline.isActive()) q->movementEnding(); } @@ -777,13 +751,13 @@ void QFxFlickable::viewportMoved() d->velocityTimeline.move(d->verticalVelocity, verticalVelocity, d->reportedVelocitySmoothing); d->velocityTimeline.move(d->verticalVelocity, 0, d->reportedVelocitySmoothing); } else { - if (d->_tl.time() != d->vTime) { - qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / (d->_tl.time() - d->vTime); - qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / (d->_tl.time() - d->vTime); + if (d->timeline.time() != d->vTime) { + qreal horizontalVelocity = (prevX - d->_moveX.value()) * 1000 / (d->timeline.time() - d->vTime); + qreal verticalVelocity = (prevY - d->_moveY.value()) * 1000 / (d->timeline.time() - d->vTime); d->horizontalVelocity.setValue(horizontalVelocity); d->verticalVelocity.setValue(verticalVelocity); } - d->vTime = d->_tl.time(); + d->vTime = d->timeline.time(); } } @@ -832,7 +806,7 @@ void QFxFlickablePrivate::data_append(QObject *o) Q_Q(QFxFlickable); QFxItem *i = qobject_cast<QFxItem *>(o); if (i) - _flick->children()->append(i); + viewport->children()->append(i); else o->setParent(q); } @@ -863,7 +837,7 @@ QmlList<QObject *> *QFxFlickable::flickableData() QmlList<QFxItem *> *QFxFlickable::flickableChildren() { Q_D(QFxFlickable); - return d->_flick->children(); + return d->viewport->children(); } /*! @@ -915,9 +889,9 @@ void QFxFlickable::setViewportWidth(qreal w) return; d->vWidth = w; if (w < 0) - d->_flick->setWidth(width()); + d->viewport->setWidth(width()); else - d->_flick->setWidth(w); + d->viewport->setWidth(w); // Make sure that we're entirely in view. if (!d->pressed) d->fixupX(); @@ -929,20 +903,20 @@ void QFxFlickable::widthChange() { Q_D(QFxFlickable); if (d->vWidth < 0) { - d->_flick->setWidth(width()); + d->viewport->setWidth(width()); emit viewportWidthChanged(); - d->updateBeginningEnd(); } + d->updateBeginningEnd(); } void QFxFlickable::heightChange() { Q_D(QFxFlickable); if (d->vHeight < 0) { - d->_flick->setHeight(height()); + d->viewport->setHeight(height()); emit viewportHeightChanged(); - d->updateBeginningEnd(); } + d->updateBeginningEnd(); } qreal QFxFlickable::viewportHeight() const @@ -958,9 +932,9 @@ void QFxFlickable::setViewportHeight(qreal h) return; d->vHeight = h; if (h < 0) - d->_flick->setHeight(height()); + d->viewport->setHeight(height()); else - d->_flick->setHeight(h); + d->viewport->setHeight(h); // Make sure that we're entirely in view. if (!d->pressed) d->fixupY(); @@ -1136,3 +1110,8 @@ void QFxFlickablePrivate::updateVelocity() } QT_END_NAMESPACE + +QML_DECLARE_TYPE(QFxFlickableVisibleArea) +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,VisibleArea,QFxFlickableVisibleArea) + +#include "qfxflickable.moc" diff --git a/src/declarative/fx/qfxflickable.h b/src/declarative/fx/qfxflickable.h index 57a01d7..4905101 100644 --- a/src/declarative/fx/qfxflickable.h +++ b/src/declarative/fx/qfxflickable.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QFxFlickablePrivate; +class QFxFlickableVisibleArea; class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem { Q_OBJECT @@ -70,17 +71,13 @@ class Q_DECLARATIVE_EXPORT QFxFlickable : public QFxItem Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged) Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive) - Q_PROPERTY(DragMode dragMode READ dragMode WRITE setDragMode) //### remove. Consider a better way to implement different drag behavior Q_PROPERTY(bool atXEnd READ isAtXEnd NOTIFY isAtBoundaryChanged) Q_PROPERTY(bool atYEnd READ isAtYEnd NOTIFY isAtBoundaryChanged) Q_PROPERTY(bool atXBeginning READ isAtXBeginning NOTIFY isAtBoundaryChanged) Q_PROPERTY(bool atYBeginning READ isAtYBeginning NOTIFY isAtBoundaryChanged) - Q_PROPERTY(qreal pageXPosition READ pageXPosition NOTIFY pageChanged) //### visibleArea.xPosition - Q_PROPERTY(qreal pageYPosition READ pageYPosition NOTIFY pageChanged) //### visibleArea.yPosition - Q_PROPERTY(qreal pageWidth READ pageWidth NOTIFY pageChanged) //### visibleArea.widthRatio - Q_PROPERTY(qreal pageHeight READ pageHeight NOTIFY pageChanged) //### visibleArea.heightRatio + Q_PROPERTY(QFxFlickableVisibleArea *visibleArea READ visibleArea CONSTANT) Q_PROPERTY(QmlList<QObject *>* flickableData READ flickableData) Q_PROPERTY(QmlList<QFxItem *>* flickableChildren READ flickableChildren) @@ -120,23 +117,13 @@ public: bool isInteractive() const; void setInteractive(bool); - Q_ENUMS(DragMode) - enum DragMode { Hard, Elastic }; - DragMode dragMode() const; - void setDragMode(DragMode mode); - qreal horizontalVelocity() const; qreal verticalVelocity() const; bool isAtXEnd() const; bool isAtXBeginning() const; - qreal pageXPosition() const; - qreal pageWidth() const; - bool isAtYEnd() const; bool isAtYBeginning() const; - qreal pageYPosition() const; - qreal pageHeight() const; QFxItem *viewport(); @@ -165,6 +152,8 @@ protected: qreal visibleX() const; qreal visibleY() const; + QFxFlickableVisibleArea *visibleArea(); + protected Q_SLOTS: virtual void ticked(); void movementStarting(); @@ -191,6 +180,7 @@ protected: private: Q_DISABLE_COPY(QFxFlickable) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxFlickable) + friend class QFxFlickableVisibleArea; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxflickable_p.h b/src/declarative/fx/qfxflickable_p.h index ad9484f..a506027 100644 --- a/src/declarative/fx/qfxflickable_p.h +++ b/src/declarative/fx/qfxflickable_p.h @@ -62,29 +62,7 @@ QT_BEGIN_NAMESPACE -class ElasticValue : public QAbstractAnimation { - Q_OBJECT -public: - ElasticValue(QmlTimeLineValue &); - void setValue(qreal to); - void clear(); - - virtual int duration() const { return 10000; } - -protected: - virtual void updateCurrentTime(int); - -Q_SIGNALS: - void updated(); - -private: - qreal _to; - qreal _myValue; - qreal _velocity; - QmlTimeLineValue &_value; - QTime _startTime; -}; - +class QFxFlickableVisibleArea; class QFxFlickablePrivate : public QFxItemPrivate { Q_DECLARE_PUBLIC(QFxFlickable) @@ -99,17 +77,22 @@ public: void updateBeginningEnd(); public: - QFxItem *_flick; + QFxItem *viewport; QmlTimeLineValueProxy<QFxItem> _moveX; QmlTimeLineValueProxy<QFxItem> _moveY; - QmlTimeLine _tl; + QmlTimeLine timeline; qreal vWidth; qreal vHeight; - bool overShoot; - bool flicked; - bool moving; - bool stealMouse; - bool pressed; + bool overShoot : 1; + bool flicked : 1; + bool moving : 1; + bool stealMouse : 1; + bool pressed : 1; + bool atXEnd : 1; + bool atXBeginning : 1; + bool atYEnd : 1; + bool atYBeginning : 1; + bool interactive : 1; QTime lastPosTime; QPointF lastPos; QPointF pressPos; @@ -121,10 +104,6 @@ public: QmlTimeLineEvent fixupXEvent; QmlTimeLineEvent fixupYEvent; qreal maxVelocity; - bool interactive; - QFxFlickable::DragMode dragMode; - ElasticValue elasticY; - ElasticValue elasticX; QTime velocityTime; QPointF lastFlickablePosition; qreal reportedVelocitySmoothing; @@ -146,14 +125,7 @@ public: Velocity verticalVelocity; int vTime; QmlTimeLine velocityTimeline; - bool atXEnd; - bool atXBeginning; - qreal pageXPosition; - qreal pageWidth; - bool atYEnd; - bool atYBeginning; - qreal pageYPosition; - qreal pageHeight; + QFxFlickableVisibleArea *visibleArea; void handleMousePressEvent(QGraphicsSceneMouseEvent *); void handleMouseMoveEvent(QGraphicsSceneMouseEvent *); @@ -166,6 +138,8 @@ public: void data_insert(int, QObject *); QObject *data_at(int) const; void data_clear(); + + friend class QFxFlickableVisibleArea; QML_DECLARE_LIST_PROXY(QFxFlickablePrivate, QObject *, data) }; diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 34fe827..523786f 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -801,8 +801,8 @@ void QFxListViewPrivate::fixupY() if (currItemMode == QFxListView::SnapAuto) { if (currentItem) { moveReason = Mouse; - _tl.clear(); - _tl.move(_moveY, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.clear(); + timeline.move(_moveY, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200); } } else if (currItemMode == QFxListView::Snap) { moveReason = Mouse; @@ -813,8 +813,8 @@ void QFxListViewPrivate::fixupY() pos = -q->maxYExtent(); else if (pos < -q->minYExtent()) pos = -q->minYExtent(); - _tl.clear(); - _tl.move(_moveY, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.clear(); + timeline.move(_moveY, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200); } } } @@ -828,8 +828,8 @@ void QFxListViewPrivate::fixupX() if (currItemMode == QFxListView::SnapAuto) { if (currentItem) { moveReason = Mouse; - _tl.clear(); - _tl.move(_moveX, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.clear(); + timeline.move(_moveX, -(currentItem->position() - snapPos), QEasingCurve(QEasingCurve::InOutQuad), 200); } } else if (currItemMode == QFxListView::Snap) { moveReason = Mouse; @@ -840,8 +840,8 @@ void QFxListViewPrivate::fixupX() pos = -q->maxXExtent(); else if (pos < -q->minXExtent()) pos = -q->minXExtent(); - _tl.clear(); - _tl.move(_moveX, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200); + timeline.clear(); + timeline.move(_moveX, -(pos), QEasingCurve(QEasingCurve::InOutQuad), 200); } } } @@ -1600,7 +1600,7 @@ void QFxListView::itemsRemoved(int modelIndex, int count) if (d->visibleItems.isEmpty()) { d->visibleIndex = 0; d->visiblePos = 0; - d->_tl.clear(); + d->timeline.clear(); d->setPosition(0); if (d->model->count() == 0) update(); diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 6519dff..b8e9d47 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -783,6 +783,7 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction create; create.type = QmlInstruction::CreateObject; create.line = obj->location.start.line; + create.create.column = obj->location.start.column; create.create.data = -1; if (!obj->custom.isEmpty()) create.create.data = output->indexForByteArray(obj->custom); @@ -939,6 +940,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj) QmlInstruction create; create.type = QmlInstruction::CreateComponent; create.line = root->location.start.line; + create.createComponent.column = root->location.start.column; create.createComponent.endLine = root->location.end.line; output->bytecode << create; int count = output->bytecode.count(); diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index ede06a2..3c6af1b 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -284,6 +284,7 @@ public: } assignSignalObject; struct { int count; + ushort column; int endLine; int metaObject; } createComponent; diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index a49cbd3..4d133e3 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -222,6 +222,14 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData case QmlInstruction::CreateComponent: { QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top()); + + QmlEngine::setContextForObject(qcomp, ctxt); + QmlDeclarativeData *ddata = QmlDeclarativeData::get(qcomp); + Q_ASSERT(ddata); + ddata->outerContext = ctxt; + ddata->lineNumber = instr.line; + ddata->columnNumber = instr.create.column; + stack.push(qcomp); ii += instr.createComponent.count; } diff --git a/src/declarative/util/qmlanimation.h b/src/declarative/util/qmlanimation.h index a898be8..7104f60 100644 --- a/src/declarative/util/qmlanimation.h +++ b/src/declarative/util/qmlanimation.h @@ -58,7 +58,7 @@ QT_MODULE(Declarative) class QmlAbstractAnimationPrivate; class QmlAnimationGroup; -class QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, public QmlParserStatus +class Q_AUTOTEST_EXPORT QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, public QmlParserStatus { Q_OBJECT Q_DECLARE_PRIVATE(QmlAbstractAnimation) @@ -68,8 +68,6 @@ class QmlAbstractAnimation : public QObject, public QmlPropertyValueSource, publ Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(bool alwaysRunToEnd READ alwaysRunToEnd WRITE setAlwaysRunToEnd NOTIFY alwaysRunToEndChanged()) Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged) - //Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) - //Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) Q_CLASSINFO("DefaultMethod", "start()") Q_INTERFACES(QmlParserStatus) @@ -252,7 +250,7 @@ protected: }; class QmlPropertyAnimationPrivate; -class QmlPropertyAnimation : public QmlAbstractAnimation +class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) @@ -304,7 +302,7 @@ Q_SIGNALS: void propertiesChanged(const QString &); }; -class QmlColorAnimation : public QmlPropertyAnimation +class Q_AUTOTEST_EXPORT QmlColorAnimation : public QmlPropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) @@ -322,7 +320,7 @@ public: void setTo(const QColor &); }; -class QmlNumberAnimation : public QmlPropertyAnimation +class Q_AUTOTEST_EXPORT QmlNumberAnimation : public QmlPropertyAnimation { Q_OBJECT Q_DECLARE_PRIVATE(QmlPropertyAnimation) diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index 508ef43..da7d429 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -359,6 +359,9 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever } } } + if (!found) + action.event->saveForwardBindings(); + //### do we ever need to do saveForwardBindings when found == true? } else { action.fromBinding = action.property.binding(); diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 0b48449..255051f 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -95,6 +95,7 @@ public: virtual QList<Action> extraActions(); virtual bool changesBindings(); + virtual void saveForwardBindings() {} virtual void clearForwardBindings(); virtual void clearReverseBindings(); virtual bool override(ActionEvent*other); diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index 858a527..50f80f6 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -305,12 +305,19 @@ public: QStringList resetList; QFxAnchorLine left; QFxAnchorLine right; + QFxAnchorLine horizontalCenter; QFxAnchorLine top; QFxAnchorLine bottom; + QFxAnchorLine verticalCenter; + QFxAnchorLine baseline; + QFxAnchorLine origLeft; QFxAnchorLine origRight; + QFxAnchorLine origHCenter; QFxAnchorLine origTop; QFxAnchorLine origBottom; + QFxAnchorLine origVCenter; + QFxAnchorLine origBaseline; qreal origX; qreal origY; qreal origWidth; @@ -364,11 +371,15 @@ void QmlAnchorChanges::setReset(const QString &reset) } /*! - \qmlproperty AnchorLine AnchorChanges::top - \qmlproperty AnchorLine AnchorChanges::bottom \qmlproperty AnchorLine AnchorChanges::left \qmlproperty AnchorLine AnchorChanges::right - These properties change the \e left, \e top, \e right and \e bottom anchors of the item + \qmlproperty AnchorLine AnchorChanges::horizontalCenter + \qmlproperty AnchorLine AnchorChanges::top + \qmlproperty AnchorLine AnchorChanges::bottom + \qmlproperty AnchorLine AnchorChanges::verticalCenter + \qmlproperty AnchorLine AnchorChanges::baseline + + These properties change the respective anchors of the item. */ QFxAnchorLine QmlAnchorChanges::left() const @@ -395,6 +406,18 @@ void QmlAnchorChanges::setRight(const QFxAnchorLine &edge) d->right = edge; } +QFxAnchorLine QmlAnchorChanges::horizontalCenter() const +{ + Q_D(const QmlAnchorChanges); + return d->horizontalCenter; +} + +void QmlAnchorChanges::setHorizontalCenter(const QFxAnchorLine &edge) +{ + Q_D(QmlAnchorChanges); + d->horizontalCenter = edge; +} + QFxAnchorLine QmlAnchorChanges::top() const { Q_D(const QmlAnchorChanges); @@ -419,6 +442,30 @@ void QmlAnchorChanges::setBottom(const QFxAnchorLine &edge) d->bottom = edge; } +QFxAnchorLine QmlAnchorChanges::verticalCenter() const +{ + Q_D(const QmlAnchorChanges); + return d->verticalCenter; +} + +void QmlAnchorChanges::setVerticalCenter(const QFxAnchorLine &edge) +{ + Q_D(QmlAnchorChanges); + d->verticalCenter = edge; +} + +QFxAnchorLine QmlAnchorChanges::baseline() const +{ + Q_D(const QmlAnchorChanges); + return d->baseline; +} + +void QmlAnchorChanges::setBaseline(const QFxAnchorLine &edge) +{ + Q_D(QmlAnchorChanges); + d->baseline = edge; +} + void QmlAnchorChanges::execute() { Q_D(QmlAnchorChanges); @@ -430,10 +477,16 @@ void QmlAnchorChanges::execute() d->target->anchors()->setLeft(d->left); if (d->right.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setRight(d->right); + if (d->horizontalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setHorizontalCenter(d->horizontalCenter); if (d->top.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setTop(d->top); if (d->bottom.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setBottom(d->bottom); + if (d->verticalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setVerticalCenter(d->verticalCenter); + if (d->baseline.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setBaseline(d->baseline); } bool QmlAnchorChanges::isReversable() @@ -452,10 +505,16 @@ void QmlAnchorChanges::reverse() d->target->anchors()->setLeft(d->origLeft); if (d->origRight.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setRight(d->origRight); + if (d->origHCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setHorizontalCenter(d->origHCenter); if (d->origTop.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setTop(d->origTop); if (d->origBottom.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->setBottom(d->origBottom); + if (d->origVCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setVerticalCenter(d->origVCenter); + if (d->origBaseline.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->setBaseline(d->origBaseline); } QString QmlAnchorChanges::typeName() const @@ -498,13 +557,21 @@ bool QmlAnchorChanges::changesBindings() return true; } -void QmlAnchorChanges::clearForwardBindings() +void QmlAnchorChanges::saveForwardBindings() { Q_D(QmlAnchorChanges); d->origLeft = d->target->anchors()->left(); d->origRight = d->target->anchors()->right(); + d->origHCenter = d->target->anchors()->horizontalCenter(); d->origTop = d->target->anchors()->top(); d->origBottom = d->target->anchors()->bottom(); + d->origVCenter = d->target->anchors()->verticalCenter(); + d->origBaseline = d->target->anchors()->baseline(); +} + +void QmlAnchorChanges::clearForwardBindings() +{ + Q_D(QmlAnchorChanges); d->origX = d->target->x(); d->origY = d->target->y(); d->origWidth = d->target->width(); @@ -515,20 +582,32 @@ void QmlAnchorChanges::clearForwardBindings() d->target->anchors()->resetLeft(); if (d->resetList.contains(QLatin1String("right"))) d->target->anchors()->resetRight(); + if (d->resetList.contains(QLatin1String("horizontalCenter"))) + d->target->anchors()->resetHorizontalCenter(); if (d->resetList.contains(QLatin1String("top"))) d->target->anchors()->resetTop(); if (d->resetList.contains(QLatin1String("bottom"))) d->target->anchors()->resetBottom(); + if (d->resetList.contains(QLatin1String("verticalCenter"))) + d->target->anchors()->resetVerticalCenter(); + if (d->resetList.contains(QLatin1String("baseline"))) + d->target->anchors()->resetBaseline(); //reset any anchors that we'll be setting in the state if (d->left.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetLeft(); if (d->right.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetRight(); + if (d->horizontalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetHorizontalCenter(); if (d->top.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetTop(); if (d->bottom.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetBottom(); + if (d->verticalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetVerticalCenter(); + if (d->baseline.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetBaseline(); } void QmlAnchorChanges::clearReverseBindings() @@ -544,20 +623,32 @@ void QmlAnchorChanges::clearReverseBindings() d->target->anchors()->resetLeft(); if (d->right.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetRight(); + if (d->horizontalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetHorizontalCenter(); if (d->top.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetTop(); if (d->bottom.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetBottom(); + if (d->verticalCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetVerticalCenter(); + if (d->baseline.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetBaseline(); //reset any anchors that were set in the original state if (d->origLeft.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetLeft(); if (d->origRight.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetRight(); + if (d->origHCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetHorizontalCenter(); if (d->origTop.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetTop(); if (d->origBottom.anchorLine != QFxAnchorLine::Invalid) d->target->anchors()->resetBottom(); + if (d->origVCenter.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetVerticalCenter(); + if (d->origBaseline.anchorLine != QFxAnchorLine::Invalid) + d->target->anchors()->resetBaseline(); } bool QmlAnchorChanges::override(ActionEvent*other) diff --git a/src/declarative/util/qmlstateoperations.h b/src/declarative/util/qmlstateoperations.h index afe0bd5..a3943e7 100644 --- a/src/declarative/util/qmlstateoperations.h +++ b/src/declarative/util/qmlstateoperations.h @@ -113,8 +113,11 @@ class Q_DECLARATIVE_EXPORT QmlAnchorChanges : public QmlStateOperation, public A Q_PROPERTY(QString reset READ reset WRITE setReset) Q_PROPERTY(QFxAnchorLine left READ left WRITE setLeft) Q_PROPERTY(QFxAnchorLine right READ right WRITE setRight) + Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter) Q_PROPERTY(QFxAnchorLine top READ top WRITE setTop) Q_PROPERTY(QFxAnchorLine bottom READ bottom WRITE setBottom) + Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter) + Q_PROPERTY(QFxAnchorLine baseline READ baseline WRITE setBaseline) public: QmlAnchorChanges(QObject *parent=0); @@ -134,12 +137,21 @@ public: QFxAnchorLine right() const; void setRight(const QFxAnchorLine &edge); + QFxAnchorLine horizontalCenter() const; + void setHorizontalCenter(const QFxAnchorLine &edge); + QFxAnchorLine top() const; void setTop(const QFxAnchorLine &edge); QFxAnchorLine bottom() const; void setBottom(const QFxAnchorLine &edge); + QFxAnchorLine verticalCenter() const; + void setVerticalCenter(const QFxAnchorLine &edge); + + QFxAnchorLine baseline() const; + void setBaseline(const QFxAnchorLine &edge); + virtual void execute(); virtual bool isReversable(); virtual void reverse(); @@ -147,6 +159,7 @@ public: virtual bool override(ActionEvent*other); virtual QList<Action> extraActions(); virtual bool changesBindings(); + virtual void saveForwardBindings(); virtual void clearForwardBindings(); virtual void clearReverseBindings(); }; diff --git a/tests/auto/declarative/animations/data/badproperty1.qml b/tests/auto/declarative/animations/data/badproperty1.qml index b88cd6f..a01753e 100644 --- a/tests/auto/declarative/animations/data/badproperty1.qml +++ b/tests/auto/declarative/animations/data/badproperty1.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: Wrapper width: 240 height: 320 - Rect { + Rectangle { id: MyRect color: "red" width: 50; height: 50 @@ -16,7 +16,7 @@ Rect { } states: State { name: "state1" - SetProperties { target: MyRect; pen.color: "blue" } + PropertyChanges { target: MyRect; pen.color: "blue" } } transitions: Transition { ColorAnimation { target: MyRect; to: "red"; properties: "pen.colr"; duration: 1000 } diff --git a/tests/auto/declarative/animations/data/badtype1.qml b/tests/auto/declarative/animations/data/badtype1.qml index 00db39e..1e689d5 100644 --- a/tests/auto/declarative/animations/data/badtype1.qml +++ b/tests/auto/declarative/animations/data/badtype1.qml @@ -1,9 +1,9 @@ import Qt 4.6 -Rect { +Rectangle { width: 240 height: 320 - Rect { + Rectangle { color: "red" width: 50; height: 50 x: 100; y: 100 diff --git a/tests/auto/declarative/animations/data/badtype2.qml b/tests/auto/declarative/animations/data/badtype2.qml index eeaaefc..e97194d 100644 --- a/tests/auto/declarative/animations/data/badtype2.qml +++ b/tests/auto/declarative/animations/data/badtype2.qml @@ -1,9 +1,9 @@ import Qt 4.6 -Rect { +Rectangle { width: 240 height: 320 - Rect { + Rectangle { color: "red" width: 50; height: 50 x: 100; y: 100 diff --git a/tests/auto/declarative/animations/data/badtype3.qml b/tests/auto/declarative/animations/data/badtype3.qml index cbb1a4d..b2d738f 100644 --- a/tests/auto/declarative/animations/data/badtype3.qml +++ b/tests/auto/declarative/animations/data/badtype3.qml @@ -1,9 +1,9 @@ import Qt 4.6 -Rect { +Rectangle { width: 240 height: 320 - Rect { + Rectangle { color: "red" color: ColorAnimation { from: 10; to: 15; running: true; } width: 50; height: 50 diff --git a/tests/auto/declarative/animations/data/badtype4.qml b/tests/auto/declarative/animations/data/badtype4.qml index 3e046fc..0c0a636 100644 --- a/tests/auto/declarative/animations/data/badtype4.qml +++ b/tests/auto/declarative/animations/data/badtype4.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: Wrapper width: 240 height: 320 - Rect { + Rectangle { id: MyRect color: "red" width: 50; height: 50 @@ -16,10 +16,11 @@ Rect { } states: State { name: "state1" - SetProperties { target: MyRect; x: 200; color: "blue" } + PropertyChanges { target: MyRect; x: 200; color: "blue" } } transitions: Transition { + //comment out each in turn to make sure each only animates the relevant property ColorAnimation { properties: "x,color"; duration: 1000 } //x is real, color is color - //NumberAnimation { properties: "x,color"; duration: 1000 } //x is real, color is color + NumberAnimation { properties: "x,color"; duration: 1000 } //x is real, color is color } } diff --git a/tests/auto/declarative/animations/data/color.qml b/tests/auto/declarative/animations/data/color.qml deleted file mode 100644 index 8a9ab8a..0000000 --- a/tests/auto/declarative/animations/data/color.qml +++ /dev/null @@ -1,12 +0,0 @@ -import Qt 4.6 - -Rect { - width: 240 - height: 320 - Rect { - color: "red" - color: PropertyAnimation { to: "green"; running: true } - width: 50; height: 50 - x: 100; y: 100 - } -} diff --git a/tests/auto/declarative/animations/data/dotproperty.qml b/tests/auto/declarative/animations/data/dotproperty.qml index 25076b8..ee076c2 100644 --- a/tests/auto/declarative/animations/data/dotproperty.qml +++ b/tests/auto/declarative/animations/data/dotproperty.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: Wrapper width: 240 height: 320 - Rect { + Rectangle { id: MyRect color: "red" width: 50; height: 50 @@ -16,7 +16,7 @@ Rect { } states: State { name: "state1" - SetProperties { target: MyRect; pen.color: "blue" } + PropertyChanges { target: MyRect; pen.color: "blue" } } transitions: Transition { ColorAnimation { properties: "pen.color"; duration: 1000 } diff --git a/tests/auto/declarative/animations/data/mixedtype1.qml b/tests/auto/declarative/animations/data/mixedtype1.qml index 8b8262b..ed50582 100644 --- a/tests/auto/declarative/animations/data/mixedtype1.qml +++ b/tests/auto/declarative/animations/data/mixedtype1.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: Wrapper width: 240 height: 320 - Rect { + Rectangle { id: MyRect color: "red" width: 50; height: 50 @@ -16,9 +16,9 @@ Rect { } states: State { name: "state1" - SetProperties { target: MyRect; x: 200; width: 40 } + PropertyChanges { target: MyRect; x: 200; border.width: 10 } } transitions: Transition { - PropertyAnimation { properties: "x,width"; duration: 1000 } //x is real, width is int + PropertyAnimation { properties: "x,border.width"; duration: 1000 } //x is real, border.width is int } } diff --git a/tests/auto/declarative/animations/data/mixedtype2.qml b/tests/auto/declarative/animations/data/mixedtype2.qml index 95b8ed7..4854c2e 100644 --- a/tests/auto/declarative/animations/data/mixedtype2.qml +++ b/tests/auto/declarative/animations/data/mixedtype2.qml @@ -1,10 +1,10 @@ import Qt 4.6 -Rect { +Rectangle { id: Wrapper width: 240 height: 320 - Rect { + Rectangle { id: MyRect color: "red" width: 50; height: 50 @@ -16,7 +16,7 @@ Rect { } states: State { name: "state1" - SetProperties { target: MyRect; x: 200; color: "blue" } + PropertyChanges { target: MyRect; x: 200; color: "blue" } } transitions: Transition { PropertyAnimation { properties: "x,color"; duration: 1000 } //x is real, color is color diff --git a/tests/auto/declarative/animations/data/number.qml b/tests/auto/declarative/animations/data/number.qml deleted file mode 100644 index bde1168..0000000 --- a/tests/auto/declarative/animations/data/number.qml +++ /dev/null @@ -1,12 +0,0 @@ -import Qt 4.6 - -Rect { - width: 240 - height: 320 - Rect { - color: "red" - width: 50; height: 50 - x: 100; y: 100 - x: PropertyAnimation { from: 0; to: 200; duration: 1000; running: true } - } -} diff --git a/tests/auto/declarative/animations/tst_animations.cpp b/tests/auto/declarative/animations/tst_animations.cpp index 889d9b7..8e1abc6 100644 --- a/tests/auto/declarative/animations/tst_animations.cpp +++ b/tests/auto/declarative/animations/tst_animations.cpp @@ -3,6 +3,7 @@ #include <QtDeclarative/qmlcomponent.h> #include <QtDeclarative/qfxview.h> #include <QtDeclarative/qfxrect.h> +#include <QtDeclarative/QmlNumberAnimation> class tst_animations : public QObject { @@ -11,11 +12,87 @@ public: tst_animations() {} private slots: + void simpleNumber(); + void simpleColor(); + void alwaysRunToEnd(); + void dotProperty(); void badTypes(); void badProperties(); - //void mixedTypes(); + void mixedTypes(); }; +void tst_animations::simpleNumber() +{ + QFxRect rect; + QmlNumberAnimation animation; + animation.setTarget(&rect); + animation.setProperty("x"); + animation.setTo(200); + animation.start(); + QTest::qWait(animation.duration() + 50); + QCOMPARE(rect.x(), qreal(200)); + + rect.setX(0); + animation.start(); + animation.pause(); + animation.setCurrentTime(125); + QCOMPARE(rect.x(), qreal(100)); +} + +void tst_animations::simpleColor() +{ + QFxRect rect; + QmlColorAnimation animation; + animation.setTarget(&rect); + animation.setProperty("color"); + animation.setTo(QColor("red")); + animation.start(); + QTest::qWait(animation.duration() + 50); + QCOMPARE(rect.color(), QColor("red")); + + rect.setColor(QColor("blue")); + animation.start(); + animation.pause(); + animation.setCurrentTime(125); + QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1)); +} + +void tst_animations::alwaysRunToEnd() +{ + QFxRect rect; + QmlPropertyAnimation animation; + animation.setTarget(&rect); + animation.setProperty("x"); + animation.setTo(200); + animation.setDuration(1000); + animation.setRepeat(true); + animation.setAlwaysRunToEnd(true); + animation.start(); + QTest::qWait(1500); + animation.stop(); + QVERIFY(rect.x() != qreal(200)); + QTest::qWait(500 + 50); + QCOMPARE(rect.x(), qreal(200)); +} + +void tst_animations::dotProperty() +{ + QFxRect rect; + QmlNumberAnimation animation; + animation.setTarget(&rect); + animation.setProperty("border.width"); + animation.setTo(10); + animation.start(); + QTest::qWait(animation.duration() + 50); + QCOMPARE(rect.border()->width(), 10); + + rect.border()->setWidth(1); + animation.start(); + animation.pause(); + animation.setCurrentTime(125); + QCOMPARE(rect.border()->width(), 5); +} + void tst_animations::badTypes() { //don't crash @@ -50,47 +127,73 @@ void tst_animations::badTypes() QVERIFY(c.errors().count() == 1); QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected")); } + + //don't crash + { + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/badtype4.qml")); + QFxRect *rect = qobject_cast<QFxRect*>(c.create()); + QVERIFY(rect); + + rect->setState("state1"); + QTest::qWait(1000 + 50); + QFxRect *myRect = qobject_cast<QFxRect*>(rect->QGraphicsObject::children().at(3)); //### not robust + QVERIFY(myRect); + QCOMPARE(myRect->x(),qreal(200)); + } } void tst_animations::badProperties() { - //don't crash (should be runtime error) + //make sure we get a runtime error { - QFxView *view = new QFxView; - view->setUrl(QUrl("file://" SRCDIR "/data/badproperty1.qml")); - - view->execute(); - qApp->processEvents(); + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/badproperty1.qml")); + QFxRect *rect = qobject_cast<QFxRect*>(c.create()); + QVERIFY(rect); - delete view; + QTest::ignoreMessage(QtWarningMsg, "QML QmlColorAnimation (file://" SRCDIR "/data/badproperty1.qml:22:9) Cannot animate non-existant property \"pen.colr\" "); + rect->setState("state1"); } } -/*//test animating mixed types with property animation - //for example, int + real; color + real; etc +//test animating mixed types with property animation in a transition +//for example, int + real; color + real; etc void tst_animations::mixedTypes() { - //### this one isn't real robust because width will likely change to real as well + //assumes border.width stats a real -- not real robust { - QFxView *view = new QFxView; - view->setUrl(QUrl("file://" SRCDIR "/data/mixedtype1.qml")); - - view->execute(); - qApp->processEvents(); - - delete view; + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/mixedtype1.qml")); + QFxRect *rect = qobject_cast<QFxRect*>(c.create()); + QVERIFY(rect); + + rect->setState("state1"); + QTest::qWait(500); + QFxRect *myRect = qobject_cast<QFxRect*>(rect->QGraphicsObject::children().at(3)); //### not robust + QVERIFY(myRect); + + //rather inexact -- is there a better way? + QVERIFY(myRect->x() > 100 && myRect->x() < 200); + QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10); } { - QFxView *view = new QFxView; - view->setUrl(QUrl("file://" SRCDIR "/data/mixedtype2.qml")); - - view->execute(); - qApp->processEvents(); - - delete view; + QmlEngine engine; + QmlComponent c(&engine, QUrl("file://" SRCDIR "/data/mixedtype2.qml")); + QFxRect *rect = qobject_cast<QFxRect*>(c.create()); + QVERIFY(rect); + + rect->setState("state1"); + QTest::qWait(500); + QFxRect *myRect = qobject_cast<QFxRect*>(rect->QGraphicsObject::children().at(3)); //### not robust + QVERIFY(myRect); + + //rather inexact -- is there a better way? + QVERIFY(myRect->x() > 100 && myRect->x() < 200); + QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue")); } -}*/ +} QTEST_MAIN(tst_animations) |