Merge lp:~qqworini/ubuntu-rssreader-app/optimization-0 into lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk

Proposed by Joey Chan
Status: Merged
Approved by: Nicholas Skaggs
Approved revision: 81
Merged at revision: 83
Proposed branch: lp:~qqworini/ubuntu-rssreader-app/optimization-0
Merge into: lp:~ubuntu-shorts-dev/ubuntu-rssreader-app/trunk
Diff against target: 740 lines (+316/-134)
9 files modified
OrganicGrid.qml (+142/-18)
article_items/ArticleFullImg.qml (+4/-0)
article_items/ArticleOneImgA.qml (+25/-14)
databasemodule_v2.js (+2/-2)
feeds/AppendFeedPage.qml (+1/-0)
feeds/ChooseTopicPage.qml (+1/-0)
feeds/EditFeed.qml (+9/-10)
feeds/TopicComponent.qml (+109/-90)
feeds/TopicManagement.qml (+23/-0)
To merge this branch: bzr merge lp:~qqworini/ubuntu-rssreader-app/optimization-0
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Nicholas Skaggs (community) Needs Fixing
Roman Shchekin Approve
Review via email: mp+188259@code.launchpad.net

Commit message

optimization for gridview, articles, input method, edit-topic

optimization:
1. dynamic loads in gridview
2. now all articles' images has max height
3. database, table article add column "media_group"
4. optimize edit-topic, now click other topics will also cancel editing
5. virtual keybroad now will hide itself automatically
6. edit-feed page, feed name and feed url are read-only now

Description of the change

optimization for gridview, articles, input method, edit-topic

optimization:
1. dynamic loads in gridview
2. now all articles' images has max height
3. database, table article add column "media_group"
4. optimize edit-topic, now click other topics will also cancel editing
5. virtual keybroad now will hide itself automatically
6. edit-feed page, feed name and feed url are read-only now

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Roman Shchekin (mrqtros) wrote :

Wow, Joey, works pretty fine, and consumes only ~60 mb of memory in start (empty app ~40).

Revision history for this message
Roman Shchekin (mrqtros) wrote :

I want to use "top approve" of course, but someone from Canonical may want take a look too :)

review: Approve
Revision history for this message
Roman Shchekin (mrqtros) wrote :

This merge fixes slow image loading too (because if all components are created simultaneously they are simultaneously too trying too download their image, even components in background. And user must w8)

Revision history for this message
Joey Chan (qqworini) wrote :

I added a simple algorithm, lets the gridview only loads 10 articles at the beginning, then loads more when it detect about to reach the edge.

> This merge fixes slow image loading too (because if all components are created
> simultaneously they are simultaneously too trying too download their image,
> even components in background. And user must w8)

Revision history for this message
Roman Shchekin (mrqtros) wrote :

Yes, programming must be simple to reach prefect results ;)
App now starts much faster and uses less memory =)

30.09.13 10:44 Joey Chan написал(а):

I added a simple algorithm, lets the gridview only loads 10 articles at the beginning, then loads more when it detect about to reach the edge.

> This merge fixes slow image loading too (because if all components are created
> simultaneously they are simultaneously too trying too download their image,
> even components in background. And user must w8)

--
https://code.launchpad.net/~qqworini/ubuntu-rssreader-app/optimization-0/+merge/188259

You are reviewing the proposed merge of lp:~qqworini/ubuntu-rssreader-app/optimization-0 into lp:ubuntu-rssreader-app.

Revision history for this message
David Planella (dpm) wrote :

On Mon, Sep 30, 2013 at 7:47 AM, Roman Shchekin <email address hidden> wrote:

> Review: Approve
>
> I want to use "top approve" of course, but someone from Canonical may want
> take a look too :)
>
>
Feel free to top-approve if you think the changes make sense and there is
nothing to fix, no need to block on approval from Canonical folks (unless
you explicitly want someone to review it). These apps are all
community-driven and meritocracy-driven, so you should think of Canonical
employees as reviewers with the same status as you guys, we're all Ubuntu
community members :)

