Merge lp:~fredoust/sudoku-app/profiles into lp:sudoku-app

Proposed by Frédéric Delgado
Status: Merged
Approved by: Dinko Osmankovic
Approved revision: 66
Merged at revision: 67
Proposed branch: lp:~fredoust/sudoku-app/profiles
Merge into: lp:sudoku-app
Diff against target: 755 lines (+547/-42)
6 files modified
components/AddProfileDialog.qml (+97/-0)
components/ManageProfileDialog.qml (+115/-0)
components/SudokuDialogButton.qml (+3/-3)
js/SudokuCU.js (+0/-7)
js/localStorage.js (+112/-0)
sudoku-app.qml (+220/-32)
To merge this branch: bzr merge lp:~fredoust/sudoku-app/profiles
Reviewer Review Type Date Requested Status
Dinko Osmankovic Approve
Review via email: mp+173681@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dinko Osmankovic (dinko-metalac) :
review: Approve
lp:~fredoust/sudoku-app/profiles updated
67. By Frédéric Delgado

Clean code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'components/AddProfileDialog.qml'
2--- components/AddProfileDialog.qml 1970-01-01 00:00:00 +0000
3+++ components/AddProfileDialog.qml 2013-07-09 09:59:26 +0000
4@@ -0,0 +1,97 @@
5+import QtQuick 2.0
6+import Ubuntu.Components 0.1
7+import Ubuntu.Components.Popups 0.1
8+import "../js/localStorage.js" as Settings
9+import QtQuick.LocalStorage 2.0
10+
11+Component {
12+ id: addProfileDialog
13+
14+ Dialog {
15+ id: addProfileDialogue
16+ title: i18n.tr("Add new profile")
17+ width: parent.width
18+
19+
20+ Column {
21+ width: parent.width
22+ spacing: units.gu(2)
23+
24+ Rectangle{
25+ width: units.gu(25)
26+ height: units.gu(4)
27+ radius: 9
28+ anchors.horizontalCenter: parent.horizontalCenter
29+ TextField {
30+ id:lastnameField
31+
32+ placeholderText: i18n.tr("Lastname")
33+
34+ }
35+ }
36+ Rectangle{
37+ width: units.gu(25)
38+ height: units.gu(4)
39+ radius: 9
40+ anchors.horizontalCenter: parent.horizontalCenter
41+ TextField {
42+ id:firstnameField
43+ anchors.horizontalCenter: parent.horizontalCenter
44+ placeholderText: i18n.tr("Firstname")
45+ }
46+ }
47+
48+
49+ Row{
50+ width: parent.width
51+ spacing: units.gu(1)
52+
53+ SudokuDialogButton{
54+ id:okButton
55+ buttonText: i18n.tr("OK")
56+ width: parent.width/2;
57+ size: units.gu(5)
58+ onTriggered: {
59+
60+ if(lastnameField.text!="" && firstnameField.text!="")
61+ {
62+
63+ if(!Settings.existProfile(lastnameField.text, firstnameField.text))
64+ {
65+
66+ Settings.insertProfile(lastnameField.text, firstnameField.text);
67+ PopupUtils.close(addProfileDialogue)
68+ }else{
69+ mainView.showAlert(i18n.tr("Warning"), i18n.tr("User already exist."), okButton)
70+ }
71+
72+
73+ } else{
74+mainView.showAlert(i18n.tr("Warning"), i18n.tr("Lastname and firstname must not be empty."), okButton)
75+ }
76+
77+
78+
79+
80+
81+ }
82+ }
83+
84+ SudokuDialogButton{
85+ buttonText: i18n.tr("Cancel")
86+ width: parent.width/2;
87+ size: units.gu(5)
88+ onTriggered: {
89+ PopupUtils.close(addProfileDialogue)
90+ }
91+ }
92+ }
93+
94+
95+
96+ }
97+
98+
99+ }
100+}
101+
102
103=== added file 'components/ManageProfileDialog.qml'
104--- components/ManageProfileDialog.qml 1970-01-01 00:00:00 +0000
105+++ components/ManageProfileDialog.qml 2013-07-09 09:59:26 +0000
106@@ -0,0 +1,115 @@
107+import QtQuick 2.0
108+import Ubuntu.Components 0.1
109+import Ubuntu.Components.Popups 0.1
110+import "../js/localStorage.js" as Settings
111+import QtQuick.LocalStorage 2.0
112+
113+Component {
114+ id: editProfileDialog
115+
116+ Dialog {
117+ id: editProfileDialogue
118+ title: i18n.tr("Edit profile")
119+ width: parent.width
120+
121+
122+ Column {
123+ width: parent.width
124+ spacing: units.gu(2)
125+
126+ Rectangle{
127+ width: 200
128+ height: 32
129+ radius: 9
130+ anchors.horizontalCenter: parent.horizontalCenter
131+ TextField {
132+ id:lastnameField
133+ text: Settings.getUserLastName(editUserId)
134+ placeholderText: i18n.tr("Lastname")
135+
136+ }
137+ }
138+ Rectangle{
139+ width: 200
140+ height: 32
141+ radius: 9
142+ anchors.horizontalCenter: parent.horizontalCenter
143+ TextField {
144+ id:firstnameField
145+ anchors.horizontalCenter: parent.horizontalCenter
146+ placeholderText: i18n.tr("Firstname")
147+ text: Settings.getUserFirstName(editUserId)
148+ }
149+ }
150+
151+
152+ Row{
153+ width: parent.width
154+ spacing: units.gu(1)
155+
156+ SudokuDialogButton{
157+ id:okButton
158+ buttonText: i18n.tr("OK")
159+ width: parent.width/2;
160+ size: units.gu(5)
161+ onTriggered: {
162+
163+ if(lastnameField.text!="" && firstnameField.text!="")
164+ {
165+
166+ if(!Settings.existProfile( lastnameField.text, firstnameField.text))
167+ {
168+
169+ Settings.updateProfile(editUserId, lastnameField.text, firstnameField.text);
170+ var userId = currentUserId
171+ currentUserId = -1
172+ currentUserId = userId
173+
174+ PopupUtils.close(editProfileDialogue)
175+ }else{
176+ PopupUtils.close(editProfileDialogue)
177+ }
178+
179+
180+ } else{
181+ mainView.showAlert(i18n.tr("Warning"), i18n.tr("Lastname and firstname must not be empty."), okButton)
182+ }
183+
184+
185+
186+
187+
188+ }
189+ }
190+
191+ SudokuDialogButton{
192+ buttonText: i18n.tr("Delete")
193+ width: parent.width/2;
194+ size: units.gu(5)
195+ onTriggered: {
196+ Settings.deleteProfile(editUserId)
197+ if(editUserId == currentUserId)
198+ currentUserId = -1
199+
200+
201+ PopupUtils.close(editProfileDialogue)
202+ }
203+ }
204+ }
205+ SudokuDialogButton{
206+ anchors.horizontalCenter: parent.horizontalCenter
207+ buttonText: i18n.tr("Cancel")
208+ width: parent.width/2;
209+ size: units.gu(5)
210+ onTriggered: {
211+ PopupUtils.close(editProfileDialogue)
212+ }
213+ }
214+
215+
216+ }
217+
218+
219+ }
220+}
221+
222
223=== modified file 'components/SudokuDialogButton.qml'
224--- components/SudokuDialogButton.qml 2013-07-05 21:36:31 +0000
225+++ components/SudokuDialogButton.qml 2013-07-09 09:59:26 +0000
226@@ -3,9 +3,9 @@
227
228 SudokuButton {
229 id: dialogButton
230- border.color: defaultBorderColor
231+ border.color: sudokuBlocksGrid.defaultBorderColor
232 //border.width: 3
233- textColor: defaultTextColor;
234+ textColor: sudokuBlocksGrid.defaultTextColor;
235
236 signal triggered;
237
238@@ -43,5 +43,5 @@
239 animateDialogButton.start();
240 }
241 }
242- buttonColor: buttonMouseArea.pressed ? String(Qt.darker(defaultColor,1.2)):defaultColor
243+ buttonColor: buttonMouseArea.pressed ? String(Qt.darker(sudokuBlocksGrid.defaultColor,1.2)):sudokuBlocksGrid.defaultColor
244 }
245
246=== modified file 'js/SudokuCU.js'
247--- js/SudokuCU.js 2013-07-03 17:08:32 +0000
248+++ js/SudokuCU.js 2013-07-09 09:59:26 +0000
249@@ -159,20 +159,17 @@
250 if(value == 0)
251 return false;
252
253- console.log("test for "+value)
254 for(var i = 0; i < 9; i++)
255 {
256 console.log("test with col"+this.rows[i][column])
257 if(i != row && this.rows[i][column] == value)
258 {
259- console.log("find row")
260 return true;
261 }
262
263 // console.log("test with row"+this.rows[row][i])
264 if(i != column && this.rows[row][i] == value)
265 {
266- console.log("find col")
267 return true;
268 }
269 }
270@@ -209,8 +206,6 @@
271 if(value == 0)
272 continue;
273
274- console.log("test minigrid "+value)
275-
276 //if(App.Utils.arrayContains(numbers, value))
277 // return false;
278 if (numbers.indexOf(value) != -1 )
279@@ -252,8 +247,6 @@
280 if(value == 0)
281 continue;
282
283- console.log("test minigrid "+value)
284-
285 //if(App.Utils.arrayContains(numbers, value))
286 // return false;
287 if (numbers.indexOf(value) != -1 && value == val)
288
289=== modified file 'js/localStorage.js'
290--- js/localStorage.js 2013-07-06 06:18:26 +0000
291+++ js/localStorage.js 2013-07-09 09:59:26 +0000
292@@ -12,14 +12,19 @@
293 // Create the settings table if it doesn't already exist
294 // If the table exists, this is skipped
295 tx.executeSql('PRAGMA foreign_keys = ON;');
296+
297+
298 tx.executeSql('CREATE TABLE IF NOT EXISTS settings(setting TEXT UNIQUE, value TEXT)');
299 print("setting table created.")
300 tx.executeSql('CREATE TABLE IF NOT EXISTS profiles(id INTEGER PRIMARY KEY AUTOINCREMENT, first_name TEXT, last_name TEXT, UNIQUE(first_name, last_name) ON CONFLICT ROLLBACK)');
301 print("profile table created.")
302+
303 tx.executeSql('INSERT OR IGNORE INTO profiles VALUES (null,?,?);', ["Sudoku","User"]);
304 tx.executeSql('CREATE TABLE IF NOT EXISTS scores(id INTEGER PRIMARY KEY AUTOINCREMENT, profile_id INTEGER, score INTEGER NOT NULL, game_date DATE, FOREIGN KEY(profile_id) REFERENCES profiles(id))');
305 print("scores table created.")
306
307+
308+
309 });
310 }
311 function setSetting(setting, value) {
312@@ -113,6 +118,113 @@
313 return res;
314 }
315
316+function printObject(o)
317+{
318+ var out = '';
319+ for(var p in o){
320+ out+=p+': '+o[p]+'\n';
321+ }
322+ console.log(out)
323+}
324+
325+function getAllProfiles()
326+{
327+ var db = getDatabase();
328+ var res=new Array();
329+
330+ print("GETTING ALL PROFILES")
331+ db.transaction( function(tx) {
332+ var rs = tx.executeSql("SELECT * FROM profiles limit 10;");
333+ for(var i = 0; i < rs.rows.length; i++) {
334+ var dbItem = rs.rows.item(i);
335+ var o = new Object();
336+ o["id"] = dbItem.id;
337+ o["lastname"] = dbItem.last_name;
338+ o["firstname"] = dbItem.first_name;
339+ res.push(o)
340+ }
341+ });
342+ print(res);
343+ return res;
344+}
345+
346+
347+function deleteProfile(id)
348+{
349+
350+ var db = getDatabase();
351+ var res="";
352+ db.transaction(function(tx) {
353+ var rs = tx.executeSql('DELETE FROM profiles WHERE id=? ;', [id]);
354+
355+ if (rs.rowsAffected > 0) {
356+ res = "OK";
357+ } else {
358+ res = "Error";
359+ }
360+ }
361+ );
362+ // The function returns “OK” if it was successful, or “Error” if it wasn't
363+ return res;
364+}
365+
366+
367+function updateProfile(id, lastname, firstname)
368+{
369+
370+ var db = getDatabase();
371+ var res="";
372+ db.transaction(function(tx) {
373+ var rs = tx.executeSql('UPDATE profiles SET first_name=?, last_name=? WHERE id=? ;', [firstname, lastname, id]);
374+
375+ if (rs.rowsAffected > 0) {
376+ res = "OK";
377+ } else {
378+ res = "Error";
379+ }
380+ }
381+ );
382+ // The function returns “OK” if it was successful, or “Error” if it wasn't
383+ return res;
384+}
385+
386+function insertProfile(lastname, firstname)
387+{
388+
389+ var db = getDatabase();
390+ var res="";
391+ db.transaction(function(tx) {
392+ var rs = tx.executeSql('INSERT OR IGNORE INTO profiles VALUES (null,?,?);', [firstname, lastname]);
393+
394+ if (rs.rowsAffected > 0) {
395+ res = "OK";
396+ } else {
397+ res = "Error";
398+ }
399+ }
400+ );
401+ // The function returns “OK” if it was successful, or “Error” if it wasn't
402+ return res;
403+}
404+
405+function existProfile(lastname, firstname)
406+{
407+ var db = getDatabase();
408+ var res="";
409+
410+ db.transaction(function(tx) {
411+ var rs = tx.executeSql('SELECT id FROM profiles WHERE last_name=? AND first_name=?;', [lastname, firstname]);
412+ if (rs.rows.length > 0) {
413+ res = true
414+ } else {
415+ res = false
416+ }
417+ })
418+
419+
420+ return res
421+}
422+
423 function getUserFirstName(profile_id)
424 {
425 var db = getDatabase();
426
427=== modified file 'sudoku-app.qml'
428--- sudoku-app.qml 2013-07-08 09:38:32 +0000
429+++ sudoku-app.qml 2013-07-09 09:59:26 +0000
430@@ -2,6 +2,7 @@
431 import Ubuntu.Components 0.1
432 import Ubuntu.Components.ListItems 0.1 as ListItem
433 import QtQuick.LocalStorage 2.0
434+import Ubuntu.Components.Popups 0.1
435 import "js/localStorage.js" as Settings
436 import "components"
437
438@@ -17,12 +18,21 @@
439 property real blockDistance: pageWidth/200;
440 property bool alreadyCreated: false;
441 property bool gridLoaded: false;
442- property int currentUserId: 1;
443+ property int currentUserId: -1;
444 property string highscoresHeaderText: i18n.tr("<b>Best scores for all players</b>")
445
446+ property string alertTitle: ""
447+ property string alertText : ""
448+
449+ property int editUserId : -1;
450+
451 width: pageWidth;
452 height: pageHeight;
453
454+ onCurrentUserIdChanged: {
455+ Settings.setSetting("currentUserId", currentUserId)
456+ }
457+
458 function newSize(width, height) {
459 pageWidth = width;
460 pageHeight = height;
461@@ -58,6 +68,36 @@
462 //buttonsGridPublic.update();
463 }
464
465+
466+ Component {
467+ id: alertDialog
468+ Dialog {
469+ id: alertDialogue
470+ title: alertTitle
471+ text: alertText
472+
473+ SudokuDialogButton{
474+ buttonText: i18n.tr("OK")
475+ width: parent.width/2;
476+ size: units.gu(5)
477+ onTriggered: {
478+ PopupUtils.close(alertDialogue)
479+ }
480+ }
481+
482+ }
483+ }
484+
485+ function showAlert(title, text, caller)
486+ {
487+ alertTitle = title
488+ alertText = text
489+ PopupUtils.open(alertDialog, caller)
490+
491+ }
492+
493+
494+
495 onHeightChanged: {
496 if (!gridLoaded)
497 return;
498@@ -98,6 +138,14 @@
499 'lastname': lastName,
500 'score': rowItem[1] });
501 }
502+
503+ if(Settings.getSetting("currentUserId")=="Unknown")
504+ currentUserId = -1;
505+ else
506+ {
507+ currentUserId = Settings.getSetting("currentUserId")
508+ }
509+
510 }
511
512 Tabs {
513@@ -259,6 +307,7 @@
514 SudokuBlocksGrid {
515 id: sudokuBlocksGrid;
516 }
517+
518 }
519 }
520
521@@ -364,19 +413,102 @@
522 property alias difficultyIndex: difficultySelector.selectedIndex;
523 property alias themeIndex: themeSelector.selectedIndex;
524
525+
526+
527 title: i18n.tr("Settings")
528- page: Page {
529- /*
530- tools: ToolbarActions {
531-
532- Action {
533- iconSource: Qt.resolvedUrl("icons/close.svg")
534- text: i18n.tr("Close");
535- onTriggered: Qt.quit()
536- }
537- }
538- */
539+ page:
540+
541+ Page {
542+
543 Column {
544+
545+ Component {
546+ id: profileSelector
547+ DefaultSheet {
548+ title: i18n.tr("Select profile")
549+ contentsHeight: mainView.height
550+
551+ /*
552+ Column {
553+ anchors {
554+ top: parent.top
555+ left: parent.left
556+ right: parent.right
557+ }
558+ height: mainColumnSettings.height
559+
560+ ListItem.Header {
561+ id: header
562+ text: i18n.tr("Select profile")
563+ }
564+ */
565+
566+
567+
568+ ListView {
569+ height: mainColumnSettings.height
570+ id: profileListView
571+ clip: true
572+ width: parent.width
573+ // height: parent.height - header.height
574+ model: profilesModel
575+
576+ delegate:
577+ ListItem.Standard {
578+
579+ text: firstname + " " + lastname
580+ progression: true
581+ onTriggered: {
582+ console.log("clicked "+index)
583+ currentUserId = profileId;
584+ hide()
585+ }
586+ }
587+
588+ }
589+ }
590+ // }
591+ }
592+
593+ Component {
594+ id: manageProfileSelector
595+ DefaultSheet {
596+ title: i18n.tr("Select profile")
597+ contentsHeight: mainView.height
598+
599+
600+
601+ ListView {
602+ id: manageProfileListView
603+ clip: true
604+ width: parent.width
605+ height: mainColumnSettings.height
606+ model: profilesModel
607+
608+ delegate:
609+
610+ ListItem.Standard {
611+
612+ text: firstname + " " + lastname
613+
614+ progression: true
615+ onTriggered: {
616+ hide()
617+ editUserId = profileId
618+ PopupUtils.open(manageProfileDialog, selectorProfile)
619+ }
620+ }
621+
622+
623+
624+ }
625+ }
626+ }
627+
628+ ListModel{
629+ id: profilesModel
630+ }
631+
632 id: mainColumnSettings;
633 //width: settingsTab.width;
634 //height: settingsTab.height;
635@@ -460,9 +592,76 @@
636 }
637 }
638 }
639+ ListItem.Header {
640+ text: i18n.tr("<b>Profiles settings</b>")
641+ }
642+ ListItem.SingleValue {
643+ text: "Current profile"
644+ id: selectorProfile
645+ value: {
646+ if(currentUserId==-1)
647+ return i18n.tr("None")
648+ else
649+ return Settings.getUserFirstName(currentUserId)+" "+Settings.getUserLastName(currentUserId);
650+
651+ }
652+
653+ onClicked: {
654+
655+ var allProfiles = new Array();
656+ allProfiles = Settings.getAllProfiles()
657+
658+ profilesModel.clear()
659+
660+ for(var i = 0; i < allProfiles.length; i++)
661+ {
662+ profilesModel.append({"profileId":allProfiles[i].id,"lastname":allProfiles[i].lastname, "firstname":allProfiles[i].firstname})
663+ }
664+ PopupUtils.open(profileSelector, selectorProfile)
665+ }
666+ }
667+
668+ AddProfileDialog{
669+ id:addProfileDialog
670+ }
671+
672+ ManageProfileDialog{
673+ id:manageProfileDialog
674+ }
675+
676+
677+ ListItem.SingleValue {
678+ id:addSingleValue
679+ text: i18n.tr("Add profile")
680+ onClicked: {
681+ PopupUtils.open(addProfileDialog, addSingleValue);
682+ }
683+ }
684+
685+ ListItem.SingleValue {
686+ id:manageProfileSingleValue
687+ text: i18n.tr("Manage profiles")
688+ onClicked: {
689+
690+ var allProfiles = new Array();
691+ allProfiles = Settings.getAllProfiles()
692+
693+ profilesModel.clear()
694+
695+ for(var i = 0; i < allProfiles.length; i++)
696+ {
697+ profilesModel.append({"profileId":allProfiles[i].id,"lastname":allProfiles[i].lastname, "firstname":allProfiles[i].firstname})
698+ }
699+
700+ PopupUtils.open(manageProfileSelector, manageProfileSingleValue)
701+ }
702+ }
703+
704+
705 }
706 }
707
708+
709 }
710
711 Tab {
712@@ -470,18 +669,7 @@
713 objectName: "aboutTab"
714 title: i18n.tr("About")
715 page: Page {
716- /*
717- tools: ToolbarActions {
718-
719-
720- Action {
721- iconSource: Qt.resolvedUrl("icons/close.svg");
722- text: i18n.tr("Close");
723- onTriggered: Qt.quit()
724- }
725-
726- }
727- */
728+
729 Column {
730 id: aboutColumn;
731 spacing: 5;
732@@ -489,15 +677,15 @@
733 anchors.horizontalCenter: parent.horizontalCenter;
734 y: units.gu(8);
735 Image {
736- property real maxWidth: units.gu(100)
737- anchors.horizontalCenter: parent.horizontalCenter
738- width: Math.min(mainView.width, maxWidth)/1.75
739- //height: width
740- source: "icons/sudoko-vector-about.svg"
741- smooth: true
742- fillMode: Image.PreserveAspectFit
743+ property real maxWidth: units.gu(100)
744+ anchors.horizontalCenter: parent.horizontalCenter
745+ width: Math.min(mainView.width, maxWidth)/1.75
746+ //height: width
747+ source: "icons/sudoko-vector-about.svg"
748+ smooth: true
749+ fillMode: Image.PreserveAspectFit
750
751- }
752+ }
753 Row {
754 //anchors.horizontalCenter: parent.horizontalCenter;
755 anchors.left: aboutColumn.left

Subscribers

People subscribed via source and target branches