blob: af28900397408ca35f9f436e6a04846f403cadab [file] [log] [blame]
Sébastien Blin1f915762020-08-03 13:27:42 -04001/*
2 * Copyright (C) 2019-2020 by Savoir-faire Linux
3 * Author: Yang Wang <yang.wang@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.15
20import QtQuick.Window 2.15
21import QtQuick.Controls 2.15
22import QtQuick.Controls.Universal 2.12
23import QtQuick.Layouts 1.3
24import QtGraphicalEffects 1.14
25import net.jami.Models 1.0
26
27import "../constant"
28import "../wizardview/components"
29/*
30 * Account Migration Dialog for migrating account
31 */
32
33Window{
34 id: accountMigrationDialog
35
36 AccountsToMigrateListModel{
37 id: accountsToMigrateListModel
38 }
39
40 property string accountID: ""
41 property string password: ""
42
43 property bool nonOperationClosing: true
44 property bool successState : true
45 property string imgBase64: ""
46
47 signal accountMigrationFinished
48
49 function startAccountMigrationOfTopStack(){
50 passwordInputLineEdit.clear()
51 accountsToMigrateListModel.reset()
52
53 if(accountsToMigrateListModel.rowCount() <= 0){
54 closeWithoutOperation()
55
56 return false
57 }
58
59 var managerUsername = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
60 0, 0), AccountsToMigrateListModel.ManagerUsername)
61 var managerUri = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
62 0, 0), AccountsToMigrateListModel.ManagerUri)
63 var username = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
64 0, 0), AccountsToMigrateListModel.Username)
65 var alias = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
66 0, 0), AccountsToMigrateListModel.Alias)
67
68 if(managerUri.length !== 0){
69 managerUriInputLabel.text = managerUri
70 } else {
71 managerUriInputLabel.text = "N/A"
72 }
73
74 if(username.length !== 0){
75 usernameInputLabel.text = username
76 } else if(managerUsername.length !== 0){
77 usernameInputLabel.text = managerUsername
78 } else {
79 usernameInputLabel.text = "N/A"
80 }
81
82 if(alias.length !== 0){
83 aliasInputLabel.text = alias
84 } else {
85 aliasInputLabel.text = "N/A"
86 }
87
88 accountID = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
89 0, 0), AccountsToMigrateListModel.Account_ID)
90
91 imgBase64 = accountsToMigrateListModel.data(accountsToMigrateListModel.index(
92 0, 0), AccountsToMigrateListModel.Picture)
93
94 connectionMigrationEnded.enabled = false
95 migrationPushButton.enabled = false
96 stackedWidget.currentIndex = 0
97
98 successState = true
99 nonOperationClosing = true
100
101 accountMigrationDialog.show()
102 return true
103 }
104
105 function checkIfAccountMigrationFinishedAndClose(){
106 accountsToMigrateListModel.reset()
107 if(accountsToMigrateListModel.rowCount() > 0){
108 startAccountMigrationOfTopStack()
109 } else {
110 accountMigrationFinished()
111 if(!nonOperationClosing){
112 nonOperationClosing = true
113 accountMigrationDialog.close()
114 }
115 }
116 }
117
118 function acceptMigration(){
119 nonOperationClosing = false
120 accountsToMigrateListModel.dataChanged(accountsToMigrateListModel.index(0, 0),
121 accountsToMigrateListModel.index(
122 accountsToMigrateListModel.rowCount() - 1, 0))
123 checkIfAccountMigrationFinishedAndClose()
124 }
125
126 function refuseMigrationAndDeleteAccount(){
127 ClientWrapper.accountModel.removeAccount(accountID)
128 acceptMigration()
129 }
130
131 function closeWithoutOperation(){
132 nonOperationClosing = false
133 accountMigrationDialog.close()
134 }
135
136 Timer{
137 id: timerFailureReturn
138
139 interval: 1000
140 repeat: false
141
142 onTriggered: {
143 stackedWidget.currentIndex = 0
144 successState = true
145 }
146 }
147
148 Connections{
149 id: connectionMigrationEnded
150 enabled: false
151 target: ClientWrapper.accountModel
152
153 function onMigrationEnded(accountIdIn, ok){
154 nonOperationClosing = true
155 connectionMigrationEnded.enabled = false
156 if(accountID !== accountIdIn){
157 return
158 }
159 if(!ok){
160 successState = false
161 timerFailureReturn.restart()
162 } else {
163 acceptMigration()
164 }
165 }
166 }
167
168 function slotMigrationButtonClicked(){
169 successState = true
170 stackedWidget.currentIndex = 1
171
172 connectionMigrationEnded.enabled = true
173 ClientWrapper.accountAdaptor.setArchivePasswordAsync(accountID,password)
174 }
175
176 function slotDeleteButtonClicked(){
177 nonOperationClosing = false
178 refuseMigrationAndDeleteAccount()
179 }
180
181 onClosing: {
182 connectionMigrationEnded.enabled = false
183 stackedWidget.currentIndex = 0
184 accountID = ""
185 password = ""
186 passwordInputLineEdit.clear()
187 managerUriInputLabel.text = ""
188 usernameInputLabel.text = ""
189 aliasInputLabel.text = ""
190
191 if(nonOperationClosing){
192 checkIfAccountMigrationFinishedAndClose()
193 }
194 nonOperationClosing = true
195 }
196
197 visible: false
198
199 width: 455
200 height: 594
201
202 Component.onCompleted: {
203 setX(Screen.width / 2 - width / 2)
204 setY(Screen.height / 2 - height / 2)
205 }
206
207 ColumnLayout {
208 anchors.fill: parent
209 Layout.alignment: Qt.AlignHCenter
210
211 StackLayout{
212 id: stackedWidget
213
214 Layout.fillWidth: true
215 Layout.fillHeight: true
216 Layout.alignment: Qt.AlignHCenter
217
218 currentIndex: 0
219
220 Rectangle{
221 id: accountMigrationPage
222
223 Layout.fillWidth: true
224 Layout.fillHeight: true
225 Layout.alignment: Qt.AlignHCenter
226
227 Layout.leftMargin: 11
228 Layout.rightMargin: 11
229 Layout.topMargin: 11
230 Layout.bottomMargin: 11
231
232 x: (parent.width - width) /2
233 y: (parent.height - height) /2
234
235 ScrollView {
236 id: accountMigrationPageScroll
237 anchors.fill: parent
238
239 clip: true
240
241 ScrollBar.horizontal.policy: ScrollBar.AsNeeded
242 ScrollBar.vertical.policy: ScrollBar.AsNeeded
243
244 ColumnLayout{
245 spacing: 7
246
247 width: stackedWidget.width
248 height: stackedWidget.height
249 Layout.alignment: Qt.AlignHCenter
250
251 RowLayout{
252 Layout.fillWidth: true
253
254 Item{
255 Layout.fillWidth: true
256
257 Layout.minimumHeight: 20
258 Layout.preferredHeight: 20
259 Layout.maximumHeight: 20
260 }
261
262 Label{
263 id: accountMigrationLabel
264
265 Layout.alignment: Qt.AlignHCenter
266 Layout.preferredHeight: 27
267
268 font.pointSize: 13
269 font.kerning: true
270 wrapMode:Text.Wrap
271
272 text: qsTr("Account Migration Required")
273
274 horizontalAlignment: Text.AlignLeft
275 verticalAlignment: Text.AlignVCenter
276 }
277
278 Item{
279 Layout.fillWidth: true
280
281 Layout.minimumHeight: 20
282 Layout.preferredHeight: 20
283 Layout.maximumHeight: 20
284 }
285 }
286
287 RowLayout{
288 spacing: 7
289
290 Item{
291 Layout.fillWidth: true
292
293 Layout.minimumHeight: 20
294 Layout.preferredHeight: 20
295 Layout.maximumHeight: 20
296 }
297
298 Label{
299 id: migrationReasonLabel
300
301 Layout.alignment: Qt.AlignHCenter
302 Layout.preferredHeight: 21
303
304 font.pointSize: 10
305 font.kerning: true
306 wrapMode:Text.Wrap
307
308 text: qsTr("This account is malformed. Please enter your password")
309
310 horizontalAlignment: Text.AlignLeft
311 verticalAlignment: Text.AlignVCenter
312 }
313
314 Item{
315 Layout.fillWidth: true
316
317 Layout.minimumHeight: 20
318 Layout.preferredHeight: 20
319 Layout.maximumHeight: 20
320 }
321 }
322
323 Item{
324 Layout.minimumWidth: 20
325 Layout.preferredWidth: 20
326 Layout.maximumWidth: 20
327
328 Layout.minimumHeight: 20
329 Layout.preferredHeight: 20
330 Layout.maximumHeight: 20
331 }
332
333 ColumnLayout{
334 spacing: 7
335
336 Layout.fillWidth: true
337
338 RowLayout{
339 Layout.fillWidth: true
340 Layout.alignment: Qt.AlignCenter
341
342 Item{
343 Layout.fillWidth: true
344
345 Layout.minimumHeight: 20
346 Layout.preferredHeight: 20
347 Layout.maximumHeight: 20
348 }
349
350 Label{
351 id: avatarLabel
352
353 Layout.maximumWidth: 200
354 Layout.preferredWidth: 200
355 Layout.minimumWidth: 200
356
357 Layout.maximumHeight: 200
358 Layout.preferredHeight: 200
359 Layout.minimumHeight: 200
360
361 Layout.alignment: Qt.AlignHCenter
362
363 background: Rectangle {
364 id: avatarLabelBackground
365
366 anchors.fill: parent
367 color: "transparent"
368
369 Image{
370 id: avatarImg
371
372 anchors.fill: parent
373 source: {
374 if(imgBase64.length === 0){
375 return ""
376 } else {
377 return "data:image/png;base64," + imgBase64
378 }
379 }
380 fillMode: Image.PreserveAspectCrop
381 layer.enabled: true
382 layer.effect: OpacityMask {
383 maskSource: Rectangle{
384 width: avatarImg.width
385 height: avatarImg.height
386 radius: {
387 var size = ((avatarImg.width <= avatarImg.height)? avatarImg.width:avatarImg.height)
388 return size /2
389 }
390 }
391 }
392 }
393 }
394 }
395
396 Item{
397 Layout.fillWidth: true
398
399 Layout.minimumHeight: 20
400 Layout.preferredHeight: 20
401 Layout.maximumHeight: 20
402 }
403 }
404 }
405
406 Item{
407 Layout.minimumWidth: 20
408 Layout.preferredWidth: 20
409 Layout.maximumWidth: 20
410
411 Layout.minimumHeight: 30
412 Layout.preferredHeight: 30
413 Layout.maximumHeight: 30
414 }
415
416 GridLayout{
417 rows: 4
418 columns: 5
419 rowSpacing: 7
420 columnSpacing: 7
421
422 Layout.fillWidth: true
423
424 // 1st Row
425 Item{
426 Layout.row: 0
427 Layout.column: 0
428
429 Layout.fillWidth: true
430 Layout.preferredWidth:40
431
432 Layout.minimumHeight: 20
433 Layout.preferredHeight: 20
434 Layout.maximumHeight: 20
435 }
436
437 Label{
438 id: aliasLabel
439
440 Layout.row: 0
441 Layout.column: 1
442
443 Layout.preferredWidth: 92
444 Layout.preferredHeight: 30
445
446 text: qsTr("Alias")
447 font.pointSize: 10
448 font.kerning: true
449
450 horizontalAlignment: Text.AlignLeft
451 verticalAlignment: Text.AlignVCenter
452 }
453
454 Item{
455 Layout.row: 0
456 Layout.column: 2
457
458 Layout.fillWidth: true
459 Layout.preferredWidth:40
460 Layout.maximumWidth: 40
461
462 Layout.minimumHeight: 20
463 Layout.preferredHeight: 20
464 Layout.maximumHeight: 20
465 }
466
467 Label{
468 id: aliasInputLabel
469
470 Layout.row: 0
471 Layout.column: 3
472
473 Layout.preferredWidth: 142
474
475 Layout.minimumHeight: 30
476 Layout.preferredHeight: 30
477
478 font.pointSize: 10
479 font.kerning: true
480
481 horizontalAlignment: Text.AlignLeft
482 verticalAlignment: Text.AlignVCenter
483 }
484
485 Item{
486 Layout.row: 0
487 Layout.column: 4
488
489 Layout.fillWidth: true
490 Layout.preferredWidth:40
491
492 Layout.minimumHeight: 20
493 Layout.preferredHeight: 20
494 Layout.maximumHeight: 20
495 }
496
497 // 2nd Row
498 Item{
499 Layout.row: 1
500 Layout.column: 0
501
502 Layout.fillWidth: true
503 Layout.preferredWidth:40
504
505 Layout.minimumHeight: 20
506 Layout.preferredHeight: 20
507 Layout.maximumHeight: 20
508 }
509
510 Label{
511 id: usernameLabel
512
513 Layout.row: 1
514 Layout.column: 1
515
516 Layout.preferredWidth: 92
517 Layout.preferredHeight: 30
518
519 text: qsTr("Username")
520 font.pointSize: 10
521 font.kerning: true
522
523 horizontalAlignment: Text.AlignLeft
524 verticalAlignment: Text.AlignVCenter
525 }
526
527 Item{
528 Layout.row: 1
529 Layout.column: 2
530
531 Layout.fillWidth: true
532 Layout.preferredWidth:40
533 Layout.maximumWidth: 40
534
535 Layout.minimumHeight: 20
536 Layout.preferredHeight: 20
537 Layout.maximumHeight: 20
538 }
539
540 Label{
541 id: usernameInputLabel
542
543 Layout.row: 1
544 Layout.column: 3
545
546 Layout.preferredWidth: 142
547
548 Layout.minimumHeight: 30
549 Layout.preferredHeight: 30
550
551 font.pointSize: 10
552 font.kerning: true
553
554 horizontalAlignment: Text.AlignLeft
555 verticalAlignment: Text.AlignVCenter
556 }
557
558 Item{
559 Layout.row: 1
560 Layout.column: 4
561
562 Layout.fillWidth: true
563 Layout.preferredWidth:40
564
565 Layout.minimumHeight: 20
566 Layout.preferredHeight: 20
567 Layout.maximumHeight: 20
568 }
569
570 // 3rd Row
571 Item{
572 Layout.row: 2
573 Layout.column: 0
574
575 Layout.fillWidth: true
576 Layout.preferredWidth:40
577
578 Layout.minimumHeight: 20
579 Layout.preferredHeight: 20
580 Layout.maximumHeight: 20
581 }
582
583 Label{
584 id: managerUriLabel
585
586 Layout.row: 2
587 Layout.column: 1
588
589 Layout.preferredWidth: 92
590 Layout.preferredHeight: 30
591
592 text: qsTr("Manager Uri")
593 font.pointSize: 10
594 font.kerning: true
595
596 horizontalAlignment: Text.AlignLeft
597 verticalAlignment: Text.AlignVCenter
598 }
599
600 Item{
601 Layout.row: 2
602 Layout.column: 2
603
604 Layout.fillWidth: true
605 Layout.preferredWidth:40
606 Layout.maximumWidth: 40
607
608 Layout.minimumHeight: 20
609 Layout.preferredHeight: 20
610 Layout.maximumHeight: 20
611 }
612
613 Label{
614 id: managerUriInputLabel
615
616 Layout.row: 2
617 Layout.column: 3
618
619 Layout.preferredWidth: 142
620
621 Layout.minimumHeight: 30
622 Layout.preferredHeight: 30
623
624 font.pointSize: 10
625 font.kerning: true
626
627 horizontalAlignment: Text.AlignLeft
628 verticalAlignment: Text.AlignVCenter
629 }
630
631 Item{
632 Layout.row: 2
633 Layout.column: 4
634
635 Layout.fillWidth: true
636 Layout.preferredWidth:40
637
638 Layout.minimumHeight: 20
639 Layout.preferredHeight: 20
640 Layout.maximumHeight: 20
641 }
642
643 // 4th Row
644 Item{
645 Layout.row: 3
646 Layout.column: 0
647
648 Layout.fillWidth: true
649 Layout.preferredWidth:40
650
651 Layout.minimumHeight: 20
652 Layout.preferredHeight: 20
653 Layout.maximumHeight: 20
654 }
655
656 Label{
657 id: passwordLabel
658
659 Layout.row: 3
660 Layout.column: 1
661
662 Layout.preferredWidth: 92
663 Layout.preferredHeight: 30
664
665 text: qsTr("Password")
666 font.pointSize: 10
667 font.kerning: true
668
669 horizontalAlignment: Text.AlignLeft
670 verticalAlignment: Text.AlignVCenter
671 }
672
673 Item{
674 Layout.row: 3
675 Layout.column: 2
676
677 Layout.fillWidth: true
678 Layout.preferredWidth:40
679 Layout.maximumWidth: 40
680
681 Layout.minimumHeight: 20
682 Layout.preferredHeight: 20
683 Layout.maximumHeight: 20
684 }
685
686 InfoLineEdit{
687 id: passwordInputLineEdit
688
689 Layout.row: 3
690 Layout.column: 3
691
692 Layout.preferredWidth: 142
693
694 Layout.minimumHeight: 30
695 Layout.preferredHeight: 30
696
697 font.pointSize: 10
698 font.kerning: true
699
700 horizontalAlignment: Text.AlignLeft
701 verticalAlignment: Text.AlignVCenter
702
703 echoMode: TextInput.Password
704
705 placeholderText: qsTr("Password")
706
707 onTextChanged: {
708 if(text.length === 0){
709 migrationPushButton.enabled = false
710 } else {
711 migrationPushButton.enabled = true
712 }
713 password = text
714 }
715
716 onEditingFinished: {
717 password = text
718 }
719 }
720
721 Item{
722 Layout.row: 3
723 Layout.column: 4
724
725 Layout.fillWidth: true
726 Layout.preferredWidth:40
727
728 Layout.minimumHeight: 20
729 Layout.preferredHeight: 20
730 Layout.maximumHeight: 20
731 }
732 }
733
734 Item{
735 Layout.minimumWidth: 20
736 Layout.preferredWidth: 20
737 Layout.maximumWidth: 20
738
739 Layout.minimumHeight: 40
740 Layout.preferredHeight: 40
741 Layout.maximumHeight: 40
742 }
743
744 RowLayout{
745 spacing: 0
746 Layout.fillWidth: true
747
748 Item {
749 Layout.minimumWidth: 20
750 Layout.preferredWidth: 20
751 Layout.maximumWidth: 20
752
753 Layout.minimumHeight: 40
754 Layout.preferredHeight: 40
755 Layout.maximumHeight: 40
756 }
757
758 HoverableGradientButton {
759 id: migrationPushButton
760
761 Layout.alignment: Qt.AlignLeft
762 Layout.maximumWidth: 100
763 Layout.preferredWidth: 100
764
765 Layout.maximumHeight: 30
766 Layout.preferredHeight: 30
767 Layout.minimumHeight: 30
768
769 text: qsTr("Migrate")
770 font.pointSize: 10
771 font.kerning: true
772
773 radius: height / 2
774 backgroundColor: JamiTheme.releaseColor
775
776 onClicked: {
777 slotMigrationButtonClicked()
778 }
779 }
780
781 Item {
782 Layout.fillWidth: true
783
784 Layout.minimumHeight: 40
785 Layout.preferredHeight: 40
786 Layout.maximumHeight: 40
787 }
788
789 HoverableButtonTextItem {
790 id: deleteAccountPushButton
791
792 backgroundColor: "red"
793 onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7)
794 onDisabledBackgroundColor: Qt.rgba(
795 255 / 256,
796 0, 0, 0.8)
797 onPressColor: backgroundColor
798 textColor: "white"
799
800 Layout.alignment: Qt.AlignRight
801 Layout.maximumWidth: 100
802 Layout.preferredWidth: 100
803
804 Layout.maximumHeight: 30
805 Layout.preferredHeight: 30
806 Layout.minimumHeight: 30
807
808 text: qsTr("Delete")
809 font.pointSize: 10
810 font.kerning: true
811
812 radius: height / 2
813
814 onClicked: {
815 slotDeleteButtonClicked()
816 }
817 }
818
819 Item {
820 Layout.minimumWidth: 20
821 Layout.preferredWidth: 20
822 Layout.maximumWidth: 20
823
824 Layout.minimumHeight: 40
825 Layout.preferredHeight: 40
826 Layout.maximumHeight: 40
827 }
828 }
829 }
830
831 }
832 }
833
834 Rectangle{
835 id: migrationWaitingPage
836
837 Layout.fillWidth: true
838 Layout.fillHeight: true
839 Layout.alignment: Qt.AlignHCenter
840
841 Layout.leftMargin: 11
842 Layout.rightMargin: 11
843 Layout.topMargin: 11
844 Layout.bottomMargin: 11
845
846 x: (parent.width - width) /2
847 y: (parent.height - height) /2
848
849 ScrollView {
850 id: migrationWaitingPageScroll
851 anchors.fill: parent
852
853 clip: true
854
855 ScrollBar.horizontal.policy: ScrollBar.AsNeeded
856 ScrollBar.vertical.policy: ScrollBar.AsNeeded
857
858 ColumnLayout{
859 spacing: 7
860
861 width: stackedWidget.width
862 height: stackedWidget.height
863 Layout.alignment: Qt.AlignHCenter
864
865 Item{
866 Layout.fillWidth: true
867 Layout.fillHeight: true
868
869 Layout.preferredHeight: 211
870 }
871
872 RowLayout{
873 spacing: 7
874
875 Layout.alignment: Qt.AlignHCenter
876 Layout.fillWidth: true
877
878 Item{
879 Layout.alignment: Qt.AlignLeft
880 Layout.fillWidth: true
881 Layout.fillHeight: true
882
883 Layout.minimumWidth: 20
884 }
885
886 Label{
887 id: spinnerLabel
888
889 Layout.alignment: Qt.AlignHCenter
890
891 Layout.maximumWidth: 200
892 Layout.preferredWidth: 200
893 Layout.minimumWidth: 200
894
895 Layout.maximumHeight: 200
896 Layout.preferredHeight: 200
897 Layout.minimumHeight: 200
898
899 property string spinnerDisplyState: successState ? "spinnerLabel_Regular" : "spinnerLabel_Failure"
900 onSpinnerDisplyStateChanged: {
901 switch (spinnerDisplyState) {
902 case "spinnerLabel_Regular":
903 background = Qt.createQmlObject("import QtQuick 2.14;
904 AnimatedImage {
905 source: \"qrc:/images/jami_eclipse_spinner.gif\"
906
907 playing: true
908 paused: false
909 fillMode: Image.PreserveAspectFit
910 mipmap: true
911 }", spinnerLabel)
912 break
913 case "spinnerLabel_Failure":
914 background = Qt.createQmlObject("import QtQuick 2.14;
915 import \"qrc:/src/constant/\";
916 Image {
917 anchors.fill: parent;
918 source:\"image://tintedPixmap/\" + (\"qrc:/images/icons/baseline-error_outline-24px.svg\").replace(\"qrc:/images/icons/\", \"\") + \"+\" + JamiTheme.urgentOrange_;
919 mipmap: true;}", spinnerLabel)
920 break
921 }
922 }
923 }
924
925 Item {
926 Layout.alignment: Qt.AlignRight
927 Layout.fillWidth: true
928 Layout.fillHeight: true
929
930 Layout.minimumWidth: 20
931 }
932 }
933
934 Item{
935 Layout.fillWidth: true
936 Layout.fillHeight: true
937
938 Layout.preferredHeight: 211
939 }
940
941 Label{
942 id: progressLabel
943
944 Layout.alignment: Qt.AlignHCenter
945 Layout.fillWidth: true
946
947 color: successState? "black" : "red"
948 text: successState? qsTr("Migrating your Jami account...") : qsTr("Migration Failed")
949 font.pointSize: 11
950 font.kerning: true
951
952 horizontalAlignment: Text.AlignHCenter
953 verticalAlignment: Text.AlignVCenter
954 wrapMode: Label.WordWrap
955 }
956
957 Item{
958 Layout.fillWidth: true
959
960 Layout.minimumHeight: 20
961 Layout.preferredHeight: 20
962 Layout.maximumHeight: 20
963 }
964 }
965 }
966 }
967 }
968 }
969}