Cheers,
David.

Revision history for this message
Roman Shchekin (mrqtros) wrote :

Thanks, David, I can do it in evening only, can you please approve? =)

Btw, I've got device today =)

30.09.13 13:30 David Planella написал(а):

On Mon, Sep 30, 2013 at 7:47 AM, Roman Shchekin <email address hidden> wrote:

> Review: Approve
>
> I want to use "top approve" of course, but someone from Canonical may want
> take a look too :)
>
>
Feel free to top-approve if you think the changes make sense and there is
nothing to fix, no need to block on approval from Canonical folks (unless
you explicitly want someone to review it). These apps are all
community-driven and meritocracy-driven, so you should think of Canonical
employees as reviewers with the same status as you guys, we're all Ubuntu
community members :)

Cheers,
David.

--
https://code.launchpad.net/~qqworini/ubuntu-rssreader-app/optimization-0/+merge/188259

You are reviewing the proposed merge of lp:~qqworini/ubuntu-rssreader-app/optimization-0 into lp:ubuntu-rssreader-app.

Revision history for this message
David Planella (dpm) wrote :

Sure, proxy-approving :)

Revision history for this message
David Planella (dpm) wrote :

Ah, sorry, I hadn't realized: tests are failing, so I can't top-approve. Joey: could you have a look at the tests that are failing and get in touch with fginther or balloons on IRC if you need help? Thanks!

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Joey Chan (qqworini) wrote :

I asked balloons, he said that is the same problem (add feed toolbar missing) happened, but I can't reproduce it ...

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Let me update my device quickly and run again. The tests pass on the desktop, but fail to open the toolbar on the device.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

On the latests phone build, the tests still fail to open the toolbar. The current tests don't have this issue, so this is definitely a regression that needs fixed before merging this.

(The current trunk tests suffer from the missing 'next' button on the 'add feeds' screen)

review: Needs Fixing
Revision history for this message
Joey Chan (qqworini) wrote :

Could somebody help try this branch, I still can't reproduce the "miss-toolbar-bug", thanks

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

As there are pending sdk issues with the application, and this merge fixes one of those issues, I approved despite the failing tests. This brings us closer to the tests completely working (because the app is working properly with these changes)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'OrganicGrid.qml'
2--- OrganicGrid.qml 2013-09-22 15:38:03 +0000
3+++ OrganicGrid.qml 2013-09-30 04:16:05 +0000
4@@ -14,6 +14,14 @@
5 property bool isAll: false
6 property var feedArray: []
7
8+ // Initial values for the starting column of items
9+ property int xEdge : 0
10+ property int lastColumnX : 0
11+ property int itemY : randomMargin()
12+ property var sequence : [0,1,0,1,2,1,0,0,2,1,0,1,0,0]
13+
14+ property int currentLoadedIndex: 0
15+
16 Component.onCompleted: {
17 prepareComponents()
18 }
19@@ -77,6 +85,7 @@
20 */
21 function reload() {
22 console.time("reload_grid")
23+// connFlickable.target = null
24 clear()
25 // Decide if we should load all articles in our database or a subset.
26 if (!isAll)
27@@ -105,16 +114,18 @@
28 }
29
30 // Initial values for the starting column of items
31- var xEdge = 0;
32- var lastColumnX = 0;
33- var y = randomMargin();
34+ xEdge = 0;
35+ lastColumnX = 0;
36+ itemY = randomMargin();
37
38 // A hard-coded sequence that gives an organic look, but is not
39 // completely random
40- var sequence = [0,1,0,1,2,1,0,0,2,1,0,1,0,0];
41+// var sequence = [0,1,0,1,2,1,0,0,2,1,0,1,0,0];
42 // var componentsPath = "article_items/" + "Article"
43
44- for(var i = 0; i < articleModel.count; i++) {
45+ currentLoadedIndex = 0
46+ var numAdd = articleModel.count > 10 ? 10 : articleModel.count
47+ for(var i = 0; i < numAdd /*articleModel.count*/; i++) {
48 var article = articleModel.get(i);
49 // var imageArray = ImageSeparator.separate(article.content)
50 var imageArray = [article.image]
51@@ -172,8 +183,8 @@
52 // This is the actual item that will be on display
53 var articleItem = component.createObject(itemContainer /*organicFlickable.contentItem*/, properties);
54
55- if(y + articleItem.height > organicGridRoot.height) {
56- y = randomMargin();
57+ if(itemY + articleItem.height > organicGridRoot.height) {
58+ itemY = randomMargin();
59 xEdge = lastColumnX;
60 }
61
62@@ -185,9 +196,9 @@
63 x += randomMargin();
64
65 articleItem.x = x
66- articleItem.y = y
67+ articleItem.y = itemY
68
69- // Check for collisions with all other items
70+ // Check for collisions with all other itemsy
71 // mrqtros: Now we are look only at 0xA last items.
72 //for(var j = 0; j < rectangleList.length; j++) { // mrqtros
73 for(var j = Math.max(0, rectangleList.length - 0xA); j < rectangleList.length; j++) {
74@@ -202,15 +213,124 @@
75
76 rectangleList.push(articleItem)
77
78- // Increment y for the next item
79- y += articleItem.height + randomMargin();
80+ // Increment itemY for the next item
81+ itemY += articleItem.height + randomMargin();
82 }
83
84 organicFlickable.scrollToStart()
85+ currentLoadedIndex += numAdd
86+// connFlickable.target = organicFlickable
87 console.timeEnd("reload_grid")
88 }
89
90 /*!
91+ * dynamic loads others articles in organic view.
92+ */
93+ function loadMore () {
94+ console.time("loadmore")
95+ var numAdd
96+ var tempAdd = articleModel.count - currentLoadedIndex
97+ if (tempAdd > 20) {
98+ numAdd = 20
99+ }
100+ else if (tempAdd > 0) {
101+ numAdd = tempAdd
102+ }
103+ else
104+ return
105+
106+ for(var i = currentLoadedIndex; i < currentLoadedIndex + numAdd /*articleModel.count*/; i++) {
107+ var article = articleModel.get(i);
108+// var imageArray = ImageSeparator.separate(article.content)
109+ var imageArray = [article.image]
110+// console.log("imageArray: ", imageArray)
111+ var hasImage = (article.image !== "");
112+
113+ // Pick the type of size we will use for this item from the sequence
114+ var sizeType = sequence[i % sequence.length];
115+ var alignType = Math.round(Math.random())
116+
117+ //var alignName
118+ var alignIndex
119+
120+ if(!hasImage) {
121+ switch(alignType) {
122+ case 0:
123+ //alignName = "TextA"
124+ alignIndex = 0
125+ break;
126+ case 1:
127+ //alignName = "TextB"
128+ alignIndex = 1
129+ break;
130+ }
131+ //noImageName += "NoImage";
132+ sizeType = 0;
133+ }
134+ else {
135+ switch(alignType) {
136+ case 0:
137+ //alignName = "OneImgA"
138+ alignIndex = 2
139+ break;
140+ case 1:
141+ //alignName = "FullImg"
142+ alignIndex = 3
143+ break;
144+ }
145+ }
146+
147+ var component = delegateComponents[alignIndex] //Qt.createComponent(componentName);
148+
149+ var properties = {
150+ "modelItem": article,
151+ "imageArray": imageArray,
152+ "rssModel": articleModel,
153+ "modelIndex": article.modelIndex
154+ }
155+
156+ // This is the actual item that will be on display
157+ var articleItem = component.createObject(itemContainer /*organicFlickable.contentItem*/, properties);
158+
159+ if(itemY + articleItem.height > organicGridRoot.height) {
160+ itemY = randomMargin();
161+ xEdge = lastColumnX;
162+ }
163+
164+ // The xEdge is where the last "column" of items were placed last
165+ // This keeps us moving forward in x-direction
166+ var x = xEdge + randomMargin();
167+
168+ // We add some extra random margin to make it look a bit more organic
169+ x += randomMargin();
170+
171+ articleItem.x = x
172+ articleItem.y = itemY
173+
174+ // Check for collisions with all other itemsy
175+ // mrqtros: Now we are look only at 0xA last items.
176+ //for(var j = 0; j < rectangleList.length; j++) { // mrqtros
177+ for(var j = Math.max(0, rectangleList.length - 0xA); j < rectangleList.length; j++) {
178+ var rect2 = rectangleList[j]
179+ if(checkCollision(articleItem, rect2)) {
180+ articleItem.x = rect2.x + rect2.width + randomMargin();
181+ }
182+ }
183+
184+ // Did we move the x-edge value further to the right than before?
185+ lastColumnX = Math.max(articleItem.x, lastColumnX);
186+
187+ rectangleList.push(articleItem)
188+
189+ // Increment itemY for the next item
190+ itemY += articleItem.height + randomMargin();
191+ }
192+ currentLoadedIndex += numAdd
193+ organicFlickable.canAdd = true
194+ console.timeEnd("loadmore")
195+ }
196+
197+ /*!
198 * use Flickable as articles container
199 */
200 Flickable {
201@@ -221,7 +341,6 @@
202
203 Item {
204 id: itemContainer
205- // color: "white"
206 anchors {
207 left: parent.left
208 top: parent.top
209@@ -231,12 +350,17 @@
210 height: parent.height
211 }
212
213-// Behavior on contentX {
214-// NumberAnimation {
215-// duration: 600
216-// easing.type: Easing.InOutQuart
217-// }
218-// }
219+ /*!
220+ * use onContentXChanged signal to detect if user is about to flick to edge
221+ * then load more articles
222+ */
223+ property bool canAdd: true
224+ onContentXChanged: {
225+ if ((visibleArea.xPosition > (1 - visibleArea.widthRatio * 1.5)) && canAdd ) {
226+ canAdd = false
227+ loadMore()
228+ }
229+ }
230
231 function scrollToStart() {
232 contentX = 0
233
234=== modified file 'article_items/ArticleFullImg.qml'
235--- article_items/ArticleFullImg.qml 2013-09-22 15:05:33 +0000
236+++ article_items/ArticleFullImg.qml 2013-09-30 04:16:05 +0000
237@@ -38,6 +38,7 @@
238 width: parent.width
239 height: pic.height > (articleFullImg.height - units.gu(1.5)) ? (articleFullImg.height - units.gu(1.5)) : pic.height
240 radius: "medium"
241+ opacity: height
242 image: Image {
243 id: pic
244 width: {
245@@ -48,6 +49,9 @@
246 source: imageArray[0]
247 sourceSize.width: uPic.width
248 }
249+
250+ Behavior on height { UbuntuNumberAnimation{} }
251+ Behavior on opacity { NumberAnimation{} }
252 }
253 }
254
255
256=== modified file 'article_items/ArticleOneImgA.qml'
257--- article_items/ArticleOneImgA.qml 2013-09-22 15:05:33 +0000
258+++ article_items/ArticleOneImgA.qml 2013-09-30 04:16:05 +0000
259@@ -26,28 +26,39 @@
260 }
261 }
262
263- UbuntuShape {
264- id: uPic
265-
266+ Item {
267+ id: shapeClipper
268 width: parent.width
269- height: pic.height /*> units.gu(12) ? pic.height : units.gu(12)*/
270- radius: "medium"
271- image: Image {
272- id: pic
273- width: {
274- if (implicitHeight < 50 || implicitWidth < 50) return 0
275- else return uPic.width
276+ height: uPic.height > (articleOneImgA.height * 0.75) ? (articleOneImgA.height * 0.75) : uPic.height
277+ clip: true
278+
279+ UbuntuShape {
280+ id: uPic
281+
282+ width: parent.width
283+ height: pic.height /*> units.gu(12) ? pic.height : units.gu(12)*/
284+ radius: "medium"
285+ opacity: height
286+ image: Image {
287+ id: pic
288+ width: {
289+ if (implicitHeight < 50 || implicitWidth < 50) return 0
290+ else return uPic.width
291+ }
292+ height: width * implicitHeight / implicitWidth
293+ source: imageArray[0]
294+ sourceSize.width: uPic.width
295 }
296- height: width * implicitHeight / implicitWidth
297- source: imageArray[0]
298- sourceSize.width: uPic.width
299+
300+ Behavior on height { UbuntuNumberAnimation{} }
301+ Behavior on opacity { NumberAnimation{} }
302 }
303 }
304
305 Column {
306 anchors {
307 left: parent.left; right: parent.right;
308- top: uPic.bottom; bottom: parent.bottom
309+ top: shapeClipper.bottom; bottom: parent.bottom
310 topMargin: units.gu(2); bottomMargin: units.gu(1.5);
311 leftMargin: units.gu(1); rightMargin: units.gu(1.5)
312 }
313
314=== modified file 'databasemodule_v2.js'
315--- databasemodule_v2.js 2013-09-28 14:30:29 +0000
316+++ databasemodule_v2.js 2013-09-30 04:16:05 +0000
317@@ -23,10 +23,10 @@
318 // I am currently working with 190 symbols length strings, all is ok :)
319 function checkTableExists(transaction /* and additional string keys */) {
320 transaction.executeSql('PRAGMA foreign_keys = ON;') // enable foreign key support
321- transaction.executeSql("CREATE TABLE IF NOT EXISTS feed (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,source TEXT NULL,title TEXT NULL,link TEXT NULL, description TEXT NULL, status char(1) NULL DEFAULT '0', pubdate INTEGER NULL,image TEXT NULL, count INTEGER NULL DEFAULT 0);") // add "count", count user click
322+ transaction.executeSql("CREATE TABLE IF NOT EXISTS feed (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,source TEXT NULL,title TEXT NULL,link TEXT NULL, description TEXT NULL, status char(1) NULL DEFAULT '0', pubdate INTEGER NULL,image TEXT NULL, count INTEGER NULL DEFAULT 0);")
323 transaction.executeSql("CREATE TABLE IF NOT EXISTS tag (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL UNIQUE );")
324 transaction.executeSql("CREATE TABLE IF NOT EXISTS feed_tag (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,feed_id INTEGER NULL,tag_id INTEGER NULL,FOREIGN KEY(feed_id) REFERENCES feed(id) on delete cascade);")
325- transaction.executeSql("CREATE TABLE IF NOT EXISTS article ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title TEXT NULL, content TEXT NULL, link TEXT NULL, description TEXT NULL, pubdate INTEGER NULL, status char(1) NULL DEFAULT '0', favourite char(1) NULL DEFAULT '0', image TEXT NULL, guid TEXT NULL, feed_id INTEGER NULL,count INTEGER NULL DEFAULT 0);")
326+ transaction.executeSql("CREATE TABLE IF NOT EXISTS article ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title TEXT NULL, content TEXT NULL, link TEXT NULL, description TEXT NULL, pubdate INTEGER NULL, status char(1) NULL DEFAULT '0', favourite char(1) NULL DEFAULT '0', image TEXT NULL, guid TEXT NULL, feed_id INTEGER NULL,count INTEGER NULL DEFAULT 0, media_groups TEXT NULL);")
327 transaction.executeSql("CREATE TABLE IF NOT EXISTS settings ( id INTEGER, current_database_version TEXT NULL, database_last_updated TEXT NULL, view_mode char(1) NULL DEFAULT '0', update_interval INTEGER NULL DEFAULT 0, network_mode char(1) NULL DEFAULT '0');")
328 var rs = transaction.executeSql("select * from settings")
329 if (rs.rows.length == 0)
330
331=== modified file 'feeds/AppendFeedPage.qml'
332--- feeds/AppendFeedPage.qml 2013-09-27 09:49:16 +0000
333+++ feeds/AppendFeedPage.qml 2013-09-30 04:16:05 +0000
334@@ -184,6 +184,7 @@
335 }
336
337 onAccepted: {
338+ Qt.inputMethod.hide()
339 var userInput = text
340
341 if (userInput == "")
342
343=== modified file 'feeds/ChooseTopicPage.qml'
344--- feeds/ChooseTopicPage.qml 2013-09-27 09:49:16 +0000
345+++ feeds/ChooseTopicPage.qml 2013-09-30 04:16:05 +0000
346@@ -119,6 +119,7 @@
347 }
348
349 onAccepted: {
350+ Qt.inputMethod.hide()
351 if (text.replace(/^\s+|\s+$/g, '') != "") { // Check that text contains only spaces.
352 var tagName = text
353
354
355=== modified file 'feeds/EditFeed.qml'
356--- feeds/EditFeed.qml 2013-09-21 09:27:59 +0000
357+++ feeds/EditFeed.qml 2013-09-30 04:16:05 +0000
358@@ -11,19 +11,14 @@
359 objectName: "editfeedpage"
360 title: i18n.tr("Edit Feed")
361 flickable: null/*content*/
362- tools: ToolbarItems {
363+ tools: null
364+
365+ ToolbarItems {
366 id: toolbar
367
368 opened: true
369 locked: true
370
371-// ToolbarButton {
372-// id: actionsButton
373-// text: i18n.tr("Reads")
374-// iconSource: Qt.resolvedUrl("avatar.png")
375-// onTriggered: ;
376-// visible: true
377-// }
378 Button
379 {
380 id: btnDelete
381@@ -49,7 +44,7 @@
382
383 onClicked:
384 {
385- DB.updateFeedByUser(feedId, feedTitle, feedURL) ;
386+// DB.updateFeedByUser(feedId, feedTitle, feedURL) ;
387 DB.deleteFeedTag(feedId, previousTopicId) ;
388 DB.addFeedTag(feedId, newTopicId) ;
389 apply(feedId, newTopicId, previousTopicId) ;
390@@ -95,7 +90,7 @@
391 }
392
393 function reloadPageContent() {
394-
395+ editPage.tools = toolbar
396 }
397
398 Flickable {
399@@ -127,6 +122,8 @@
400 text: feedTitle
401 width: parent.width - labelTitle.width - parent.spacing
402 anchors.verticalCenter: parent.verticalCenter
403+ readOnly: true
404+ hasClearButton: false
405 }
406 }
407
408@@ -148,6 +145,8 @@
409 text: feedURL
410 width: parent.width - labelURL.width - parent.spacing
411 anchors.verticalCenter: parent.verticalCenter
412+ readOnly: true
413+ hasClearButton: false
414 }
415 }
416
417
418=== modified file 'feeds/TopicComponent.qml'
419--- feeds/TopicComponent.qml 2013-09-18 12:03:36 +0000
420+++ feeds/TopicComponent.qml 2013-09-30 04:16:05 +0000
421@@ -19,6 +19,7 @@
422 property int modelIndex
423
424 signal edit()
425+ signal editCanceled()
426
427 // onClicked: isExpended = !isExpended ;
428
429@@ -64,28 +65,38 @@
430 id: columnContent
431 anchors{ left: parent.left; right: parent.right }
432
433+ /*
434+ topic item
435+ */
436 Item
437 {
438 anchors{ left: parent.left; right: parent.right }
439 height: units.gu(5)
440
441+ /*
442+ topic header for showing name and swipe remove
443+ */
444 ListItem.Base{
445 id: headerTopic
446+ enabled: !rowTopicContent.isEditing
447 removable: true
448 height: units.gu(5)
449
450- onClicked: isExpended = !isExpended
451+ onClicked: {
452+ isExpended = !isExpended
453+ editCanceled()
454+ }
455
456 onItemRemoved:{
457 console.log("item about to be removed: ", topicComponent.topicId)
458-// itemCancelDelete.startCounting()
459+ // itemCancelDelete.startCounting()
460 var result = DB.deleteFeedByTagId(topicComponent.topicId)
461 if (result.rowsAffected == undefined)
462 {
463 topicManagement.reloadTopics()
464 }
465 result = DB.deleteTag(topicComponent.topicId)
466-// topicManagement.reloadTopics()
467+ // topicManagement.reloadTopics()
468 if (result.rowsAffected == 1)
469 {
470 topicManagement.removeModelItem(topicComponent.modelIndex)
471@@ -95,105 +106,113 @@
472 topicManagement.reloadTopics()
473 }
474 }
475-
476- Row{
477- id: rowTopicContent
478- anchors
479- {
480- top: parent.top; bottom: parent.bottom; left: parent.left;
481- leftMargin: units.gu(0); topMargin: units.gu(1); bottomMargin: units.gu(1);
482- }
483- spacing: units.gu(2)
484-
485- property bool isEditing: false
486-
487- Image{
488- anchors
489- {
490- top: parent.top; bottom: parent.bottom;
491- topMargin: units.gu(0.5); bottomMargin: units.gu(0.5);
492- }
493- fillMode: Image.PreserveAspectFit
494- source: Qt.resolvedUrl("../icons_tmp/compose.svg")
495- smooth: true
496-
497- MouseArea{
498- enabled: !rowTopicContent.isEditing
499- anchors { fill: parent; margins: units.gu(-1) }
500- onClicked:
501- {
502- rowTopicContent.isEditing = true
503- topicComponent.edit()
504- }
505- }
506- }
507-
508- Label{
509- id: labelTopicName
510- anchors.verticalCenter: parent.verticalCenter
511- text: topicName
512- width: rowTopicContent.isEditing ? 0 : paintedWidth
513- opacity: rowTopicContent.isEditing ? 0 : 1
514-
515- // Behavior on width { UbuntuNumberAnimation{} }
516- }
517-
518- TextField{
519- id: inputTopicName
520- anchors.verticalCenter: parent.verticalCenter
521- text: topicName
522- width: rowTopicContent.isEditing ? headerTopic.width - units.gu(15) : 0
523- opacity: rowTopicContent.isEditing ? 1 : 0
524- hasClearButton: true
525- activeFocusOnPress: true
526-
527- Behavior on width { UbuntuNumberAnimation{} }
528-
529- onAccepted: {
530- Qt.inputMethod.hide()
531- }
532-
533- Connections {
534- target: Qt.inputMethod
535- onVisibleChanged: {
536- if (!Qt.inputMethod.visible) {
537- topicComponent.focus = true
538- }
539- }
540- }
541- }
542+ }
543+
544+ /*
545+ enable if edit mode active
546+ */
547+ Row{
548+ id: rowTopicContent
549+ anchors
550+ {
551+ top: parent.top; bottom: parent.bottom; left: parent.left;
552+ leftMargin: units.gu(1); topMargin: units.gu(0.7); bottomMargin: units.gu(1);
553 }
554+ spacing: units.gu(2)
555+
556+ property bool isEditing: false
557
558 Image{
559- id: imgArrow
560 anchors
561 {
562- right: parent.right; top: parent.top; bottom: parent.bottom;
563- topMargin: units.gu(1.5); bottomMargin: units.gu(1.5); rightMargin: units.gu(2)
564+ top: parent.top; bottom: parent.bottom;
565+ topMargin: units.gu(0.5); bottomMargin: units.gu(0.5);
566 }
567 fillMode: Image.PreserveAspectFit
568- source: Qt.resolvedUrl("../icons_tmp/go-to.svg")
569+ source: Qt.resolvedUrl("../icons_tmp/compose.svg")
570 smooth: true
571
572- Behavior on rotation { UbuntuNumberAnimation{} }
573-
574- states: [
575- State {
576- name: "expended"
577- when: topicComponent.isExpended
578-
579- PropertyChanges
580- {
581- target: imgArrow
582- rotation: 90
583- }
584- }
585- ]
586- }
587- }
588+ MouseArea{
589+ enabled: !rowTopicContent.isEditing
590+ anchors { fill: parent; margins: units.gu(-1) }
591+ onClicked:
592+ {
593+ rowTopicContent.isEditing = true
594+ topicComponent.edit()
595+ inputTopicName.focus = true
596+ }
597+ }
598+ }
599+
600+ Label{
601+ id: labelTopicName
602+ anchors.verticalCenter: parent.verticalCenter
603+ text: topicName
604+ width: rowTopicContent.isEditing ? 0 : paintedWidth
605+ opacity: rowTopicContent.isEditing ? 0 : 1
606+
607+ // Behavior on width { UbuntuNumberAnimation{} }
608+ }
609+
610+ TextField{
611+ id: inputTopicName
612+ anchors.verticalCenter: parent.verticalCenter
613+ text: topicName
614+ width: rowTopicContent.isEditing ? headerTopic.width - units.gu(15) : 0
615+ opacity: rowTopicContent.isEditing ? 1 : 0
616+ hasClearButton: true
617+ activeFocusOnPress: true
618+
619+ Behavior on width { UbuntuNumberAnimation{} }
620+
621+ onAccepted: {
622+ console.log("accepted?")
623+ Qt.inputMethod.hide()
624+ }
625+
626+ Keys.enabled: rowTopicContent.isEditing
627+ Keys.onPressed: {
628+ event.accepted = false
629+ if (event.key == Qt.Key_Return) {
630+ Qt.inputMethod.hide()
631+ }
632+ }
633+ }
634+ }
635+
636+ Image{
637+ id: imgArrow
638+ anchors
639+ {
640+ right: parent.right; top: parent.top; bottom: parent.bottom;
641+ topMargin: units.gu(1.5); bottomMargin: units.gu(1.5); rightMargin: units.gu(2)
642+ }
643+ fillMode: Image.PreserveAspectFit
644+ source: Qt.resolvedUrl("../icons_tmp/go-to.svg")
645+ smooth: true
646+
647+ Behavior on rotation { UbuntuNumberAnimation{} }
648+
649+ states: [
650+ State {
651+ name: "expended"
652+ when: topicComponent.isExpended
653+
654+ PropertyChanges
655+ {
656+ target: imgArrow
657+ rotation: 90
658+ }
659+ }
660+ ]
661+ }
662+
663
664 }
665
666+ /*
667+ feeds listview
668+ */
669 ListView
670 {
671 id: feedList
672
673=== modified file 'feeds/TopicManagement.qml'
674--- feeds/TopicManagement.qml 2013-09-18 12:03:36 +0000
675+++ feeds/TopicManagement.qml 2013-09-30 04:16:05 +0000
676@@ -40,6 +40,9 @@
677
678 }
679
680+ /*
681+ toolbar for normal state
682+ */
683 ToolbarItems {
684 id: toolbar
685
686@@ -52,6 +55,9 @@
687 }
688 }
689
690+ /*
691+ toolbar for editing state
692+ */
693 ToolbarItems {
694 id: editConfirm
695 opened: true
696@@ -87,6 +93,9 @@
697 }
698 }
699
700+ /*
701+ main content
702+ */
703 Flickable {
704 id: content
705 anchors.fill: parent
706@@ -96,6 +105,9 @@
707 Column{
708 anchors{ left: parent.left; right: parent.right }
709
710+ /*
711+ add topic button
712+ */
713 Item {
714 id: itemAddTopic
715 objectName: "addTopic"
716@@ -135,6 +147,9 @@
717 }
718 }
719
720+ /*
721+ topic listview
722+ */
723 ListView {
724 id: topicList
725 anchors{ left: parent.left; right: parent.right }
726@@ -190,6 +205,14 @@
727 editConfirm.visible = true
728 topicList.currentIndex = index
729 }
730+
731+ onEditCanceled: {
732+ if (topicList.currentItem)
733+ topicList.currentItem.cancelEdit()
734+ topicManagement.state = ""
735+ editConfirm.visible = false
736+ topicList.currentIndex = -1
737+ }
738 }
739
740 DropArea {

Subscribers

People subscribed via source and target branches