--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svn/pc-suite/!svn/ver/650/trunk/tabletsuite/debian
+END
+control
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/pc-suite/!svn/ver/650/trunk/tabletsuite/debian/control
+END
+compat
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/debian/compat
+END
+changelog
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/649/trunk/tabletsuite/debian/changelog
+END
+copyright
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/debian/copyright
+END
+docs
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/debian/docs
+END
+rules
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/debian/rules
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/debian
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-09-29T15:40:22.681741Z
+650
+otacilio
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+control
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+3f11fa51870d30106bcaba2287c59637
+2009-09-29T15:40:22.681741Z
+650
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+397
+\f
+compat
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+84bc3da1b3e33a18e8d5e1bdd7a18d7a
+2009-07-30T18:46:46.398336Z
+495
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2
+\f
+changelog
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+1b9dbce6d0ba853bfec1ac3ed6bb8e2d
+2009-09-28T17:26:29.361774Z
+649
+melunko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+156
+\f
+copyright
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+dee7a3d70eedde5d9959617122de4083
+2009-07-30T18:46:46.398336Z
+495
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+696
+\f
+docs
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-07-30T18:46:46.398336Z
+495
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
+rules
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+bb04c0b837f042492f69dd6a707c39df
+2009-08-04T13:54:03.919326Z
+505
+otacilio
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+169
+\f
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null
+tablet-suite (0.1) unstable; urgency=low
+
+ * Initial release
+
+ -- Otacilio Freitas de Lacerda <otaciliolacerda@gmail.com> Thu, 30 Jul 2009 13:26:51 -0300
--- /dev/null
+Source: tablet-suite
+Section: python
+Priority: optional
+Maintainer: Otacilio Freitas de Lacerda <otaciliolacerda@gmail.com>
+Build-Depends: cdbs, debhelper (>= 7), python2.6
+Standards-Version: 3.8.0
+
+Package: tablet-suite
+Architecture: all
+Depends: sshfs, python-qt4, python2.6, openssh-client, python-paramiko
+Description: <TabletSuite Alpha>
+ <.
+ This package contains the tablet-suite project.>
--- /dev/null
+This package was debianized by Otacilio Freitas de Lacerda <otacilio@unknown> on
+Thu, 30 Jul 2009 13:26:51 -0300.
+
+It was downloaded from <url://example.com>
+
+Upstream Author(s):
+
+ <put author's name and email here>
+ <likewise for another author>
+
+Copyright:
+
+ <Copyright (C) YYYY Name OfAuthor>
+ <likewise for another author>
+
+License:
+
+ <Put the license of the package here indented by 4 spaces>
+
+The Debian packaging is copyright 2009, Otacilio Freitas de Lacerda <otacilio@unknown> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
--- /dev/null
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+
--- /dev/null
+tablet-suite (0.1) unstable; urgency=low
+
+ * Initial release
+
+ -- Otacilio Freitas de Lacerda <otaciliolacerda@gmail.com> Thu, 30 Jul 2009 13:26:51 -0300
--- /dev/null
+Source: tablet-suite
+Section: python
+Priority: optional
+Maintainer: Otacilio Freitas de Lacerda <otaciliolacerda@gmail.com>
+Build-Depends: cdbs, debhelper (>= 7), python2.6
+Standards-Version: 3.8.0
+
+Package: tablet-suite
+Architecture: all
+Depends: sshfs, python-qt4, python2.6, openssh-client, python-paramiko
+Description: <TabletSuite Alpha>
+ <.
+ This package contains the tablet-suite project.>
--- /dev/null
+This package was debianized by Otacilio Freitas de Lacerda <otacilio@unknown> on
+Thu, 30 Jul 2009 13:26:51 -0300.
+
+It was downloaded from <url://example.com>
+
+Upstream Author(s):
+
+ <put author's name and email here>
+ <likewise for another author>
+
+Copyright:
+
+ <Copyright (C) YYYY Name OfAuthor>
+ <likewise for another author>
+
+License:
+
+ <Put the license of the package here indented by 4 spaces>
+
+The Debian packaging is copyright 2009, Otacilio Freitas de Lacerda <otacilio@unknown> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
--- /dev/null
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 50
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts
+END
+pf_tempesta_seven.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven.ttf
+END
+pf_tempesta_seven_bold.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_bold.ttf
+END
+pf_tempesta_seven_extended.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_extended.ttf
+END
+pf_tempesta_seven_extended_bold.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_extended_bold.ttf
+END
+pf_tempesta_seven_condensed.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_condensed.ttf
+END
+pf_tempesta_seven_condensed_bold.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_condensed_bold.ttf
+END
+BROWA.TTF
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/BROWA.TTF
+END
+pf_tempesta_seven_compressed.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_compressed.ttf
+END
+pf_tempesta_seven_compressed_bold.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/svn/pc-suite/!svn/ver/632/trunk/tabletsuite/fonts/pf_tempesta_seven_compressed_bold.ttf
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/fonts
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-09-15T18:22:54.599315Z
+632
+amaury
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+pf_tempesta_seven.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+9f70908a87757dce7c6e692cd9b6dacb
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+22176
+\f
+pf_tempesta_seven_bold.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+31fbb55b275dbdededfc430f50ad9354
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21780
+\f
+pf_tempesta_seven_extended.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+07b0d01caeb4f8a81ae384119e1c182d
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+22464
+\f
+pf_tempesta_seven_extended_bold.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8e2f92fc5a949a2cca42e28d019f5681
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+22160
+\f
+pf_tempesta_seven_condensed.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+18f38e87a9c2dfd026026d8922d5ce9e
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21616
+\f
+pf_tempesta_seven_condensed_bold.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+6b38585aac6b3b3a37e218faa4f06ae7
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21160
+\f
+BROWA.TTF
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+558e1f7c26d9405ac41942266ebac11d
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+80392
+\f
+pf_tempesta_seven_compressed.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+ff7b35bf8a97fbb416e5d475a6cff55f
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+20396
+\f
+pf_tempesta_seven_compressed_bold.ttf
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8cc607fb27e7fdc770eea5c45dc9d823
+2009-09-15T18:22:54.599315Z
+632
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+20796
+\f
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svn/pc-suite/!svn/ver/643/trunk/tabletsuite/img
+END
+checkbox_checked.png
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/checkbox_checked.png
+END
+scroll_handle_v.png
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/610/trunk/tabletsuite/img/scroll_handle_v.png
+END
+scroll_base_h.png
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/610/trunk/tabletsuite/img/scroll_base_h.png
+END
+ip_list_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/591/trunk/tabletsuite/img/ip_list_border.png
+END
+progress_bar_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/progress_bar_bg.png
+END
+backup_name_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/backup_name_border.png
+END
+large_arrow_image.png
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/large_arrow_image.png
+END
+small_default_button.png
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/pc-suite/!svn/ver/591/trunk/tabletsuite/img/small_default_button.png
+END
+progress_bar_connecting_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svn/pc-suite/!svn/ver/612/trunk/tabletsuite/img/progress_bar_connecting_bg.png
+END
+scroll_base_v.png
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/610/trunk/tabletsuite/img/scroll_base_v.png
+END
+progress_bar_chunk.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/609/trunk/tabletsuite/img/progress_bar_chunk.png
+END
+view_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/600/trunk/tabletsuite/img/view_bg.png
+END
+bg_geral0.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bg_geral0.png
+END
+table_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/table_border.png
+END
+bg_geral2.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bg_geral2.png
+END
+progress_bar_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/progress_bar_border.png
+END
+N810_file.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N810_file.png
+END
+N800.png
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N800.png
+END
+small_default_button_clicked.png
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/pc-suite/!svn/ver/591/trunk/tabletsuite/img/small_default_button_clicked.png
+END
+disconnected_backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/624/trunk/tabletsuite/img/disconnected_backup.png
+END
+white_arrow.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/white_arrow.png
+END
+device_file_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_file_border.png
+END
+bg_restore.png
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bg_restore.png
+END
+icon-ref-restorebackups.png
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/icon-ref-restorebackups.png
+END
+default_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/610/trunk/tabletsuite/img/default_bg.png
+END
+browse_button.png
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/browse_button.png
+END
+bg_backup0.png
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bg_backup0.png
+END
+pc_name_border_file.png
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/pc_name_border_file.png
+END
+pc_file_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/pc_file_border.png
+END
+checkbox_unchecked.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/checkbox_unchecked.png
+END
+icon-ref-settings.png
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/icon-ref-settings.png
+END
+large_arrow_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/large_arrow_border.png
+END
+device_checkbox_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_checkbox_border.png
+END
+device_name_border_checkbox.png
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_name_border_checkbox.png
+END
+disconnected.png
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/disconnected.png
+END
+backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/backup.png
+END
+back_arrow_on.png
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/back_arrow_on.png
+END
+view_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/600/trunk/tabletsuite/img/view_border.png
+END
+icon-alert-ref.png
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/icon-alert-ref.png
+END
+tabletsuite.desktop
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/643/trunk/tabletsuite/img/tabletsuite.desktop
+END
+N800_backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N800_backup.png
+END
+forward_arrow_on.png
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/forward_arrow_on.png
+END
+N810_backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N810_backup.png
+END
+lista.png
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/lista.png
+END
+bg_backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bg_backup.png
+END
+icon-ref-newbackup.png
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/icon-ref-newbackup.png
+END
+device_backup_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_backup_border.png
+END
+N810.png
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N810.png
+END
+arrow.png
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/arrow.png
+END
+device_name_border_file.png
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_name_border_file.png
+END
+tab_bg_1.png
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/tab_bg_1.png
+END
+tab_bg_2.png
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/tab_bg_2.png
+END
+progress_bar_chunk_dialog.png
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svn/pc-suite/!svn/ver/609/trunk/tabletsuite/img/progress_bar_chunk_dialog.png
+END
+tab_bg_3.png
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/tab_bg_3.png
+END
+icon-ref-managebackups.png
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/icon-ref-managebackups.png
+END
+pc_image.png
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/614/trunk/tabletsuite/img/pc_image.png
+END
+progress_bar_dialog_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/609/trunk/tabletsuite/img/progress_bar_dialog_bg.png
+END
+device_name_border_backup.png
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_name_border_backup.png
+END
+checkbox_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/checkbox_border.png
+END
+button_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/button_bg.png
+END
+small_icon-ref-restorebackups.png
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/small_icon-ref-restorebackups.png
+END
+N800_file.png
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/608/trunk/tabletsuite/img/N800_file.png
+END
+button_with_icon_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/button_with_icon_bg.png
+END
+black_arrow.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/black_arrow.png
+END
+small_icon-ref-settings.png
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/small_icon-ref-settings.png
+END
+memory_bar.png
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/memory_bar.png
+END
+ssh.png
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/ssh.png
+END
+battery_bar.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/battery_bar.png
+END
+button_bg_clicked.png
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/button_bg_clicked.png
+END
+bt_next.png
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bt_next.png
+END
+path_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/path_bg.png
+END
+backup_default_button.png
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/backup_default_button.png
+END
+back_arrow_off.png
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/back_arrow_off.png
+END
+button_with_icon_bg_clicked.png
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/button_with_icon_bg_clicked.png
+END
+tabletSuite_logo.png
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/tabletSuite_logo.png
+END
+copy_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/copy_border.png
+END
+small_icon-ref-newbackup.png
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/small_icon-ref-newbackup.png
+END
+forward_arrow_off.png
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/forward_arrow_off.png
+END
+device_selection_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/600/trunk/tabletsuite/img/device_selection_bg.png
+END
+backup_name_bg.png
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/backup_name_bg.png
+END
+scroll_handle_h.png
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/610/trunk/tabletsuite/img/scroll_handle_h.png
+END
+bt_next_clicked.png
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/bt_next_clicked.png
+END
+backup_default_button_clicked.png
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/backup_default_button_clicked.png
+END
+bg_manager.png
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/596/trunk/tabletsuite/img/bg_manager.png
+END
+device_memory.png
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/device_memory.png
+END
+path_border.png
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/img/path_border.png
+END
+small_icon-ref-managebackups.png
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/pc-suite/!svn/ver/626/trunk/tabletsuite/img/small_icon-ref-managebackups.png
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/img
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-09-24T18:11:29.733195Z
+643
+otacilio
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+checkbox_checked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+a01bf9fbe352b626b8e5b3484c9e645e
+2009-08-13T17:08:11.546686Z
+550
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+822
+\f
+scroll_handle_v.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+cfbffd47da519d20e6c645586e1be0fc
+2009-09-09T16:10:10.046818Z
+610
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3103
+\f
+scroll_base_h.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+23e767ca7a1bf2a2158e52837f6e415b
+2009-09-09T16:10:10.046818Z
+610
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+844
+\f
+progress_bar_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+342126781b58ecf007b3faad2568af64
+2009-08-21T18:19:06.773534Z
+573
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3756
+\f
+ip_list_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+eaca0b8358ab0e84df410a39886c9d6f
+2009-09-03T16:03:51.683671Z
+591
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4841
+\f
+backup_name_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+78844d8e12b99fab3f63869565651301
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3410
+\f
+large_arrow_image.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+2957d2a0847d5844f5a130b40d11271a
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5609
+\f
+progress_bar_connecting_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+00f570e8e6010180c9bd53f241fae029
+2009-09-10T20:35:15.948790Z
+612
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3699
+\f
+small_default_button.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+13644f0774d460563f934c46e2cd8056
+2009-09-03T16:03:51.683671Z
+591
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3443
+\f
+scroll_base_v.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+3230dc7d26417d0b4d968c9a6f2c71c5
+2009-09-09T16:10:10.046818Z
+610
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3597
+\f
+progress_bar_chunk.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+f9a64d04eb7eae7900af543bedf374be
+2009-09-08T17:01:54.301655Z
+609
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3279
+\f
+bg_geral0.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+91111ff0319924d279c47e55423dec94
+2009-07-28T18:31:05.094742Z
+476
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+79464
+\f
+view_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+6d46d6caa3a6ca58e35094b664a39a6b
+2009-09-03T22:08:31.931352Z
+600
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3281
+\f
+bg_geral2.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+e6e8a6c49810a752be37c0e22f753781
+2009-07-16T17:37:19.503117Z
+437
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+52909
+\f
+table_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+aec2ba53080f3ffa7ee774e73211b8f5
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4887
+\f
+progress_bar_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d888d82dcd05b6055888ba810fa25799
+2009-08-21T18:19:06.773534Z
+573
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3273
+\f
+N810_file.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+de0f0760975780acd73d91f857d05426
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10288
+\f
+N800.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8ed3e9ce544ea2f26a4dbd7657122398
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6231
+\f
+small_default_button_clicked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+a1fa5275ce8a0ec5e68d25b3e9f02883
+2009-09-03T16:03:51.683671Z
+591
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3579
+\f
+disconnected_backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+7414015bc4afd729f9b54b05ea9c04f7
+2009-09-14T19:20:21.821743Z
+624
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21287
+\f
+white_arrow.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+690dc22ed876c3436a427891a9115362
+2009-07-29T09:45:01.027130Z
+482
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2817
+\f
+device_file_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+4211e9d5c31659da6d66dad550c9d646
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4224
+\f
+bg_restore.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+460acdb041c97f3b866c48bd01e6dcc4
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+62107
+\f
+icon-ref-restorebackups.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+06caf36fbbacfa1e892c62e6ad6cd104
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4633
+\f
+default_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+562028809d59ea75c5bb4fc2face91b7
+2009-09-09T16:10:10.046818Z
+610
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2396
+\f
+browse_button.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+850dd65278e2b1ab21ad0a9bd34e6c31
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3991
+\f
+bg_backup0.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+71b7252b3021dd09f8ec587549118893
+2009-08-11T16:36:01.916949Z
+539
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+48940
+\f
+pc_name_border_file.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+cafe36896b8b58e92d5d351b0c153720
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3468
+\f
+pc_file_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+20068b0940926d1110879ab4a59fb44f
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4230
+\f
+checkbox_unchecked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+118a0f804bcc4d7e90be766910bbc51c
+2009-08-13T17:08:11.546686Z
+550
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+688
+\f
+icon-ref-settings.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+1a0d9597956dda69c405967db13fed7c
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5214
+\f
+large_arrow_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+0f34a62a541a7caa7aa2f1d4b1d9b112
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6248
+\f
+disconnected.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+ff9a15db496d8dae6461766710d6686d
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12211
+\f
+device_name_border_checkbox.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+bd2ca576ffc5981ec2323064d2dadb65
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3324
+\f
+device_checkbox_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+cf98ab9a0bb3870789b4853bd1957667
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4304
+\f
+backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+870aca33c4343973c09b83e3dfe45ab4
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4657
+\f
+back_arrow_on.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d259ebab223ef56773733ce28676fb3e
+2009-07-29T12:18:32.451141Z
+490
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2954
+\f
+icon-alert-ref.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+36c02dce8980394a63d0716986846db4
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3604
+\f
+view_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+07c9e5b9c933aab32c52d83369f1749b
+2009-09-03T22:08:31.931352Z
+600
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4512
+\f
+forward_arrow_on.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+972f112af726e4cc1048c4957987df5c
+2009-07-29T12:18:32.451141Z
+490
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2950
+\f
+N800_backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+3a755c3c2d6016b103280e1dfac404c3
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10860
+\f
+tabletsuite.desktop
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+57206ed9fbe3ad7e9f6035587fc0a20d
+2009-09-24T18:11:29.733195Z
+643
+otacilio
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+269
+\f
+N810_backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+f42fa915e09e712f6904561390845c73
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+19137
+\f
+lista.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+21abea4315d51598bc9493ba74507eb5
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3363
+\f
+bg_backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+929064a3d451a8c7e72c8e211401db87
+2009-08-07T19:29:53.557169Z
+529
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+74676
+\f
+icon-ref-newbackup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+207b1bdc88279b56c6755a3841021208
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4895
+\f
+device_backup_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+afb641c1d2d237b8be0b564ed6c979c1
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4792
+\f
+N810.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+24f08a897165cee8770aee6a05e0ed65
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12356
+\f
+arrow.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+690dc22ed876c3436a427891a9115362
+2009-07-28T17:43:56.280909Z
+474
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2817
+\f
+device_name_border_file.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d425373982afaea21744991e30f584fe
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3399
+\f
+tab_bg_1.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+5cd4e834dcd5137cf36f48552cb30ef6
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11985
+\f
+progress_bar_chunk_dialog.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8201eaae0da8f4f292365a716b4d527a
+2009-09-08T17:01:54.301655Z
+609
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3228
+\f
+tab_bg_2.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+e822a037236b010e3285fd7c6b0026c2
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10955
+\f
+tab_bg_3.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+53bb3b054aa1ae191d9a3caf0f3d5cb8
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7825
+\f
+icon-ref-managebackups.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+1d823eb2520527d96b65d79292c3bfdb
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5154
+\f
+pc_image.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8aef2711997e0be150bfb960d4b22f3d
+2009-09-10T22:40:29.655655Z
+614
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6196
+\f
+progress_bar_dialog_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+4a2c3ade46963dee17dcf765773e9274
+2009-09-08T17:01:54.301655Z
+609
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3903
+\f
+device_name_border_backup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+845b4976344776d80ab27ef9baf073d4
+2009-08-10T18:42:02.033426Z
+532
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3487
+\f
+button_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8f7e66a13a3d77964b89ecc60062fd8b
+2009-08-05T16:55:19.618241Z
+511
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5430
+\f
+checkbox_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+335ed6a4799668bd6d0e2e84f69c6f62
+2009-08-12T10:13:12.305172Z
+544
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3953
+\f
+N800_file.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+de991fbf0dde3cf6b7bfa3f5bc1dbdad
+2009-09-08T14:59:55.898571Z
+608
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5012
+\f
+small_icon-ref-restorebackups.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+822f5e0ed76fb0bb47a8d2f90f375469
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3725
+\f
+black_arrow.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+03e716d26ee1913272983b9cfcc199f8
+2009-07-29T09:45:01.027130Z
+482
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2824
+\f
+button_with_icon_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d4ffa3fe7a2f3e2eba14b66936411a85
+2009-08-10T11:25:57.599617Z
+531
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3896
+\f
+small_icon-ref-settings.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+1140c565d18d21a1efd190bc1a2ec8dc
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4242
+\f
+memory_bar.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+35fa29ba1087512051d27bf08766942c
+2009-07-27T10:04:31.020564Z
+466
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3563
+\f
+ssh.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+40dfa113ff4dbf710d29e9c965f94e97
+2009-07-02T12:53:33.231762Z
+373
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3437
+\f
+battery_bar.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+23a300c76eb873d8b2f35a037151a0b7
+2009-07-27T10:04:31.020564Z
+466
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3659
+\f
+button_bg_clicked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+b4331208b1129b52d060a67e9f812335
+2009-08-05T16:55:19.618241Z
+511
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4360
+\f
+bt_next.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+0ea17926855c030924cd0375de12cbe6
+2009-08-11T18:11:13.211844Z
+540
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3705
+\f
+path_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+2e9149e73f319bd8c29b46e4f68bd29b
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3856
+\f
+backup_default_button.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+507a2a81d9894d081cd48286cabc08be
+2009-08-27T20:31:13.838494Z
+579
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3604
+\f
+back_arrow_off.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+e08a8e19f58dcc1ae9993676fa2d2273
+2009-07-29T12:18:32.451141Z
+490
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2954
+\f
+button_with_icon_bg_clicked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+1ca5a51cd91b76b1d00ed4f75e4ddbd5
+2009-08-10T11:25:57.599617Z
+531
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4141
+\f
+tabletSuite_logo.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+1a1166670a4205cfd08c1befc674c2bb
+2009-08-18T15:36:29.586124Z
+570
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7324
+\f
+copy_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+e92a79031af207d5615413f878bcaa27
+2009-08-13T17:08:11.546686Z
+550
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4924
+\f
+small_icon-ref-newbackup.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+cf9ba7641b827a058912d9379915ecad
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4003
+\f
+forward_arrow_off.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+3379a96302f63597c319c50a264933a8
+2009-07-29T12:18:32.451141Z
+490
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2950
+\f
+device_selection_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+63b1ba933149d0ffcb6e17edefa09c70
+2009-09-03T22:08:31.931352Z
+600
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5927
+\f
+backup_name_bg.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+abfde4ac92d9205f446eef12a951f024
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3909
+\f
+scroll_handle_h.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+25c1fa8f802f15ba9575b98a6f645346
+2009-09-09T16:10:10.046818Z
+610
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+446
+\f
+bt_next_clicked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+ff7a184854f8fc2301f35393d62102f5
+2009-08-11T18:11:13.211844Z
+540
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3836
+\f
+backup_default_button_clicked.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+df78c1f41a82b17a499c603b5fd4f381
+2009-08-27T20:31:13.838494Z
+579
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3732
+\f
+bg_manager.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+460acdb041c97f3b866c48bd01e6dcc4
+2009-09-03T21:14:33.964127Z
+596
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+62107
+\f
+device_memory.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+ead62093235e632745d327a6e05fb890
+2009-07-27T10:04:31.020564Z
+466
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3715
+\f
+path_border.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+e2bf32a0e2b5b49abd45777ddb597fd0
+2009-08-13T19:38:57.115054Z
+551
+pauloouriques
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3412
+\f
+small_icon-ref-managebackups.png
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+35938d68793a64ddc63691a22bbbb912
+2009-09-15T12:07:49.302204Z
+626
+amaury
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4022
+\f
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null
+#!/usr/bin/env xdg-open
+[Desktop Entry]
+Name=TabletSuite
+Comment=TabletSuite Application
+Version=0.0.1
+Exec=tabletsuite
+Icon=/usr/share/tabletsuite/tabletSuite_logo.png
+Type=Application
+Terminal=false
+Categories=Application;
+StartupNotify=false
+Name[en_US]=tabletsuite
--- /dev/null
+#!/usr/bin/env xdg-open
+[Desktop Entry]
+Name=TabletSuite
+Comment=TabletSuite Application
+Version=0.0.1
+Exec=tabletsuite
+Icon=/usr/share/tabletsuite/tabletSuite_logo.png
+Type=Application
+Terminal=false
+Categories=Application;
+StartupNotify=false
+Name[en_US]=tabletsuite
--- /dev/null
+#!/usr/bin/env python
+
+from distutils.core import setup
+from subprocess import *
+import os
+import glob
+
+dist = setup(name='tabletsuite',
+ version='0.0.1',
+ maintainer='Otacilio Lacerda',
+ maintainer_email='otaciliolacerda@gmail.com',
+ description='TabletSuite application',
+ long_description='',
+ license='GNU GPL',
+ platforms='all',
+ scripts=['tabletsuite'],
+ packages=['src', 'src/backup', 'src/pcsuite', 'src/ui', 'src/style'],
+ data_files=[('share/tabletsuite', glob.glob("img/*")),
+ ('share/applications', ['img/tabletsuite.desktop']),
+ ('share/fonts/extras', glob.glob('fonts/*'))],
+)
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svn/pc-suite/!svn/ver/653/trunk/tabletsuite/src
+END
+battery.py
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/pc-suite/!svn/ver/617/trunk/tabletsuite/src/battery.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/__init__.py
+END
+pcsdevicemanager.py
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/642/trunk/tabletsuite/src/pcsdevicemanager.py
+END
+settings.py
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/settings.py
+END
+pcsdeviceinfo.py
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/pcsdeviceinfo.py
+END
+tabletsuite.py
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/tabletsuite.py
+END
+pcsdeviceutils.py
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/643/trunk/tabletsuite/src/pcsdeviceutils.py
+END
+pcsutils.py
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/pc-suite/!svn/ver/611/trunk/tabletsuite/src/pcsutils.py
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-10-06T17:00:03.678569Z
+653
+pauloouriques
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+style
+dir
+\f
+plugins
+dir
+\f
+battery.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+9e4cc0a1ebba665c2fe12b76ba889647
+2009-09-14T12:56:51.357750Z
+617
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1811
+\f
+backup
+dir
+\f
+__init__.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-03-29T21:16:15.145020Z
+24
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
+pcsdevicemanager.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+c759b16ea11f886c17310a1daa147d15
+2009-09-24T17:39:24.743743Z
+642
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4001
+\f
+settings.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+a624870d9c3018ae79cfc67d37fa1abf
+2009-06-23T17:46:40.723124Z
+346
+melunko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1158
+\f
+pcsdeviceinfo.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+027acaec3db77d7c557936ef39ae9e75
+2009-07-08T15:53:48.428567Z
+394
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+417
+\f
+pcsuite
+dir
+\f
+tabletsuite.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+0e1bae3cfc483abe88238c96c4ac1798
+2009-09-03T11:08:46.919187Z
+588
+otacilio
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+775
+\f
+ui
+dir
+\f
+pcsdeviceutils.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+99e1f832b7dab66b04bd0742b4f90423
+2009-09-24T18:11:29.733195Z
+643
+otacilio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5128
+\f
+pcsutils.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+6bac19aba73e3f938e4cdb3aea339c13
+2009-09-10T18:11:56.305145Z
+611
+nicholas
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4727
+\f
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+#!/usr/bin/python
+
+# Ainda continua sendo o codigo do cara, apenas retirei as partes que nao nos interessa.
+# Ainda tem que ver se pode usar o codigo, ou seja, olhar a licensa.
+# Deve ser istalado no dispositivo
+# Otacilio Lacerda
+
+import dbus
+import dbus.service
+import dbus.glib
+import gobject
+
+percent_left = -1
+charging = False
+
+loop = gobject.MainLoop()
+
+class Request(dbus.service.Object):
+ def __init__(self, bus_name):
+ dbus.service.Object.__init__(self, bus_name, '/com/nokia/bme/request')
+
+ @dbus.service.signal('com.nokia.bme.request')
+ def timeleft_info_req(self):
+ pass
+
+ @dbus.service.signal('com.nokia.bme.request')
+ def status_info_req(self):
+ pass
+
+def timeleft_handler(idle_time, active_time):
+ global percent_left
+ percent_left = min(100, 100.0 * idle_time / 15000)
+ loop.quit()
+
+def charging_on_handler():
+ global charging
+ charging = True
+ loop.quit()
+
+def charging_off_handler():
+ global charging
+ charging = False
+ loop.quit()
+
+def getBatteryState(request):
+ global percent_left
+ global charging
+
+ request.status_info_req()
+ loop.run()
+
+ if charging:
+ return -1
+ request.timeleft_info_req()
+ loop.run()
+ return percent_left
+
+if __name__ == "__main__":
+
+ bus = dbus.SystemBus(private = True)
+ bus.add_signal_receiver(timeleft_handler, 'battery_timeleft')
+ bus.add_signal_receiver(charging_on_handler, 'charger_charging_on')
+ bus.add_signal_receiver(charging_on_handler, 'battery_full')
+ bus.add_signal_receiver(charging_off_handler, 'charger_charging_off')
+ bus_name = dbus.service.BusName('com.nokia.bme.request', bus)
+ request = Request(bus_name)
+
+ percent = getBatteryState(request)
+ if percent < 0:
+ print '-1'
+ else:
+ print '%.1f' % (percent)
+
--- /dev/null
+# low_device_info module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+
+class PcsDeviceInfo:
+
+ def __init__(self):
+ self.ip = ""
+ self.storage = 0 # list memory data (FIXME: document the array information
+ self.battery = 0
+ self.model = ""
+ self.name = ""
+ self.hostname = ""
+ self.system = ""
+ self.charging = False
+ self.ossoBackup = ""
--- /dev/null
+# low_device_manager module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+# Module responsible for management of devices informations.
+
+import pickle
+import os
+
+from PyQt4.QtCore import *
+
+import pcsutils as utils
+from pcsdeviceinfo import PcsDeviceInfo
+from pcsdeviceutils import *
+from ui.tsuigeneralmethods import showMessageBox
+
+USER_HOST = 'root'
+HOME = os.path.expanduser("~")
+DEVICES_FILE = os.path.join(HOME, ".pcsuite/devices/.ip_list")
+
+
+class PcsDeviceManager(QObject):
+ """Class responsible for devices management such as adding and removing
+ devices, get batery, memory and name informations and saving Device objects.
+
+ The DeviceManager holds a list of Devices objects and can save and load this
+ list on a file and retrieve information about each Device.
+
+ """
+ _currentIp = None
+ def __init__(self):
+ QObject.__init__(self)
+ self._deviceList = []
+
+ # FIXME: initialize this in another place
+ utils.initDirs()
+ self.loadDevices()
+
+ self._currentIp = None
+
+ def _batteryException(self):
+ errorMessage = "Could not get device battery status, check if " +\
+ "python is installed on your device. To get information about " + \
+ "python installation visit: " +\
+ "http://pymaemo.garage.maemo.org/installation.html"
+ showMessageBox(errorMessage,
+ "Error while collecting device information")
+
+ def _addDevice(self, deviceIp):
+ """Add a new device to list connecting to it in the process.
+
+ Arguments:
+ host_ip -- The IP of the device to connect.
+
+ """
+ self.loadDevices()
+
+ deviceInfo = PcsDeviceInfo()
+ deviceInfo.ip = deviceIp
+ (deviceInfo.name, deviceInfo.system,
+ deviceInfo.ossoBackup) = queryProductInformation(deviceIp)
+ if deviceInfo.name == "NO INFORMATION":
+ return "connectException"
+ try:
+ deviceInfo.battery = float(queryDeviceBattery(deviceIp))
+ except:
+ return "batteryException"
+
+ if deviceInfo.battery < 0:
+ deviceInfo.charging = True
+
+ deviceInfo.storage = queryDeviceStorage(deviceIp)
+
+ if self.getDevice(deviceIp) != None:
+ return deviceInfo
+
+ self._deviceList.append(deviceInfo)
+ self.saveDevices()
+ return deviceInfo
+
+ def removeDevice(self, deviceIp):
+ """Remove a Device from list.
+
+ Arguments:
+ device_ip -- The IP of the device to remove
+
+ """
+ deviceInfo = self.getDevice(deviceIp)
+ if deviceInfo != -1:
+ self._deviceList.remove(deviceInfo)
+ self.saveDevices()
+ return 1
+ else:
+ raise Exception("No device with that ip was found")
+
+ def getDevices(self):
+ """Returns a list with the IP address of all devices in the object's
+ devices list.
+
+ """
+ ips = []
+ for deviceInfo in self._deviceList:
+ ips.append(deviceInfo.ip)
+ return ips
+
+ def saveDevices(self):
+ """Save the list of Device objects in DEVICES_FILE file."""
+ obj = self._deviceList
+ file = open(DEVICES_FILE, "w")
+ pickle.dump(obj, file)
+ file.close()
+
+ def loadDevices(self):
+ """Loads the list of Device objects from DEVICES_FILE path if possible."""
+
+ if os.path.exists(DEVICES_FILE):
+ file = open(DEVICES_FILE)
+ self._deviceList = pickle.load(file)
+ file.close()
+
+ def getDevice(self, ip):
+ # Returns the Device object with the provided ip
+ for deviceInfo in self._deviceList:
+ if deviceInfo.ip == ip:
+ return deviceInfo
+ return None
+
+ def setCurrentDevice (self, ip):
+ self._currentIp = ip
+
+ def getCurrentDevice(self):
+ return self.getDevice(self._currentIp)
+
--- /dev/null
+# low_backup module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+
+import commands
+import os
+
+BATTERY = os.environ['BATTERY_PATH'] + 'battery.py'
+EXECUTE = "./"
+USER_HOST = "root"
+
+def queryProductInformation(deviceIp):
+ """ Update device name by getting device product name and os version
+ informations.
+
+ Use osso-product-info command to get the device and device OS short
+ names and set each to it correspondent attribute.
+
+ """
+
+ info = commands.getoutput("ssh -l %s %s osso-product-info" %
+ (USER_HOST, deviceIp))
+
+ deviceName = _extractOssoInfo(info, "shortName")
+ deviceOs = _extractOssoInfo(info, "shortOS")
+ ossoVersion = _extractOssoInfo(info, "ossoVersion")
+ if deviceName != -1 and deviceOs != -1:
+ deviceName = deviceName.strip("'")
+ deviceOs = deviceOs.strip("'")
+ else:
+ deviceName = "NO INFORMATION"
+ deviceOs = "NO INFORMATION"
+
+ return (deviceName, deviceOs, ossoVersion)
+
+def queryDeviceStorage(deviceIp):
+ """Returns a list of tuples, each tuple representing a memory status.
+
+ Tuples are in this format: (total, used)
+
+ Returns:
+ mem_infos -- List with all tuples holding memory info
+
+ """
+ info = commands.getoutput("ssh -l root %s df" %
+ deviceIp).splitlines()
+ mem_infos = [-1, -1, -1]
+ for line in info:
+ if line.find("/dev/mtdblock4") != -1:
+ if line[-1] == "/":
+ total_used = _get_memory(line, "/dev/mtdblock4")
+ mem_infos.pop(0)
+ mem_infos.insert(0, total_used)
+
+ elif line.find("/media/mmc1") != -1:
+ total_used = _get_memory(line, "/dev/mmcblk0p1")
+ mem_infos.pop(1)
+ mem_infos.insert(1, total_used)
+
+ elif line.find("/media/mmc2") != -1:
+ total_used = _get_memory(line, "/dev/mmcblk1p1")
+ mem_infos.pop(2)
+ mem_infos.insert(2, total_used)
+
+ return mem_infos
+
+def queryDeviceBattery(deviceIp):
+ """Return device current battery status in a string.
+
+ This method runs a python script in the device that returns the battery
+ status, this status is represented by one string with the percentage of
+ battery current charge or the number -1 case battery is charging.
+
+ Returns:
+ text -- Text with the battery status
+
+ """
+
+ # Calls script that returns device battery status
+ os.system("scp %s %s@%s:/tmp" % (BATTERY, USER_HOST, deviceIp))
+ battery_status = commands.getoutput("ssh -l %s %s /usr/bin/python \
+ /tmp/battery.py" % (USER_HOST,
+ deviceIp))
+ return battery_status
+
+def _get_memory(line, path):
+ """Retrieve and return total and used memory information from the given
+ line using the memory path to retrieve the right information.
+
+ This function is to be used with a line of the return of a df command.
+
+ Arguments:
+ line -- The line where the memory information is
+ path -- The path in the begining of the line
+
+ Returns:
+ total -- Total memory
+ used -- Amount of used memory
+
+ """
+ number_of_infos = 0
+ i = len(path) + 1
+ while number_of_infos < 2:
+ char = line[i]
+ if char != " ":
+ start = i
+ end = line.find(" ", start + 1)
+ if number_of_infos == 0:
+ total = line[start: end]
+ elif number_of_infos == 1:
+ used = line[start: end]
+ i = end
+ number_of_infos += 1
+ i += 1
+ return total, used
+
+def _extractOssoInfo(osso_string, info_type="name"):
+ """Read the osso-product-info command return string and extract the
+ needed info depeding on info_type argument.
+
+ Arguments:
+ osso_string -- The string returned by osso-product-info command
+ info_type -- the kind of information to b extracted, can be:
+ name - returns device full name (default)
+ OS - returns device OS full name
+ shortName - returns device short name
+ shortOS - returns device short OS name
+
+ Returns:
+ info -- String with the needed information
+ -1 -- Case the information couldn't be found in the given string
+
+ """
+ detailed_type = ""
+ if info_type == "shortName":
+ detailed_type = "OSSO_PRODUCT_NAME"
+ elif info_type == "shortOS":
+ detailed_type = "OSSO_PRODUCT_RELEASE_NAME"
+ elif info_type == "name":
+ detailed_type = "OSSO_PRODUCT_FULL_NAME"
+ elif info_type == "OS":
+ detailed_type = "OSSO_PRODUCT_RELEASE_FULL_NAME"
+ elif info_type == "ossoVersion":
+ detailed_type = "OSSO_VERSION"
+ else:
+ detailed_type = "OSSO_PRODUCT_FULL_NAME"
+
+ types_list = osso_string.splitlines()
+ info = -1
+ for type_line in types_list:
+ if type_line.startswith(detailed_type):
+ # The second argument is the information itself since informations
+ # are displayed like: OSSO_PRODUCT_RELEASE_NAME='OS 2008'
+ info = type_line.split("=")[1]
+
+ return info
--- /dev/null
+import os.path
+
+import commands
+import os
+import pwd
+import settings
+import socket
+import sys
+
+import paramiko
+
+from backup.pcsbackuputils import createFolder
+
+sshPath = os.path.expanduser('~/.ssh/')
+known_hosts = os.path.join(sshPath, 'known_hosts')
+log_file = os.path.expanduser('~/.pcsuite/.ssh_log')
+user = 'root'
+keyName = 'rsa_key'
+
+def create_route(host, port=22):
+ # Verify Auth with privateKey
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(15)
+ sock.connect((host, port))
+ sock.close()
+ return True
+ except:
+ print 'No route to host'
+ return False
+
+def verify_exist_keys(host, port=22):
+ try:
+ transport = _create_transport(host, port)
+ except:
+ return False
+ try:
+ getKey = paramiko.RSAKey.from_private_key_file(sshPath + keyName)
+ transport.start_client()
+ transport.auth_publickey(user, getKey)
+ if transport.is_authenticated():
+ transport.close()
+ return True
+ except:
+ # 'Error in auth with publickey, try with password...'
+ return False
+ return False
+
+def keyExchange(host, passwd, port=22):
+ if not os.path.exists(sshPath):
+ createFolder(sshPath)
+
+ # Clean cached keys in ssh-agent
+ os.system('ssh-add -d')
+
+ try:
+ transport = _create_transport(host, port)
+ except:
+ transport.close()
+ return False
+
+ if not _add_host_fingerprint(host):
+ transport.close()
+ return False
+
+ if not _authenticate(user, passwd, transport):
+ transport.close()
+ return False
+
+ if not _add_key_to_host(host, transport):
+ transport.close()
+ return False
+
+ transport.stop_thread()
+ transport.close()
+ return True
+
+def initDirs():
+ settings.makeDirs()
+
+def _create_transport(host, port):
+ # Create a transport and initiate client mode
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(15)
+ sock.connect((host, port))
+ except Exception, msg:
+ print 'Connect failed: ' + str(msg)
+ raise Exception('Error while create sockets.')
+ transport = paramiko.Transport(sock)
+ return transport
+
+def _add_host_fingerprint(host):
+ if not os.path.exists(known_hosts):
+ os.system('touch %s' %known_hosts)
+ if os.system('ssh-keyscan -t rsa %s >> %s' %(host, known_hosts)) != 0:
+ return False
+ return True
+
+def _generate_keys():
+ # Generate public and private RSAKey
+ keyFile = os.path.join(sshPath, keyName)
+ if not os.path.exists(keyFile):
+ privateKey = paramiko.RSAKey.generate(2048)
+ privateKey.write_private_key_file(keyFile)
+ login = pwd.getpwuid(os.geteuid())[0]
+ publicKey = '%s %s %s@%s' %(privateKey.get_name(),
+ privateKey.get_base64(),
+ login , socket.gethostname())
+ try:
+ keyFile = open(keyFile + '.pub','w')
+ keyFile.write(publicKey)
+ keyFile.close()
+ except:
+ print 'Error while save the public key'
+ raise Exception()
+ else:
+ try:
+ privateKey = paramiko.RSAKey.from_private_key_file(keyFile)
+ login = pwd.getpwuid(os.geteuid())[0]
+ publicKey = '%s %s %s@%s' %(privateKey.get_name(),
+ privateKey.get_base64(),
+ login , socket.gethostname())
+ except:
+ print 'Error while read the private key'
+ raise Exception()
+ return publicKey
+
+def _authenticate(user, passwd, transport):
+ # Try Auth with password
+ try:
+ transport.start_client()
+ transport.auth_password(user, passwd)
+ except:
+ print 'Verify user or password.'
+ return False
+ if not transport.is_authenticated():
+ print 'Authentication fail'
+ return False
+
+ try:
+ exception = transport.get_exception()
+ if exception:
+ raise exception
+ except Exception, msg:
+ print 'Error in connection: ' + str(msg)
+ return False
+ return True
+
+def _add_key_to_host(host, transport):
+ # Add publickey in host
+ if not transport.is_active():
+ print 'Channel is not active'
+ return False
+
+ paramiko.util.log_to_file(log_file, 10)
+ channel = transport.open_session()
+ try:
+ channel.exec_command('mkdir -p ~/.ssh; echo %s >> .ssh/authorized_keys' % (_generate_keys()))
+ except Exception, msg:
+ print 'Error while generate or add the keys.'
+ channel.close()
+ return False
+ channel.close()
+ return True
--- /dev/null
+import os
+import os.path
+
+class Settings:
+ def __init__(self):
+ self.home = os.path.expanduser("~")
+ self.default_folder = os.path.join(self.home, ".pcsuite")
+ self.devices_folder = os.path.join(self.default_folder,
+ "devices")
+ self.backup_config_path = os.path.join(self.default_folder, "config")
+ self.backup_folder = os.path.join(self.default_folder, "Backup")
+
+ def initalize(self):
+
+ """Check the existence of required project folders, creating
+ them if needed. Also gives execution permission to all scripts.
+
+ """
+
+ # This is checking if the default folder exists too, because
+ # if it doesn't exist the mount_point won't exist either
+ if not os.path.exists(self.devices_folder):
+ os.makedirs(self.devices_folder)
+ if not os.path.exists(self.backup_config_path):
+ os.makedirs(self.backup_config_path)
+ if not os.path.exists(self.backup_folder):
+ os.makedirs(self.backup_folder)
+
+def makeDirs():
+ s = Settings()
+ s.initalize()
+
+if __name__ == "__main__":
+ makeDirs()
+
+
--- /dev/null
+#!/usr/bin/python
+
+import sys, os
+import optparse
+from PyQt4.QtGui import *
+
+parser = optparse.OptionParser(usage="%prog [options] [project-file]")
+parser.add_option("-l", "--local-dirs", action="store_true", dest="use_local_dirs",
+ help="Use files from the local directory tree")
+
+(options, args) = parser.parse_args()
+if options.use_local_dirs:
+ PATHS = {"IMAGE_PATH" : os.pardir + "/img/",
+ "BATTERY_PATH" : "./"}
+else:
+ PATHS = {"IMAGE_PATH" : "/usr/share/tabletsuite/",
+ "BATTERY_PATH" : "/usr/lib/python2.6/site-packages/src/"}
+
+for var, path in PATHS.iteritems():
+ os.environ.setdefault(var, path)
+
+
+from pcsuite.pcsuite import PCSuite
+
+app = QApplication(sys.argv)
+ps = PCSuite()
+ps.show()
+
+app.exec_()
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 55
+/svn/pc-suite/!svn/ver/653/trunk/tabletsuite/src/backup
+END
+pcsopenfilewizard.py
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcsopenfilewizard.py
+END
+pcsbackupparser.py
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/backup/pcsbackupparser.py
+END
+pcspcbackupmanager.py
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcspcbackupmanager.py
+END
+pcsprogressdialog.py
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/639/trunk/tabletsuite/src/backup/pcsprogressdialog.py
+END
+pcsprogresswizard.py
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/636/trunk/tabletsuite/src/backup/pcsprogresswizard.py
+END
+pcsbackupxml.py
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/620/trunk/tabletsuite/src/backup/pcsbackupxml.py
+END
+pcsbackupwizard.py
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/653/trunk/tabletsuite/src/backup/pcsbackupwizard.py
+END
+pcsbackuputils.py
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcsbackuputils.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/backup/__init__.py
+END
+pcsbackupmanagerui.py
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/pc-suite/!svn/ver/652/trunk/tabletsuite/src/backup/pcsbackupmanagerui.py
+END
+pcsbackuplocation.py
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/backup/pcsbackuplocation.py
+END
+pcsbackuplistui.py
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/backup/pcsbackuplistui.py
+END
+pcsbackupmanager.py
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcsbackupmanager.py
+END
+pcswindowmanager.py
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/630/trunk/tabletsuite/src/backup/pcswindowmanager.py
+END
+pcsrestoredialog.py
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/pc-suite/!svn/ver/606/trunk/tabletsuite/src/backup/pcsrestoredialog.py
+END
+pcsbackup.py
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/652/trunk/tabletsuite/src/backup/pcsbackup.py
+END
+pcscheckboxwizard.py
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/pc-suite/!svn/ver/641/trunk/tabletsuite/src/backup/pcscheckboxwizard.py
+END
+pcsrestorebackupui.py
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcsrestorebackupui.py
+END
+pcsdevicebackupmanager.py
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/backup/pcsdevicebackupmanager.py
+END
+pcsbackupinfo.py
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/backup/pcsbackupinfo.py
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src/backup
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-10-06T17:00:03.678569Z
+653
+pauloouriques
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+pcsopenfilewizard.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+bd7d89e9e75d7a71828842740bf96bc9
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9749
+\f
+pcsbackupparser.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+cb732e14b18419973e32171f4ab44586
+2009-08-20T18:08:50.977477Z
+571
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4071
+\f
+pcspcbackupmanager.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+ce87348b076ca74e6cb7c6453cae7683
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+19153
+\f
+pcsprogressdialog.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+8f8ede17cf9c329d29af777bae73a556
+2009-09-18T09:51:12.321968Z
+639
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4432
+\f
+pcsprogresswizard.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+3982df75bf944d1b5b8eb49df76460f7
+2009-09-17T14:38:23.185224Z
+636
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9496
+\f
+pcsbackupxml.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+cfc2951c78dbc548e271022d230fa645
+2009-09-14T16:31:07.677300Z
+620
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3174
+\f
+pcsbackupwizard.py
+file
+
+
+
+
+2009-10-08T18:25:37.000000Z
+3171ca50afa16f0dcaf44c048cfa62c6
+2009-10-06T17:00:03.678569Z
+653
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6759
+\f
+pcsbackuputils.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+9f9b1db376f86057eb1dac85a386e05c
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5583
+\f
+__init__.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-03-30T19:44:37.661351Z
+26
+amaury
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
+pcsbackupmanagerui.py
+file
+
+
+
+
+2009-10-08T18:25:37.000000Z
+9c5a36ddecd9d79d7d7988c6b8fd673a
+2009-10-05T11:14:02.602311Z
+652
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+19623
+\f
+pcsbackuplocation.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+dd0ceb1377ef5b46c6dc79c44dcee7ba
+2009-06-23T16:10:35.956172Z
+345
+melunko
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+337
+\f
+pcsbackuplistui.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+313275d8fa5de6a6a67dcc3a0b75bf7a
+2009-08-27T10:01:51.549755Z
+577
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3915
+\f
+pcsbackupmanager.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+d61dc11dd6cfdfe3d2eec0b7ebd3a643
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6801
+\f
+pcswindowmanager.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+8f77ded896d07d7f62d101b3f70ba23d
+2009-09-15T17:59:33.111110Z
+630
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1279
+\f
+pcsrestoredialog.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+44f071048e2ac8dd3e4944866fa857c4
+2009-09-08T13:49:13.253249Z
+606
+amaury
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7658
+\f
+pcsbackup.py
+file
+
+
+
+
+2009-10-08T18:25:37.000000Z
+6b5f22c2382885b7cd8d0f3d468c2597
+2009-10-05T11:14:02.602311Z
+652
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4784
+\f
+pcscheckboxwizard.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+c7bce3b7fe62f58f2c84b72690008619
+2009-09-24T16:33:15.553218Z
+641
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11024
+\f
+pcsrestorebackupui.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+6229aa92dec31b2d6350a936e4f05849
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+16050
+\f
+pcsdevicebackupmanager.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+a6eca97d9d73c00c79d1afa06a79c98d
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3340
+\f
+pcsbackupinfo.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+227e4c627b4f06fb55da1e3d9e59ec4d
+2009-08-12T12:26:15.094255Z
+548
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2055
+\f
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsapp import PcsApp
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+from ui.pcsbutton import *
+from ui.tsuigeneralmethods import *
+
+from ui.pcscustombuttons import PcsCustomButton as customButton
+
+from pcswindowmanager import *
+
+class PcsBackup(PcsApp):
+
+ def __init__(self, deviceInfo, parent=None):
+ PcsApp.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+
+ if (self.deviceInfo != None):
+ self.windowManager = PcsWindowManager(self.deviceInfo, self)
+
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup" % APPLICATION_NAME)
+
+ self.hLayout = QHBoxLayout()
+ self.hLayout.setMargin(8)
+ self.vLayout = QVBoxLayout()
+
+ spc = QSpacerItem(0,50)
+ self.optionsLayout = QVBoxLayout()
+ self.optionsLayout.addItem(spc)
+ self._addButtons()
+ self.optionsLayout.addItem(spc)
+
+ self.deviceWidget = PcsDeviceWidget(1)
+ self.deviceWidget.addBorder()
+ self.deviceWidget.addDeviceName()
+ self.deviceWidget.setDeviceInfo(self.deviceInfo)
+
+ self.optionsBorderLayout = QGridLayout()
+ self.optionsBorderLabel = QLabel()
+ self.optionsBorderLabel.setFixedSize(208, 205)
+ self.optionsBorderLabel.setPixmap(QPixmap(DEVICE_BACKUP_BORDER))
+ self.optionsBorderLayout.addWidget(self.optionsBorderLabel, 0, 0, Qt.AlignCenter)
+ self.optionsBorderLayout.addLayout(self.optionsLayout, 0, 0, Qt.AlignCenter)
+ self.hLayout.addLayout(self.optionsBorderLayout)
+ self.hLayout.addWidget(self.deviceWidget)
+
+ #FIXE ME
+ l1 = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ self.vLayout.addItem(TOP_SPACER)
+ self.vLayout.addWidget(l1)
+ self.vLayout.addLayout(self.hLayout)
+ informationLayout = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ information = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select an action.</font>")
+ informationLayout.addItem(spc)
+ informationLayout.addWidget(iconAlert)
+ informationLayout.addWidget(information, Qt.AlignLeft)
+ self.vLayout.addLayout(informationLayout)
+ self.vLayout.setMargin(8)
+ self.setLayout(self.vLayout)
+
+ def openBackupWizard(self):
+
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backup_wizard = self.windowManager.getNewBackup()
+ centralize(backup_wizard)
+ backup_wizard.setGeometry(self.geometry())
+ backup_wizard.exec_()
+ self.setVisible(False)
+ self.setGeometry(backup_wizard.geometry())
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def openBackupManagerDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.show()
+ self.setVisible(False)
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def openRestoreBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.show()
+ self.setVisible(False)
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def _addButtons(self):
+ infList = [("New Backup ", ICON_NEW_BACKUP),
+ ("Manage Backups", ICON_MANAGER_BACKUP),
+ ("Restore Backups ", ICON_RESTORE_BACKUP)]
+ buttonsList = []
+ for inf in infList:
+ buttonOptions = PcsButton(inf[0])
+ buttonOptions.setStyleSheet("background-image\
+ :url("+ BUTTON_WITH_ICON_BG +");\
+ qproperty-icon:url("+inf[1]+");\
+ min-height:50px; min-width:188px;\
+ max-height:50px; max-width:188px;\
+ qproperty-iconSize: 43px 36px")
+ self.optionsLayout.addWidget(buttonOptions)
+ buttonsList.append(buttonOptions)
+
+ self.connect(buttonsList[0], SIGNAL("clicked()"),
+ self.openBackupWizard)
+ self.connect(buttonsList[1], SIGNAL("clicked()"),
+ self.openBackupManagerDialog)
+ self.connect(buttonsList[2], SIGNAL("clicked()"),
+ self.openRestoreBackupDialog)
+
--- /dev/null
+import time
+from datetime import datetime
+
+class PcsBackupInfo:
+ """Class that represents a backup
+
+ Attributes:
+ _name -- Backup name
+ path -- Backup directory path
+ date -- Date when backup was created
+ _comment -- Any comment about backup
+ size -- Backup file size
+ files_number = total number of backup files
+ _time = time object was created in seconds since epoch
+
+ """
+
+ def __init__(self, name, path, size, comment=""):
+ """Initialize object attributes."""
+ self._name = name
+ self.path = path
+ self._time = time.time()
+ self.date = datetime.fromtimestamp(self._time).replace(microsecond=0)
+ self.size = size
+ self.files_number = 0
+ self._comment = comment
+ self.fromDevice = False
+
+ def getPath(self):
+ """Return object path."""
+ return self.path
+
+ def getName(self):
+ """Return object name."""
+ return self._name
+
+ def getDate(self):
+ """Return object creation date."""
+ return self.date
+
+ def getComment(self):
+ """Return object _comment attribute."""
+ return self._comment
+
+ def getSize(self):
+ """Return object file size."""
+ return self.size
+
+ def getTime(self):
+ """ Returns the object creation time in seconds since epoch. """
+ return self._time
+
+ def getFilesNumber(self):
+ """ Return number of files this backup holds. """
+ return self.files_number
+
+ def setComment(self, new_comment):
+ """Set object _comment attribute to the given string"""
+ self._comment = new_comment
+
+ def setName(self, new_name):
+ """Set object name to a new name"""
+ self._name = new_name
+
+ def setDate(self, newDate):
+ self.date = newDate
+
+ def setFilesNumber(self, number_of_files):
+ """ Set number of files this backup holds to number_of_files ."""
+ self.files_number = number_of_files
+
+ def setAtDevice(self, bool=False):
+ self.fromDevice = bool
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PCSBackupListUi(QTableView):
+
+ ''' Class that creates a table, where the backups will be shown '''
+
+ def __init__(self, backupManager):
+ super(PCSBackupListUi, self).__init__()
+
+ self.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.setSelectionMode(QAbstractItemView.ExtendedSelection)
+ self.setAlternatingRowColors(True)
+ self.setShowGrid(False)
+ self.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.model = QStandardItemModel()
+ self.setModel(self.model)
+
+ hHeader = QHeaderView(Qt.Horizontal)
+ hHeader.setObjectName("listHeader")
+ hHeader.setAttribute(Qt.WA_NoSystemBackground)
+ hHeader.setStretchLastSection(True)
+ hHeader.setResizeMode(QHeaderView.ResizeToContents)
+ hHeader.setMinimumSectionSize(100)
+
+ hHeader.setClickable(False)
+
+ self.setHorizontalHeader(hHeader)
+
+ vHeader = QHeaderView(Qt.Vertical)
+ vHeader.setVisible(False)
+ self.setVerticalHeader(vHeader)
+ self._backupManager = backupManager
+
+ def updateBackupList(self):
+ self.model.clear()
+ self.model.setHorizontalHeaderItem(0, QStandardItem("NAME"))
+ self.model.setHorizontalHeaderItem(1, QStandardItem("SIZE"))
+ self.model.setHorizontalHeaderItem(2, QStandardItem("DATE"))
+
+ backupList = self._backupManager.getBackupList()
+ for backupInfo in backupList:
+ name = backupInfo.getName()
+ date = str(backupInfo.getDate())
+ size = self._formatBackupSize(backupInfo.getSize())
+ backupData = [QStandardItem(name), QStandardItem(size), QStandardItem(date)]
+ self.model.appendRow(backupData)
+
+ def removeSelectedBackups(self):
+ selectionModel = self.selectionModel()
+ indexList = selectionModel.selectedRows()
+ for index in reversed(sorted(indexList)):
+ if index.isValid():
+ row = index.row()
+ data = self.model.itemData(index)
+ backupName = data[0].toString()
+ if self._backupManager.removeBackup((str(backupName).strip())):
+ self.model.removeRow(row)
+ self.updateBackupList()
+
+ def renameSelectedBackup (self, newName):
+ #!!!!!!! getSelectedBackup
+ backupName = (str(self.getSelectedBackup())).strip()
+ if backupName != None:
+ if self._backupManager.renameBackup(backupName, newName):
+ self.updateBackupList()
+ return True
+
+ return False
+
+ def getSelectedBackup(self):
+ list = self.getSelectedBackupList()
+ if list and len(list) > 0:
+ return list[0]
+
+ return None
+
+ def getSelectedBackupList(self):
+ selectionModel = self.selectionModel()
+ indexList = selectionModel.selectedRows()
+ backupList = []
+ for index in indexList:
+ if index.isValid():
+ row = index.row()
+ data = self.model.itemData(index)
+ backupList.append(data[0].toString())
+ return backupList
+
+ def getBackupManager(self):
+ return self._backupManager
+
+ def _formatBackupSize(self, size):
+ """ Return a string with a more suited size and byte multiple for the
+ received size.
+
+ Attributes:
+ String/Float/Int size - size in bytes or string representing it.
+
+ """
+ size = float(size)
+ multiples = ["B", "KB", "MB", "GB"]
+ divisions = 0
+ while size > 1000 and divisions <= 3:
+ size = size / 1024.
+ divisions += 1
+
+ return "%.1f %s" % (size, multiples[divisions])
--- /dev/null
+# Class Backup_Category holds osso-backup .conf files informations
+
+class PcsBackupLocation:
+ """Backup_Location class.
+ Used for holding location attributes from parsed osso-backup xml files.
+
+ """
+ def __init__(self, type, category, path):
+ self.category = category
+ self.type = type
+ self.path = path
--- /dev/null
+import os
+
+from PyQt4.QtCore import *
+from zipfile import *
+
+import pcsbackuputils as utils
+
+
+HOME = os.path.expanduser("~")
+USER_HOST = "root"
+DEVICES_POINT = "%s/.pcsuite/devices/" % HOME
+
+
+class PcsBackupManager(QObject):
+
+ def __init__(self):
+ QObject.__init__(self)
+ self._backupList = []
+
+ def loadBackups(self):
+ return False
+
+ def saveBackups(self):
+ return False
+
+ def getBackupList(self):
+ return None
+
+ def createBackup(self, backup_name, path, host_ip, categories, comment=""):
+ return False
+
+ def removeBackup(self, backup_name):
+ return False
+
+ def getBackupInfo(self, backupName):
+ return None
+
+ def renameBackup(self, backupName, newName):
+ return False
+
+ def changeBackupComment(self, backupName, new_comment):
+ return False
+
+ def listBackupContent(self, backupName):
+ content = []
+ backupInfo = self.getBackupInfo(backupName)
+ backupPath = backupInfo.getPath()
+ fullPath = os.path.join(str(backupPath), str(backupName))
+
+ for entry in os.listdir(fullPath):
+ if entry.endswith(".zip"):
+ zipfile = utils.openZip(os.path.join(fullPath, entry), "r")
+ for member in zipfile.namelist():
+ folders = member.split("/")
+ memberName = "../" + "/".join([folders[-2], folders[-1]])
+ content.append(memberName)
+ return content
+
+ def restoreBackup(self, backupInfo, host_ip, categories):
+ """ Restore a PC backup to device with given IP address.
+
+ Attributes:
+ String backupInfo - Object representing the backup
+ String host_ip - IP address of device.
+ Dictionary categories - dictionary with categories as keys and with
+ value True if that category should be restored.
+
+ """
+ self.setRestoreInProgress(True)
+ # Set restore needed paths
+ devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
+ mountPath = os.path.join(devicePath, "Root" )
+ tempPath = os.path.join(mountPath, "tmp/paths")
+ restScriptsPath = ("/etc/osso-backup/restore.d/always")
+ try:
+ utils.mountDevice(USER_HOST, host_ip, mountPath)
+ # Get backup location depending from backup source
+ if backupInfo == None:
+ return False
+ if backupInfo.fromDevice:
+ backup_path = backupInfo.getPath()
+ else:
+ backup_path = os.path.join(str(backupInfo.getPath()),
+ str(backupInfo.getName()))
+ # Get backup files list for each category and write it on a file
+ # that will be needed by restore scripts.
+ pathsDictonary = utils.getBackupFilesPath(backup_path)
+ if utils.writeBackupFilesPath(pathsDictonary, tempPath) == False:
+ return False
+ # --- Initialize restore progress ---
+ currentSize = 0
+ # Get total number of files to restore
+ numberOfFiles = 0
+ for categ in pathsDictonary:
+ for file in pathsDictonary[categ]:
+ numberOfFiles += 1
+ # Get size of all categories being restored
+ totalSize = 0
+ for file in os.listdir(backup_path):
+ if file.endswith(".zip"):
+ categ = file[:-4]
+ if categories[categ]:
+ catPath = os.path.join(backup_path, file)
+ zip = utils.openZip(catPath)
+ for member in zip.namelist():
+ totalSize += zip.getinfo(member).file_size
+ # Extract zip files to device
+ for entry in os.listdir(backup_path):
+ category = entry[:-4]
+ if entry.endswith(".zip") and categories[category]:
+ zipPath = os.path.join(backup_path, entry)
+ zip = utils.openZip(zipPath)
+ # Update restore progress, extract current f print "member %s: %.2f" % (member, zip.getinfo(member).file_size)ile and emit
+ # progress sinal
+ for member in zip.namelist():
+ if not self.restoreInProgress:
+ return 0
+ percentage = "%.1f" % self.computePercentage(totalSize,
+ currentSize)
+
+ status = (percentage, category, numberOfFiles, totalSize)
+ self.emit(SIGNAL("restoreProgress"), status)
+ zip.extract(member, devicePath)
+ currentSize += zip.getinfo(member).file_size
+ percentage = "%.1f" % ((currentSize / float(totalSize)) * 100)
+ status = (percentage, category, numberOfFiles, totalSize)
+ self.emit(SIGNAL("restoreProgress"), status)
+ zip.close()
+ # Execute restore scripts
+ os.system("ssh %s@%s ..%s/*.sh %s" % (USER_HOST, host_ip,
+ restScriptsPath, tempPath))
+ self.setRestoreInProgress(False)
+ # --- Restore finished ---
+ finally:
+ utils.unmountDevice(mountPath)
+
+
+ def computePercentage(self, totalSize, currentSize):
+ if totalSize == 0:
+ percentage = 100
+ else:
+ percentage = (currentSize / float(totalSize)) * 100
+ if percentage > 100:
+ percentage = 100
+ return percentage
+
+ def copy(self, sourcePath, destinationPath):
+ numberOfFiles = 0
+ for entry in os.listdir(sourcePath):
+ zipPath = os.path.join(sourcePath, entry)
+ if zipPath.endswith(".zip"):
+ zip = utils.openZip(zipPath)
+ numberOfFiles += len(zip.namelist())
+ totalSize = float(utils.getSize(sourcePath))
+ currentSize = 0
+ self.emit(SIGNAL("copyProgress"), ("0.00", numberOfFiles, totalSize))
+ for entry in os.listdir(sourcePath):
+ if not self.copyInProgress:
+ utils.removePath(destinationPath)
+ return 0
+ entryPath = os.path.join(sourcePath, entry)
+ utils.copy(entryPath, destinationPath)
+ currentSize += utils.getSize(entryPath)
+ progress = "%.2f" % ((currentSize / totalSize) * 100)
+ self.emit(SIGNAL("copyProgress"), (progress, numberOfFiles,
+ totalSize))
+
+
\ No newline at end of file
--- /dev/null
+# Software License: GPL
+
+import os
+import sys
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from ui.tsuigeneralmethods import *
+from ui.pcsapp import PcsApp
+from backup.pcsbackuputils import *
+
+from pcsbackuplistui import PCSBackupListUi
+from pcspcbackupmanager import PcsPcBackupManager
+from pcsdevicebackupmanager import PcsDeviceBackupManager
+from pcsprogressdialog import PcsProgressDialog
+from style.styleTabletSuite import *
+
+COPY_BUTTON_ID = 0
+DELETE_BUTTON_ID = 1
+RENAME_BUTTON_ID = 2
+VIEW_BUTTON_ID = 3
+_home_dir = os.path.expanduser("~")
+_default_dir = _home_dir + "/.pcsuite/Backup"
+
+
+class PcsBackupManagerUi(QDialog):
+
+ ''' Class that calls a Backup Pc Suite application
+ with a Table Viewer'''
+
+ def __init__(self, deviceInfo, windowManager, parent=None):
+ QDialog.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup Manager" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ self._home_dir = os.path.expanduser("~")
+ self._default_dir = _home_dir + "/.pcsuite/Backup"
+ self.copyPath = self._default_dir
+ self.name_change = None
+ self._setupUi()
+
+ def _setupUi(self):
+ # Creates the lists
+ self.pcBackupManager = PcsPcBackupManager()
+ self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
+
+ self.pcListView = PCSBackupListUi(self.pcBackupManager)
+ self.pcListView.setObjectName("ListView")
+ # "Update pc list view"
+ pcListViewSelectionModel = self.pcListView.selectionModel()
+ self.connect(pcListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+ self.pcListView.updateBackupList()
+
+ self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
+ self.deviceListView.setObjectName("ListView")
+ deviceListViewSelectionModel = self.deviceListView.selectionModel()
+ self.connect(deviceListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+ # "Update device List view"
+ self.deviceListView.updateBackupList()
+
+ layout = QVBoxLayout()
+ menuLayout = self._menuButtons()
+ layout.addLayout(menuLayout, Qt.AlignTop)
+ wayLayout = self._wayLayout()
+ layout.addLayout(wayLayout, Qt.AlignLeft)
+ layout.addItem(QSpacerItem(0,3))
+ layout.addLayout(self._centerLayout(), Qt.AlignTop)
+
+ layout.addItem(QSpacerItem(0,15))
+ informationLayout = self._createInformationsLabel()
+ layout.addLayout(informationLayout)
+ layout.addItem(QSpacerItem(0,2))
+ self.setLayout(layout)
+
+ def _centerLayout(self):
+ # Creates the tabs
+ layout = QVBoxLayout()
+ tabLayout = QVBoxLayout()
+ tab = QTabBar()
+ tab.setObjectName("managerTabs")
+ self.tabBar = QTabWidget()
+ self.tabBar.setTabBar(tab)
+ self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
+ self.tabBar.setObjectName("tabBar")
+ self.tabBar.addTab(self.pcListView, "PC Backups")
+ self.tabBar.addTab(self.deviceListView, "Device Backups")
+ self.connect(self.tabBar, SIGNAL("currentChanged(int)"), self._updateButtonsState)
+ tabLayout.addWidget(self.tabBar)
+ layout.addLayout(tabLayout)
+ #Spacer
+ layout.addItem(QSpacerItem(0,5))
+ # Creates the buttons
+ buttonBox = QHBoxLayout()
+ self._buttonCopy = QPushButton("Copy")
+ self._buttonCopy.setDisabled(True)
+ self._buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ buttonBox.addWidget(self._buttonCopy)
+ self.connect (self._buttonCopy, SIGNAL("clicked()"), self._doCopyBackup)
+
+ self._buttonDelete = QPushButton("Delete")
+ self._buttonDelete.setDisabled(True)
+ buttonBox.addWidget(self._buttonDelete)
+ self._buttonDelete.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonDelete, SIGNAL("clicked()"), self._doDeleteBackup)
+
+ self._buttonRename = QPushButton("Rename")
+ self._buttonRename.setDisabled(True)
+ buttonBox.addWidget(self._buttonRename)
+ self._buttonRename.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonRename, SIGNAL("clicked()"), self._doRenameBackup)
+
+ self._buttonView = QPushButton("View")
+ self._buttonView.setDisabled(True)
+ buttonBox.addWidget(self._buttonView)
+ self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
+
+ self._buttonUpdate = QPushButton("Update")
+ self._buttonUpdate.setDisabled(False)
+ self._buttonUpdate.setVisible(False)
+ buttonBox.addWidget(self._buttonUpdate)
+ self._buttonUpdate.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonUpdate, SIGNAL("clicked()"), self._doUpdateList)
+
+ layout.addLayout(buttonBox)
+ return layout
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE_SELECTED),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+
+ buttonsLayout = QHBoxLayout()
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 1:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ buttonsLayout.setMargin(0)
+ return buttonsLayout
+
+ def _newBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ newBackup = self.windowManager.getNewBackup()
+ centralize(newBackup)
+ newBackup.setGeometry(self.geometry())
+ newBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.geometry())
+ restoreBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _wayLayout(self):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ spc = QSpacerItem(8, 0)
+ self.barLayout.addItem(spc)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ restore = QLabel("<font style='color: #FFFFFF'; size=2> Manage backups</font>")
+ spc = QSpacerItem(2, 0)
+ widgetList = [main, self._arrow(), restore]
+
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the backup you wish to manipulate.</font>")
+ iconAlert = QLabel()
+ hLay.setMargin(0)
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ spc = QSpacerItem(15, 0)
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _doUpdateList(self):
+ self._currentBackupList().updateBackupList()
+ self._updateButtonsState(0)
+
+ def _execCopyDialogToDevice(self):
+ self._copyDialogToDevice = QDialog(self, Qt.FramelessWindowHint)
+ self._copyDialogToDevice.setObjectName("copyDialogToDevice")
+
+ self.rb1 = QRadioButton()
+ self.rb1.setText("External Memory Card")
+ self.rb2 = QRadioButton()
+ self.rb2.setText("Internal Memory Card")
+
+ layout = QVBoxLayout()
+ layout.addWidget(self.rb1)
+ layout.addWidget(self.rb2)
+
+ buttonCopy = QPushButton("Copy")
+ buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyToDevice)
+ buttonCancel = QPushButton("Cancel")
+ buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogToDevice.close)
+
+ hlay = QHBoxLayout()
+ hlay.addWidget(buttonCancel)
+ hlay.addWidget(buttonCopy)
+ layout.addLayout(hlay)
+ self._copyDialogToDevice.setLayout(layout)
+ self._copyDialogToDevice.exec_()
+
+ def _execCopyDialogFromDevice(self):
+ self._copyDialogFromDevice = QDialog(self, Qt.FramelessWindowHint)
+ self._copyDialogFromDevice.setObjectName("copyDialogFromDevice")
+
+ hLayout = QHBoxLayout()
+ hLayout.setMargin(0)
+ self.textField = QLineEdit(self)
+ buttonOpen = QPushButton()
+ buttonOpen.setObjectName("buttonBrowse")
+ self.connect(buttonOpen, SIGNAL("clicked()"), self._doBrowse)
+ copyPath = str(self._default_dir)
+ self.textField.setReadOnly(True)
+ self.textField.setText(self._default_dir)
+ hLayout.addWidget(self.textField)
+ hLayout.addWidget(buttonOpen)
+
+ message = QLabel("<font style='color: #333333'; size=2> Backup copy destination: </font>")
+ message.setFixedHeight(15)
+
+ layout = QVBoxLayout()
+ layout.addWidget(message)
+ layout.addLayout(hLayout)
+
+ buttonCopy = QPushButton("Copy")
+ buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyFromDevice)
+ buttonCancel = QPushButton("Cancel")
+ buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogFromDevice.close)
+
+ hlay = QHBoxLayout()
+ hlay.addWidget(buttonCancel)
+ hlay.addWidget(buttonCopy)
+ layout.addLayout(hlay)
+ self._copyDialogFromDevice.setLayout(layout)
+ self._copyDialogFromDevice.exec_()
+
+ def _doCopyBackup(self):
+ if self.tabBar.currentIndex() == 0:
+ self._execCopyDialogToDevice()
+ else:
+ self._execCopyDialogFromDevice()
+
+ def doCopy(self, device_ip, backupName, ret, destinationPath):
+ self.copyThread = CopyBackupThread(self, device_ip, backupName, ret, destinationPath)
+ self.copyThread.start()
+ self._runCopyProgress()
+
+ self.connect(self.copyThread, SIGNAL("openFileError"), self._onOpenFileError)
+ self.connect(self.copyThread, SIGNAL("copyProgress"), self._updateProgress)
+ self.connect(self.copyThread, SIGNAL("copyDone"), self._onCopyDone)
+
+ def _doCopyToDevice(self):
+ self._copyDialogToDevice.close()
+ ret = 1
+ if self.rb1.isChecked():
+ ret = 0
+ selectedBackupList = self._currentBackupList().getSelectedBackupList()
+ for backup in selectedBackupList:
+ self.doCopy(self.deviceInfo.ip, str(backup).strip(), ret, "")
+
+ def _doCopyFromDevice(self):
+ self._copyDialogFromDevice.close()
+ if self.copyPath != "":
+ selectedBackupList = self._currentBackupList().getSelectedBackupList()
+ self.name_change = False
+ for backup in selectedBackupList:
+ self.pcBackupManager.loadBackups()
+ self.correct_name = self.pcBackupManager._verify_backup_name(str(backup).strip())
+ self.doCopy(self.deviceInfo.ip, str(backup).strip(), 0, self.copyPath)
+ if self.correct_name != backup:
+ self.name_change = True
+
+ def _showMessageCopyBackupDone(self):
+ if self.name_change == None or not self.name_change:
+ QMessageBox.information(self, "Copy Backup", "Backup(s) copied")
+ else:
+ QMessageBox.information(sopenFileErrorelf, "Copy Backup",
+ "Backup copied with name: %s" % self.correct_name)
+
+ def _doBrowse(self):
+ pathDialog = QFileDialog()
+ prompt = "Select the folder you wish to copy your backup(s):"
+ self.copyPath = pathDialog.getExistingDirectory(self, prompt, self._home_dir)
+ if(self.copyPath != ""):
+ self.textField.setText(self.copyPath)
+
+ def _doRenameBackup(self):
+ res = False
+ (newName, ok) = QInputDialog.getText(self, "Rename Backup", "New Backup Name:",
+ QLineEdit.Normal, QString(),
+ Qt.FramelessWindowHint)
+ if ok:
+ if newName:
+ newName = QString(str(newName).strip())
+ if not newName.isEmpty():
+ list = self._currentBackupList()
+ res = list.renameSelectedBackup(newName)
+ if res:
+ showMessageBox("Backup Renamed", "")
+ else:
+ showMessageBox("Error while renaming the backup", "")
+
+ def _doDeleteBackup(self):
+
+ dialog = QMessageBox()
+ dialog.setText("Remove selected backup?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ list = self._currentBackupList()
+ list.removeSelectedBackups()
+ showMessageBox("Backup Removed", "")
+
+ def _currentBackupList(self):
+ if self.tabBar.currentIndex() == 0:
+ self._buttonRename.setVisible(True)
+ self._buttonDelete.setVisible(True)
+ self._buttonView.setVisible(True)
+ self._buttonUpdate.setVisible(False)
+ return self.pcListView
+ else:
+ self._buttonUpdate.setVisible(True)
+ self._buttonRename.setVisible(False)
+ self._buttonDelete.setVisible(False)
+ self._buttonView.setVisible(False)
+ return self.deviceListView
+
+ def _updateButtonsState(self, index):
+ list = self._currentBackupList()
+ selectionModel = list.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ if len(indexList) != 1:
+ self._buttonRename.setDisabled(True)
+ self._buttonView.setDisabled(True)
+ self._buttonCopy.setDisabled(True)
+ else:
+ self._buttonRename.setEnabled(True)
+ self._buttonView.setEnabled(True)
+ self._buttonCopy.setEnabled(True)
+
+ if len(indexList) == 0:
+ self._buttonDelete.setDisabled(True)
+# self._buttonCopy.setDisabled(True)
+ else:
+ self._buttonDelete.setEnabled(True)
+# self._buttonCopy.setEnabled(True)
+
+
+ def _doViewBackup(self):
+ list = self._currentBackupList()
+ backupManager = list.getBackupManager()
+ backupName = (str(list.getSelectedBackup())).strip()
+ if backupName == None:
+ return False
+
+ dialog = QDialog(self, Qt.FramelessWindowHint)
+ dialog.setObjectName("viewDialog")
+ dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ dialog.setWindowTitle("Backup Files")
+ dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+
+ layout = QVBoxLayout()
+ listWidget = QListWidget()
+ listWidget.setObjectName("viewList")
+ listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ try:
+ backupContentList = backupManager.listBackupContent(backupName)
+ except IOError:
+ showMessageBox(self.openFileError, "Error while opening file")
+ return False
+
+ for backupContent in backupContentList:
+ backup_button = QListWidgetItem()
+ backup_button.setText(backupContent)
+ listWidget.addItem(backup_button)
+
+ okButton = QPushButton("OK")
+ okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
+ visible = partial(dialog.setVisible, False)
+ self.connect(okButton, SIGNAL("clicked()"), visible)
+ hLay = QHBoxLayout()
+ hLay.addItem(QSpacerItem(200,0))
+ hLay.addWidget(okButton)
+
+ layout.addWidget(listWidget)
+ layout.addLayout(hLay)
+ dialog.setLayout(layout)
+ dialog.show()
+
+ def _runCopyProgress(self):
+ self._progressDialog = PcsProgressDialog(self)
+ self._progressDialog.setAction("copy")
+ self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
+ self._onCopyCancel)
+ self._progressDialog.show()
+
+ def _updateProgress(self, information):
+ progress, self.numberOfFiles, self.totalSize = information
+ self._progressDialog.setProgress(progress)
+
+ def _onCopyDone(self):
+ self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
+ self._progressDialog.progressDone()
+ self.pcListView.updateBackupList()
+
+ def _onCopyCancel(self):
+ if self.tabBar.currentIndex() == 0:
+ self.pcBackupManager.setCopyInProgress(False)
+ else:
+ self.deviceBackupManager.setCopyInProgress(False)
+ self._progressDialog.progressCanceled()
+
+ def _onOpenFileError(self):
+ self._progressDialog.close()
+ showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
+
+
+
+class CopyBackupThread(QThread):
+ def __init__(self, manager, deviceIp, backupName, ret, destinationPath ):
+ QThread.__init__(self)
+ self.uiManager = manager
+ self.deviceIp = deviceIp
+ self.backupName = backupName
+ self.memoryCard = ret
+ self.destinationPath = destinationPath
+ self.connect(self.uiManager.pcBackupManager, SIGNAL("copyProgress"),
+ self.reEmit)
+ self.connect(self.uiManager.deviceBackupManager, SIGNAL("copyProgress"),
+ self.reEmit)
+
+ def reEmit(self, inf):
+ self.emit(SIGNAL("copyProgress"), inf)
+
+ def run(self):
+ try:
+ if self.uiManager.tabBar.currentIndex() == 0:
+ manager = self.uiManager.pcBackupManager
+ manager.copyBackupToDevice(self.deviceIp, self.backupName,
+ self.memoryCard)
+ else:
+ manager = self.uiManager.deviceBackupManager
+ manager.copyBackupFromDevice(self.backupName,
+ self.destinationPath)
+
+ except IOError:
+ self.emit(SIGNAL("openFileError"))
+ return
+ self.emit(SIGNAL("copyDone"))
+
+
+
+
--- /dev/null
+# Module used to parse osso-backup xml conf files, retrieving categories and
+# backup paths information
+
+import os.path
+import xml.dom
+import xml.dom.minidom
+
+from pcsbackuplocation import *
+
+
+class PcsBackupParser:
+ """Holds a list of Backup_location objects
+
+ Can parse .conf xml files with osso-backup format at the given path with
+ fill_locations_list, creating Backup_location objects based on type,
+ category and path of each location inside each xml file and then holding
+ all objects in the locations_list attribute.
+
+ """
+ def __init__(self):
+ self.locationsDict = {}
+
+ def getLocationsDict(self):
+ return self.locationsDict
+
+ def addLocation(self, location):
+ """Add a location to locations_list attribute of theis class.
+
+ Arguments:
+ location -- the location object to be added
+
+ """
+ category = location.category
+ if category in self.locationsDict.keys():
+ self.locationsDict[category].append(location)
+ else:
+ self.locationsDict[category] = [location]
+
+ def fillLocationsDict(self, path):
+ """Add all locations that can be found inside xml files of the given
+ path.
+
+ This method reads all .conf files inside the directory path given and
+ puts on its locations_list attribute all the Backup_location objects
+ created with the informations returned from the files parsing.
+
+ Arguments:
+ path -- Path of directory containing files to parse
+
+ """
+ for file in os.listdir(path):
+ if file.endswith(".conf"):
+ locations = self.locationsFromFile(os.path.join(path, file))
+ for location in locations:
+ self.addLocation(location)
+
+ def locationsFromFile(self, xml_file):
+ """Return a list with all locations objects inside the given file.
+
+ The file is parsed and all informations retrieved from it are used to
+ create Backup_location objects and these objects are appended to a list
+ that is returned to caller.
+
+ Arguments:
+ xml_file -- File to parse
+
+ Returns:
+ locations -- List with all Backup_location objects created from file
+
+ """
+ locations_map = self._parser(xml_file)
+ locations = []
+ number_of_locations = len(locations_map["types"])
+ for i in range(number_of_locations):
+ type = locations_map["types"][i]
+ category = locations_map["categories"][i]
+ path = locations_map["paths"][i]
+ path = self._fixPath(path)
+ new_loc = PcsBackupLocation(type, category, path)
+ locations.append(new_loc)
+ return locations
+
+
+ def _parser(self, xml_file):
+ # Parses the xml_file, divide each location element information on a
+ # dictonary with key to respective information.
+ # Dictonary format:
+ # { "types": list of types in order of location appereance,
+ # "categories": list of categories ordered like types
+ # "paths" list of install paths in the same order as the others }
+ dom = xml.dom.minidom.parse(xml_file)
+ types = []
+ categories = []
+ paths = []
+ for node in dom.getElementsByTagName("location"):
+ type = node.getAttribute("type")
+ category = node.getAttribute("category")
+ path = node.childNodes[0].data.strip()
+ types.append(type)
+ categories.append(category)
+ paths.append(path)
+
+ location_map = {"types": types, "categories": categories, "paths": paths}
+ return location_map
+
+ def _fixPath(self, path):
+ # Fix any file path containing device specific constants, modifying
+ # them to its values
+ modifications = {"$HOME":"/home/user", "$USER":"user"}
+ for key in modifications.keys():
+ path = path.replace(key, modifications[key])
+ if not path.startswith("/"):
+ path = "/".join(path)
+ return path
+
--- /dev/null
+
+from pcsbackupinfo import *
+import zipfile
+import os
+import xml.dom.minidom
+
+
+def copyOssoBackupConfigFiles(destination, mountPath):
+ """ Copy all osso-backup .conf files to the given path. The device must be
+ already mounted in the mountPath.
+
+ Attributes:
+ - String mountPath - Path of the folder where the device is mounted
+ - String destination - Destination folder path where config files should be
+ copied to.
+
+ """
+ os.system("cp %s/etc/osso-backup/applications/*.conf %s" %
+ (mountPath, destination))
+
+
+def mountDevice(user, ip, path):
+ # Mount device file system using sshfs in the given path
+ try:
+ if not os.path.exists(path):
+ createFolder(path)
+ os.system('sshfs %s@%s:/ %s' % (user, ip, path))
+ except:
+ raise Exception("Error while mounting device file system")
+
+
+def unmountDevice(path):
+ try:
+ os.system('fusermount -uz %s' % path)
+ except:
+ raise Exception("Error while unmounting device file system")
+
+
+def createFolder(complete_path):
+ if not os.path.exists(complete_path):
+ os.makedirs(complete_path)
+
+ # FIXME
+ return True
+
+
+def removePath(complete_path):
+ for entry in os.listdir(complete_path):
+ if os.path.isdir(entry):
+ removePath(os.path.join(complete_path, entry))
+ else:
+ os.remove(os.path.join(complete_path, entry))
+ os.rmdir(complete_path)
+
+
+def getDeviceBackupList(mountPoint):
+ """This function return a list of backupInfo objects for each backup found
+ in the mount point.
+
+ """
+ deviceBackups = []
+ mmc1 = '%s/media/mmc1/backups' % mountPoint
+ mmc2 = '%s/media/mmc2/backups' % mountPoint
+
+ if os.path.exists(mmc1):
+ deviceBackups += _getDeviceBackupsInfo(mmc1)
+ if os.path.exists(mmc2):
+ deviceBackups += _getDeviceBackupsInfo(mmc2)
+
+ return deviceBackups
+
+
+def copy(original, destination):
+ original = original.replace(" ", "\ ")
+ destination = destination.replace(" ", "\ ")
+ createFolder(destination)
+ os.system("cp %s %s" % (original, destination))
+
+
+def getSize(path):
+ if not os.path.exists(path):
+ return False
+ if os.path.isdir(path):
+ files_and_folders = os.listdir(path)
+ sum_size = 0
+ for entry in files_and_folders:
+ if os.path.isdir(os.path.join(path, entry)):
+ sum_size += getSize(os.path.join(path, entry))
+ else:
+ try:
+ sum_size += os.stat(os.path.join(path, entry)).st_size
+ except:
+ sum_size += 1
+ return sum_size
+ else:
+ return os.stat(path).st_size
+
+
+def getBackupFilesPath(backupPath):
+ dic = {}
+ for entry in os.listdir(backupPath):
+ if entry.endswith(".zip"):
+ zip = openZip(os.path.join(backupPath, entry))
+ dic[entry.replace(".zip", "")] = zip.namelist()
+ return dic
+
+
+def getBackupCategories(backupInfo):
+ backupPath = str(backupInfo.path)
+ if not backupInfo.fromDevice:
+ backupPath = os.path.join(backupPath, str(backupInfo._name))
+ categoriesList = []
+ for entry in os.listdir(backupPath):
+ if entry.endswith(".zip"):
+ categoriesList.append(entry.replace(".zip", ""))
+ return categoriesList
+
+
+def writeBackupFilesPath(paths_dictionary, file_path):
+ try:
+ file = open(file_path, "w")
+ except:
+ return False
+ for category in paths_dictionary.keys():
+ file.write("[" + category + "]\n")
+ for path in paths_dictionary[category]:
+ file.write(path + "\n")
+
+ file.close()
+
+def openZip(zipPath, mode="r"):
+ """ Open a .zip file using python ZipFile library.
+
+ Attributes:
+ String zipPath - The directory path to the file
+ String mode - "w" to open file for writting.
+ "a" to open file for appending.
+ "r" to open file for reading.
+
+ """
+ try:
+ zip = zipfile.ZipFile(zipPath, mode)
+ return zip
+ except zipfile.BadZipfile, msg:
+ raise IOError("Problem while opening %s: %s" % (zipPath, msg))
+ except:
+ raise
+
+def closeZip(zipfile):
+ zipfile.close()
+
+def zip(zipfile, path):
+ # Compress the file in the given path to the zipfile
+ try:
+ zipfile.write(path.encode('UTF'))
+ return True
+ except:
+ return False
+
+def rebootDevice(deviceIp):
+ return os.system("ssh root@%s reboot" % deviceIp) == 0
+
+
+def _parseMetadata(metadata_path):
+ document = xml.dom.minidom.parse(metadata_path)
+ node = document.getElementsByTagName("size")[0]
+ size = int(str(node.firstChild.nodeValue))
+ node = document.getElementsByTagName("timestamp")[0]
+ objDate = datetime.fromtimestamp(float(str(node.firstChild.nodeValue)))
+ return size, str(objDate)
+
+def _getDeviceBackupsInfo(memoryCardPath):
+ deviceBackups = []
+ for backup in os.listdir(memoryCardPath):
+ temporaryFolder = os.path.join(memoryCardPath, backup)
+ if os.path.isdir(temporaryFolder):
+ metadataPath = os.path.join(temporaryFolder,'backup.metadata')
+ if os.path.exists(metadataPath):
+ size, date = _parseMetadata(metadataPath)
+ backupInfo = PcsBackupInfo(backup, temporaryFolder, size)
+ backupInfo.setDate(date)
+ deviceBackups.append(backupInfo)
+ return deviceBackups
+
--- /dev/null
+from time import sleep
+import threading
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+
+from pcsprogresswizard import *
+from pcscheckboxwizard import *
+from pcsopenfilewizard import *
+from pcspcbackupmanager import *
+from pcsdevicemanager import *
+
+class PcsBackupWizard(QWizard):
+
+ ''' Class that creates a wizard responsible for doing backup '''
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizard.__init__(self, parent)
+ self.windowManager = windowManager
+ self.deviceInfo = deviceInfo
+ stylesheet = '''QWizard{background-image:url('''+ BACKUP_BG + ''')};'''
+ self.setStyleSheet(stylesheet)
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH,WINDOW_HEIGHT)
+
+ self.setButtonLayout([])
+ self.setWizardStyle(4)
+
+ self.checkboxPage = PcsCheckboxWizard(self.deviceInfo, windowManager, self)
+ self.addPage(self.checkboxPage)
+
+ self.chooseFilePage = PcsOpenFileWizard(self.deviceInfo, windowManager, self)
+ self.connect(self.chooseFilePage.finishButton, SIGNAL("clicked()"),
+ self.noNameTest)
+ self.addPage(self.chooseFilePage)
+
+ self.progressWizard = PcsProgressWizard(self.deviceInfo,self, windowManager, self)
+ self.connect(self.progressWizard.cancelButton, SIGNAL("clicked()"),
+ self._confirmsCancel)
+ self.connect(self.progressWizard.doneButton, SIGNAL("clicked()"), self._done)
+ self.connect(self.progressWizard, SIGNAL("destroyed()"), self.test)
+ self.addPage(self.progressWizard)
+
+ def test(self):
+ print "entrou caraiiiiii"
+
+ def noNameTest(self):
+ if(str(self.chooseFilePage.getBackupName()).strip() == ""):
+ message = "Your backup name can't be blank."
+ showMessageBox(message, "Backup name blank")
+ else:
+ self.doNewBackup()
+ self.next()
+
+ def _done(self):
+ self.done(0)
+ self.progressWizard._resetPage()
+ self.chooseFilePage._resetPage()
+
+ def doNewBackup(self):
+
+ hostIp = self.deviceInfo.ip
+ backupName = self.chooseFilePage.getBackupName()
+ backupPath = self.chooseFilePage.getPath()
+ categories = self.checkboxPage.getCategories()
+ self.backupManager = PcsPcBackupManager()
+ self.backupManager.loadBackups()
+ comments = ""
+
+ self._updateThread = UpdateBackupProgress(backupName, backupPath,
+ hostIp,categories, comments,
+ self.backupManager,
+ self.progressWizard)
+ self.connect(self._updateThread, SIGNAL("backupFinished"),
+ self._onBackupDone)
+ self.connect(self._updateThread, SIGNAL("backupCanceled"),
+ self._onBackupCancel)
+ self.connect(self._updateThread, SIGNAL("backupNameChanged"),
+ self._onBackupNameChanged)
+ self.connect(self._updateThread, SIGNAL("backupProgress"),
+ self._updateCategoriesAndProgress)
+
+ self._updateThread.start()
+
+ def _updateCategoriesAndProgress(self, information):
+ progress, category = information
+ self.progressWizard.setProgress(progress)
+ self.progressWizard.setCategory(category)
+
+
+ def _onBackupDone(self, info):
+ self.progressWizard.updateInfo(info[0], info[1])
+ self.progressWizard.progressDone()
+ self.windowManager.getBackupManager().pcListView.updateBackupList()
+
+ def _onBackupNameChanged(self, correct_name):
+ """
+ Check if backup name was changed and show message case positive.
+ """
+ nameChangeMessage = "Backup with same name was found in" + \
+ " backup list, Backup name changed to %s" \
+ % correct_name
+ showMessageBox(nameChangeMessage, "Backup name changed")
+
+ def _confirmsCancel(self):
+ """
+ Confirms the backup canceling.
+ """
+ dialog = QMessageBox()
+ dialog.setText("Do you really want cancel this backup?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ self._onBackupCancel()
+
+ def _onBackupCancel(self):
+ """
+ Stops current backup process in backup manager.
+ Also, shows a message box informing about canceling.
+
+ """
+ self.progressWizard.progressCanceled()
+ self.backupManager.setBackupInProgress(False)
+
+ def setVisible (self, visible):
+ if(visible == False):
+ self.emit("")
+
+
+class UpdateBackupProgress(QThread):
+
+ def __init__(self, backupName, path, hostIp, categories, comment,
+ backupManager, progressWizard):
+ QThread.__init__(self)
+
+ self.backupName = backupName
+ self.path = path
+ self.hostIp = hostIp
+ self.categories = categories
+ self.comment = comment
+ self.backupManager = backupManager
+
+
+ def run(self):
+ self._backupFlag = True
+
+ self.correctName = self.backupManager._verify_backup_name(self.backupName)
+ self.nameChanged = self.correctName != self.backupName
+
+ self.connect(self.backupManager, SIGNAL("backupProgress"), self._reEmitSignal)
+ self.connect(self.backupManager, SIGNAL("backupDone"), self._onBackupDone)
+ res = self.backupManager.createBackup(self.correctName, self.path,
+ self.hostIp, self.categories,
+ self.comment)
+
+ while (self._backupFlag):
+ sleep(0.1)
+
+ def _reEmitSignal(self, informations):
+ self.emit(SIGNAL("backupProgress"), informations)
+
+ def _onBackupDone(self, res, info):
+ self._backupFlag = False
+ # If backup was not canceled, emit done signal
+ if res != 0:
+ if self.nameChanged:
+ self.emit(SIGNAL("backupNameChanged"), self.correctName)
+ self.emit(SIGNAL("backupFinished"), info)
+ else:
+ self.emit(SIGNAL("backupCanceled"))
+
+
\ No newline at end of file
--- /dev/null
+'''
+@author: Nicholas Alexander
+
+Created on 07/07/2009
+
+Module with functions used to create backup metadata xml file with same format
+as osso-backup metadata.
+
+'''
+import os
+
+import xml.dom.minidom
+
+from backup.pcsbackuputils import getSize
+from pcsdevicemanager import PcsDeviceManager
+
+
+def createXml(backup_info, filesByCategory, host_ip):
+ doc = xml.dom.minidom.Document()
+ root = doc.createElement("backup-metadata")
+ doc.appendChild(root)
+ _appendSizeNode(backup_info, doc, root)
+ _appendFilesNumberNode(backup_info, doc, root)
+ _appendTimeNode(backup_info, doc, root)
+ _appendProtectedNode(doc, root)
+ _appendDeviceInfoNode(doc, root, host_ip)
+ backupFullPath = os.path.join(backup_info.getPath(), backup_info.getName())
+ _appendCategoriesNode(doc, root, filesByCategory, backupFullPath)
+ metadata_path = os.path.join(backupFullPath, "backup.metadata")
+ file = open(metadata_path, "w")
+ doc.writexml(file)
+ file.close()
+
+
+
+def _appendSizeNode(backupInfo, document, node):
+ sizeNode = document.createElement("size")
+ size = document.createTextNode(str(backupInfo.getSize()))
+ sizeNode.appendChild(size)
+ node.appendChild(sizeNode)
+
+def _appendFilesNumberNode(backupInfo, document, node):
+ filesNode = document.createElement("number-of-files")
+ files = document.createTextNode(str(backupInfo.getFilesNumber()))
+ filesNode.appendChild(files)
+ node.appendChild(filesNode)
+
+def _appendTimeNode(backupInfo, document, node):
+ timeNode = document.createElement("timestamp")
+ time = document.createTextNode(str(int(backupInfo.getTime())))
+ timeNode.appendChild(time)
+ node.appendChild(timeNode)
+
+def _appendProtectedNode(document, node):
+ protectedNode = document.createElement("protected")
+ protected = document.createTextNode("false")
+ protectedNode.appendChild(protected)
+ node.appendChild(protectedNode)
+
+def _appendDeviceInfoNode(document, node, hostIp):
+ deviceManager = PcsDeviceManager()
+ deviceManager.loadDevices()
+ device = deviceManager.getDevice(hostIp)
+ versionNode = document.createElement("device-version")
+ version = document.createTextNode(device.ossoBackup)
+ versionNode.appendChild(version)
+ node.appendChild(versionNode)
+
+def _appendCategoriesNode(document, node, filesByCategory, backupPath):
+ categories = document.createElement("categories")
+ for category in filesByCategory.keys():
+ categoryPath = os.path.join(backupPath, "%s.zip" % category)
+ size = getSize(categoryPath)
+ if size == False:
+ continue
+ categoryNode = document.createElement("%s" % category)
+ categorySize = document.createElement("size")
+ categoryFiles = document.createElement("number-of-files")
+ filesText = document.createTextNode(str(filesByCategory[category]))
+ sizeText = document.createTextNode(str(size))
+ categorySize.appendChild(sizeText)
+ categoryFiles.appendChild(filesText)
+ categoryNode.appendChild(categorySize)
+ categoryNode.appendChild(categoryFiles)
+ categories.appendChild(categoryNode)
+ node.appendChild(categories)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsbutton import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcscustombuttons import PcsCustomButton as customButton
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+
+class PcsCheckboxWizard(QWizardPage):
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.layout.setSpacing(0)
+ buttonsLayout = self._menuButtons()
+ self.layout.addLayout(buttonsLayout)
+ self.layout.addItem(QSpacerItem(0, 8))
+ wayLayout = self._wayLayout()
+ self.layout.addLayout(wayLayout)
+
+ self.layout.addItem(QSpacerItem(0, 10))
+
+ self.hlayout = QHBoxLayout()
+ self.hlayout.setMargin(0)
+
+ self.vertical = QVBoxLayout()
+ self.vertical.setMargin(0)
+ self.vertical.setSpacing(0)
+ self.create_vertical_components()
+ self.hlayout.addLayout(self.vertical)
+ self.hlayout.setMargin(0)
+ self.hlayout.setSpacing(0)
+
+ self.create_checkbox_frame()
+# self.hlayout.addItem(QSpacerItem(30, 0))
+ self.layout.addLayout(self.hlayout)
+
+ self.layout.addItem(QSpacerItem(0, 35))
+ informationLayout = QHBoxLayout()
+ informationLayout.setMargin(0)
+ spc = QSpacerItem(10, 0)
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ information = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the types of file you wish to backup.</font>")
+ informationLayout.addItem(spc)
+ informationLayout.addWidget(iconAlert)
+ informationLayout.addWidget(information, Qt.AlignLeft)
+
+ self.layout.addLayout(informationLayout)
+
+ self.setLayout(self.layout)
+ self.map_checked = {self.documents.name: False,
+ self.emails.name: False, self.media.name: False,
+ self.contacts.name: False,
+ self.bookmarks.name: False,
+ self.settings.name: False,
+ self.applications.name: False}
+ self.enableNext = QLineEdit()
+ self.registerField("enableNext*", self.enableNext)
+
+ def _wayLayout(self):
+ barLayout = QHBoxLayout()
+ barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow = self._arrow()
+ arrow2 = self._arrow()
+ spc = QSpacerItem(5, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #FFFFFF'; size=2>Files</font>")
+ widgetList = [main, arrow, newBackup, arrow2, files]
+ for widget in widgetList:
+ barLayout.addWidget(widget, Qt.AlignLeft)
+ barLayout.addItem(spc)
+ barLayout.addItem(QSpacerItem(300, 0))
+ return barLayout
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard().geometry())
+ backupManager.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard().geometry())
+ restoreBackup.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _goNextPage(self):
+ if self.empty_map():
+ return False
+ else:
+ self.wizard().next()
+
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def create_checkbox_frame(self):
+ layout = QVBoxLayout()
+ l = QLabel()
+ l.setPixmap(QPixmap(COPY_BORDER))
+
+ self.frame = QScrollArea(self)
+ self.frame.setWidgetResizable(True)
+ widget = QWidget(self.frame)
+ widget.setStyleSheet("QWidget{background: transparent;}")
+ self.grid = QGridLayout()
+ self.grid.setSpacing(0)
+ self.createCheckboxPanel()
+ widget.setLayout(self.grid)
+ self.frame.setWidget(widget)
+ layout.addItem(QSpacerItem(0,25))
+ layout.addWidget(self.frame)
+ self.hlayout.addLayout(layout)
+
+
+ def empty_map(self):
+ for index in self.map_checked.keys():
+ if self.map_checked[index]:
+ return False
+ return True
+
+ def createCheckboxPanel(self):
+ #Add Checkboxes
+# self.add_select_all()
+ self.add_documents()
+ self.add_emails()
+ self.add_media()
+ self.add_contacts()
+ self.add_bookmarks()
+ self.add_settings()
+ self.add_applications()
+
+# def add_select_all(self):
+# self.select_all = QCheckBox("Select All")
+# self.connect(self.select_all, SIGNAL("stateChanged(int)"),
+# self.select_all_func)
+# self.grid.addWidget(self.select_all, 0, 0, Qt.AlignTop)
+#
+ def add_documents(self):
+ self.documents = QCheckBox("Documents")
+ self.documents.name = "documents"
+ callback = partial(self.select_func, self.documents)
+ self.connect(self.documents, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.documents, 1, 0, Qt.AlignTop)
+
+ def add_emails(self):
+ self.emails = QCheckBox("Emails")
+ self.emails.name = "emails"
+ callback = partial(self.select_func, self.emails)
+ self.connect(self.emails, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.emails, 2, 0, Qt.AlignTop)
+
+ def add_media(self):
+ self.media = QCheckBox("Media")
+ self.media.name = "media"
+ callback = partial(self.select_func, self.media)
+ self.connect(self.media, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.media, 3, 0, Qt.AlignTop)
+
+ def add_contacts(self):
+ self.contacts = QCheckBox("Contacts")
+ self.contacts.name = "contacts"
+ callback = partial(self.select_func, self.contacts)
+ self.connect(self.contacts, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.contacts, 4, 0, Qt.AlignTop)
+
+ def add_bookmarks(self):
+ self.bookmarks = QCheckBox("Bookmarks")
+ self.bookmarks.name = "bookmarks"
+ callback = partial(self.select_func, self.bookmarks)
+ self.connect(self.bookmarks, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.bookmarks, 5, 0, Qt.AlignTop)
+
+ def add_settings(self):
+ self.settings = QCheckBox("Settings")
+ self.settings.name = "settings"
+ callback = partial(self.select_func, self.settings)
+ self.connect(self.settings, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.settings, 6, 0, Qt.AlignTop)
+
+ def add_applications(self):
+ self.applications = QCheckBox("Applications")
+ self.applications.name = "applications"
+ callback = partial(self.select_func, self.applications)
+ self.connect(self.applications, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.applications, 7, 0, Qt.AlignTop)
+
+# def select_all_func(self):
+# checked = self.select_all.isChecked()
+# list = self.map_checked.keys()
+# for element in list:
+# self.map_checked[element] = checked
+# for i in range(1,8):
+# self.grid.itemAtPosition(i, 0).widget().setChecked(checked)
+#
+ def select_func(self, checkbox):
+ checked = checkbox.isChecked()
+ self.map_checked[checkbox.name] = checked
+ if not checked:
+ list = []
+ for i in range(1,8):
+ item = self.grid.itemAtPosition(i, 0).widget()
+# if item == self.select_all:
+# pass
+ if item.isChecked():
+ list.append(item)
+# self.select_all.setChecked(False)
+ for element in list:
+ element.setChecked(True)
+ if self.empty_map():
+ self.enableNext.setText("")
+ else:
+ self.enableNext.setText("Next Button Enabled")
+
+ def getCategories(self):
+ return self.map_checked
+
+ def create_vertical_components(self):
+ deviceWidget = PcsDeviceWidget(2)
+ deviceWidget.setImage(DEVICE_DISCONNECTED)
+ deviceWidget.addBorder()
+ deviceWidget.addDeviceName()
+ deviceWidget.setDeviceInfo(self.deviceInfo)
+ self.vertical.addWidget(deviceWidget, Qt.AlignTop)
+ self.nextButton = QPushButton()
+ self.nextButton.setText("Next")
+ self.nextButton.setStyleSheet(BACKUP_BUTTON_STYLE)
+ self.connect(self.nextButton, SIGNAL("clicked()"), self._goNextPage)
+ self.vertical.addItem(QSpacerItem(0, 20))
+ buttonLayout = QHBoxLayout()
+ buttonLayout.addItem(QSpacerItem(5,0))
+ buttonLayout.addWidget(self.nextButton, Qt.AlignCenter)
+ self.vertical.addLayout(buttonLayout)
+ self.vertical.addItem(QSpacerItem(0,10))
+
\ No newline at end of file
--- /dev/null
+
+from pcsbackupmanager import *
+from pcspcbackupmanager import PcsPcBackupManager
+from pcsbackupinfo import PcsBackupInfo
+import pcsbackuputils as utils
+
+
+class PcsDeviceBackupManager(PcsBackupManager):
+
+
+ def __init__(self, deviceInfo):
+ PcsBackupManager.__init__(self)
+ self._backupList = []
+ self._deviceInfo = deviceInfo
+ self.restoreInProgress = False
+ self.copyInProgress = False
+
+ def loadBackups(self):
+
+ # FIXME, error handling is wrong!! return list of PcsBackupInfo
+ try:
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % self._deviceInfo.ip)
+ utils.mountDevice(USER_HOST, self._deviceInfo.ip, mountPoint)
+
+ self._backupList = utils.getDeviceBackupList(mountPoint)
+ return True
+
+ except Exception, x:
+ print str(x)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+ return False
+
+ def getBackupList(self):
+ self.loadBackups()
+ for backup in self._backupList:
+ backup.setAtDevice(True)
+ return self._backupList
+
+ def copyBackupFromDevice(self, backupName, destinationPath):
+ try:
+ self.loadBackups()
+ device_backups = self.getBackupList()
+
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % self._deviceInfo.ip)
+ utils.mountDevice(USER_HOST, self._deviceInfo.ip, mountPoint)
+
+ # Search complete_path
+ completePath = ''
+ for backup in device_backups:
+ if backupName == backup.getName():
+ completePath = backup.getPath()
+ break
+ if completePath == '':
+ raise Exception("Backup not found.")
+
+ pcBackupManager = PcsPcBackupManager()
+ pcBackupManager.loadBackups()
+ correctName = pcBackupManager._verify_backup_name(backupName)
+ destination = os.path.join(destinationPath, correctName)
+
+ self.setCopyInProgress(True)
+ if self.copy(completePath, destination) == 0:
+ return 0
+ self.setCopyInProgress(False)
+
+ backup_size = utils.getSize(destination)
+ backup = PcsBackupInfo(correctName, destinationPath, backup_size,
+ 'Copied from device')
+ backup.setAtDevice(False)
+ pcBackupManager._backupList.append(backup)
+ pcBackupManager.saveBackups()
+
+ finally:
+ utils.unmountDevice(mountPoint)
+
+
+ def startBackupRestore(self, backupInfo, categories):
+ device_ip = self._deviceInfo.ip
+ return self.restoreBackup(backupInfo, device_ip, categories)
+
+
+ def setCopyInProgress(self, status):
+ self.copyInProgress = status
+
+
+ def setRestoreInProgress(self, status):
+ self.restoreInProgress = status
+
+
+ def getBackupInfo(self, backupName):
+ self.loadBackups()
+ for backupInfo in self._backupList:
+ if backupInfo.getName() == backupName:
+ backupInfo.setAtDevice(True)
+ return backupInfo
+
+ return None
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+import os
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+from style.styleTabletSuite import *
+
+
+class PcsOpenFileWizard(QWizardPage):
+
+ _home_dir = os.path.expanduser("~")
+ _default_dir = _home_dir + "/.pcsuite/Backup"
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+
+ self.path = self._default_dir
+ self.file_name = "Backup"
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.hLayout = QHBoxLayout()
+ self.hLayout.setMargin(0)
+ self.vLayout = QVBoxLayout()
+ self.vLayout.setMargin(0)
+
+ wayLayout = self._wayLayout()
+
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ spc = QSpacerItem(0, 12)
+ self.vLayout.addLayout(wayLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+ self.vLayout.addItem(spc)
+ spc2 = QSpacerItem(350, 0)
+ self.finishButton = QPushButton("Finish")
+ self.finishButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.finishButton.setShortcut(Qt.Key_Return)
+ self.hLayout.addItem(spc2)
+ self.hLayout.addWidget(self.finishButton)
+ self.vLayout.addLayout(self.hLayout)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self):
+ barLayout = QHBoxLayout()
+ barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow = self._arrow()
+ arrow2 = self._arrow()
+ arrow3 = self._arrow()
+ spc = QSpacerItem(2, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #333333'; size=2>Files</font>")
+ folder = QLabel("<font style='color: #FFFFFF'; size=2>Folder</font>")
+ widgetList = [main, arrow, newBackup, arrow2, files, arrow3, folder]
+ for widget in widgetList:
+ barLayout.addWidget(widget, Qt.AlignLeft)
+ barLayout.addItem(spc)
+ barLayout.addItem(QSpacerItem(300, 0))
+ return barLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard().geometry())
+ backupManager.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard().geometry())
+ restoreBackup.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createDeviceWidget(self):
+ deviceWidget = PcsDeviceWidget(3)
+ deviceWidget.addBorder()
+ deviceWidget.addDeviceName()
+ deviceWidget.setDeviceInfo(self.deviceInfo)
+
+ return deviceWidget
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Do backup from Device to your PC.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(infLabel, Qt.AlignLeft)
+
+
+ return hLay
+
+ def _createCenterLayout(self):
+ hLay = QHBoxLayout()
+ hLay.setMargin(0)
+ vLay = QVBoxLayout()
+ vLay.setMargin(0)
+ hLayWithSpacer = QHBoxLayout()
+ hLayWithSpacer.setMargin(0)
+ spc = QSpacerItem(62, 0)
+
+ deviceWidget = self._createDeviceWidget()
+ arrowLabel = self._createArrowLabel()
+ pcLabel = self._createPcLabel()
+ pathField = self._createPathField()
+ nameField = self._createBackupNameField()
+
+ hLay.addWidget(deviceWidget, Qt.AlignVCenter)
+ hLay.addLayout(arrowLabel, Qt.AlignVCenter)
+ hLay.addLayout(pcLabel, Qt.AlignVCenter)
+
+ vLay.addLayout(nameField)
+ vLay.addLayout(hLay)
+ vLay.addLayout(pathField)
+
+ hLayWithSpacer.addItem(spc)
+ hLayWithSpacer.addLayout(vLay)
+ hLayWithSpacer.addItem(spc)
+
+ return hLayWithSpacer
+
+ def _createArrowLabel(self):
+ arrowLayout = QGridLayout()
+ arrowLabel = QLabel()
+ arrowLabel.setPixmap(QPixmap(LARGE_ARROW_IMAGE))
+ borderArrowLabel = QLabel()
+ borderArrowLabel.setFixedSize(42, 65)
+ borderArrowLabel.setPixmap(QPixmap(LARGE_ARROW_BORDER))
+ arrowLayout.addWidget(arrowLabel, 0, 0, Qt.AlignCenter)
+ arrowLayout.addWidget(borderArrowLabel, 0, 0, Qt.AlignCenter)
+ return arrowLayout
+
+ def _createPcLabel(self):
+ gridLay = QGridLayout()
+ pcLabelLayout = QGridLayout()
+ pcLabel = QLabel()
+ pcLabel.setPixmap(QPixmap(PC_IMAGE))
+ pcBorder = QLabel()
+ pcBorder.setFixedSize(112, 127)
+ pcBorder.setPixmap(QPixmap(PC_BORDER_FILE))
+ nameLabel = QLabel("PC")
+ nameBorder = QLabel()
+ nameBorder.setPixmap(QPixmap(PC_NAME_BORDER_FILE))
+ nameBorder.setFixedSize(92, 26)
+ gridLay.addWidget(pcLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addWidget(nameLabel, 1, 0, Qt.AlignCenter)
+ gridLay.addWidget(nameBorder, 1, 0, Qt.AlignCenter)
+ pcLabelLayout.addLayout(gridLay, 0, 0, Qt.AlignCenter)
+ pcLabelLayout.addWidget(pcBorder, 0, 0, Qt.AlignCenter)
+ return pcLabelLayout
+
+ def _createPathField(self):
+ pathLayout = QHBoxLayout()
+ self.pathField = QLineEdit()
+ self.pathField.setReadOnly(True)
+ self.pathField.setText(self._default_dir)
+ self.pathField.setObjectName("pathField")
+ buttonBrowse = QPushButton()
+ buttonBrowse.setObjectName("buttonBrowse")
+ self.connect(buttonBrowse, SIGNAL("clicked()"), self._openFileDialog)
+ pathLayout.addWidget(self.pathField)
+ pathLayout.addWidget(buttonBrowse)
+
+ borderLabel = QLabel()
+ borderLabel.setPixmap(QPixmap(PATH_BG))
+ borderLabel.setFixedSize(304, 40)
+ gridLay = QGridLayout()
+ gridLay.addWidget(borderLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addLayout(pathLayout, 0, 0, Qt.AlignCenter)
+
+ return gridLay
+
+ def _createBackupNameField(self):
+ label = QLabel("Backup Name:")
+ backupNameLayout = QHBoxLayout()
+ backupNameLayout.addWidget(label)
+ self.backupNameField = QLineEdit()
+ self.backupNameField.setObjectName("backupNameField")
+ self.backupNameField.setText("Backup")
+ backupNameLayout.addWidget(self.backupNameField,
+ Qt.AlignHCenter)
+ borderLabel = QLabel()
+ borderLabel.setPixmap(QPixmap(BACKUP_NAME_BG))
+ borderLabel.setFixedSize(304, 40)
+ gridLay = QGridLayout()
+ gridLay.addWidget(borderLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addLayout(backupNameLayout, 0, 0, Qt.AlignCenter)
+
+ return gridLay
+
+ def _openFileDialog(self):
+ pathDialog = QFileDialog()
+ prompt = "Select the folder you wish to save your backup"
+ self.path = pathDialog.getExistingDirectory(self, prompt,
+ self._default_dir)
+ if self.path != "":
+ self.pathField.setText(self.path)
+
+ def _resetPage(self):
+ self.path = self._default_dir
+ self.pathField.setText(self._default_dir)
+ self.backupNameField.setText("Backup")
+
+ def getBackupName(self):
+ return str(self.backupNameField.text())
+
+ def getPath(self):
+ return str(self.pathField.text())
+
--- /dev/null
+# low_backup_manager module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+# Backup_manager class:
+# Class responsible for backup functions like creating and removing backups
+
+import os.path
+import os
+import zlib
+import pickle
+
+from PyQt4.QtCore import *
+from zipfile import *
+
+from pcsbackupparser import *
+from pcsbackupinfo import *
+from pcsbackupmanager import *
+from pcsbackupxml import *
+
+import pcsbackuputils as utils
+
+HOME = os.path.expanduser("~")
+BACKUP_FILES_PATH = os.path.join(HOME, ".pcsuite/Backup")
+DEFAULT_CONFIG_PATH = "%s/.pcsuite/config" % HOME
+BACKUPS_FILE = os.path.join(HOME, ".pcsuite/Backup/.backups")
+
+
+class PcsPcBackupManager(PcsBackupManager):
+
+ def __init__(self):
+ PcsBackupManager.__init__(self)
+ self._backupList = []
+ self.backupInProgress = False
+ self.restoreInProgress = False
+ self.copyInProgress = False
+
+ self.myDocsPath = "Root/home/user/MyDocs/"
+ self.backupPath = ""
+ self.currentCategory = ""
+ self.totalSize = 0
+
+ def loadBackups(self):
+ # 'XX Loading the backup list available in the PC'
+ try:
+ if os.path.exists(BACKUPS_FILE):
+ file = open(BACKUPS_FILE)
+ self._backupList = pickle.load(file)
+ file.close()
+ except IOError:
+ print "IOError while loading the PC backups"
+ # FIXME
+ #raise Exception("Error while reading backups")
+ return False
+
+ return True
+
+ def saveBackups(self):
+ # 'XX Saving the backup list in the config file'
+ try:
+ obj = self._backupList
+ file = open(BACKUPS_FILE, "w")
+ pickle.dump(obj, file)
+ file.close()
+ except:
+ #raise Exception("Error while saving backups")
+ return False
+
+ return True
+
+ def getBackupList(self):
+ """Return a list with the name of all done backups. """
+ self.loadBackups()
+ return self._backupList[:]
+
+ def createBackup(self, backup_name, path, host_ip, categories, comment=""):
+ self.backupThread = NewBackupThread(self, backup_name, path, host_ip,
+ categories, comment)
+ self.backupThread.start()
+
+
+ def renameBackup(self, backupName, newName):
+ self.loadBackups()
+
+ backupInfo = self.getBackupInfo(backupName)
+ if backupInfo != None:
+ try:
+ old = os.path.join(str(backupInfo.getPath()), str(backupName))
+ new = os.path.join(str(backupInfo.getPath()), str(newName))
+ os.rename(old, new)
+ backupInfo.setName(newName)
+ except:
+ print "Error while changing backup name"
+ return False
+ else:
+ # "Backup not found"
+ return False
+
+ self.saveBackups()
+ return True
+
+ def removeBackup(self, backupName):
+ """
+ Remove a backup from pc and from _backupList.
+ """
+ self.loadBackups()
+ backupInfo = self.getBackupInfo(backupName)
+ completePath = os.path.join(str(backupInfo.getPath()),
+ str(backupInfo.getName()))
+ if os.path.exists(completePath):
+ utils.removePath(completePath)
+ self._backupList.remove(backupInfo)
+ self.saveBackups()
+
+ return True
+
+ def copyBackupToDevice(self, deviceIp, backupName, memoryStick):
+ """ Copy a backup in the PC to some memory card inside the chosen device.
+
+ Attributes:
+ String deviceIp - String with ip address of device.
+ String backupName - Name of backup to be copied.
+ Int memoryStick - Integer representing which memory stick backup
+ should be copied to.
+ 0 - Removable memory stick
+ 1 - Internal memory stick
+ """
+ try:
+ self.loadBackups()
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % deviceIp)
+ utils.mountDevice(USER_HOST, deviceIp, mountPoint)
+
+ backup = self.getBackupInfo(backupName)
+ backupPath = os.path.join(str(backup.getPath()), str(backupName))
+ if memoryStick != 0 and memoryStick != 1:
+ return -1
+ destination = os.path.join(mountPoint, 'media/mmc%s' %
+ (memoryStick+1), 'backups', backupName)
+
+ self.setCopyInProgress(True)
+ if self.copy(backupPath, destination) == 0:
+ return 0
+ self.setCopyInProgress(False)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+
+ def getBackupInfo(self, backupName):
+ for backupInfo in self._backupList:
+ if backupInfo.getName() == backupName:
+ return backupInfo
+ return None
+
+ def startBackupRestore(self, backupInfo, device_ip, categories):
+ return self.restoreBackup(backupInfo, device_ip, categories)
+
+ def setCopyInProgress(self, status):
+ self.copyInProgress = status
+
+ def setBackupInProgress(self, status):
+ self.backupInProgress = status
+
+
+ def setRestoreInProgress(self, status):
+ self.restoreInProgress = status
+
+ # FIXME: rewrite this method. Add error handling, some more reliable code
+ def _runCreateBackup(self, backup_name, path, host_ip, categories, comment=""):
+ """Create a backup and add it to _backupList.
+
+ Backup all files and directories of categories chosen. The device
+ system file is mounted on PC and them files are compressed in a zip
+ format. All zip files from each category are saved in the given path.
+
+ Arguments:
+ backup_name -- Backup's name. This name will be the name of the backup
+ folder.
+ path -- Location to save Backup file
+ host_ip -- The device IP address.
+ categories -- A python dictonary where the keys are the categories from
+ osso-backup, and the value can be either True or False, to identify
+ which categories to backup.
+ comment -- Any comment about the backup. It will be saved in Backup
+ object.
+
+ """
+
+ backupInfo = None
+ self.setBackupInProgress(True)
+ self.currentCategory = ""
+
+ try:
+ # Mount device folders
+ self.loadBackups()
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % host_ip)
+ utils.mountDevice(USER_HOST, host_ip, mountPoint)
+
+ # Create backup folder in the given path
+ self.backupPath = os.path.join(str(path), backup_name)
+ self._createBackupFolder(self.backupPath)
+
+ # Copying osso-backup configuration files to TabletSuite folder and
+ # parsing backup information from these files.
+ # ( Information = which paths should be in each backup category)
+ utils.copyOssoBackupConfigFiles(DEFAULT_CONFIG_PATH, mountPoint)
+ xmlParser = PcsBackupParser()
+ xmlParser.fillLocationsDict(DEFAULT_CONFIG_PATH)
+ backupItemDict = xmlParser.getLocationsDict()
+
+ # Changing work directory to ease file search. Keeping previous
+ # folder to come back after backup process.
+ current_dir = os.getcwd()
+ workPath = DEVICES_POINT + str(host_ip)
+ os.chdir(workPath)
+
+ # Computing total size that this backup will have.
+ self.totalSize = self._getTotalSize(backupItemDict, categories)
+
+
+ # Start backup process. Create backup of paths for each locations
+ # category
+ self.backedUpNumber = 0
+ filesByCategory = {}
+ for category in backupItemDict.keys():
+ self.currentCategory = category
+
+ for backupItem in backupItemDict[category]:
+ self._emitProgress()
+ # If current backupInfo category is valid and it's value is
+ # True in categories dictionary, add it to current backup.
+ if (category in categories) and (categories[category]):
+ categoryFilesNumber = 0
+ categoryFile = os.path.join(self.backupPath,
+ category + '.zip')
+
+ if os.path.exists(categoryFile):
+ zipfile = utils.openZip(categoryFile, 'a')
+ else:
+ zipfile = utils.openZip(categoryFile, 'w')
+
+ objPath = backupItem.path.replace('/','Root/',1)
+ backupFolder = os.path.join(workPath, objPath)
+ categoryFilesNumber = self.zipFolder(backupFolder,
+ zipfile, objPath,
+ category)
+ if categoryFilesNumber == -1:
+ os.chdir(current_dir)
+ return 0
+ self.backedUpNumber += categoryFilesNumber
+ self._emitProgress()
+
+ # Update the filesByCategory dictionary with the
+ # current number of files from current category that
+ # were already copied.
+ self._updateCategoryCount(filesByCategory, category,
+ categoryFilesNumber)
+ utils.closeZip(zipfile)
+ # If category had no file to copy remove its folder
+ if int(utils.getSize(categoryFile) == 0):
+ os.remove(categoryFile)
+
+
+ # Copying media files from device user folder if media category is
+ # True in categories dictionary.
+ if ("media" in categories) and (categories["media"]):
+ self.currentCategory = "media"
+ result = self._backupMedias(workPath)
+ if result == -1:
+ os.chdir(current_dir)
+ return 0
+ # Update backup files number count
+ self.backedUpNumber += result
+ self._updateCategoryCount(filesByCategory, "media", result)
+ zipPath = os.path.join(self.backupPath,'media.zip')
+ if int(utils.getSize(zipPath) == 0):
+ os.remove(zipPath)
+
+
+ # Copying documents files from device user folder if documents
+ # category is True in categories dictionary.
+ if ("documents" in categories) and (categories["documents"]):
+ self.currentCategory = "documents"
+ result = self._backupDocuments(workPath)
+ # Update backup files number count
+ self.backedUpNumber += result
+ if result == -1:
+ os.chdir(current_dir)
+ return 0
+ self._updateCategoryCount(filesByCategory, "documents",
+ result)
+ zipPath = os.path.join(self.backupPath, 'documents.zip')
+ if int(utils.getSize(zipPath) == 0):
+ os.remove(zipPath)
+
+
+ # Change to previous work directory
+ os.chdir(current_dir)
+
+ if self.backedUpNumber == 0:
+ utils.removePath(self.backupPath)
+ return -1
+
+ # Create Backup Object, add it to this manager backup list and save
+ # the list in the backup file.
+ backup_size = utils.getSize(self.backupPath)
+ backupInfo = PcsBackupInfo(backup_name, path, backup_size, comment)
+ backupInfo.setFilesNumber(self.backedUpNumber)
+ self._backupList.append(backupInfo)
+ self.saveBackups()
+
+ createXml(backupInfo, filesByCategory, host_ip)
+ self.setBackupInProgress(False)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+ return backupInfo
+
+
+ def _backupDocuments(self, workPath):
+ """ Create backup of documents files in user folder. """
+ categoryFilesNumber = 0
+ destinationPath = os.path.join(self.backupPath,'documents.zip')
+ if os.path.exists(destinationPath):
+ zipfile = utils.openZip(destinationPath, 'a')
+ else:
+ zipfile = utils.openZip(destinationPath, 'w')
+
+ docsPath = os.path.join(self.myDocsPath, ".documents")
+
+ if os.path.exists(docsPath):
+ backupPath = os.path.join(workPath, docsPath)
+ categoryFilesNumber = self.zipFolder(backupPath, zipfile, docsPath,
+ "documents")
+
+ utils.closeZip(zipfile)
+ return categoryFilesNumber
+
+
+ def _backupMedias(self, workPath):
+ """ Create backup of media files in user folder. """
+ categoryFilesNumber = 0
+ destinationPath = os.path.join(self.backupPath,'media.zip')
+ if os.path.exists(destinationPath):
+ zipfile = utils.openZip(destinationPath, 'a')
+ else:
+ zipfile = utils.openZip(destinationPath, 'w')
+
+ userFilesPath = self.myDocsPath
+ if os.path.exists(os.path.join(userFilesPath)):
+ for folder in os.listdir(userFilesPath):
+ if folder != '.documents':
+ objPath = os.path.join(userFilesPath, folder)
+ backupDir = os.path.join(workPath, objPath)
+ result = self.zipFolder(backupDir, zipfile,
+ objPath, "media")
+ if result != -1:
+ categoryFilesNumber += result
+ else:
+ return result
+
+ utils.closeZip(zipfile)
+ return categoryFilesNumber
+
+
+ def _createBackupFolder(self, newBackupPath):
+ if not utils.createFolder(newBackupPath):
+ return False
+
+
+ def _emitProgress(self):
+ currentSize = utils.getSize(self.backupPath)
+ percentage = self.computePercentage(self.totalSize, currentSize)
+ self.emit(SIGNAL("backupProgress"), (percentage, self.currentCategory))
+
+
+ def _getTotalSize(self, backupFileDict, categories):
+ size = 0
+ for category in backupFileDict.keys():
+ for backupItem in backupFileDict[category]:
+ if (category in categories) and (categories[category]):
+ objPath = backupItem.path.replace('/','Root/',1)
+ size += utils.getSize(objPath)
+
+ if categories["documents"]:
+ size += utils.getSize(os.path.join(self.myDocsPath,
+ ".documents"))
+ if categories["media"]:
+ for folder in os.listdir(self.myDocsPath):
+ if folder != '.documents':
+ objPath = os.path.join(self.myDocsPath, folder)
+ size += utils.getSize(objPath)
+ return size
+
+ def _updateCategoryCount(self, filesByCategory, category, backed_up_number):
+ if str(category) not in filesByCategory.keys():
+ filesByCategory[category] = backed_up_number
+ else:
+ filesByCategory[category] += backed_up_number
+
+
+ def _verify_backup_name(self, backup_name):
+ """ Check if already exists any backup with the given name inside the
+ pc backup list. In case there is one, this function will return another
+ name to be set as the new backup name, else it will return the same
+ name that was given.
+
+ """
+ if self.getBackupInfo(backup_name) != None:
+ counter = 1
+ new_name = backup_name + "%02d" % counter
+ while(self.getBackupInfo(new_name)) != None:
+ counter += 1
+ new_name = backup_name + "%02d" % counter
+
+ backup_name = new_name
+ return backup_name
+
+ def zipFolder(self, path, zipfile, obj_path, category):
+ # Compress the folder from the given path, with all directories and
+ # files inside it
+ # zipfile: The ZipFile object to append the folder
+ # obj_path: The ZipFile path
+ count = 0
+ self._emitProgress()
+ if os.path.exists(path):
+ if os.path.isdir(path):
+ files = os.listdir(path)
+ for node in files:
+ if os.path.isdir(os.path.join(path, node)):
+ zipCount = self.zipFolder(os.path.join(path, node), zipfile,
+ os.path.join(obj_path, node), category)
+ if zipCount == -1:
+ return -1
+ else:
+ count += zipCount
+ else:
+ # Check if backup was canceled and return -1 case positive
+ if not self.backupInProgress:
+ utils.removePath(self.backupPath)
+ return -1
+
+ if utils.zip(zipfile, os.path.join(obj_path, node)):
+ count += 1
+ self._emitProgress()
+ else:
+ # Check if backup was canceled and return -1 case positive
+ if not self.backupInProgress:
+ utils.removePath(self.backupPath)
+ return -1
+
+ if utils.zip(zipfile, obj_path):
+ count += 1
+ self._emitProgress()
+ return count
+
+
+
+class NewBackupThread(QThread):
+ def __init__(self, manager, backupName, path, hostIp, categories, comment):
+ QThread.__init__(self)
+
+ self.manager = manager
+ self.backupName = backupName
+ self.path = path
+ self.hostIp = hostIp
+ self.categories = categories
+ self.comment = comment
+
+ def run(self):
+ ret = self.manager._runCreateBackup (self.backupName, self.path,
+ self.hostIp, self.categories,
+ str(self.comment))
+ self.manager.emit(SIGNAL("backupDone"), ret,
+ (self.manager.totalSize, self.manager.backedUpNumber))
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from style.styleTabletSuite import *
+from ui.pcsuiutils import *
+
+class PcsProgressDialog(QDialog):
+
+ def __init__(self, parent = None):
+ QDialog.__init__(self, parent, Qt.FramelessWindowHint)
+ self.cancelButton = QPushButton("Cancel")
+ self.doneButton = QPushButton("Done")
+ self.connect(self.doneButton, SIGNAL("clicked()"), self.close)
+ self.actionLabel = QLabel("Action...")
+ self.categoryLabel = QLabel("")
+ self.progressReport = QLabel("")
+ self.setLayout(self._insertLayout())
+
+
+ def setAction(self, action):
+ self.action = action
+ if action == "copy":
+ message = "Copying..."
+
+ elif action == "restore":
+ message = "Restoring..."
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ +str(action).capitalize()+
+ " in progress...</font>")
+
+ self.actionLabel.setText('''<font style=color:
+ black; size=3>
+ '''+ message +'''</font>''')
+
+ def _insertLayout(self):
+ vLay = QVBoxLayout()
+ vLay.addWidget(self.actionLabel)
+ vLay.addLayout(self._createCenterLayout())
+ return vLay
+
+ def _createCenterLayout(self):
+
+ bgLabel = QLabel()
+ bgLabel.setPixmap(QPixmap(PROGRESS_BAR_DIALOG_BG))
+ grid = QGridLayout()
+
+ self.progressBar = QProgressBar()
+ self.progressBar.setObjectName("progressBarDialog")
+ self.progressBar.setValue(0)
+ self.progressBar.setTextVisible(False)
+
+ grid.addWidget(bgLabel, 0, 0, Qt.AlignCenter)
+ grid.addWidget(self.progressBar, 0, 0, Qt.AlignCenter)
+
+ self.cancelButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.cancelButton.setShortcut(Qt.Key_Return)
+ self.doneButton.setVisible(False)
+ self.doneButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+
+ gridLayout = QGridLayout()
+ gridLayout.setSpacing(3)
+ gridLayout.addWidget(self.categoryLabel, 0, 0, Qt.AlignRight)
+ gridLayout.addLayout(grid, 1, 0)
+ gridLayout.addWidget(self.progressReport, 2, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.cancelButton, 3, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.doneButton, 3, 0, Qt.AlignRight)
+
+ return gridLayout
+
+ def progressCanceled(self):
+ self.progressDone(True)
+
+ def progressDone(self, cancel=False):
+ self.cancelButton.setVisible(False)
+ self.doneButton.setVisible(True)
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"+\
+ str(self.action).capitalize()
+ +" finished.</font>")
+ if not cancel:
+ totalSize = "%.2f" % (self.totalSize/(1024.0**2))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(self.numberOfFiles) +\
+ " Files - " + totalSize + " MB</font>")
+ else:
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2> Canceled")
+ self.categoryLabel.setText("")
+ self.progressBar.setValue(100)
+
+ def updateInfo(self, totalSize, numberOfFiles):
+ self.totalSize = totalSize
+ self.numberOfFiles = numberOfFiles
+
+ def setProgress(self, progress):
+ self.progressBar.setValue(float(progress))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + progress +\
+ "% Complete</font>")
+
+ def setCategory(self, catogory):
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2> Category name: "\
+ + catogory +"</font>")
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+from style.styleTabletSuite import *
+
+
+class PcsProgressWizard(QWizardPage):
+
+ def __init__(self, deviceInfo, wizard, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+ self.windowManager = windowManager
+ self.deviceInfo = deviceInfo
+ self.wizard = wizard
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.cancelButton = QPushButton("Cancel")
+ self.doneButton = QPushButton("Done")
+ self.completeReportButton = QPushButton("View Complete Report")
+ self.lockMenuButtons = True
+ self._insertLayout()
+
+ def _insertLayout(self, name = ""):
+ self.vLayout = QVBoxLayout()
+ self.vLayout.setMargin(0)
+ self.wayLayout = self._wayLayout(name)
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
+ spc = QSpacerItem(0, 68)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manager Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self, name = ""):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow1 = self._arrow()
+ arrow2 = self._arrow()
+ arrow3 = self._arrow()
+ arrow4 = self._arrow()
+ spc = QSpacerItem(2, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #333333'; size=2>Files</font>")
+ folder = QLabel("<font style='color: #333333'; size=2>Folder</font>")
+ if name != "":
+ loading = QLabel("<font style='color: #333333'; size=2>loading</font>")
+ else:
+ loading = QLabel("<font style='color: #FFFFFF'; size=2>loading</font>")
+ widgetList = [main, self._arrow(), newBackup, self._arrow(), files,
+ self._arrow(), folder, self._arrow(), loading]
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+ if name != "":
+ newLabel = QLabel("<font style='color: #FFFFFF'; size=2>"+ name +"</font>")
+ self.barLayout.addWidget(self._arrow(), Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+ self.barLayout.addWidget(newLabel, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _manageDialog(self):
+ if self.lockMenuButtons == False:
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard.geometry())
+ backupManager.show()
+ self.close()
+ self.wizard.close()
+ self.lockMenuButtons = True
+ self._resetPage()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if self.lockMenuButtons == False:
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard.geometry())
+ restoreBackup.show()
+ self.wizard.close()
+ self.close()
+ self.lockMenuButtons = True
+ self._resetPage()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Do backup from Device to your PC.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _resetPage(self):
+ self.lockMenuButtons = True
+ self.cancelButton.setVisible(True)
+ self.doneButton.setVisible(False)
+ self.progressBar.setValue(0)
+ self.progressReport.setText("")
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup starting...</font>")
+
+ def _createCenterLayout(self):
+ gridLayout = QGridLayout()
+ gridLayout.setMargin(27)
+
+ self.categoryLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup starting...</font>")
+
+ bgLabel = QLabel()
+ bgLabel.setPixmap(QPixmap(PROGRESS_BAR_BG))
+ grid = QGridLayout()
+
+ self.progressBar = QProgressBar()
+ self.progressBar.setObjectName("progressBarWizard")
+ self.progressBar.setValue(0)
+ self.progressBar.setTextVisible(False)
+
+ grid.addWidget(bgLabel, 0, 0, Qt.AlignCenter)
+ grid.addWidget(self.progressBar, 0, 0, Qt.AlignCenter)
+
+ self.progressReport = QLabel("")
+
+ self.cancelButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.cancelButton.setShortcut(Qt.Key_Return)
+ self.doneButton.setVisible(False)
+ self.doneButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+# self.completeReportButton.setStyleSheet()
+
+ gridLayout.setSpacing(3)
+ gridLayout.addWidget(self.categoryLabel, 0, 0, Qt.AlignRight)
+ gridLayout.addLayout(grid, 1, 0)
+ gridLayout.addWidget(self.progressReport, 2, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.cancelButton, 3, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.doneButton, 3, 0, Qt.AlignRight)
+
+ return gridLayout
+
+ def progressCanceled(self):
+ self.progressDone(True)
+
+ def progressDone(self, cancel=False):
+ self.lockMenuButtons = False
+ self.cancelButton.setVisible(False)
+ self.doneButton.setVisible(True)
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup finished.</font>")
+ if not cancel:
+ totalSize = "%.2f" % (self.totalSize/(1024.0**2))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(self.backedUpNumber) +\
+ " Files - " + totalSize + " MB</font>")
+ else:
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2> Canceled")
+ self.categoryLabel.setText("")
+ self.progressBar.setValue(100)
+
+
+ self.infLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select an action</font>")
+
+ def updateInfo(self, totalSize, backedUpNumber):
+ self.totalSize = totalSize
+ self.backedUpNumber = backedUpNumber
+
+ def setProgress(self, progress):
+ self.progressBar.setValue(progress)
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(int(progress))+\
+ "% Complete</font>")
+
+ def setCategory(self, category):
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2> Category name: "\
+ + category +"</font>")
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from functools import partial
+
+from ui.pcsuiutils import *
+from ui.tsuigeneralmethods import *
+
+from style.styleTabletSuite import *
+
+from backup.pcsbackupmanager import PcsBackupManager, DEVICES_POINT, USER_HOST
+from backup.pcspcbackupmanager import PcsPcBackupManager
+from backup.pcsdevicebackupmanager import PcsDeviceBackupManager
+from pcsbackuplistui import PCSBackupListUi
+from pcsprogressdialog import PcsProgressDialog
+from pcsrestoredialog import PcsRestoreDialog
+from pcsbackuputils import *
+
+
+class PcsRestoreBackupUi(QDialog):
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ super(PcsRestoreBackupUi, self).__init__(parent)
+ self.deviceInfo = deviceInfo
+
+ self.windowManager = windowManager
+ self.pcBackupManager = PcsPcBackupManager()
+ self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
+ self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
+
+ self._buttonRestoreI = QPushButton("Restore")
+ self.connect (self._buttonRestoreI, SIGNAL("clicked()"), self._openRestoreBackup)
+ self._buttonRestoreII = QPushButton("Restore")
+ self.connect (self._buttonRestoreII, SIGNAL("clicked()"), self._openRestoreBackup)
+ self._buttonView = QPushButton("View")
+ self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
+
+ self.pcListView = PCSBackupListUi(self.pcBackupManager)
+
+ self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ self.vLayout = QVBoxLayout()
+
+ self._insertLayout()
+
+ def _createCenterLayout(self):
+ self.deviceListView.updateBackupList()
+ tab = QTabBar()
+ tab.setObjectName("restoreTabs")
+ self.tabBar = QTabWidget()
+ self.tabBar.setTabBar(tab)
+ self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
+ self.tabBar.setObjectName("tabBar")
+ self.tabBar.addTab(self._createPcListViewWidget(), "PC Backups")
+ self.tabBar.addTab(self._createDeviceListViewWidget(), "Device Backups")
+ self.connect(self.tabBar, SIGNAL("currentChanged(int)"),
+ self._updateButtonsState)
+
+ layout = QVBoxLayout()
+ layout.addWidget(self.tabBar)
+
+ return layout
+
+ def _createButtons(self, pcFlag = False):
+ buttonBox = QHBoxLayout()
+ self._buttonRestoreI.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonRestoreI.setDisabled(True)
+ self._buttonRestoreII.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonRestoreII.setDisabled(True)
+ self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonView.setDisabled(True)
+
+ if pcFlag:
+ buttonBox.addWidget(self._buttonView)
+ buttonBox.addWidget(self._buttonRestoreI)
+ else:
+ buttonBox.addWidget(self._buttonRestoreII)
+
+ return buttonBox
+
+ def _createPcListViewWidget(self):
+ self.pcListView.setObjectName("ListView")
+ pcListViewSelectionModel = self.pcListView.selectionModel()
+ self.connect(pcListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ self.pcListView.updateBackupList()
+
+ panel = QWidget()
+ panel.setAttribute(Qt.WA_NoSystemBackground)
+ panel.setObjectName("DeviceListPanel")
+ vLay = QVBoxLayout()
+
+ vLay.addWidget(self.pcListView)
+ vLay.addLayout(self._createButtons(True))
+ panel.setLayout(vLay)
+
+ return panel
+
+ def _createDeviceListViewWidget(self):
+ self.deviceListView.setObjectName("ListView")
+ deviceListViewSelectionModel = self.deviceListView.selectionModel()
+ self.connect(deviceListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ self.deviceListView.updateBackupList()
+
+ panel = QWidget()
+ panel.setAttribute(Qt.WA_NoSystemBackground)
+ panel.setObjectName("DeviceListPanel")
+ vLay = QVBoxLayout()
+
+ vLay.addWidget(self.deviceListView)
+ vLay.addLayout(self._createButtons())
+ panel.setLayout(vLay)
+
+ return panel
+
+
+ def _insertLayout(self):
+
+ self.vLayout.setMargin(0)
+ self.wayLayout = self._wayLayout()
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 6)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ spc = QSpacerItem(0, 5)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+ spc = QSpacerItem(0, 8)
+ self.vLayout.addItem(spc)
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED)]
+
+ buttonsLayout = QHBoxLayout()
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 2:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ spc = QSpacerItem(8, 0)
+ self.barLayout.addItem(spc)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ restore = QLabel("<font style='color: #FFFFFF'; size=2> Restore backups</font>")
+ spc = QSpacerItem(2, 0)
+ widgetList = [main, self._arrow(), restore]
+
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.geometry())
+ backupManager.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _newBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ newBackup = self.windowManager.getNewBackup()
+ centralize(newBackup)
+ newBackup.setGeometry(self.geometry())
+ newBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the backup you wish to restore.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ spc = QSpacerItem(15, 0)
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _updateButtonsState(self, index):
+ list = self._currentBackupList()
+ selectionModel = list.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ if len(indexList) <> 1:
+ self._buttonView.setDisabled(True)
+ self._buttonRestoreI.setDisabled(True)
+ self._buttonRestoreII.setDisabled(True)
+ else:
+ self._buttonView.setEnabled(True)
+ self._buttonRestoreI.setEnabled(True)
+ self._buttonRestoreII.setEnabled(True)
+
+ def _currentBackupList(self):
+ if self.tabBar.currentIndex() == 0:
+ return self.pcListView
+ else:
+ return self.deviceListView
+
+
+ def doRestoreBackup(self, categories):
+ if self._currentBackupList() == self.pcListView:
+ manager = self.pcBackupManager
+ else:
+ manager = self.deviceBackupManager
+
+ self.restoreBackupThread = RestoreBackupThread(self, manager, categories)
+ self.restoreBackupThread.start()
+ self._runRestoreProgress()
+ self.connect(self.restoreBackupThread, SIGNAL("restoreProgress"),
+ self._updateCategoriesAndProgress)
+ self.connect(self.restoreBackupThread, SIGNAL("restoreDone"),
+ self._onRestodeDone)
+ self.connect(self.restoreBackupThread, SIGNAL("openFileError"),
+ self._onOpenFileError)
+
+ def _openRestoreBackup(self):
+ backup = self._currentBackupList().getSelectedBackup()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.loadBackups()
+ backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+ else:
+ self.deviceBackupManager.loadBackups()
+ backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+
+ host_ip = self.deviceInfo.ip
+ devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
+ mountPath = os.path.join(devicePath, "Root" )
+ mountDevice(USER_HOST, host_ip, mountPath)
+ list = getBackupCategories(backupInfo)
+ unmountDevice(mountPath)
+
+ self.restoreDialog = PcsRestoreDialog(self.deviceInfo, list, self)
+ self.connect(self.restoreDialog.buttonCancel, SIGNAL("clicked()"),
+ self.restoreDialog.close)
+
+ self.connect(self.restoreDialog.buttonOk, SIGNAL("clicked()"),
+ self._doRestoreAndCloseDialog)
+ self.restoreDialog.exec_()
+
+
+ def _doRestoreAndCloseDialog(self):
+ categories = self.restoreDialog.getCategories()
+ self.restoreDialog.close()
+ self.doRestoreBackup(categories)
+
+ def _doRestoreBackup(self, categories):
+ selectedBackups = self._currentBackupList().getSelectedBackupList()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.loadBackups()
+ for backup in selectedBackups:
+ backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+ ip = self.deviceBackupManager._deviceInfo.ip
+ self.emit(SIGNAL("restoreStarted"))
+ result = self.pcBackupManager.startBackupRestore(backupInfo, ip,
+ categories)
+ if result == False or result == 0:
+ return result
+ else:
+ self.deviceBackupManager.loadBackups()
+ for backup in selectedBackups:
+ backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+ self.emit(SIGNAL("restoreStarted"))
+ result = self.deviceBackupManager.startBackupRestore(backupInfo,
+ categories)
+ if result == False or result == 0:
+ return result
+ return True
+
+ def showRestoreMessage(self, done):
+ if done != 0:
+ self._progressDialog.cancel()
+ ip = self.deviceBackupManager._deviceInfo.ip
+ if done:
+ doneMessage = "Restore done. Your device will be rebooted now"
+ showMessageBox(doneMessage, "Restore successfully Done")
+ rebootDevice(ip)
+ else:
+ showMessageBox("An error occurred while restoring backup",
+ "Restore error")
+
+ def _doViewBackup(self):
+ list = self._currentBackupList()
+ backupManager = list.getBackupManager()
+ backupName = (str(list.getSelectedBackup())).strip()
+ if backupName == None:
+ return False
+
+ dialog = QDialog(self, Qt.FramelessWindowHint)
+ dialog.setObjectName("viewDialog")
+ dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ dialog.setWindowTitle("Backup Files")
+ dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+
+ layout = QVBoxLayout()
+ layout.setMargin(10)
+ listWidget = QListWidget()
+ listWidget.setObjectName("viewList")
+ listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ backupContentList = backupManager.listBackupContent(backupName)
+ if not backupContentList:
+ showMessageBox("Could not open backup files", "Error")
+ return False
+ for backupContent in backupContentList:
+ backup_button = QListWidgetItem()
+ backup_button.setText(backupContent)
+ listWidget.addItem(backup_button)
+
+ okButton = QPushButton("OK")
+ okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
+ visible = partial(dialog.setVisible, False)
+ self.connect(okButton, SIGNAL("clicked()"), visible)
+ hLay = QHBoxLayout()
+ hLay.addItem(QSpacerItem(200,0))
+ hLay.addWidget(okButton)
+ layout.addWidget(listWidget)
+ layout.addLayout(hLay)
+ dialog.setLayout(layout)
+ dialog.show()
+
+ def _runRestoreProgress(self):
+ self._progressDialog = PcsProgressDialog(self)
+ self._progressDialog.setAction("restore")
+ self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
+ self._onRestoreCancel)
+
+ self._progressDialog.show()
+
+ def _updateCategoriesAndProgress(self, information):
+ progress, category, self.numberOfFiles, self.totalSize = information
+
+ self._progressDialog.setProgress(progress)
+ self._progressDialog.setCategory(category)
+
+ def _onRestodeDone(self):
+ self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
+ self._progressDialog.progressDone()
+
+ def _onRestoreCancel(self):
+ self._progressDialog.progressCanceled()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.setRestoreInProgress(False)
+ else:
+ self.deviceBackupManager.setRestoreInProgress(False)
+
+ def _onOpenFileError(self):
+ self._progressDialog.close()
+ showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
+
+class RestoreBackupThread(QThread):
+ def __init__(self, restoreBackup, manager, categories):
+ QThread.__init__(self)
+ self.restoreBackup = restoreBackup
+ self.categories = categories
+ self.connect(manager, SIGNAL("restoreProgress"), self._reEmitSignal)
+
+ def _reEmitSignal(self, informations):
+ self.emit(SIGNAL("restoreProgress"), informations)
+
+ def run(self):
+ try:
+ done = self.restoreBackup._doRestoreBackup(self.categories)
+ except IOError:
+ self.emit(SIGNAL("openFileError"))
+ return
+ self.emit(SIGNAL("restoreDone"))
+
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from style.styleTabletSuite import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+
+class PcsRestoreDialog(QDialog):
+
+ def __init__(self, deviceInfo, categoriesList, parent = None):
+ QDialog.__init__(self, parent, Qt.FramelessWindowHint)
+ self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
+ self.setFixedSize(200, 300)
+ self.deviceInfo = deviceInfo
+ self.categories = categoriesList
+ self.validPositions = []
+ self.validCategories = []
+
+ self.layout = QVBoxLayout()
+
+ self.labelLayout = QHBoxLayout()
+ spc = QSpacerItem(15, 0)
+ self.labelLayout.addItem(spc)
+ label = QLabel("Which categories you want to restore?")
+ label.setWordWrap(True)
+ self.labelLayout.addWidget(label)
+ self.labelLayout.setMargin(0)
+ self.layout.addLayout(self.labelLayout)
+
+# self.grid = QGridLayout()
+# self.create_dialog()
+# self.grid.setMargin(0)
+# self.layout.addLayout(self.grid)
+ self.create_checkbox_frame()
+
+ self.buttonLayout = QHBoxLayout()
+ self.create_buttons()
+ self.buttonLayout.setMargin(0)
+ self.layout.addLayout(self.buttonLayout)
+
+ self.setLayout(self.layout)
+ self.map_checked = {self.documents.name: False,
+ self.emails.name: False, self.media.name: False,
+ self.contacts.name: False,
+ self.bookmarks.name: False,
+ self.settings.name: False,
+ self.applications.name: False}
+
+ def empty_map(self):
+ for index in self.map_checked.keys():
+ if self.map_checked[index]:
+ return False
+ return True
+
+ def create_buttons(self):
+ self.buttonOk = QPushButton("Ok")
+ self.buttonOk.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.buttonLayout.addWidget(self.buttonOk)
+
+ self.buttonCancel = QPushButton("Cancel")
+ self.buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.buttonLayout.addWidget(self.buttonCancel)
+
+ def create_checkbox_frame(self):
+ layout = QVBoxLayout()
+ l = QLabel()
+ l.setPixmap(QPixmap(COPY_BORDER))
+
+ self.frame = QScrollArea(self)
+ self.frame.setObjectName("restoreScroll")
+ self.frame.setWidgetResizable(True)
+ widget = QWidget(self.frame)
+ widget.setStyleSheet("QWidget{background: transparent;}")
+ self.grid = QGridLayout()
+ self.grid.setSpacing(0)
+ self.create_dialog()
+ widget.setLayout(self.grid)
+ self.frame.setWidget(widget)
+ layout.addWidget(self.frame)
+ self.layout.addLayout(layout)
+
+ def create_dialog(self):
+ #Add Checkboxes
+# self.add_select_all()
+ self.add_documents()
+ self.add_emails()
+ self.add_media()
+ self.add_contacts()
+ self.add_bookmarks()
+ self.add_settings()
+ self.add_applications()
+
+# def add_select_all(self):
+# self.select_all = QCheckBox("Select All")
+# self.connect(self.select_all, SIGNAL("stateChanged(int)"),
+# self.select_all_func)
+# self.validPositions.append((1,0))
+# self.grid.addWidget(self.select_all, 1, 0, Qt.AlignTop)
+#
+ def add_documents(self):
+ self.documents = QCheckBox("Documents")
+ self.documents.name = "documents"
+ callback = partial(self.select_func, self.documents)
+ self.connect(self.documents, SIGNAL("stateChanged(int)"),
+ callback)
+ if "documents" in self.categories:
+ self.validPositions.append((2, 0))
+ self.grid.addWidget(self.documents, 2, 0, Qt.AlignTop)
+
+ def add_emails(self):
+ self.emails = QCheckBox("Emails")
+ self.emails.name = "emails"
+ callback = partial(self.select_func, self.emails)
+ self.connect(self.emails, SIGNAL("stateChanged(int)"),
+ callback)
+ if "emails" in self.categories:
+ self.validPositions.append((3, 0))
+ self.grid.addWidget(self.emails, 3, 0, Qt.AlignTop)
+
+ def add_media(self):
+ self.media = QCheckBox("Media")
+ self.media.name = "media"
+ callback = partial(self.select_func, self.media)
+ self.connect(self.media, SIGNAL("stateChanged(int)"),
+ callback)
+ if "media" in self.categories:
+ self.validPositions.append((4, 0))
+ self.grid.addWidget(self.media, 4, 0, Qt.AlignTop)
+
+ def add_contacts(self):
+ self.contacts = QCheckBox("Contacts")
+ self.contacts.name = "contacts"
+ callback = partial(self.select_func, self.contacts)
+ self.connect(self.contacts, SIGNAL("stateChanged(int)"),
+ callback)
+ if "contacts" in self.categories:
+ self.validPositions.append((5, 0))
+ self.grid.addWidget(self.contacts, 5, 0, Qt.AlignTop)
+
+ def add_bookmarks(self):
+ self.bookmarks = QCheckBox("Bookmarks")
+ self.bookmarks.name = "bookmarks"
+ callback = partial(self.select_func, self.bookmarks)
+ self.connect(self.bookmarks, SIGNAL("stateChanged(int)"),
+ callback)
+ if "bookmarks" in self.categories:
+ self.validPositions.append((6, 0))
+ self.grid.addWidget(self.bookmarks, 6, 0, Qt.AlignTop)
+
+ def add_settings(self):
+ self.settings = QCheckBox("Settings")
+ self.settings.name = "settings"
+ callback = partial(self.select_func, self.settings)
+ self.connect(self.settings, SIGNAL("stateChanged(int)"),
+ callback)
+ if "settings" in self.categories:
+ self.validPositions.append((7, 0))
+ self.grid.addWidget(self.settings, 7, 0, Qt.AlignTop)
+
+ def add_applications(self):
+ self.applications = QCheckBox("Applications")
+ self.applications.name = "applications"
+ callback = partial(self.select_func, self.applications)
+ self.connect(self.applications, SIGNAL("stateChanged(int)"),
+ callback)
+ if "applications" in self.categories:
+ self.validPositions.append((8, 0))
+ self.grid.addWidget(self.applications, 8, 0, Qt.AlignTop)
+
+# def select_all_func(self):
+# checked = self.select_all.isChecked()
+# list = self.map_checked.keys()
+# for element in list:
+# self.map_checked[element] = checked
+# for tuple in self.validPositions:
+# self.grid.itemAtPosition(tuple[0], tuple[1]).widget().setChecked(checked)
+#
+ def select_func(self, checkbox):
+ checked = checkbox.isChecked()
+ self.map_checked[checkbox.name] = checked
+ if not checked:
+ list = []
+ for tuple in self.validPositions:
+ item = self.grid.itemAtPosition(tuple[0], tuple[1]).widget()
+# if item == self.select_all:
+# pass
+ if item.isChecked():
+ list.append(item)
+# self.select_all.setChecked(False)
+ for element in list:
+ element.setChecked(True)
+
+ def getCategories(self):
+ return self.map_checked
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from pcsbackupwizard import PcsBackupWizard
+from pcsrestorebackupui import PcsRestoreBackupUi
+from pcsbackupmanagerui import PcsBackupManagerUi
+
+class PcsWindowManager:
+ class _impl:
+ def __init__(self, deviceInfo, parent = None):
+ self.__newBackup = PcsBackupWizard(deviceInfo, self, parent)
+ self.__restoreBackup = PcsRestoreBackupUi(deviceInfo, self, parent)
+ self.__backupManager = PcsBackupManagerUi(deviceInfo, self, parent)
+
+ def getNewBackup(self):
+ return self.__newBackup
+
+ def getRestoreBackup(self):
+ return self.__restoreBackup
+
+ def getBackupManager(self):
+ return self.__backupManager
+
+ __instance = None
+
+ def __init__(self, deviceInfo = None, parent = None):
+ if PcsWindowManager.__instance is None:
+ PcsWindowManager.__instance = PcsWindowManager._impl(deviceInfo, parent)
+ self.__dict__['Singleton_instance'] = PcsWindowManager.__instance
+
+ def __getattr__(self, attr):
+ return getattr(self.__instance, attr)
+
+ def __setattr__(self, attr, value):
+ return setattr(self.__instance, attr, value)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsapp import PcsApp
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+from ui.pcsbutton import *
+from ui.tsuigeneralmethods import *
+
+from ui.pcscustombuttons import PcsCustomButton as customButton
+
+from pcswindowmanager import *
+
+class PcsBackup(PcsApp):
+
+ def __init__(self, deviceInfo, parent=None):
+ PcsApp.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+
+ if (self.deviceInfo != None):
+ self.windowManager = PcsWindowManager(self.deviceInfo, self)
+
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup" % APPLICATION_NAME)
+
+ self.hLayout = QHBoxLayout()
+ self.hLayout.setMargin(8)
+ self.vLayout = QVBoxLayout()
+
+ spc = QSpacerItem(0,50)
+ self.optionsLayout = QVBoxLayout()
+ self.optionsLayout.addItem(spc)
+ self._addButtons()
+ self.optionsLayout.addItem(spc)
+
+ self.deviceWidget = PcsDeviceWidget(1)
+ self.deviceWidget.addBorder()
+ self.deviceWidget.addDeviceName()
+ self.deviceWidget.setDeviceInfo(self.deviceInfo)
+
+ self.optionsBorderLayout = QGridLayout()
+ self.optionsBorderLabel = QLabel()
+ self.optionsBorderLabel.setFixedSize(208, 205)
+ self.optionsBorderLabel.setPixmap(QPixmap(DEVICE_BACKUP_BORDER))
+ self.optionsBorderLayout.addWidget(self.optionsBorderLabel, 0, 0, Qt.AlignCenter)
+ self.optionsBorderLayout.addLayout(self.optionsLayout, 0, 0, Qt.AlignCenter)
+ self.hLayout.addLayout(self.optionsBorderLayout)
+ self.hLayout.addWidget(self.deviceWidget)
+
+ #FIXE ME
+ l1 = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ self.vLayout.addItem(TOP_SPACER)
+ self.vLayout.addWidget(l1)
+ self.vLayout.addLayout(self.hLayout)
+ informationLayout = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ information = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select an action.</font>")
+ informationLayout.addItem(spc)
+ informationLayout.addWidget(iconAlert)
+ informationLayout.addWidget(information, Qt.AlignLeft)
+ self.vLayout.addLayout(informationLayout)
+ self.vLayout.setMargin(8)
+ self.setLayout(self.vLayout)
+
+ def openBackupWizard(self):
+
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backup_wizard = self.windowManager.getNewBackup()
+ centralize(backup_wizard)
+ backup_wizard.setGeometry(self.geometry())
+ backup_wizard.exec_()
+ self.setVisible(False)
+ self.setGeometry(backup_wizard.geometry())
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def openBackupManagerDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.show()
+ self.setVisible(False)
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def openRestoreBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.show()
+ self.setVisible(False)
+ else:
+ showMessageBox("No devices were found.", "")
+
+ def _addButtons(self):
+ infList = [("New Backup ", ICON_NEW_BACKUP),
+ ("Manage Backups", ICON_MANAGER_BACKUP),
+ ("Restore Backups ", ICON_RESTORE_BACKUP)]
+ buttonsList = []
+ for inf in infList:
+ buttonOptions = PcsButton(inf[0])
+ buttonOptions.setStyleSheet("background-image\
+ :url("+ BUTTON_WITH_ICON_BG +");\
+ qproperty-icon:url("+inf[1]+");\
+ min-height:50px; min-width:188px;\
+ max-height:50px; max-width:188px;\
+ qproperty-iconSize: 43px 36px")
+ self.optionsLayout.addWidget(buttonOptions)
+ buttonsList.append(buttonOptions)
+
+ self.connect(buttonsList[0], SIGNAL("clicked()"),
+ self.openBackupWizard)
+ self.connect(buttonsList[1], SIGNAL("clicked()"),
+ self.openBackupManagerDialog)
+ self.connect(buttonsList[2], SIGNAL("clicked()"),
+ self.openRestoreBackupDialog)
+
--- /dev/null
+import time
+from datetime import datetime
+
+class PcsBackupInfo:
+ """Class that represents a backup
+
+ Attributes:
+ _name -- Backup name
+ path -- Backup directory path
+ date -- Date when backup was created
+ _comment -- Any comment about backup
+ size -- Backup file size
+ files_number = total number of backup files
+ _time = time object was created in seconds since epoch
+
+ """
+
+ def __init__(self, name, path, size, comment=""):
+ """Initialize object attributes."""
+ self._name = name
+ self.path = path
+ self._time = time.time()
+ self.date = datetime.fromtimestamp(self._time).replace(microsecond=0)
+ self.size = size
+ self.files_number = 0
+ self._comment = comment
+ self.fromDevice = False
+
+ def getPath(self):
+ """Return object path."""
+ return self.path
+
+ def getName(self):
+ """Return object name."""
+ return self._name
+
+ def getDate(self):
+ """Return object creation date."""
+ return self.date
+
+ def getComment(self):
+ """Return object _comment attribute."""
+ return self._comment
+
+ def getSize(self):
+ """Return object file size."""
+ return self.size
+
+ def getTime(self):
+ """ Returns the object creation time in seconds since epoch. """
+ return self._time
+
+ def getFilesNumber(self):
+ """ Return number of files this backup holds. """
+ return self.files_number
+
+ def setComment(self, new_comment):
+ """Set object _comment attribute to the given string"""
+ self._comment = new_comment
+
+ def setName(self, new_name):
+ """Set object name to a new name"""
+ self._name = new_name
+
+ def setDate(self, newDate):
+ self.date = newDate
+
+ def setFilesNumber(self, number_of_files):
+ """ Set number of files this backup holds to number_of_files ."""
+ self.files_number = number_of_files
+
+ def setAtDevice(self, bool=False):
+ self.fromDevice = bool
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PCSBackupListUi(QTableView):
+
+ ''' Class that creates a table, where the backups will be shown '''
+
+ def __init__(self, backupManager):
+ super(PCSBackupListUi, self).__init__()
+
+ self.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.setSelectionMode(QAbstractItemView.ExtendedSelection)
+ self.setAlternatingRowColors(True)
+ self.setShowGrid(False)
+ self.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.model = QStandardItemModel()
+ self.setModel(self.model)
+
+ hHeader = QHeaderView(Qt.Horizontal)
+ hHeader.setObjectName("listHeader")
+ hHeader.setAttribute(Qt.WA_NoSystemBackground)
+ hHeader.setStretchLastSection(True)
+ hHeader.setResizeMode(QHeaderView.ResizeToContents)
+ hHeader.setMinimumSectionSize(100)
+
+ hHeader.setClickable(False)
+
+ self.setHorizontalHeader(hHeader)
+
+ vHeader = QHeaderView(Qt.Vertical)
+ vHeader.setVisible(False)
+ self.setVerticalHeader(vHeader)
+ self._backupManager = backupManager
+
+ def updateBackupList(self):
+ self.model.clear()
+ self.model.setHorizontalHeaderItem(0, QStandardItem("NAME"))
+ self.model.setHorizontalHeaderItem(1, QStandardItem("SIZE"))
+ self.model.setHorizontalHeaderItem(2, QStandardItem("DATE"))
+
+ backupList = self._backupManager.getBackupList()
+ for backupInfo in backupList:
+ name = backupInfo.getName()
+ date = str(backupInfo.getDate())
+ size = self._formatBackupSize(backupInfo.getSize())
+ backupData = [QStandardItem(name), QStandardItem(size), QStandardItem(date)]
+ self.model.appendRow(backupData)
+
+ def removeSelectedBackups(self):
+ selectionModel = self.selectionModel()
+ indexList = selectionModel.selectedRows()
+ for index in reversed(sorted(indexList)):
+ if index.isValid():
+ row = index.row()
+ data = self.model.itemData(index)
+ backupName = data[0].toString()
+ if self._backupManager.removeBackup((str(backupName).strip())):
+ self.model.removeRow(row)
+ self.updateBackupList()
+
+ def renameSelectedBackup (self, newName):
+ #!!!!!!! getSelectedBackup
+ backupName = (str(self.getSelectedBackup())).strip()
+ if backupName != None:
+ if self._backupManager.renameBackup(backupName, newName):
+ self.updateBackupList()
+ return True
+
+ return False
+
+ def getSelectedBackup(self):
+ list = self.getSelectedBackupList()
+ if list and len(list) > 0:
+ return list[0]
+
+ return None
+
+ def getSelectedBackupList(self):
+ selectionModel = self.selectionModel()
+ indexList = selectionModel.selectedRows()
+ backupList = []
+ for index in indexList:
+ if index.isValid():
+ row = index.row()
+ data = self.model.itemData(index)
+ backupList.append(data[0].toString())
+ return backupList
+
+ def getBackupManager(self):
+ return self._backupManager
+
+ def _formatBackupSize(self, size):
+ """ Return a string with a more suited size and byte multiple for the
+ received size.
+
+ Attributes:
+ String/Float/Int size - size in bytes or string representing it.
+
+ """
+ size = float(size)
+ multiples = ["B", "KB", "MB", "GB"]
+ divisions = 0
+ while size > 1000 and divisions <= 3:
+ size = size / 1024.
+ divisions += 1
+
+ return "%.1f %s" % (size, multiples[divisions])
--- /dev/null
+# Class Backup_Category holds osso-backup .conf files informations
+
+class PcsBackupLocation:
+ """Backup_Location class.
+ Used for holding location attributes from parsed osso-backup xml files.
+
+ """
+ def __init__(self, type, category, path):
+ self.category = category
+ self.type = type
+ self.path = path
--- /dev/null
+import os
+
+from PyQt4.QtCore import *
+from zipfile import *
+
+import pcsbackuputils as utils
+
+
+HOME = os.path.expanduser("~")
+USER_HOST = "root"
+DEVICES_POINT = "%s/.pcsuite/devices/" % HOME
+
+
+class PcsBackupManager(QObject):
+
+ def __init__(self):
+ QObject.__init__(self)
+ self._backupList = []
+
+ def loadBackups(self):
+ return False
+
+ def saveBackups(self):
+ return False
+
+ def getBackupList(self):
+ return None
+
+ def createBackup(self, backup_name, path, host_ip, categories, comment=""):
+ return False
+
+ def removeBackup(self, backup_name):
+ return False
+
+ def getBackupInfo(self, backupName):
+ return None
+
+ def renameBackup(self, backupName, newName):
+ return False
+
+ def changeBackupComment(self, backupName, new_comment):
+ return False
+
+ def listBackupContent(self, backupName):
+ content = []
+ backupInfo = self.getBackupInfo(backupName)
+ backupPath = backupInfo.getPath()
+ fullPath = os.path.join(str(backupPath), str(backupName))
+
+ for entry in os.listdir(fullPath):
+ if entry.endswith(".zip"):
+ zipfile = utils.openZip(os.path.join(fullPath, entry), "r")
+ for member in zipfile.namelist():
+ folders = member.split("/")
+ memberName = "../" + "/".join([folders[-2], folders[-1]])
+ content.append(memberName)
+ return content
+
+ def restoreBackup(self, backupInfo, host_ip, categories):
+ """ Restore a PC backup to device with given IP address.
+
+ Attributes:
+ String backupInfo - Object representing the backup
+ String host_ip - IP address of device.
+ Dictionary categories - dictionary with categories as keys and with
+ value True if that category should be restored.
+
+ """
+ self.setRestoreInProgress(True)
+ # Set restore needed paths
+ devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
+ mountPath = os.path.join(devicePath, "Root" )
+ tempPath = os.path.join(mountPath, "tmp/paths")
+ restScriptsPath = ("/etc/osso-backup/restore.d/always")
+ try:
+ utils.mountDevice(USER_HOST, host_ip, mountPath)
+ # Get backup location depending from backup source
+ if backupInfo == None:
+ return False
+ if backupInfo.fromDevice:
+ backup_path = backupInfo.getPath()
+ else:
+ backup_path = os.path.join(str(backupInfo.getPath()),
+ str(backupInfo.getName()))
+ # Get backup files list for each category and write it on a file
+ # that will be needed by restore scripts.
+ pathsDictonary = utils.getBackupFilesPath(backup_path)
+ if utils.writeBackupFilesPath(pathsDictonary, tempPath) == False:
+ return False
+ # --- Initialize restore progress ---
+ currentSize = 0
+ # Get total number of files to restore
+ numberOfFiles = 0
+ for categ in pathsDictonary:
+ for file in pathsDictonary[categ]:
+ numberOfFiles += 1
+ # Get size of all categories being restored
+ totalSize = 0
+ for file in os.listdir(backup_path):
+ if file.endswith(".zip"):
+ categ = file[:-4]
+ if categories[categ]:
+ catPath = os.path.join(backup_path, file)
+ zip = utils.openZip(catPath)
+ for member in zip.namelist():
+ totalSize += zip.getinfo(member).file_size
+ # Extract zip files to device
+ for entry in os.listdir(backup_path):
+ category = entry[:-4]
+ if entry.endswith(".zip") and categories[category]:
+ zipPath = os.path.join(backup_path, entry)
+ zip = utils.openZip(zipPath)
+ # Update restore progress, extract current f print "member %s: %.2f" % (member, zip.getinfo(member).file_size)ile and emit
+ # progress sinal
+ for member in zip.namelist():
+ if not self.restoreInProgress:
+ return 0
+ percentage = "%.1f" % self.computePercentage(totalSize,
+ currentSize)
+
+ status = (percentage, category, numberOfFiles, totalSize)
+ self.emit(SIGNAL("restoreProgress"), status)
+ zip.extract(member, devicePath)
+ currentSize += zip.getinfo(member).file_size
+ percentage = "%.1f" % ((currentSize / float(totalSize)) * 100)
+ status = (percentage, category, numberOfFiles, totalSize)
+ self.emit(SIGNAL("restoreProgress"), status)
+ zip.close()
+ # Execute restore scripts
+ os.system("ssh %s@%s ..%s/*.sh %s" % (USER_HOST, host_ip,
+ restScriptsPath, tempPath))
+ self.setRestoreInProgress(False)
+ # --- Restore finished ---
+ finally:
+ utils.unmountDevice(mountPath)
+
+
+ def computePercentage(self, totalSize, currentSize):
+ if totalSize == 0:
+ percentage = 100
+ else:
+ percentage = (currentSize / float(totalSize)) * 100
+ if percentage > 100:
+ percentage = 100
+ return percentage
+
+ def copy(self, sourcePath, destinationPath):
+ numberOfFiles = 0
+ for entry in os.listdir(sourcePath):
+ zipPath = os.path.join(sourcePath, entry)
+ if zipPath.endswith(".zip"):
+ zip = utils.openZip(zipPath)
+ numberOfFiles += len(zip.namelist())
+ totalSize = float(utils.getSize(sourcePath))
+ currentSize = 0
+ self.emit(SIGNAL("copyProgress"), ("0.00", numberOfFiles, totalSize))
+ for entry in os.listdir(sourcePath):
+ if not self.copyInProgress:
+ utils.removePath(destinationPath)
+ return 0
+ entryPath = os.path.join(sourcePath, entry)
+ utils.copy(entryPath, destinationPath)
+ currentSize += utils.getSize(entryPath)
+ progress = "%.2f" % ((currentSize / totalSize) * 100)
+ self.emit(SIGNAL("copyProgress"), (progress, numberOfFiles,
+ totalSize))
+
+
\ No newline at end of file
--- /dev/null
+# Software License: GPL
+
+import os
+import sys
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from ui.tsuigeneralmethods import *
+from ui.pcsapp import PcsApp
+from backup.pcsbackuputils import *
+
+from pcsbackuplistui import PCSBackupListUi
+from pcspcbackupmanager import PcsPcBackupManager
+from pcsdevicebackupmanager import PcsDeviceBackupManager
+from pcsprogressdialog import PcsProgressDialog
+from style.styleTabletSuite import *
+
+COPY_BUTTON_ID = 0
+DELETE_BUTTON_ID = 1
+RENAME_BUTTON_ID = 2
+VIEW_BUTTON_ID = 3
+_home_dir = os.path.expanduser("~")
+_default_dir = _home_dir + "/.pcsuite/Backup"
+
+
+class PcsBackupManagerUi(QDialog):
+
+ ''' Class that calls a Backup Pc Suite application
+ with a Table Viewer'''
+
+ def __init__(self, deviceInfo, windowManager, parent=None):
+ QDialog.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup Manager" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ self._home_dir = os.path.expanduser("~")
+ self._default_dir = _home_dir + "/.pcsuite/Backup"
+ self.copyPath = self._default_dir
+ self.name_change = None
+ self._setupUi()
+
+ def _setupUi(self):
+ # Creates the lists
+ self.pcBackupManager = PcsPcBackupManager()
+ self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
+
+ self.pcListView = PCSBackupListUi(self.pcBackupManager)
+ self.pcListView.setObjectName("ListView")
+ # "Update pc list view"
+ pcListViewSelectionModel = self.pcListView.selectionModel()
+ self.connect(pcListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+ self.pcListView.updateBackupList()
+
+ self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
+ self.deviceListView.setObjectName("ListView")
+ deviceListViewSelectionModel = self.deviceListView.selectionModel()
+ self.connect(deviceListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+ # "Update device List view"
+ self.deviceListView.updateBackupList()
+
+ layout = QVBoxLayout()
+ menuLayout = self._menuButtons()
+ layout.addLayout(menuLayout, Qt.AlignTop)
+ wayLayout = self._wayLayout()
+ layout.addLayout(wayLayout, Qt.AlignLeft)
+ layout.addItem(QSpacerItem(0,3))
+ layout.addLayout(self._centerLayout(), Qt.AlignTop)
+
+ layout.addItem(QSpacerItem(0,15))
+ informationLayout = self._createInformationsLabel()
+ layout.addLayout(informationLayout)
+ layout.addItem(QSpacerItem(0,2))
+ self.setLayout(layout)
+
+ def _centerLayout(self):
+ # Creates the tabs
+ layout = QVBoxLayout()
+ tabLayout = QVBoxLayout()
+ tab = QTabBar()
+ tab.setObjectName("managerTabs")
+ self.tabBar = QTabWidget()
+ self.tabBar.setTabBar(tab)
+ self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
+ self.tabBar.setObjectName("tabBar")
+ self.tabBar.addTab(self.pcListView, "PC Backups")
+ self.tabBar.addTab(self.deviceListView, "Device Backups")
+ self.connect(self.tabBar, SIGNAL("currentChanged(int)"), self._updateButtonsState)
+ tabLayout.addWidget(self.tabBar)
+ layout.addLayout(tabLayout)
+ #Spacer
+ layout.addItem(QSpacerItem(0,5))
+ # Creates the buttons
+ buttonBox = QHBoxLayout()
+ self._buttonCopy = QPushButton("Copy")
+ self._buttonCopy.setDisabled(True)
+ self._buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ buttonBox.addWidget(self._buttonCopy)
+ self.connect (self._buttonCopy, SIGNAL("clicked()"), self._doCopyBackup)
+
+ self._buttonDelete = QPushButton("Delete")
+ self._buttonDelete.setDisabled(True)
+ buttonBox.addWidget(self._buttonDelete)
+ self._buttonDelete.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonDelete, SIGNAL("clicked()"), self._doDeleteBackup)
+
+ self._buttonRename = QPushButton("Rename")
+ self._buttonRename.setDisabled(True)
+ buttonBox.addWidget(self._buttonRename)
+ self._buttonRename.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonRename, SIGNAL("clicked()"), self._doRenameBackup)
+
+ self._buttonView = QPushButton("View")
+ self._buttonView.setDisabled(True)
+ buttonBox.addWidget(self._buttonView)
+ self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
+
+ self._buttonUpdate = QPushButton("Update")
+ self._buttonUpdate.setDisabled(False)
+ self._buttonUpdate.setVisible(False)
+ buttonBox.addWidget(self._buttonUpdate)
+ self._buttonUpdate.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect (self._buttonUpdate, SIGNAL("clicked()"), self._doUpdateList)
+
+ layout.addLayout(buttonBox)
+ return layout
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE_SELECTED),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+
+ buttonsLayout = QHBoxLayout()
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 1:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ buttonsLayout.setMargin(0)
+ return buttonsLayout
+
+ def _newBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ newBackup = self.windowManager.getNewBackup()
+ centralize(newBackup)
+ newBackup.setGeometry(self.geometry())
+ newBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.geometry())
+ restoreBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _wayLayout(self):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ spc = QSpacerItem(8, 0)
+ self.barLayout.addItem(spc)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ restore = QLabel("<font style='color: #FFFFFF'; size=2> Manage backups</font>")
+ spc = QSpacerItem(2, 0)
+ widgetList = [main, self._arrow(), restore]
+
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the backup you wish to manipulate.</font>")
+ iconAlert = QLabel()
+ hLay.setMargin(0)
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ spc = QSpacerItem(15, 0)
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _doUpdateList(self):
+ self._currentBackupList().updateBackupList()
+ self._updateButtonsState(0)
+
+ def _execCopyDialogToDevice(self):
+ self._copyDialogToDevice = QDialog(self, Qt.FramelessWindowHint)
+ self._copyDialogToDevice.setObjectName("copyDialogToDevice")
+
+ self.rb1 = QRadioButton()
+ self.rb1.setText("External Memory Card")
+ self.rb2 = QRadioButton()
+ self.rb2.setText("Internal Memory Card")
+
+ layout = QVBoxLayout()
+ layout.addWidget(self.rb1)
+ layout.addWidget(self.rb2)
+
+ buttonCopy = QPushButton("Copy")
+ buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyToDevice)
+ buttonCancel = QPushButton("Cancel")
+ buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogToDevice.close)
+
+ hlay = QHBoxLayout()
+ hlay.addWidget(buttonCancel)
+ hlay.addWidget(buttonCopy)
+ layout.addLayout(hlay)
+ self._copyDialogToDevice.setLayout(layout)
+ self._copyDialogToDevice.exec_()
+
+ def _execCopyDialogFromDevice(self):
+ self._copyDialogFromDevice = QDialog(self, Qt.FramelessWindowHint)
+ self._copyDialogFromDevice.setObjectName("copyDialogFromDevice")
+
+ hLayout = QHBoxLayout()
+ hLayout.setMargin(0)
+ self.textField = QLineEdit(self)
+ buttonOpen = QPushButton()
+ buttonOpen.setObjectName("buttonBrowse")
+ self.connect(buttonOpen, SIGNAL("clicked()"), self._doBrowse)
+ copyPath = str(self._default_dir)
+ self.textField.setReadOnly(True)
+ self.textField.setText(self._default_dir)
+ hLayout.addWidget(self.textField)
+ hLayout.addWidget(buttonOpen)
+
+ message = QLabel("<font style='color: #333333'; size=2> Backup copy destination: </font>")
+ message.setFixedHeight(15)
+
+ layout = QVBoxLayout()
+ layout.addWidget(message)
+ layout.addLayout(hLayout)
+
+ buttonCopy = QPushButton("Copy")
+ buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyFromDevice)
+ buttonCancel = QPushButton("Cancel")
+ buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogFromDevice.close)
+
+ hlay = QHBoxLayout()
+ hlay.addWidget(buttonCancel)
+ hlay.addWidget(buttonCopy)
+ layout.addLayout(hlay)
+ self._copyDialogFromDevice.setLayout(layout)
+ self._copyDialogFromDevice.exec_()
+
+ def _doCopyBackup(self):
+ if self.tabBar.currentIndex() == 0:
+ self._execCopyDialogToDevice()
+ else:
+ self._execCopyDialogFromDevice()
+
+ def doCopy(self, device_ip, backupName, ret, destinationPath):
+ self.copyThread = CopyBackupThread(self, device_ip, backupName, ret, destinationPath)
+ self.copyThread.start()
+ self._runCopyProgress()
+
+ self.connect(self.copyThread, SIGNAL("openFileError"), self._onOpenFileError)
+ self.connect(self.copyThread, SIGNAL("copyProgress"), self._updateProgress)
+ self.connect(self.copyThread, SIGNAL("copyDone"), self._onCopyDone)
+
+ def _doCopyToDevice(self):
+ self._copyDialogToDevice.close()
+ ret = 1
+ if self.rb1.isChecked():
+ ret = 0
+ selectedBackupList = self._currentBackupList().getSelectedBackupList()
+ for backup in selectedBackupList:
+ self.doCopy(self.deviceInfo.ip, str(backup).strip(), ret, "")
+
+ def _doCopyFromDevice(self):
+ self._copyDialogFromDevice.close()
+ if self.copyPath != "":
+ selectedBackupList = self._currentBackupList().getSelectedBackupList()
+ self.name_change = False
+ for backup in selectedBackupList:
+ self.pcBackupManager.loadBackups()
+ self.correct_name = self.pcBackupManager._verify_backup_name(str(backup).strip())
+ self.doCopy(self.deviceInfo.ip, str(backup).strip(), 0, self.copyPath)
+ if self.correct_name != backup:
+ self.name_change = True
+
+ def _showMessageCopyBackupDone(self):
+ if self.name_change == None or not self.name_change:
+ QMessageBox.information(self, "Copy Backup", "Backup(s) copied")
+ else:
+ QMessageBox.information(sopenFileErrorelf, "Copy Backup",
+ "Backup copied with name: %s" % self.correct_name)
+
+ def _doBrowse(self):
+ pathDialog = QFileDialog()
+ prompt = "Select the folder you wish to copy your backup(s):"
+ self.copyPath = pathDialog.getExistingDirectory(self, prompt, self._home_dir)
+ if(self.copyPath != ""):
+ self.textField.setText(self.copyPath)
+
+ def _doRenameBackup(self):
+ res = False
+ (newName, ok) = QInputDialog.getText(self, "Rename Backup", "New Backup Name:",
+ QLineEdit.Normal, QString(),
+ Qt.FramelessWindowHint)
+ if ok:
+ if newName:
+ newName = QString(str(newName).strip())
+ if not newName.isEmpty():
+ list = self._currentBackupList()
+ res = list.renameSelectedBackup(newName)
+ if res:
+ showMessageBox("Backup Renamed", "")
+ else:
+ showMessageBox("Error while renaming the backup", "")
+
+ def _doDeleteBackup(self):
+
+ dialog = QMessageBox()
+ dialog.setText("Remove selected backup?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ list = self._currentBackupList()
+ list.removeSelectedBackups()
+ showMessageBox("Backup Removed", "")
+
+ def _currentBackupList(self):
+ if self.tabBar.currentIndex() == 0:
+ self._buttonRename.setVisible(True)
+ self._buttonDelete.setVisible(True)
+ self._buttonView.setVisible(True)
+ self._buttonUpdate.setVisible(False)
+ return self.pcListView
+ else:
+ self._buttonUpdate.setVisible(True)
+ self._buttonRename.setVisible(False)
+ self._buttonDelete.setVisible(False)
+ self._buttonView.setVisible(False)
+ return self.deviceListView
+
+ def _updateButtonsState(self, index):
+ list = self._currentBackupList()
+ selectionModel = list.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ if len(indexList) != 1:
+ self._buttonRename.setDisabled(True)
+ self._buttonView.setDisabled(True)
+ self._buttonCopy.setDisabled(True)
+ else:
+ self._buttonRename.setEnabled(True)
+ self._buttonView.setEnabled(True)
+ self._buttonCopy.setEnabled(True)
+
+ if len(indexList) == 0:
+ self._buttonDelete.setDisabled(True)
+# self._buttonCopy.setDisabled(True)
+ else:
+ self._buttonDelete.setEnabled(True)
+# self._buttonCopy.setEnabled(True)
+
+
+ def _doViewBackup(self):
+ list = self._currentBackupList()
+ backupManager = list.getBackupManager()
+ backupName = (str(list.getSelectedBackup())).strip()
+ if backupName == None:
+ return False
+
+ dialog = QDialog(self, Qt.FramelessWindowHint)
+ dialog.setObjectName("viewDialog")
+ dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ dialog.setWindowTitle("Backup Files")
+ dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+
+ layout = QVBoxLayout()
+ listWidget = QListWidget()
+ listWidget.setObjectName("viewList")
+ listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ try:
+ backupContentList = backupManager.listBackupContent(backupName)
+ except IOError:
+ showMessageBox(self.openFileError, "Error while opening file")
+ return False
+
+ for backupContent in backupContentList:
+ backup_button = QListWidgetItem()
+ backup_button.setText(backupContent)
+ listWidget.addItem(backup_button)
+
+ okButton = QPushButton("OK")
+ okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
+ visible = partial(dialog.setVisible, False)
+ self.connect(okButton, SIGNAL("clicked()"), visible)
+ hLay = QHBoxLayout()
+ hLay.addItem(QSpacerItem(200,0))
+ hLay.addWidget(okButton)
+
+ layout.addWidget(listWidget)
+ layout.addLayout(hLay)
+ dialog.setLayout(layout)
+ dialog.show()
+
+ def _runCopyProgress(self):
+ self._progressDialog = PcsProgressDialog(self)
+ self._progressDialog.setAction("copy")
+ self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
+ self._onCopyCancel)
+ self._progressDialog.show()
+
+ def _updateProgress(self, information):
+ progress, self.numberOfFiles, self.totalSize = information
+ self._progressDialog.setProgress(progress)
+
+ def _onCopyDone(self):
+ self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
+ self._progressDialog.progressDone()
+ self.pcListView.updateBackupList()
+
+ def _onCopyCancel(self):
+ if self.tabBar.currentIndex() == 0:
+ self.pcBackupManager.setCopyInProgress(False)
+ else:
+ self.deviceBackupManager.setCopyInProgress(False)
+ self._progressDialog.progressCanceled()
+
+ def _onOpenFileError(self):
+ self._progressDialog.close()
+ showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
+
+
+
+class CopyBackupThread(QThread):
+ def __init__(self, manager, deviceIp, backupName, ret, destinationPath ):
+ QThread.__init__(self)
+ self.uiManager = manager
+ self.deviceIp = deviceIp
+ self.backupName = backupName
+ self.memoryCard = ret
+ self.destinationPath = destinationPath
+ self.connect(self.uiManager.pcBackupManager, SIGNAL("copyProgress"),
+ self.reEmit)
+ self.connect(self.uiManager.deviceBackupManager, SIGNAL("copyProgress"),
+ self.reEmit)
+
+ def reEmit(self, inf):
+ self.emit(SIGNAL("copyProgress"), inf)
+
+ def run(self):
+ try:
+ if self.uiManager.tabBar.currentIndex() == 0:
+ manager = self.uiManager.pcBackupManager
+ manager.copyBackupToDevice(self.deviceIp, self.backupName,
+ self.memoryCard)
+ else:
+ manager = self.uiManager.deviceBackupManager
+ manager.copyBackupFromDevice(self.backupName,
+ self.destinationPath)
+
+ except IOError:
+ self.emit(SIGNAL("openFileError"))
+ return
+ self.emit(SIGNAL("copyDone"))
+
+
+
+
--- /dev/null
+# Module used to parse osso-backup xml conf files, retrieving categories and
+# backup paths information
+
+import os.path
+import xml.dom
+import xml.dom.minidom
+
+from pcsbackuplocation import *
+
+
+class PcsBackupParser:
+ """Holds a list of Backup_location objects
+
+ Can parse .conf xml files with osso-backup format at the given path with
+ fill_locations_list, creating Backup_location objects based on type,
+ category and path of each location inside each xml file and then holding
+ all objects in the locations_list attribute.
+
+ """
+ def __init__(self):
+ self.locationsDict = {}
+
+ def getLocationsDict(self):
+ return self.locationsDict
+
+ def addLocation(self, location):
+ """Add a location to locations_list attribute of theis class.
+
+ Arguments:
+ location -- the location object to be added
+
+ """
+ category = location.category
+ if category in self.locationsDict.keys():
+ self.locationsDict[category].append(location)
+ else:
+ self.locationsDict[category] = [location]
+
+ def fillLocationsDict(self, path):
+ """Add all locations that can be found inside xml files of the given
+ path.
+
+ This method reads all .conf files inside the directory path given and
+ puts on its locations_list attribute all the Backup_location objects
+ created with the informations returned from the files parsing.
+
+ Arguments:
+ path -- Path of directory containing files to parse
+
+ """
+ for file in os.listdir(path):
+ if file.endswith(".conf"):
+ locations = self.locationsFromFile(os.path.join(path, file))
+ for location in locations:
+ self.addLocation(location)
+
+ def locationsFromFile(self, xml_file):
+ """Return a list with all locations objects inside the given file.
+
+ The file is parsed and all informations retrieved from it are used to
+ create Backup_location objects and these objects are appended to a list
+ that is returned to caller.
+
+ Arguments:
+ xml_file -- File to parse
+
+ Returns:
+ locations -- List with all Backup_location objects created from file
+
+ """
+ locations_map = self._parser(xml_file)
+ locations = []
+ number_of_locations = len(locations_map["types"])
+ for i in range(number_of_locations):
+ type = locations_map["types"][i]
+ category = locations_map["categories"][i]
+ path = locations_map["paths"][i]
+ path = self._fixPath(path)
+ new_loc = PcsBackupLocation(type, category, path)
+ locations.append(new_loc)
+ return locations
+
+
+ def _parser(self, xml_file):
+ # Parses the xml_file, divide each location element information on a
+ # dictonary with key to respective information.
+ # Dictonary format:
+ # { "types": list of types in order of location appereance,
+ # "categories": list of categories ordered like types
+ # "paths" list of install paths in the same order as the others }
+ dom = xml.dom.minidom.parse(xml_file)
+ types = []
+ categories = []
+ paths = []
+ for node in dom.getElementsByTagName("location"):
+ type = node.getAttribute("type")
+ category = node.getAttribute("category")
+ path = node.childNodes[0].data.strip()
+ types.append(type)
+ categories.append(category)
+ paths.append(path)
+
+ location_map = {"types": types, "categories": categories, "paths": paths}
+ return location_map
+
+ def _fixPath(self, path):
+ # Fix any file path containing device specific constants, modifying
+ # them to its values
+ modifications = {"$HOME":"/home/user", "$USER":"user"}
+ for key in modifications.keys():
+ path = path.replace(key, modifications[key])
+ if not path.startswith("/"):
+ path = "/".join(path)
+ return path
+
--- /dev/null
+
+from pcsbackupinfo import *
+import zipfile
+import os
+import xml.dom.minidom
+
+
+def copyOssoBackupConfigFiles(destination, mountPath):
+ """ Copy all osso-backup .conf files to the given path. The device must be
+ already mounted in the mountPath.
+
+ Attributes:
+ - String mountPath - Path of the folder where the device is mounted
+ - String destination - Destination folder path where config files should be
+ copied to.
+
+ """
+ os.system("cp %s/etc/osso-backup/applications/*.conf %s" %
+ (mountPath, destination))
+
+
+def mountDevice(user, ip, path):
+ # Mount device file system using sshfs in the given path
+ try:
+ if not os.path.exists(path):
+ createFolder(path)
+ os.system('sshfs %s@%s:/ %s' % (user, ip, path))
+ except:
+ raise Exception("Error while mounting device file system")
+
+
+def unmountDevice(path):
+ try:
+ os.system('fusermount -uz %s' % path)
+ except:
+ raise Exception("Error while unmounting device file system")
+
+
+def createFolder(complete_path):
+ if not os.path.exists(complete_path):
+ os.makedirs(complete_path)
+
+ # FIXME
+ return True
+
+
+def removePath(complete_path):
+ for entry in os.listdir(complete_path):
+ if os.path.isdir(entry):
+ removePath(os.path.join(complete_path, entry))
+ else:
+ os.remove(os.path.join(complete_path, entry))
+ os.rmdir(complete_path)
+
+
+def getDeviceBackupList(mountPoint):
+ """This function return a list of backupInfo objects for each backup found
+ in the mount point.
+
+ """
+ deviceBackups = []
+ mmc1 = '%s/media/mmc1/backups' % mountPoint
+ mmc2 = '%s/media/mmc2/backups' % mountPoint
+
+ if os.path.exists(mmc1):
+ deviceBackups += _getDeviceBackupsInfo(mmc1)
+ if os.path.exists(mmc2):
+ deviceBackups += _getDeviceBackupsInfo(mmc2)
+
+ return deviceBackups
+
+
+def copy(original, destination):
+ original = original.replace(" ", "\ ")
+ destination = destination.replace(" ", "\ ")
+ createFolder(destination)
+ os.system("cp %s %s" % (original, destination))
+
+
+def getSize(path):
+ if not os.path.exists(path):
+ return False
+ if os.path.isdir(path):
+ files_and_folders = os.listdir(path)
+ sum_size = 0
+ for entry in files_and_folders:
+ if os.path.isdir(os.path.join(path, entry)):
+ sum_size += getSize(os.path.join(path, entry))
+ else:
+ try:
+ sum_size += os.stat(os.path.join(path, entry)).st_size
+ except:
+ sum_size += 1
+ return sum_size
+ else:
+ return os.stat(path).st_size
+
+
+def getBackupFilesPath(backupPath):
+ dic = {}
+ for entry in os.listdir(backupPath):
+ if entry.endswith(".zip"):
+ zip = openZip(os.path.join(backupPath, entry))
+ dic[entry.replace(".zip", "")] = zip.namelist()
+ return dic
+
+
+def getBackupCategories(backupInfo):
+ backupPath = str(backupInfo.path)
+ if not backupInfo.fromDevice:
+ backupPath = os.path.join(backupPath, str(backupInfo._name))
+ categoriesList = []
+ for entry in os.listdir(backupPath):
+ if entry.endswith(".zip"):
+ categoriesList.append(entry.replace(".zip", ""))
+ return categoriesList
+
+
+def writeBackupFilesPath(paths_dictionary, file_path):
+ try:
+ file = open(file_path, "w")
+ except:
+ return False
+ for category in paths_dictionary.keys():
+ file.write("[" + category + "]\n")
+ for path in paths_dictionary[category]:
+ file.write(path + "\n")
+
+ file.close()
+
+def openZip(zipPath, mode="r"):
+ """ Open a .zip file using python ZipFile library.
+
+ Attributes:
+ String zipPath - The directory path to the file
+ String mode - "w" to open file for writting.
+ "a" to open file for appending.
+ "r" to open file for reading.
+
+ """
+ try:
+ zip = zipfile.ZipFile(zipPath, mode)
+ return zip
+ except zipfile.BadZipfile, msg:
+ raise IOError("Problem while opening %s: %s" % (zipPath, msg))
+ except:
+ raise
+
+def closeZip(zipfile):
+ zipfile.close()
+
+def zip(zipfile, path):
+ # Compress the file in the given path to the zipfile
+ try:
+ zipfile.write(path.encode('UTF'))
+ return True
+ except:
+ return False
+
+def rebootDevice(deviceIp):
+ return os.system("ssh root@%s reboot" % deviceIp) == 0
+
+
+def _parseMetadata(metadata_path):
+ document = xml.dom.minidom.parse(metadata_path)
+ node = document.getElementsByTagName("size")[0]
+ size = int(str(node.firstChild.nodeValue))
+ node = document.getElementsByTagName("timestamp")[0]
+ objDate = datetime.fromtimestamp(float(str(node.firstChild.nodeValue)))
+ return size, str(objDate)
+
+def _getDeviceBackupsInfo(memoryCardPath):
+ deviceBackups = []
+ for backup in os.listdir(memoryCardPath):
+ temporaryFolder = os.path.join(memoryCardPath, backup)
+ if os.path.isdir(temporaryFolder):
+ metadataPath = os.path.join(temporaryFolder,'backup.metadata')
+ if os.path.exists(metadataPath):
+ size, date = _parseMetadata(metadataPath)
+ backupInfo = PcsBackupInfo(backup, temporaryFolder, size)
+ backupInfo.setDate(date)
+ deviceBackups.append(backupInfo)
+ return deviceBackups
+
--- /dev/null
+from time import sleep
+import threading
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+
+from pcsprogresswizard import *
+from pcscheckboxwizard import *
+from pcsopenfilewizard import *
+from pcspcbackupmanager import *
+from pcsdevicemanager import *
+
+class PcsBackupWizard(QWizard):
+
+ ''' Class that creates a wizard responsible for doing backup '''
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizard.__init__(self, parent)
+ self.windowManager = windowManager
+ self.deviceInfo = deviceInfo
+ stylesheet = '''QWizard{background-image:url('''+ BACKUP_BG + ''')};'''
+ self.setStyleSheet(stylesheet)
+ self.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self.setWindowTitle("%s Backup" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH,WINDOW_HEIGHT)
+
+ self.setButtonLayout([])
+ self.setWizardStyle(4)
+
+ self.checkboxPage = PcsCheckboxWizard(self.deviceInfo, windowManager, self)
+ self.addPage(self.checkboxPage)
+
+ self.chooseFilePage = PcsOpenFileWizard(self.deviceInfo, windowManager, self)
+ self.connect(self.chooseFilePage.finishButton, SIGNAL("clicked()"),
+ self.noNameTest)
+ self.addPage(self.chooseFilePage)
+
+ self.progressWizard = PcsProgressWizard(self.deviceInfo,self, windowManager, self)
+ self.connect(self.progressWizard.cancelButton, SIGNAL("clicked()"),
+ self._confirmsCancel)
+ self.connect(self.progressWizard.doneButton, SIGNAL("clicked()"), self._done)
+ self.connect(self.progressWizard, SIGNAL("destroyed()"), self.test)
+ self.addPage(self.progressWizard)
+
+ def test(self):
+ print "entrou caraiiiiii"
+
+ def noNameTest(self):
+ if(str(self.chooseFilePage.getBackupName()).strip() == ""):
+ message = "Your backup name can't be blank."
+ showMessageBox(message, "Backup name blank")
+ else:
+ self.doNewBackup()
+ self.next()
+
+ def _done(self):
+ self.done(0)
+ self.progressWizard._resetPage()
+ self.chooseFilePage._resetPage()
+
+ def doNewBackup(self):
+
+ hostIp = self.deviceInfo.ip
+ backupName = self.chooseFilePage.getBackupName()
+ backupPath = self.chooseFilePage.getPath()
+ categories = self.checkboxPage.getCategories()
+ self.backupManager = PcsPcBackupManager()
+ self.backupManager.loadBackups()
+ comments = ""
+
+ self._updateThread = UpdateBackupProgress(backupName, backupPath,
+ hostIp,categories, comments,
+ self.backupManager,
+ self.progressWizard)
+ self.connect(self._updateThread, SIGNAL("backupFinished"),
+ self._onBackupDone)
+ self.connect(self._updateThread, SIGNAL("backupCanceled"),
+ self._onBackupCancel)
+ self.connect(self._updateThread, SIGNAL("backupNameChanged"),
+ self._onBackupNameChanged)
+ self.connect(self._updateThread, SIGNAL("backupProgress"),
+ self._updateCategoriesAndProgress)
+
+ self._updateThread.start()
+
+ def _updateCategoriesAndProgress(self, information):
+ progress, category = information
+ self.progressWizard.setProgress(progress)
+ self.progressWizard.setCategory(category)
+
+
+ def _onBackupDone(self, info):
+ self.progressWizard.updateInfo(info[0], info[1])
+ self.progressWizard.progressDone()
+ self.windowManager.getBackupManager().pcListView.updateBackupList()
+
+ def _onBackupNameChanged(self, correct_name):
+ """
+ Check if backup name was changed and show message case positive.
+ """
+ nameChangeMessage = "Backup with same name was found in" + \
+ " backup list, Backup name changed to %s" \
+ % correct_name
+ showMessageBox(nameChangeMessage, "Backup name changed")
+
+ def _confirmsCancel(self):
+ """
+ Confirms the backup canceling.
+ """
+ dialog = QMessageBox()
+ dialog.setText("Do you really want cancel this backup?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ self._onBackupCancel()
+
+ def _onBackupCancel(self):
+ """
+ Stops current backup process in backup manager.
+ Also, shows a message box informing about canceling.
+
+ """
+ self.progressWizard.progressCanceled()
+ self.backupManager.setBackupInProgress(False)
+
+ def setVisible (self, visible):
+ if(visible == False):
+ self.emit("")
+
+
+class UpdateBackupProgress(QThread):
+
+ def __init__(self, backupName, path, hostIp, categories, comment,
+ backupManager, progressWizard):
+ QThread.__init__(self)
+
+ self.backupName = backupName
+ self.path = path
+ self.hostIp = hostIp
+ self.categories = categories
+ self.comment = comment
+ self.backupManager = backupManager
+
+
+ def run(self):
+ self._backupFlag = True
+
+ self.correctName = self.backupManager._verify_backup_name(self.backupName)
+ self.nameChanged = self.correctName != self.backupName
+
+ self.connect(self.backupManager, SIGNAL("backupProgress"), self._reEmitSignal)
+ self.connect(self.backupManager, SIGNAL("backupDone"), self._onBackupDone)
+ res = self.backupManager.createBackup(self.correctName, self.path,
+ self.hostIp, self.categories,
+ self.comment)
+
+ while (self._backupFlag):
+ sleep(0.1)
+
+ def _reEmitSignal(self, informations):
+ self.emit(SIGNAL("backupProgress"), informations)
+
+ def _onBackupDone(self, res, info):
+ self._backupFlag = False
+ # If backup was not canceled, emit done signal
+ if res != 0:
+ if self.nameChanged:
+ self.emit(SIGNAL("backupNameChanged"), self.correctName)
+ self.emit(SIGNAL("backupFinished"), info)
+ else:
+ self.emit(SIGNAL("backupCanceled"))
+
+
\ No newline at end of file
--- /dev/null
+'''
+@author: Nicholas Alexander
+
+Created on 07/07/2009
+
+Module with functions used to create backup metadata xml file with same format
+as osso-backup metadata.
+
+'''
+import os
+
+import xml.dom.minidom
+
+from backup.pcsbackuputils import getSize
+from pcsdevicemanager import PcsDeviceManager
+
+
+def createXml(backup_info, filesByCategory, host_ip):
+ doc = xml.dom.minidom.Document()
+ root = doc.createElement("backup-metadata")
+ doc.appendChild(root)
+ _appendSizeNode(backup_info, doc, root)
+ _appendFilesNumberNode(backup_info, doc, root)
+ _appendTimeNode(backup_info, doc, root)
+ _appendProtectedNode(doc, root)
+ _appendDeviceInfoNode(doc, root, host_ip)
+ backupFullPath = os.path.join(backup_info.getPath(), backup_info.getName())
+ _appendCategoriesNode(doc, root, filesByCategory, backupFullPath)
+ metadata_path = os.path.join(backupFullPath, "backup.metadata")
+ file = open(metadata_path, "w")
+ doc.writexml(file)
+ file.close()
+
+
+
+def _appendSizeNode(backupInfo, document, node):
+ sizeNode = document.createElement("size")
+ size = document.createTextNode(str(backupInfo.getSize()))
+ sizeNode.appendChild(size)
+ node.appendChild(sizeNode)
+
+def _appendFilesNumberNode(backupInfo, document, node):
+ filesNode = document.createElement("number-of-files")
+ files = document.createTextNode(str(backupInfo.getFilesNumber()))
+ filesNode.appendChild(files)
+ node.appendChild(filesNode)
+
+def _appendTimeNode(backupInfo, document, node):
+ timeNode = document.createElement("timestamp")
+ time = document.createTextNode(str(int(backupInfo.getTime())))
+ timeNode.appendChild(time)
+ node.appendChild(timeNode)
+
+def _appendProtectedNode(document, node):
+ protectedNode = document.createElement("protected")
+ protected = document.createTextNode("false")
+ protectedNode.appendChild(protected)
+ node.appendChild(protectedNode)
+
+def _appendDeviceInfoNode(document, node, hostIp):
+ deviceManager = PcsDeviceManager()
+ deviceManager.loadDevices()
+ device = deviceManager.getDevice(hostIp)
+ versionNode = document.createElement("device-version")
+ version = document.createTextNode(device.ossoBackup)
+ versionNode.appendChild(version)
+ node.appendChild(versionNode)
+
+def _appendCategoriesNode(document, node, filesByCategory, backupPath):
+ categories = document.createElement("categories")
+ for category in filesByCategory.keys():
+ categoryPath = os.path.join(backupPath, "%s.zip" % category)
+ size = getSize(categoryPath)
+ if size == False:
+ continue
+ categoryNode = document.createElement("%s" % category)
+ categorySize = document.createElement("size")
+ categoryFiles = document.createElement("number-of-files")
+ filesText = document.createTextNode(str(filesByCategory[category]))
+ sizeText = document.createTextNode(str(size))
+ categorySize.appendChild(sizeText)
+ categoryFiles.appendChild(filesText)
+ categoryNode.appendChild(categorySize)
+ categoryNode.appendChild(categoryFiles)
+ categories.appendChild(categoryNode)
+ node.appendChild(categories)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsbutton import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcscustombuttons import PcsCustomButton as customButton
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+
+class PcsCheckboxWizard(QWizardPage):
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.layout.setSpacing(0)
+ buttonsLayout = self._menuButtons()
+ self.layout.addLayout(buttonsLayout)
+ self.layout.addItem(QSpacerItem(0, 8))
+ wayLayout = self._wayLayout()
+ self.layout.addLayout(wayLayout)
+
+ self.layout.addItem(QSpacerItem(0, 10))
+
+ self.hlayout = QHBoxLayout()
+ self.hlayout.setMargin(0)
+
+ self.vertical = QVBoxLayout()
+ self.vertical.setMargin(0)
+ self.vertical.setSpacing(0)
+ self.create_vertical_components()
+ self.hlayout.addLayout(self.vertical)
+ self.hlayout.setMargin(0)
+ self.hlayout.setSpacing(0)
+
+ self.create_checkbox_frame()
+# self.hlayout.addItem(QSpacerItem(30, 0))
+ self.layout.addLayout(self.hlayout)
+
+ self.layout.addItem(QSpacerItem(0, 35))
+ informationLayout = QHBoxLayout()
+ informationLayout.setMargin(0)
+ spc = QSpacerItem(10, 0)
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ information = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the types of file you wish to backup.</font>")
+ informationLayout.addItem(spc)
+ informationLayout.addWidget(iconAlert)
+ informationLayout.addWidget(information, Qt.AlignLeft)
+
+ self.layout.addLayout(informationLayout)
+
+ self.setLayout(self.layout)
+ self.map_checked = {self.documents.name: False,
+ self.emails.name: False, self.media.name: False,
+ self.contacts.name: False,
+ self.bookmarks.name: False,
+ self.settings.name: False,
+ self.applications.name: False}
+ self.enableNext = QLineEdit()
+ self.registerField("enableNext*", self.enableNext)
+
+ def _wayLayout(self):
+ barLayout = QHBoxLayout()
+ barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow = self._arrow()
+ arrow2 = self._arrow()
+ spc = QSpacerItem(5, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #FFFFFF'; size=2>Files</font>")
+ widgetList = [main, arrow, newBackup, arrow2, files]
+ for widget in widgetList:
+ barLayout.addWidget(widget, Qt.AlignLeft)
+ barLayout.addItem(spc)
+ barLayout.addItem(QSpacerItem(300, 0))
+ return barLayout
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard().geometry())
+ backupManager.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard().geometry())
+ restoreBackup.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _goNextPage(self):
+ if self.empty_map():
+ return False
+ else:
+ self.wizard().next()
+
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def create_checkbox_frame(self):
+ layout = QVBoxLayout()
+ l = QLabel()
+ l.setPixmap(QPixmap(COPY_BORDER))
+
+ self.frame = QScrollArea(self)
+ self.frame.setWidgetResizable(True)
+ widget = QWidget(self.frame)
+ widget.setStyleSheet("QWidget{background: transparent;}")
+ self.grid = QGridLayout()
+ self.grid.setSpacing(0)
+ self.createCheckboxPanel()
+ widget.setLayout(self.grid)
+ self.frame.setWidget(widget)
+ layout.addItem(QSpacerItem(0,25))
+ layout.addWidget(self.frame)
+ self.hlayout.addLayout(layout)
+
+
+ def empty_map(self):
+ for index in self.map_checked.keys():
+ if self.map_checked[index]:
+ return False
+ return True
+
+ def createCheckboxPanel(self):
+ #Add Checkboxes
+# self.add_select_all()
+ self.add_documents()
+ self.add_emails()
+ self.add_media()
+ self.add_contacts()
+ self.add_bookmarks()
+ self.add_settings()
+ self.add_applications()
+
+# def add_select_all(self):
+# self.select_all = QCheckBox("Select All")
+# self.connect(self.select_all, SIGNAL("stateChanged(int)"),
+# self.select_all_func)
+# self.grid.addWidget(self.select_all, 0, 0, Qt.AlignTop)
+#
+ def add_documents(self):
+ self.documents = QCheckBox("Documents")
+ self.documents.name = "documents"
+ callback = partial(self.select_func, self.documents)
+ self.connect(self.documents, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.documents, 1, 0, Qt.AlignTop)
+
+ def add_emails(self):
+ self.emails = QCheckBox("Emails")
+ self.emails.name = "emails"
+ callback = partial(self.select_func, self.emails)
+ self.connect(self.emails, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.emails, 2, 0, Qt.AlignTop)
+
+ def add_media(self):
+ self.media = QCheckBox("Media")
+ self.media.name = "media"
+ callback = partial(self.select_func, self.media)
+ self.connect(self.media, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.media, 3, 0, Qt.AlignTop)
+
+ def add_contacts(self):
+ self.contacts = QCheckBox("Contacts")
+ self.contacts.name = "contacts"
+ callback = partial(self.select_func, self.contacts)
+ self.connect(self.contacts, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.contacts, 4, 0, Qt.AlignTop)
+
+ def add_bookmarks(self):
+ self.bookmarks = QCheckBox("Bookmarks")
+ self.bookmarks.name = "bookmarks"
+ callback = partial(self.select_func, self.bookmarks)
+ self.connect(self.bookmarks, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.bookmarks, 5, 0, Qt.AlignTop)
+
+ def add_settings(self):
+ self.settings = QCheckBox("Settings")
+ self.settings.name = "settings"
+ callback = partial(self.select_func, self.settings)
+ self.connect(self.settings, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.settings, 6, 0, Qt.AlignTop)
+
+ def add_applications(self):
+ self.applications = QCheckBox("Applications")
+ self.applications.name = "applications"
+ callback = partial(self.select_func, self.applications)
+ self.connect(self.applications, SIGNAL("stateChanged(int)"),
+ callback)
+ self.grid.addWidget(self.applications, 7, 0, Qt.AlignTop)
+
+# def select_all_func(self):
+# checked = self.select_all.isChecked()
+# list = self.map_checked.keys()
+# for element in list:
+# self.map_checked[element] = checked
+# for i in range(1,8):
+# self.grid.itemAtPosition(i, 0).widget().setChecked(checked)
+#
+ def select_func(self, checkbox):
+ checked = checkbox.isChecked()
+ self.map_checked[checkbox.name] = checked
+ if not checked:
+ list = []
+ for i in range(1,8):
+ item = self.grid.itemAtPosition(i, 0).widget()
+# if item == self.select_all:
+# pass
+ if item.isChecked():
+ list.append(item)
+# self.select_all.setChecked(False)
+ for element in list:
+ element.setChecked(True)
+ if self.empty_map():
+ self.enableNext.setText("")
+ else:
+ self.enableNext.setText("Next Button Enabled")
+
+ def getCategories(self):
+ return self.map_checked
+
+ def create_vertical_components(self):
+ deviceWidget = PcsDeviceWidget(2)
+ deviceWidget.setImage(DEVICE_DISCONNECTED)
+ deviceWidget.addBorder()
+ deviceWidget.addDeviceName()
+ deviceWidget.setDeviceInfo(self.deviceInfo)
+ self.vertical.addWidget(deviceWidget, Qt.AlignTop)
+ self.nextButton = QPushButton()
+ self.nextButton.setText("Next")
+ self.nextButton.setStyleSheet(BACKUP_BUTTON_STYLE)
+ self.connect(self.nextButton, SIGNAL("clicked()"), self._goNextPage)
+ self.vertical.addItem(QSpacerItem(0, 20))
+ buttonLayout = QHBoxLayout()
+ buttonLayout.addItem(QSpacerItem(5,0))
+ buttonLayout.addWidget(self.nextButton, Qt.AlignCenter)
+ self.vertical.addLayout(buttonLayout)
+ self.vertical.addItem(QSpacerItem(0,10))
+
\ No newline at end of file
--- /dev/null
+
+from pcsbackupmanager import *
+from pcspcbackupmanager import PcsPcBackupManager
+from pcsbackupinfo import PcsBackupInfo
+import pcsbackuputils as utils
+
+
+class PcsDeviceBackupManager(PcsBackupManager):
+
+
+ def __init__(self, deviceInfo):
+ PcsBackupManager.__init__(self)
+ self._backupList = []
+ self._deviceInfo = deviceInfo
+ self.restoreInProgress = False
+ self.copyInProgress = False
+
+ def loadBackups(self):
+
+ # FIXME, error handling is wrong!! return list of PcsBackupInfo
+ try:
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % self._deviceInfo.ip)
+ utils.mountDevice(USER_HOST, self._deviceInfo.ip, mountPoint)
+
+ self._backupList = utils.getDeviceBackupList(mountPoint)
+ return True
+
+ except Exception, x:
+ print str(x)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+ return False
+
+ def getBackupList(self):
+ self.loadBackups()
+ for backup in self._backupList:
+ backup.setAtDevice(True)
+ return self._backupList
+
+ def copyBackupFromDevice(self, backupName, destinationPath):
+ try:
+ self.loadBackups()
+ device_backups = self.getBackupList()
+
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % self._deviceInfo.ip)
+ utils.mountDevice(USER_HOST, self._deviceInfo.ip, mountPoint)
+
+ # Search complete_path
+ completePath = ''
+ for backup in device_backups:
+ if backupName == backup.getName():
+ completePath = backup.getPath()
+ break
+ if completePath == '':
+ raise Exception("Backup not found.")
+
+ pcBackupManager = PcsPcBackupManager()
+ pcBackupManager.loadBackups()
+ correctName = pcBackupManager._verify_backup_name(backupName)
+ destination = os.path.join(destinationPath, correctName)
+
+ self.setCopyInProgress(True)
+ if self.copy(completePath, destination) == 0:
+ return 0
+ self.setCopyInProgress(False)
+
+ backup_size = utils.getSize(destination)
+ backup = PcsBackupInfo(correctName, destinationPath, backup_size,
+ 'Copied from device')
+ backup.setAtDevice(False)
+ pcBackupManager._backupList.append(backup)
+ pcBackupManager.saveBackups()
+
+ finally:
+ utils.unmountDevice(mountPoint)
+
+
+ def startBackupRestore(self, backupInfo, categories):
+ device_ip = self._deviceInfo.ip
+ return self.restoreBackup(backupInfo, device_ip, categories)
+
+
+ def setCopyInProgress(self, status):
+ self.copyInProgress = status
+
+
+ def setRestoreInProgress(self, status):
+ self.restoreInProgress = status
+
+
+ def getBackupInfo(self, backupName):
+ self.loadBackups()
+ for backupInfo in self._backupList:
+ if backupInfo.getName() == backupName:
+ backupInfo.setAtDevice(True)
+ return backupInfo
+
+ return None
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+import os
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+from style.styleTabletSuite import *
+
+
+class PcsOpenFileWizard(QWizardPage):
+
+ _home_dir = os.path.expanduser("~")
+ _default_dir = _home_dir + "/.pcsuite/Backup"
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+
+ self.path = self._default_dir
+ self.file_name = "Backup"
+ self.deviceInfo = deviceInfo
+ self.windowManager = windowManager
+
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.hLayout = QHBoxLayout()
+ self.hLayout.setMargin(0)
+ self.vLayout = QVBoxLayout()
+ self.vLayout.setMargin(0)
+
+ wayLayout = self._wayLayout()
+
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ spc = QSpacerItem(0, 12)
+ self.vLayout.addLayout(wayLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+ self.vLayout.addItem(spc)
+ spc2 = QSpacerItem(350, 0)
+ self.finishButton = QPushButton("Finish")
+ self.finishButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.finishButton.setShortcut(Qt.Key_Return)
+ self.hLayout.addItem(spc2)
+ self.hLayout.addWidget(self.finishButton)
+ self.vLayout.addLayout(self.hLayout)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self):
+ barLayout = QHBoxLayout()
+ barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow = self._arrow()
+ arrow2 = self._arrow()
+ arrow3 = self._arrow()
+ spc = QSpacerItem(2, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #333333'; size=2>Files</font>")
+ folder = QLabel("<font style='color: #FFFFFF'; size=2>Folder</font>")
+ widgetList = [main, arrow, newBackup, arrow2, files, arrow3, folder]
+ for widget in widgetList:
+ barLayout.addWidget(widget, Qt.AlignLeft)
+ barLayout.addItem(spc)
+ barLayout.addItem(QSpacerItem(300, 0))
+ return barLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard().geometry())
+ backupManager.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard().geometry())
+ restoreBackup.show()
+ self.wizard().close()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createDeviceWidget(self):
+ deviceWidget = PcsDeviceWidget(3)
+ deviceWidget.addBorder()
+ deviceWidget.addDeviceName()
+ deviceWidget.setDeviceInfo(self.deviceInfo)
+
+ return deviceWidget
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Do backup from Device to your PC.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(infLabel, Qt.AlignLeft)
+
+
+ return hLay
+
+ def _createCenterLayout(self):
+ hLay = QHBoxLayout()
+ hLay.setMargin(0)
+ vLay = QVBoxLayout()
+ vLay.setMargin(0)
+ hLayWithSpacer = QHBoxLayout()
+ hLayWithSpacer.setMargin(0)
+ spc = QSpacerItem(62, 0)
+
+ deviceWidget = self._createDeviceWidget()
+ arrowLabel = self._createArrowLabel()
+ pcLabel = self._createPcLabel()
+ pathField = self._createPathField()
+ nameField = self._createBackupNameField()
+
+ hLay.addWidget(deviceWidget, Qt.AlignVCenter)
+ hLay.addLayout(arrowLabel, Qt.AlignVCenter)
+ hLay.addLayout(pcLabel, Qt.AlignVCenter)
+
+ vLay.addLayout(nameField)
+ vLay.addLayout(hLay)
+ vLay.addLayout(pathField)
+
+ hLayWithSpacer.addItem(spc)
+ hLayWithSpacer.addLayout(vLay)
+ hLayWithSpacer.addItem(spc)
+
+ return hLayWithSpacer
+
+ def _createArrowLabel(self):
+ arrowLayout = QGridLayout()
+ arrowLabel = QLabel()
+ arrowLabel.setPixmap(QPixmap(LARGE_ARROW_IMAGE))
+ borderArrowLabel = QLabel()
+ borderArrowLabel.setFixedSize(42, 65)
+ borderArrowLabel.setPixmap(QPixmap(LARGE_ARROW_BORDER))
+ arrowLayout.addWidget(arrowLabel, 0, 0, Qt.AlignCenter)
+ arrowLayout.addWidget(borderArrowLabel, 0, 0, Qt.AlignCenter)
+ return arrowLayout
+
+ def _createPcLabel(self):
+ gridLay = QGridLayout()
+ pcLabelLayout = QGridLayout()
+ pcLabel = QLabel()
+ pcLabel.setPixmap(QPixmap(PC_IMAGE))
+ pcBorder = QLabel()
+ pcBorder.setFixedSize(112, 127)
+ pcBorder.setPixmap(QPixmap(PC_BORDER_FILE))
+ nameLabel = QLabel("PC")
+ nameBorder = QLabel()
+ nameBorder.setPixmap(QPixmap(PC_NAME_BORDER_FILE))
+ nameBorder.setFixedSize(92, 26)
+ gridLay.addWidget(pcLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addWidget(nameLabel, 1, 0, Qt.AlignCenter)
+ gridLay.addWidget(nameBorder, 1, 0, Qt.AlignCenter)
+ pcLabelLayout.addLayout(gridLay, 0, 0, Qt.AlignCenter)
+ pcLabelLayout.addWidget(pcBorder, 0, 0, Qt.AlignCenter)
+ return pcLabelLayout
+
+ def _createPathField(self):
+ pathLayout = QHBoxLayout()
+ self.pathField = QLineEdit()
+ self.pathField.setReadOnly(True)
+ self.pathField.setText(self._default_dir)
+ self.pathField.setObjectName("pathField")
+ buttonBrowse = QPushButton()
+ buttonBrowse.setObjectName("buttonBrowse")
+ self.connect(buttonBrowse, SIGNAL("clicked()"), self._openFileDialog)
+ pathLayout.addWidget(self.pathField)
+ pathLayout.addWidget(buttonBrowse)
+
+ borderLabel = QLabel()
+ borderLabel.setPixmap(QPixmap(PATH_BG))
+ borderLabel.setFixedSize(304, 40)
+ gridLay = QGridLayout()
+ gridLay.addWidget(borderLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addLayout(pathLayout, 0, 0, Qt.AlignCenter)
+
+ return gridLay
+
+ def _createBackupNameField(self):
+ label = QLabel("Backup Name:")
+ backupNameLayout = QHBoxLayout()
+ backupNameLayout.addWidget(label)
+ self.backupNameField = QLineEdit()
+ self.backupNameField.setObjectName("backupNameField")
+ self.backupNameField.setText("Backup")
+ backupNameLayout.addWidget(self.backupNameField,
+ Qt.AlignHCenter)
+ borderLabel = QLabel()
+ borderLabel.setPixmap(QPixmap(BACKUP_NAME_BG))
+ borderLabel.setFixedSize(304, 40)
+ gridLay = QGridLayout()
+ gridLay.addWidget(borderLabel, 0, 0, Qt.AlignCenter)
+ gridLay.addLayout(backupNameLayout, 0, 0, Qt.AlignCenter)
+
+ return gridLay
+
+ def _openFileDialog(self):
+ pathDialog = QFileDialog()
+ prompt = "Select the folder you wish to save your backup"
+ self.path = pathDialog.getExistingDirectory(self, prompt,
+ self._default_dir)
+ if self.path != "":
+ self.pathField.setText(self.path)
+
+ def _resetPage(self):
+ self.path = self._default_dir
+ self.pathField.setText(self._default_dir)
+ self.backupNameField.setText("Backup")
+
+ def getBackupName(self):
+ return str(self.backupNameField.text())
+
+ def getPath(self):
+ return str(self.pathField.text())
+
--- /dev/null
+# low_backup_manager module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+# Backup_manager class:
+# Class responsible for backup functions like creating and removing backups
+
+import os.path
+import os
+import zlib
+import pickle
+
+from PyQt4.QtCore import *
+from zipfile import *
+
+from pcsbackupparser import *
+from pcsbackupinfo import *
+from pcsbackupmanager import *
+from pcsbackupxml import *
+
+import pcsbackuputils as utils
+
+HOME = os.path.expanduser("~")
+BACKUP_FILES_PATH = os.path.join(HOME, ".pcsuite/Backup")
+DEFAULT_CONFIG_PATH = "%s/.pcsuite/config" % HOME
+BACKUPS_FILE = os.path.join(HOME, ".pcsuite/Backup/.backups")
+
+
+class PcsPcBackupManager(PcsBackupManager):
+
+ def __init__(self):
+ PcsBackupManager.__init__(self)
+ self._backupList = []
+ self.backupInProgress = False
+ self.restoreInProgress = False
+ self.copyInProgress = False
+
+ self.myDocsPath = "Root/home/user/MyDocs/"
+ self.backupPath = ""
+ self.currentCategory = ""
+ self.totalSize = 0
+
+ def loadBackups(self):
+ # 'XX Loading the backup list available in the PC'
+ try:
+ if os.path.exists(BACKUPS_FILE):
+ file = open(BACKUPS_FILE)
+ self._backupList = pickle.load(file)
+ file.close()
+ except IOError:
+ print "IOError while loading the PC backups"
+ # FIXME
+ #raise Exception("Error while reading backups")
+ return False
+
+ return True
+
+ def saveBackups(self):
+ # 'XX Saving the backup list in the config file'
+ try:
+ obj = self._backupList
+ file = open(BACKUPS_FILE, "w")
+ pickle.dump(obj, file)
+ file.close()
+ except:
+ #raise Exception("Error while saving backups")
+ return False
+
+ return True
+
+ def getBackupList(self):
+ """Return a list with the name of all done backups. """
+ self.loadBackups()
+ return self._backupList[:]
+
+ def createBackup(self, backup_name, path, host_ip, categories, comment=""):
+ self.backupThread = NewBackupThread(self, backup_name, path, host_ip,
+ categories, comment)
+ self.backupThread.start()
+
+
+ def renameBackup(self, backupName, newName):
+ self.loadBackups()
+
+ backupInfo = self.getBackupInfo(backupName)
+ if backupInfo != None:
+ try:
+ old = os.path.join(str(backupInfo.getPath()), str(backupName))
+ new = os.path.join(str(backupInfo.getPath()), str(newName))
+ os.rename(old, new)
+ backupInfo.setName(newName)
+ except:
+ print "Error while changing backup name"
+ return False
+ else:
+ # "Backup not found"
+ return False
+
+ self.saveBackups()
+ return True
+
+ def removeBackup(self, backupName):
+ """
+ Remove a backup from pc and from _backupList.
+ """
+ self.loadBackups()
+ backupInfo = self.getBackupInfo(backupName)
+ completePath = os.path.join(str(backupInfo.getPath()),
+ str(backupInfo.getName()))
+ if os.path.exists(completePath):
+ utils.removePath(completePath)
+ self._backupList.remove(backupInfo)
+ self.saveBackups()
+
+ return True
+
+ def copyBackupToDevice(self, deviceIp, backupName, memoryStick):
+ """ Copy a backup in the PC to some memory card inside the chosen device.
+
+ Attributes:
+ String deviceIp - String with ip address of device.
+ String backupName - Name of backup to be copied.
+ Int memoryStick - Integer representing which memory stick backup
+ should be copied to.
+ 0 - Removable memory stick
+ 1 - Internal memory stick
+ """
+ try:
+ self.loadBackups()
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % deviceIp)
+ utils.mountDevice(USER_HOST, deviceIp, mountPoint)
+
+ backup = self.getBackupInfo(backupName)
+ backupPath = os.path.join(str(backup.getPath()), str(backupName))
+ if memoryStick != 0 and memoryStick != 1:
+ return -1
+ destination = os.path.join(mountPoint, 'media/mmc%s' %
+ (memoryStick+1), 'backups', backupName)
+
+ self.setCopyInProgress(True)
+ if self.copy(backupPath, destination) == 0:
+ return 0
+ self.setCopyInProgress(False)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+
+ def getBackupInfo(self, backupName):
+ for backupInfo in self._backupList:
+ if backupInfo.getName() == backupName:
+ return backupInfo
+ return None
+
+ def startBackupRestore(self, backupInfo, device_ip, categories):
+ return self.restoreBackup(backupInfo, device_ip, categories)
+
+ def setCopyInProgress(self, status):
+ self.copyInProgress = status
+
+ def setBackupInProgress(self, status):
+ self.backupInProgress = status
+
+
+ def setRestoreInProgress(self, status):
+ self.restoreInProgress = status
+
+ # FIXME: rewrite this method. Add error handling, some more reliable code
+ def _runCreateBackup(self, backup_name, path, host_ip, categories, comment=""):
+ """Create a backup and add it to _backupList.
+
+ Backup all files and directories of categories chosen. The device
+ system file is mounted on PC and them files are compressed in a zip
+ format. All zip files from each category are saved in the given path.
+
+ Arguments:
+ backup_name -- Backup's name. This name will be the name of the backup
+ folder.
+ path -- Location to save Backup file
+ host_ip -- The device IP address.
+ categories -- A python dictonary where the keys are the categories from
+ osso-backup, and the value can be either True or False, to identify
+ which categories to backup.
+ comment -- Any comment about the backup. It will be saved in Backup
+ object.
+
+ """
+
+ backupInfo = None
+ self.setBackupInProgress(True)
+ self.currentCategory = ""
+
+ try:
+ # Mount device folders
+ self.loadBackups()
+ mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % host_ip)
+ utils.mountDevice(USER_HOST, host_ip, mountPoint)
+
+ # Create backup folder in the given path
+ self.backupPath = os.path.join(str(path), backup_name)
+ self._createBackupFolder(self.backupPath)
+
+ # Copying osso-backup configuration files to TabletSuite folder and
+ # parsing backup information from these files.
+ # ( Information = which paths should be in each backup category)
+ utils.copyOssoBackupConfigFiles(DEFAULT_CONFIG_PATH, mountPoint)
+ xmlParser = PcsBackupParser()
+ xmlParser.fillLocationsDict(DEFAULT_CONFIG_PATH)
+ backupItemDict = xmlParser.getLocationsDict()
+
+ # Changing work directory to ease file search. Keeping previous
+ # folder to come back after backup process.
+ current_dir = os.getcwd()
+ workPath = DEVICES_POINT + str(host_ip)
+ os.chdir(workPath)
+
+ # Computing total size that this backup will have.
+ self.totalSize = self._getTotalSize(backupItemDict, categories)
+
+
+ # Start backup process. Create backup of paths for each locations
+ # category
+ self.backedUpNumber = 0
+ filesByCategory = {}
+ for category in backupItemDict.keys():
+ self.currentCategory = category
+
+ for backupItem in backupItemDict[category]:
+ self._emitProgress()
+ # If current backupInfo category is valid and it's value is
+ # True in categories dictionary, add it to current backup.
+ if (category in categories) and (categories[category]):
+ categoryFilesNumber = 0
+ categoryFile = os.path.join(self.backupPath,
+ category + '.zip')
+
+ if os.path.exists(categoryFile):
+ zipfile = utils.openZip(categoryFile, 'a')
+ else:
+ zipfile = utils.openZip(categoryFile, 'w')
+
+ objPath = backupItem.path.replace('/','Root/',1)
+ backupFolder = os.path.join(workPath, objPath)
+ categoryFilesNumber = self.zipFolder(backupFolder,
+ zipfile, objPath,
+ category)
+ if categoryFilesNumber == -1:
+ os.chdir(current_dir)
+ return 0
+ self.backedUpNumber += categoryFilesNumber
+ self._emitProgress()
+
+ # Update the filesByCategory dictionary with the
+ # current number of files from current category that
+ # were already copied.
+ self._updateCategoryCount(filesByCategory, category,
+ categoryFilesNumber)
+ utils.closeZip(zipfile)
+ # If category had no file to copy remove its folder
+ if int(utils.getSize(categoryFile) == 0):
+ os.remove(categoryFile)
+
+
+ # Copying media files from device user folder if media category is
+ # True in categories dictionary.
+ if ("media" in categories) and (categories["media"]):
+ self.currentCategory = "media"
+ result = self._backupMedias(workPath)
+ if result == -1:
+ os.chdir(current_dir)
+ return 0
+ # Update backup files number count
+ self.backedUpNumber += result
+ self._updateCategoryCount(filesByCategory, "media", result)
+ zipPath = os.path.join(self.backupPath,'media.zip')
+ if int(utils.getSize(zipPath) == 0):
+ os.remove(zipPath)
+
+
+ # Copying documents files from device user folder if documents
+ # category is True in categories dictionary.
+ if ("documents" in categories) and (categories["documents"]):
+ self.currentCategory = "documents"
+ result = self._backupDocuments(workPath)
+ # Update backup files number count
+ self.backedUpNumber += result
+ if result == -1:
+ os.chdir(current_dir)
+ return 0
+ self._updateCategoryCount(filesByCategory, "documents",
+ result)
+ zipPath = os.path.join(self.backupPath, 'documents.zip')
+ if int(utils.getSize(zipPath) == 0):
+ os.remove(zipPath)
+
+
+ # Change to previous work directory
+ os.chdir(current_dir)
+
+ if self.backedUpNumber == 0:
+ utils.removePath(self.backupPath)
+ return -1
+
+ # Create Backup Object, add it to this manager backup list and save
+ # the list in the backup file.
+ backup_size = utils.getSize(self.backupPath)
+ backupInfo = PcsBackupInfo(backup_name, path, backup_size, comment)
+ backupInfo.setFilesNumber(self.backedUpNumber)
+ self._backupList.append(backupInfo)
+ self.saveBackups()
+
+ createXml(backupInfo, filesByCategory, host_ip)
+ self.setBackupInProgress(False)
+ finally:
+ utils.unmountDevice(mountPoint)
+
+ return backupInfo
+
+
+ def _backupDocuments(self, workPath):
+ """ Create backup of documents files in user folder. """
+ categoryFilesNumber = 0
+ destinationPath = os.path.join(self.backupPath,'documents.zip')
+ if os.path.exists(destinationPath):
+ zipfile = utils.openZip(destinationPath, 'a')
+ else:
+ zipfile = utils.openZip(destinationPath, 'w')
+
+ docsPath = os.path.join(self.myDocsPath, ".documents")
+
+ if os.path.exists(docsPath):
+ backupPath = os.path.join(workPath, docsPath)
+ categoryFilesNumber = self.zipFolder(backupPath, zipfile, docsPath,
+ "documents")
+
+ utils.closeZip(zipfile)
+ return categoryFilesNumber
+
+
+ def _backupMedias(self, workPath):
+ """ Create backup of media files in user folder. """
+ categoryFilesNumber = 0
+ destinationPath = os.path.join(self.backupPath,'media.zip')
+ if os.path.exists(destinationPath):
+ zipfile = utils.openZip(destinationPath, 'a')
+ else:
+ zipfile = utils.openZip(destinationPath, 'w')
+
+ userFilesPath = self.myDocsPath
+ if os.path.exists(os.path.join(userFilesPath)):
+ for folder in os.listdir(userFilesPath):
+ if folder != '.documents':
+ objPath = os.path.join(userFilesPath, folder)
+ backupDir = os.path.join(workPath, objPath)
+ result = self.zipFolder(backupDir, zipfile,
+ objPath, "media")
+ if result != -1:
+ categoryFilesNumber += result
+ else:
+ return result
+
+ utils.closeZip(zipfile)
+ return categoryFilesNumber
+
+
+ def _createBackupFolder(self, newBackupPath):
+ if not utils.createFolder(newBackupPath):
+ return False
+
+
+ def _emitProgress(self):
+ currentSize = utils.getSize(self.backupPath)
+ percentage = self.computePercentage(self.totalSize, currentSize)
+ self.emit(SIGNAL("backupProgress"), (percentage, self.currentCategory))
+
+
+ def _getTotalSize(self, backupFileDict, categories):
+ size = 0
+ for category in backupFileDict.keys():
+ for backupItem in backupFileDict[category]:
+ if (category in categories) and (categories[category]):
+ objPath = backupItem.path.replace('/','Root/',1)
+ size += utils.getSize(objPath)
+
+ if categories["documents"]:
+ size += utils.getSize(os.path.join(self.myDocsPath,
+ ".documents"))
+ if categories["media"]:
+ for folder in os.listdir(self.myDocsPath):
+ if folder != '.documents':
+ objPath = os.path.join(self.myDocsPath, folder)
+ size += utils.getSize(objPath)
+ return size
+
+ def _updateCategoryCount(self, filesByCategory, category, backed_up_number):
+ if str(category) not in filesByCategory.keys():
+ filesByCategory[category] = backed_up_number
+ else:
+ filesByCategory[category] += backed_up_number
+
+
+ def _verify_backup_name(self, backup_name):
+ """ Check if already exists any backup with the given name inside the
+ pc backup list. In case there is one, this function will return another
+ name to be set as the new backup name, else it will return the same
+ name that was given.
+
+ """
+ if self.getBackupInfo(backup_name) != None:
+ counter = 1
+ new_name = backup_name + "%02d" % counter
+ while(self.getBackupInfo(new_name)) != None:
+ counter += 1
+ new_name = backup_name + "%02d" % counter
+
+ backup_name = new_name
+ return backup_name
+
+ def zipFolder(self, path, zipfile, obj_path, category):
+ # Compress the folder from the given path, with all directories and
+ # files inside it
+ # zipfile: The ZipFile object to append the folder
+ # obj_path: The ZipFile path
+ count = 0
+ self._emitProgress()
+ if os.path.exists(path):
+ if os.path.isdir(path):
+ files = os.listdir(path)
+ for node in files:
+ if os.path.isdir(os.path.join(path, node)):
+ zipCount = self.zipFolder(os.path.join(path, node), zipfile,
+ os.path.join(obj_path, node), category)
+ if zipCount == -1:
+ return -1
+ else:
+ count += zipCount
+ else:
+ # Check if backup was canceled and return -1 case positive
+ if not self.backupInProgress:
+ utils.removePath(self.backupPath)
+ return -1
+
+ if utils.zip(zipfile, os.path.join(obj_path, node)):
+ count += 1
+ self._emitProgress()
+ else:
+ # Check if backup was canceled and return -1 case positive
+ if not self.backupInProgress:
+ utils.removePath(self.backupPath)
+ return -1
+
+ if utils.zip(zipfile, obj_path):
+ count += 1
+ self._emitProgress()
+ return count
+
+
+
+class NewBackupThread(QThread):
+ def __init__(self, manager, backupName, path, hostIp, categories, comment):
+ QThread.__init__(self)
+
+ self.manager = manager
+ self.backupName = backupName
+ self.path = path
+ self.hostIp = hostIp
+ self.categories = categories
+ self.comment = comment
+
+ def run(self):
+ ret = self.manager._runCreateBackup (self.backupName, self.path,
+ self.hostIp, self.categories,
+ str(self.comment))
+ self.manager.emit(SIGNAL("backupDone"), ret,
+ (self.manager.totalSize, self.manager.backedUpNumber))
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from style.styleTabletSuite import *
+from ui.pcsuiutils import *
+
+class PcsProgressDialog(QDialog):
+
+ def __init__(self, parent = None):
+ QDialog.__init__(self, parent, Qt.FramelessWindowHint)
+ self.cancelButton = QPushButton("Cancel")
+ self.doneButton = QPushButton("Done")
+ self.connect(self.doneButton, SIGNAL("clicked()"), self.close)
+ self.actionLabel = QLabel("Action...")
+ self.categoryLabel = QLabel("")
+ self.progressReport = QLabel("")
+ self.setLayout(self._insertLayout())
+
+
+ def setAction(self, action):
+ self.action = action
+ if action == "copy":
+ message = "Copying..."
+
+ elif action == "restore":
+ message = "Restoring..."
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ +str(action).capitalize()+
+ " in progress...</font>")
+
+ self.actionLabel.setText('''<font style=color:
+ black; size=3>
+ '''+ message +'''</font>''')
+
+ def _insertLayout(self):
+ vLay = QVBoxLayout()
+ vLay.addWidget(self.actionLabel)
+ vLay.addLayout(self._createCenterLayout())
+ return vLay
+
+ def _createCenterLayout(self):
+
+ bgLabel = QLabel()
+ bgLabel.setPixmap(QPixmap(PROGRESS_BAR_DIALOG_BG))
+ grid = QGridLayout()
+
+ self.progressBar = QProgressBar()
+ self.progressBar.setObjectName("progressBarDialog")
+ self.progressBar.setValue(0)
+ self.progressBar.setTextVisible(False)
+
+ grid.addWidget(bgLabel, 0, 0, Qt.AlignCenter)
+ grid.addWidget(self.progressBar, 0, 0, Qt.AlignCenter)
+
+ self.cancelButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.cancelButton.setShortcut(Qt.Key_Return)
+ self.doneButton.setVisible(False)
+ self.doneButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+
+ gridLayout = QGridLayout()
+ gridLayout.setSpacing(3)
+ gridLayout.addWidget(self.categoryLabel, 0, 0, Qt.AlignRight)
+ gridLayout.addLayout(grid, 1, 0)
+ gridLayout.addWidget(self.progressReport, 2, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.cancelButton, 3, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.doneButton, 3, 0, Qt.AlignRight)
+
+ return gridLayout
+
+ def progressCanceled(self):
+ self.progressDone(True)
+
+ def progressDone(self, cancel=False):
+ self.cancelButton.setVisible(False)
+ self.doneButton.setVisible(True)
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"+\
+ str(self.action).capitalize()
+ +" finished.</font>")
+ if not cancel:
+ totalSize = "%.2f" % (self.totalSize/(1024.0**2))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(self.numberOfFiles) +\
+ " Files - " + totalSize + " MB</font>")
+ else:
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2> Canceled")
+ self.categoryLabel.setText("")
+ self.progressBar.setValue(100)
+
+ def updateInfo(self, totalSize, numberOfFiles):
+ self.totalSize = totalSize
+ self.numberOfFiles = numberOfFiles
+
+ def setProgress(self, progress):
+ self.progressBar.setValue(float(progress))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + progress +\
+ "% Complete</font>")
+
+ def setCategory(self, catogory):
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2> Category name: "\
+ + catogory +"</font>")
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from pcsbackupmanagerui import *
+from pcsrestorebackupui import *
+from style.styleTabletSuite import *
+
+
+class PcsProgressWizard(QWizardPage):
+
+ def __init__(self, deviceInfo, wizard, windowManager, parent = None):
+ QWizardPage.__init__(self, parent)
+ self.windowManager = windowManager
+ self.deviceInfo = deviceInfo
+ self.wizard = wizard
+ self.layout = QVBoxLayout()
+ self.layout.setMargin(0)
+ self.cancelButton = QPushButton("Cancel")
+ self.doneButton = QPushButton("Done")
+ self.completeReportButton = QPushButton("View Complete Report")
+ self.lockMenuButtons = True
+ self._insertLayout()
+
+ def _insertLayout(self, name = ""):
+ self.vLayout = QVBoxLayout()
+ self.vLayout.setMargin(0)
+ self.wayLayout = self._wayLayout(name)
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
+ spc = QSpacerItem(0, 68)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE_SELECTED),
+ ("Manager Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
+ buttonsLayout = QHBoxLayout()
+ buttonsLayout.setMargin(0)
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 0:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self, name = ""):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ arrow1 = self._arrow()
+ arrow2 = self._arrow()
+ arrow3 = self._arrow()
+ arrow4 = self._arrow()
+ spc = QSpacerItem(2, 0)
+ newBackup = QLabel("<font style='color: #333333'; size=2> New Backup</font>")
+ files = QLabel("<font style='color: #333333'; size=2>Files</font>")
+ folder = QLabel("<font style='color: #333333'; size=2>Folder</font>")
+ if name != "":
+ loading = QLabel("<font style='color: #333333'; size=2>loading</font>")
+ else:
+ loading = QLabel("<font style='color: #FFFFFF'; size=2>loading</font>")
+ widgetList = [main, self._arrow(), newBackup, self._arrow(), files,
+ self._arrow(), folder, self._arrow(), loading]
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+ if name != "":
+ newLabel = QLabel("<font style='color: #FFFFFF'; size=2>"+ name +"</font>")
+ self.barLayout.addWidget(self._arrow(), Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+ self.barLayout.addWidget(newLabel, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _manageDialog(self):
+ if self.lockMenuButtons == False:
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.wizard.geometry())
+ backupManager.show()
+ self.close()
+ self.wizard.close()
+ self.lockMenuButtons = True
+ self._resetPage()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _restoreDialog(self):
+ if self.lockMenuButtons == False:
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ restoreBackup = self.windowManager.getRestoreBackup()
+ centralize(restoreBackup)
+ restoreBackup.setGeometry(self.wizard.geometry())
+ restoreBackup.show()
+ self.wizard.close()
+ self.close()
+ self.lockMenuButtons = True
+ self._resetPage()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+ spc = QSpacerItem(10, 0)
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Do backup from Device to your PC.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _resetPage(self):
+ self.lockMenuButtons = True
+ self.cancelButton.setVisible(True)
+ self.doneButton.setVisible(False)
+ self.progressBar.setValue(0)
+ self.progressReport.setText("")
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup starting...</font>")
+
+ def _createCenterLayout(self):
+ gridLayout = QGridLayout()
+ gridLayout.setMargin(27)
+
+ self.categoryLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup starting...</font>")
+
+ bgLabel = QLabel()
+ bgLabel.setPixmap(QPixmap(PROGRESS_BAR_BG))
+ grid = QGridLayout()
+
+ self.progressBar = QProgressBar()
+ self.progressBar.setObjectName("progressBarWizard")
+ self.progressBar.setValue(0)
+ self.progressBar.setTextVisible(False)
+
+ grid.addWidget(bgLabel, 0, 0, Qt.AlignCenter)
+ grid.addWidget(self.progressBar, 0, 0, Qt.AlignCenter)
+
+ self.progressReport = QLabel("")
+
+ self.cancelButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.cancelButton.setShortcut(Qt.Key_Return)
+ self.doneButton.setVisible(False)
+ self.doneButton.setStyleSheet(DEFAULT_BUTTON_STYLE)
+# self.completeReportButton.setStyleSheet()
+
+ gridLayout.setSpacing(3)
+ gridLayout.addWidget(self.categoryLabel, 0, 0, Qt.AlignRight)
+ gridLayout.addLayout(grid, 1, 0)
+ gridLayout.addWidget(self.progressReport, 2, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.cancelButton, 3, 0, Qt.AlignRight)
+ gridLayout.addWidget(self.doneButton, 3, 0, Qt.AlignRight)
+
+ return gridLayout
+
+ def progressCanceled(self):
+ self.progressDone(True)
+
+ def progressDone(self, cancel=False):
+ self.lockMenuButtons = False
+ self.cancelButton.setVisible(False)
+ self.doneButton.setVisible(True)
+
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Backup finished.</font>")
+ if not cancel:
+ totalSize = "%.2f" % (self.totalSize/(1024.0**2))
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(self.backedUpNumber) +\
+ " Files - " + totalSize + " MB</font>")
+ else:
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2> Canceled")
+ self.categoryLabel.setText("")
+ self.progressBar.setValue(100)
+
+
+ self.infLabel.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select an action</font>")
+
+ def updateInfo(self, totalSize, backedUpNumber):
+ self.totalSize = totalSize
+ self.backedUpNumber = backedUpNumber
+
+ def setProgress(self, progress):
+ self.progressBar.setValue(progress)
+
+ self.progressReport.setText("<font style='color:"\
+ "#333333'; size=2>"\
+ + str(int(progress))+\
+ "% Complete</font>")
+
+ def setCategory(self, category):
+ self.categoryLabel.setText("<font style='color:"\
+ "#333333'; size=2> Category name: "\
+ + category +"</font>")
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from functools import partial
+
+from ui.pcsuiutils import *
+from ui.tsuigeneralmethods import *
+
+from style.styleTabletSuite import *
+
+from backup.pcsbackupmanager import PcsBackupManager, DEVICES_POINT, USER_HOST
+from backup.pcspcbackupmanager import PcsPcBackupManager
+from backup.pcsdevicebackupmanager import PcsDeviceBackupManager
+from pcsbackuplistui import PCSBackupListUi
+from pcsprogressdialog import PcsProgressDialog
+from pcsrestoredialog import PcsRestoreDialog
+from pcsbackuputils import *
+
+
+class PcsRestoreBackupUi(QDialog):
+
+ def __init__(self, deviceInfo, windowManager, parent = None):
+ super(PcsRestoreBackupUi, self).__init__(parent)
+ self.deviceInfo = deviceInfo
+
+ self.windowManager = windowManager
+ self.pcBackupManager = PcsPcBackupManager()
+ self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
+ self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
+
+ self._buttonRestoreI = QPushButton("Restore")
+ self.connect (self._buttonRestoreI, SIGNAL("clicked()"), self._openRestoreBackup)
+ self._buttonRestoreII = QPushButton("Restore")
+ self.connect (self._buttonRestoreII, SIGNAL("clicked()"), self._openRestoreBackup)
+ self._buttonView = QPushButton("View")
+ self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
+
+ self.pcListView = PCSBackupListUi(self.pcBackupManager)
+
+ self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ self.vLayout = QVBoxLayout()
+
+ self._insertLayout()
+
+ def _createCenterLayout(self):
+ self.deviceListView.updateBackupList()
+ tab = QTabBar()
+ tab.setObjectName("restoreTabs")
+ self.tabBar = QTabWidget()
+ self.tabBar.setTabBar(tab)
+ self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
+ self.tabBar.setObjectName("tabBar")
+ self.tabBar.addTab(self._createPcListViewWidget(), "PC Backups")
+ self.tabBar.addTab(self._createDeviceListViewWidget(), "Device Backups")
+ self.connect(self.tabBar, SIGNAL("currentChanged(int)"),
+ self._updateButtonsState)
+
+ layout = QVBoxLayout()
+ layout.addWidget(self.tabBar)
+
+ return layout
+
+ def _createButtons(self, pcFlag = False):
+ buttonBox = QHBoxLayout()
+ self._buttonRestoreI.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonRestoreI.setDisabled(True)
+ self._buttonRestoreII.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonRestoreII.setDisabled(True)
+ self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self._buttonView.setDisabled(True)
+
+ if pcFlag:
+ buttonBox.addWidget(self._buttonView)
+ buttonBox.addWidget(self._buttonRestoreI)
+ else:
+ buttonBox.addWidget(self._buttonRestoreII)
+
+ return buttonBox
+
+ def _createPcListViewWidget(self):
+ self.pcListView.setObjectName("ListView")
+ pcListViewSelectionModel = self.pcListView.selectionModel()
+ self.connect(pcListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ self.pcListView.updateBackupList()
+
+ panel = QWidget()
+ panel.setAttribute(Qt.WA_NoSystemBackground)
+ panel.setObjectName("DeviceListPanel")
+ vLay = QVBoxLayout()
+
+ vLay.addWidget(self.pcListView)
+ vLay.addLayout(self._createButtons(True))
+ panel.setLayout(vLay)
+
+ return panel
+
+ def _createDeviceListViewWidget(self):
+ self.deviceListView.setObjectName("ListView")
+ deviceListViewSelectionModel = self.deviceListView.selectionModel()
+ self.connect(deviceListViewSelectionModel,
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ self.deviceListView.updateBackupList()
+
+ panel = QWidget()
+ panel.setAttribute(Qt.WA_NoSystemBackground)
+ panel.setObjectName("DeviceListPanel")
+ vLay = QVBoxLayout()
+
+ vLay.addWidget(self.deviceListView)
+ vLay.addLayout(self._createButtons())
+ panel.setLayout(vLay)
+
+ return panel
+
+
+ def _insertLayout(self):
+
+ self.vLayout.setMargin(0)
+ self.wayLayout = self._wayLayout()
+ buttonLayout = self._menuButtons()
+ spc = QSpacerItem(0, 6)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+ spc = QSpacerItem(0, 5)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
+ spc = QSpacerItem(0, 3)
+ self.vLayout.addItem(spc)
+ self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+
+ self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+ spc = QSpacerItem(0, 8)
+ self.vLayout.addItem(spc)
+ self.setLayout(self.vLayout)
+
+ def _menuButtons(self):
+ infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog),
+ ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+ ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED)]
+
+ buttonsLayout = QHBoxLayout()
+ for i in range(3):
+ but = QPushButton(infList[i][0])
+ but.setStyleSheet(infList[i][1])
+ if i <> 2:
+ buttonsLayout.addWidget(but, Qt.AlignLeft)
+ self.connect(but, SIGNAL("clicked()"), infList[i][2])
+ else:
+ buttonsLayout.addWidget(but)
+ return buttonsLayout
+
+ def _wayLayout(self):
+ self.barLayout = QHBoxLayout()
+ self.barLayout.setMargin(0)
+ spc = QSpacerItem(8, 0)
+ self.barLayout.addItem(spc)
+ main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+ restore = QLabel("<font style='color: #FFFFFF'; size=2> Restore backups</font>")
+ spc = QSpacerItem(2, 0)
+ widgetList = [main, self._arrow(), restore]
+
+ for widget in widgetList:
+ self.barLayout.addWidget(widget, Qt.AlignLeft)
+ self.barLayout.addItem(spc)
+
+ self.barLayout.addItem(QSpacerItem(300, 0))
+ return self.barLayout
+
+ def _manageDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ backupManager = self.windowManager.getBackupManager()
+ centralize(backupManager)
+ backupManager.setGeometry(self.geometry())
+ backupManager.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _newBackupDialog(self):
+ if(self.deviceInfo and self.deviceInfo.ip != None):
+ newBackup = self.windowManager.getNewBackup()
+ centralize(newBackup)
+ newBackup.setGeometry(self.geometry())
+ newBackup.show()
+ self.close()
+ else:
+ self._showNoDeviceFoundMessage()
+
+ def _showNoDeviceFoundMessage(self):
+ inf = QMessageBox(self)
+ inf.setWindowTitle("Connect a device.")
+ inf.setText("No devices were found.")
+ inf.show()
+
+ def _arrow(self):
+ label = QLabel()
+ label.setPixmap(QPixmap(BLACK_ARROW))
+ return label
+
+ def _createInformationsLabel(self):
+ hLay = QHBoxLayout()
+
+ self.infLabel = QLabel("<font style='color:"\
+ "#333333'; size=2>"\
+ "Select the backup you wish to restore.</font>")
+ iconAlert = QLabel()
+ iconAlert.setPixmap(QPixmap(ICON_ALERT))
+ spc = QSpacerItem(15, 0)
+ hLay.addItem(spc)
+ hLay.addWidget(iconAlert)
+ hLay.addWidget(self.infLabel, Qt.AlignLeft)
+
+ return hLay
+
+ def _updateButtonsState(self, index):
+ list = self._currentBackupList()
+ selectionModel = list.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ if len(indexList) <> 1:
+ self._buttonView.setDisabled(True)
+ self._buttonRestoreI.setDisabled(True)
+ self._buttonRestoreII.setDisabled(True)
+ else:
+ self._buttonView.setEnabled(True)
+ self._buttonRestoreI.setEnabled(True)
+ self._buttonRestoreII.setEnabled(True)
+
+ def _currentBackupList(self):
+ if self.tabBar.currentIndex() == 0:
+ return self.pcListView
+ else:
+ return self.deviceListView
+
+
+ def doRestoreBackup(self, categories):
+ if self._currentBackupList() == self.pcListView:
+ manager = self.pcBackupManager
+ else:
+ manager = self.deviceBackupManager
+
+ self.restoreBackupThread = RestoreBackupThread(self, manager, categories)
+ self.restoreBackupThread.start()
+ self._runRestoreProgress()
+ self.connect(self.restoreBackupThread, SIGNAL("restoreProgress"),
+ self._updateCategoriesAndProgress)
+ self.connect(self.restoreBackupThread, SIGNAL("restoreDone"),
+ self._onRestodeDone)
+ self.connect(self.restoreBackupThread, SIGNAL("openFileError"),
+ self._onOpenFileError)
+
+ def _openRestoreBackup(self):
+ backup = self._currentBackupList().getSelectedBackup()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.loadBackups()
+ backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+ else:
+ self.deviceBackupManager.loadBackups()
+ backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+
+ host_ip = self.deviceInfo.ip
+ devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
+ mountPath = os.path.join(devicePath, "Root" )
+ mountDevice(USER_HOST, host_ip, mountPath)
+ list = getBackupCategories(backupInfo)
+ unmountDevice(mountPath)
+
+ self.restoreDialog = PcsRestoreDialog(self.deviceInfo, list, self)
+ self.connect(self.restoreDialog.buttonCancel, SIGNAL("clicked()"),
+ self.restoreDialog.close)
+
+ self.connect(self.restoreDialog.buttonOk, SIGNAL("clicked()"),
+ self._doRestoreAndCloseDialog)
+ self.restoreDialog.exec_()
+
+
+ def _doRestoreAndCloseDialog(self):
+ categories = self.restoreDialog.getCategories()
+ self.restoreDialog.close()
+ self.doRestoreBackup(categories)
+
+ def _doRestoreBackup(self, categories):
+ selectedBackups = self._currentBackupList().getSelectedBackupList()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.loadBackups()
+ for backup in selectedBackups:
+ backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+ ip = self.deviceBackupManager._deviceInfo.ip
+ self.emit(SIGNAL("restoreStarted"))
+ result = self.pcBackupManager.startBackupRestore(backupInfo, ip,
+ categories)
+ if result == False or result == 0:
+ return result
+ else:
+ self.deviceBackupManager.loadBackups()
+ for backup in selectedBackups:
+ backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+ self.emit(SIGNAL("restoreStarted"))
+ result = self.deviceBackupManager.startBackupRestore(backupInfo,
+ categories)
+ if result == False or result == 0:
+ return result
+ return True
+
+ def showRestoreMessage(self, done):
+ if done != 0:
+ self._progressDialog.cancel()
+ ip = self.deviceBackupManager._deviceInfo.ip
+ if done:
+ doneMessage = "Restore done. Your device will be rebooted now"
+ showMessageBox(doneMessage, "Restore successfully Done")
+ rebootDevice(ip)
+ else:
+ showMessageBox("An error occurred while restoring backup",
+ "Restore error")
+
+ def _doViewBackup(self):
+ list = self._currentBackupList()
+ backupManager = list.getBackupManager()
+ backupName = (str(list.getSelectedBackup())).strip()
+ if backupName == None:
+ return False
+
+ dialog = QDialog(self, Qt.FramelessWindowHint)
+ dialog.setObjectName("viewDialog")
+ dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+ dialog.setWindowTitle("Backup Files")
+ dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+
+ layout = QVBoxLayout()
+ layout.setMargin(10)
+ listWidget = QListWidget()
+ listWidget.setObjectName("viewList")
+ listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ backupContentList = backupManager.listBackupContent(backupName)
+ if not backupContentList:
+ showMessageBox("Could not open backup files", "Error")
+ return False
+ for backupContent in backupContentList:
+ backup_button = QListWidgetItem()
+ backup_button.setText(backupContent)
+ listWidget.addItem(backup_button)
+
+ okButton = QPushButton("OK")
+ okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
+ visible = partial(dialog.setVisible, False)
+ self.connect(okButton, SIGNAL("clicked()"), visible)
+ hLay = QHBoxLayout()
+ hLay.addItem(QSpacerItem(200,0))
+ hLay.addWidget(okButton)
+ layout.addWidget(listWidget)
+ layout.addLayout(hLay)
+ dialog.setLayout(layout)
+ dialog.show()
+
+ def _runRestoreProgress(self):
+ self._progressDialog = PcsProgressDialog(self)
+ self._progressDialog.setAction("restore")
+ self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
+ self._onRestoreCancel)
+
+ self._progressDialog.show()
+
+ def _updateCategoriesAndProgress(self, information):
+ progress, category, self.numberOfFiles, self.totalSize = information
+
+ self._progressDialog.setProgress(progress)
+ self._progressDialog.setCategory(category)
+
+ def _onRestodeDone(self):
+ self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
+ self._progressDialog.progressDone()
+
+ def _onRestoreCancel(self):
+ self._progressDialog.progressCanceled()
+ if self._currentBackupList() == self.pcListView:
+ self.pcBackupManager.setRestoreInProgress(False)
+ else:
+ self.deviceBackupManager.setRestoreInProgress(False)
+
+ def _onOpenFileError(self):
+ self._progressDialog.close()
+ showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
+
+class RestoreBackupThread(QThread):
+ def __init__(self, restoreBackup, manager, categories):
+ QThread.__init__(self)
+ self.restoreBackup = restoreBackup
+ self.categories = categories
+ self.connect(manager, SIGNAL("restoreProgress"), self._reEmitSignal)
+
+ def _reEmitSignal(self, informations):
+ self.emit(SIGNAL("restoreProgress"), informations)
+
+ def run(self):
+ try:
+ done = self.restoreBackup._doRestoreBackup(self.categories)
+ except IOError:
+ self.emit(SIGNAL("openFileError"))
+ return
+ self.emit(SIGNAL("restoreDone"))
+
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from style.styleTabletSuite import *
+from ui.pcsdevicewidget import PcsDeviceWidget
+from ui.pcsuiutils import *
+
+class PcsRestoreDialog(QDialog):
+
+ def __init__(self, deviceInfo, categoriesList, parent = None):
+ QDialog.__init__(self, parent, Qt.FramelessWindowHint)
+ self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
+ self.setFixedSize(200, 300)
+ self.deviceInfo = deviceInfo
+ self.categories = categoriesList
+ self.validPositions = []
+ self.validCategories = []
+
+ self.layout = QVBoxLayout()
+
+ self.labelLayout = QHBoxLayout()
+ spc = QSpacerItem(15, 0)
+ self.labelLayout.addItem(spc)
+ label = QLabel("Which categories you want to restore?")
+ label.setWordWrap(True)
+ self.labelLayout.addWidget(label)
+ self.labelLayout.setMargin(0)
+ self.layout.addLayout(self.labelLayout)
+
+# self.grid = QGridLayout()
+# self.create_dialog()
+# self.grid.setMargin(0)
+# self.layout.addLayout(self.grid)
+ self.create_checkbox_frame()
+
+ self.buttonLayout = QHBoxLayout()
+ self.create_buttons()
+ self.buttonLayout.setMargin(0)
+ self.layout.addLayout(self.buttonLayout)
+
+ self.setLayout(self.layout)
+ self.map_checked = {self.documents.name: False,
+ self.emails.name: False, self.media.name: False,
+ self.contacts.name: False,
+ self.bookmarks.name: False,
+ self.settings.name: False,
+ self.applications.name: False}
+
+ def empty_map(self):
+ for index in self.map_checked.keys():
+ if self.map_checked[index]:
+ return False
+ return True
+
+ def create_buttons(self):
+ self.buttonOk = QPushButton("Ok")
+ self.buttonOk.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.buttonLayout.addWidget(self.buttonOk)
+
+ self.buttonCancel = QPushButton("Cancel")
+ self.buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
+ self.buttonLayout.addWidget(self.buttonCancel)
+
+ def create_checkbox_frame(self):
+ layout = QVBoxLayout()
+ l = QLabel()
+ l.setPixmap(QPixmap(COPY_BORDER))
+
+ self.frame = QScrollArea(self)
+ self.frame.setObjectName("restoreScroll")
+ self.frame.setWidgetResizable(True)
+ widget = QWidget(self.frame)
+ widget.setStyleSheet("QWidget{background: transparent;}")
+ self.grid = QGridLayout()
+ self.grid.setSpacing(0)
+ self.create_dialog()
+ widget.setLayout(self.grid)
+ self.frame.setWidget(widget)
+ layout.addWidget(self.frame)
+ self.layout.addLayout(layout)
+
+ def create_dialog(self):
+ #Add Checkboxes
+# self.add_select_all()
+ self.add_documents()
+ self.add_emails()
+ self.add_media()
+ self.add_contacts()
+ self.add_bookmarks()
+ self.add_settings()
+ self.add_applications()
+
+# def add_select_all(self):
+# self.select_all = QCheckBox("Select All")
+# self.connect(self.select_all, SIGNAL("stateChanged(int)"),
+# self.select_all_func)
+# self.validPositions.append((1,0))
+# self.grid.addWidget(self.select_all, 1, 0, Qt.AlignTop)
+#
+ def add_documents(self):
+ self.documents = QCheckBox("Documents")
+ self.documents.name = "documents"
+ callback = partial(self.select_func, self.documents)
+ self.connect(self.documents, SIGNAL("stateChanged(int)"),
+ callback)
+ if "documents" in self.categories:
+ self.validPositions.append((2, 0))
+ self.grid.addWidget(self.documents, 2, 0, Qt.AlignTop)
+
+ def add_emails(self):
+ self.emails = QCheckBox("Emails")
+ self.emails.name = "emails"
+ callback = partial(self.select_func, self.emails)
+ self.connect(self.emails, SIGNAL("stateChanged(int)"),
+ callback)
+ if "emails" in self.categories:
+ self.validPositions.append((3, 0))
+ self.grid.addWidget(self.emails, 3, 0, Qt.AlignTop)
+
+ def add_media(self):
+ self.media = QCheckBox("Media")
+ self.media.name = "media"
+ callback = partial(self.select_func, self.media)
+ self.connect(self.media, SIGNAL("stateChanged(int)"),
+ callback)
+ if "media" in self.categories:
+ self.validPositions.append((4, 0))
+ self.grid.addWidget(self.media, 4, 0, Qt.AlignTop)
+
+ def add_contacts(self):
+ self.contacts = QCheckBox("Contacts")
+ self.contacts.name = "contacts"
+ callback = partial(self.select_func, self.contacts)
+ self.connect(self.contacts, SIGNAL("stateChanged(int)"),
+ callback)
+ if "contacts" in self.categories:
+ self.validPositions.append((5, 0))
+ self.grid.addWidget(self.contacts, 5, 0, Qt.AlignTop)
+
+ def add_bookmarks(self):
+ self.bookmarks = QCheckBox("Bookmarks")
+ self.bookmarks.name = "bookmarks"
+ callback = partial(self.select_func, self.bookmarks)
+ self.connect(self.bookmarks, SIGNAL("stateChanged(int)"),
+ callback)
+ if "bookmarks" in self.categories:
+ self.validPositions.append((6, 0))
+ self.grid.addWidget(self.bookmarks, 6, 0, Qt.AlignTop)
+
+ def add_settings(self):
+ self.settings = QCheckBox("Settings")
+ self.settings.name = "settings"
+ callback = partial(self.select_func, self.settings)
+ self.connect(self.settings, SIGNAL("stateChanged(int)"),
+ callback)
+ if "settings" in self.categories:
+ self.validPositions.append((7, 0))
+ self.grid.addWidget(self.settings, 7, 0, Qt.AlignTop)
+
+ def add_applications(self):
+ self.applications = QCheckBox("Applications")
+ self.applications.name = "applications"
+ callback = partial(self.select_func, self.applications)
+ self.connect(self.applications, SIGNAL("stateChanged(int)"),
+ callback)
+ if "applications" in self.categories:
+ self.validPositions.append((8, 0))
+ self.grid.addWidget(self.applications, 8, 0, Qt.AlignTop)
+
+# def select_all_func(self):
+# checked = self.select_all.isChecked()
+# list = self.map_checked.keys()
+# for element in list:
+# self.map_checked[element] = checked
+# for tuple in self.validPositions:
+# self.grid.itemAtPosition(tuple[0], tuple[1]).widget().setChecked(checked)
+#
+ def select_func(self, checkbox):
+ checked = checkbox.isChecked()
+ self.map_checked[checkbox.name] = checked
+ if not checked:
+ list = []
+ for tuple in self.validPositions:
+ item = self.grid.itemAtPosition(tuple[0], tuple[1]).widget()
+# if item == self.select_all:
+# pass
+ if item.isChecked():
+ list.append(item)
+# self.select_all.setChecked(False)
+ for element in list:
+ element.setChecked(True)
+
+ def getCategories(self):
+ return self.map_checked
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from pcsbackupwizard import PcsBackupWizard
+from pcsrestorebackupui import PcsRestoreBackupUi
+from pcsbackupmanagerui import PcsBackupManagerUi
+
+class PcsWindowManager:
+ class _impl:
+ def __init__(self, deviceInfo, parent = None):
+ self.__newBackup = PcsBackupWizard(deviceInfo, self, parent)
+ self.__restoreBackup = PcsRestoreBackupUi(deviceInfo, self, parent)
+ self.__backupManager = PcsBackupManagerUi(deviceInfo, self, parent)
+
+ def getNewBackup(self):
+ return self.__newBackup
+
+ def getRestoreBackup(self):
+ return self.__restoreBackup
+
+ def getBackupManager(self):
+ return self.__backupManager
+
+ __instance = None
+
+ def __init__(self, deviceInfo = None, parent = None):
+ if PcsWindowManager.__instance is None:
+ PcsWindowManager.__instance = PcsWindowManager._impl(deviceInfo, parent)
+ self.__dict__['Singleton_instance'] = PcsWindowManager.__instance
+
+ def __getattr__(self, attr):
+ return getattr(self.__instance, attr)
+
+ def __setattr__(self, attr, value):
+ return setattr(self.__instance, attr, value)
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python
+
+# Ainda continua sendo o codigo do cara, apenas retirei as partes que nao nos interessa.
+# Ainda tem que ver se pode usar o codigo, ou seja, olhar a licensa.
+# Deve ser istalado no dispositivo
+# Otacilio Lacerda
+
+import dbus
+import dbus.service
+import dbus.glib
+import gobject
+
+percent_left = -1
+charging = False
+
+loop = gobject.MainLoop()
+
+class Request(dbus.service.Object):
+ def __init__(self, bus_name):
+ dbus.service.Object.__init__(self, bus_name, '/com/nokia/bme/request')
+
+ @dbus.service.signal('com.nokia.bme.request')
+ def timeleft_info_req(self):
+ pass
+
+ @dbus.service.signal('com.nokia.bme.request')
+ def status_info_req(self):
+ pass
+
+def timeleft_handler(idle_time, active_time):
+ global percent_left
+ percent_left = min(100, 100.0 * idle_time / 15000)
+ loop.quit()
+
+def charging_on_handler():
+ global charging
+ charging = True
+ loop.quit()
+
+def charging_off_handler():
+ global charging
+ charging = False
+ loop.quit()
+
+def getBatteryState(request):
+ global percent_left
+ global charging
+
+ request.status_info_req()
+ loop.run()
+
+ if charging:
+ return -1
+ request.timeleft_info_req()
+ loop.run()
+ return percent_left
+
+if __name__ == "__main__":
+
+ bus = dbus.SystemBus(private = True)
+ bus.add_signal_receiver(timeleft_handler, 'battery_timeleft')
+ bus.add_signal_receiver(charging_on_handler, 'charger_charging_on')
+ bus.add_signal_receiver(charging_on_handler, 'battery_full')
+ bus.add_signal_receiver(charging_off_handler, 'charger_charging_off')
+ bus_name = dbus.service.BusName('com.nokia.bme.request', bus)
+ request = Request(bus_name)
+
+ percent = getBatteryState(request)
+ if percent < 0:
+ print '-1'
+ else:
+ print '%.1f' % (percent)
+
--- /dev/null
+# low_device_info module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+
+class PcsDeviceInfo:
+
+ def __init__(self):
+ self.ip = ""
+ self.storage = 0 # list memory data (FIXME: document the array information
+ self.battery = 0
+ self.model = ""
+ self.name = ""
+ self.hostname = ""
+ self.system = ""
+ self.charging = False
+ self.ossoBackup = ""
--- /dev/null
+# low_device_manager module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+# Module responsible for management of devices informations.
+
+import pickle
+import os
+
+from PyQt4.QtCore import *
+
+import pcsutils as utils
+from pcsdeviceinfo import PcsDeviceInfo
+from pcsdeviceutils import *
+from ui.tsuigeneralmethods import showMessageBox
+
+USER_HOST = 'root'
+HOME = os.path.expanduser("~")
+DEVICES_FILE = os.path.join(HOME, ".pcsuite/devices/.ip_list")
+
+
+class PcsDeviceManager(QObject):
+ """Class responsible for devices management such as adding and removing
+ devices, get batery, memory and name informations and saving Device objects.
+
+ The DeviceManager holds a list of Devices objects and can save and load this
+ list on a file and retrieve information about each Device.
+
+ """
+ _currentIp = None
+ def __init__(self):
+ QObject.__init__(self)
+ self._deviceList = []
+
+ # FIXME: initialize this in another place
+ utils.initDirs()
+ self.loadDevices()
+
+ self._currentIp = None
+
+ def _batteryException(self):
+ errorMessage = "Could not get device battery status, check if " +\
+ "python is installed on your device. To get information about " + \
+ "python installation visit: " +\
+ "http://pymaemo.garage.maemo.org/installation.html"
+ showMessageBox(errorMessage,
+ "Error while collecting device information")
+
+ def _addDevice(self, deviceIp):
+ """Add a new device to list connecting to it in the process.
+
+ Arguments:
+ host_ip -- The IP of the device to connect.
+
+ """
+ self.loadDevices()
+
+ deviceInfo = PcsDeviceInfo()
+ deviceInfo.ip = deviceIp
+ (deviceInfo.name, deviceInfo.system,
+ deviceInfo.ossoBackup) = queryProductInformation(deviceIp)
+ if deviceInfo.name == "NO INFORMATION":
+ return "connectException"
+ try:
+ deviceInfo.battery = float(queryDeviceBattery(deviceIp))
+ except:
+ return "batteryException"
+
+ if deviceInfo.battery < 0:
+ deviceInfo.charging = True
+
+ deviceInfo.storage = queryDeviceStorage(deviceIp)
+
+ if self.getDevice(deviceIp) != None:
+ return deviceInfo
+
+ self._deviceList.append(deviceInfo)
+ self.saveDevices()
+ return deviceInfo
+
+ def removeDevice(self, deviceIp):
+ """Remove a Device from list.
+
+ Arguments:
+ device_ip -- The IP of the device to remove
+
+ """
+ deviceInfo = self.getDevice(deviceIp)
+ if deviceInfo != -1:
+ self._deviceList.remove(deviceInfo)
+ self.saveDevices()
+ return 1
+ else:
+ raise Exception("No device with that ip was found")
+
+ def getDevices(self):
+ """Returns a list with the IP address of all devices in the object's
+ devices list.
+
+ """
+ ips = []
+ for deviceInfo in self._deviceList:
+ ips.append(deviceInfo.ip)
+ return ips
+
+ def saveDevices(self):
+ """Save the list of Device objects in DEVICES_FILE file."""
+ obj = self._deviceList
+ file = open(DEVICES_FILE, "w")
+ pickle.dump(obj, file)
+ file.close()
+
+ def loadDevices(self):
+ """Loads the list of Device objects from DEVICES_FILE path if possible."""
+
+ if os.path.exists(DEVICES_FILE):
+ file = open(DEVICES_FILE)
+ self._deviceList = pickle.load(file)
+ file.close()
+
+ def getDevice(self, ip):
+ # Returns the Device object with the provided ip
+ for deviceInfo in self._deviceList:
+ if deviceInfo.ip == ip:
+ return deviceInfo
+ return None
+
+ def setCurrentDevice (self, ip):
+ self._currentIp = ip
+
+ def getCurrentDevice(self):
+ return self.getDevice(self._currentIp)
+
--- /dev/null
+# low_backup module
+# Authors: Nicholas Alexander && Otacilio Lacerda
+
+import commands
+import os
+
+BATTERY = os.environ['BATTERY_PATH'] + 'battery.py'
+EXECUTE = "./"
+USER_HOST = "root"
+
+def queryProductInformation(deviceIp):
+ """ Update device name by getting device product name and os version
+ informations.
+
+ Use osso-product-info command to get the device and device OS short
+ names and set each to it correspondent attribute.
+
+ """
+
+ info = commands.getoutput("ssh -l %s %s osso-product-info" %
+ (USER_HOST, deviceIp))
+
+ deviceName = _extractOssoInfo(info, "shortName")
+ deviceOs = _extractOssoInfo(info, "shortOS")
+ ossoVersion = _extractOssoInfo(info, "ossoVersion")
+ if deviceName != -1 and deviceOs != -1:
+ deviceName = deviceName.strip("'")
+ deviceOs = deviceOs.strip("'")
+ else:
+ deviceName = "NO INFORMATION"
+ deviceOs = "NO INFORMATION"
+
+ return (deviceName, deviceOs, ossoVersion)
+
+def queryDeviceStorage(deviceIp):
+ """Returns a list of tuples, each tuple representing a memory status.
+
+ Tuples are in this format: (total, used)
+
+ Returns:
+ mem_infos -- List with all tuples holding memory info
+
+ """
+ info = commands.getoutput("ssh -l root %s df" %
+ deviceIp).splitlines()
+ mem_infos = [-1, -1, -1]
+ for line in info:
+ if line.find("/dev/mtdblock4") != -1:
+ if line[-1] == "/":
+ total_used = _get_memory(line, "/dev/mtdblock4")
+ mem_infos.pop(0)
+ mem_infos.insert(0, total_used)
+
+ elif line.find("/media/mmc1") != -1:
+ total_used = _get_memory(line, "/dev/mmcblk0p1")
+ mem_infos.pop(1)
+ mem_infos.insert(1, total_used)
+
+ elif line.find("/media/mmc2") != -1:
+ total_used = _get_memory(line, "/dev/mmcblk1p1")
+ mem_infos.pop(2)
+ mem_infos.insert(2, total_used)
+
+ return mem_infos
+
+def queryDeviceBattery(deviceIp):
+ """Return device current battery status in a string.
+
+ This method runs a python script in the device that returns the battery
+ status, this status is represented by one string with the percentage of
+ battery current charge or the number -1 case battery is charging.
+
+ Returns:
+ text -- Text with the battery status
+
+ """
+
+ # Calls script that returns device battery status
+ os.system("scp %s %s@%s:/tmp" % (BATTERY, USER_HOST, deviceIp))
+ battery_status = commands.getoutput("ssh -l %s %s /usr/bin/python \
+ /tmp/battery.py" % (USER_HOST,
+ deviceIp))
+ return battery_status
+
+def _get_memory(line, path):
+ """Retrieve and return total and used memory information from the given
+ line using the memory path to retrieve the right information.
+
+ This function is to be used with a line of the return of a df command.
+
+ Arguments:
+ line -- The line where the memory information is
+ path -- The path in the begining of the line
+
+ Returns:
+ total -- Total memory
+ used -- Amount of used memory
+
+ """
+ number_of_infos = 0
+ i = len(path) + 1
+ while number_of_infos < 2:
+ char = line[i]
+ if char != " ":
+ start = i
+ end = line.find(" ", start + 1)
+ if number_of_infos == 0:
+ total = line[start: end]
+ elif number_of_infos == 1:
+ used = line[start: end]
+ i = end
+ number_of_infos += 1
+ i += 1
+ return total, used
+
+def _extractOssoInfo(osso_string, info_type="name"):
+ """Read the osso-product-info command return string and extract the
+ needed info depeding on info_type argument.
+
+ Arguments:
+ osso_string -- The string returned by osso-product-info command
+ info_type -- the kind of information to b extracted, can be:
+ name - returns device full name (default)
+ OS - returns device OS full name
+ shortName - returns device short name
+ shortOS - returns device short OS name
+
+ Returns:
+ info -- String with the needed information
+ -1 -- Case the information couldn't be found in the given string
+
+ """
+ detailed_type = ""
+ if info_type == "shortName":
+ detailed_type = "OSSO_PRODUCT_NAME"
+ elif info_type == "shortOS":
+ detailed_type = "OSSO_PRODUCT_RELEASE_NAME"
+ elif info_type == "name":
+ detailed_type = "OSSO_PRODUCT_FULL_NAME"
+ elif info_type == "OS":
+ detailed_type = "OSSO_PRODUCT_RELEASE_FULL_NAME"
+ elif info_type == "ossoVersion":
+ detailed_type = "OSSO_VERSION"
+ else:
+ detailed_type = "OSSO_PRODUCT_FULL_NAME"
+
+ types_list = osso_string.splitlines()
+ info = -1
+ for type_line in types_list:
+ if type_line.startswith(detailed_type):
+ # The second argument is the information itself since informations
+ # are displayed like: OSSO_PRODUCT_RELEASE_NAME='OS 2008'
+ info = type_line.split("=")[1]
+
+ return info
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/pc-suite/!svn/ver/612/trunk/tabletsuite/src/pcsuite
+END
+pcsuite.py
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/pc-suite/!svn/ver/612/trunk/tabletsuite/src/pcsuite/pcsuite.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/pcsuite/__init__.py
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src/pcsuite
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-09-10T20:35:15.948790Z
+612
+pauloouriques
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+pcsuite.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+1762e558bf43ba18c805db6698bf3945
+2009-09-10T20:35:15.948790Z
+612
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2373
+\f
+__init__.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-04-02T19:30:47.227755Z
+61
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+import sys
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsmenu import *
+from ui.pcsapplicationlist import *
+from ui.pcsdeviceviewer import *
+from ui.pcsuiutils import *
+from pcsdevicemanager import PcsDeviceManager
+from ui.pcscustombuttons import PcsCustomButton as customButton
+from ui.pcsbutton import PcsButton
+from style.styleTabletSuite import *
+
+class PCSuite(QMainWindow):
+
+ ''' Class that creates the main window of Pc Suite. '''
+
+ def __init__(self):
+ QMainWindow.__init__(self)
+
+ self.setWindowIcon(QIcon(TABLET_SUITE_LOGO))
+ self.setWindowTitle(APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+
+ self.deviceManager = PcsDeviceManager()
+ self.menuBar = PcsMenu(self.deviceManager, self)
+# self.menuBar.setVisible(False)
+ self.setMenuBar(self.menuBar)
+
+ self.topPanel = PcsApplicationList(self.deviceManager)
+ self.bottomPanel = PcsDeviceViewer(self.deviceManager, self)
+
+ layout = QVBoxLayout()
+ spacer = QSpacerItem(0, 70)
+ layout.addItem(spacer)
+ layout.addWidget(self.topPanel)
+ layout.addWidget(self.bottomPanel)
+ layout.setMargin(0)
+ layout.setSpacing(0)
+ centralize(self)
+
+ centralPanel = QFrame()
+ centralPanel.setLayout(layout)
+ self.setCentralWidget(centralPanel)
+
+ self.connectLabel = PcsButton("connect", self)
+ self.connectLabel.setObjectName("tsButton")
+ self.connectLabel.setGeometry(QRect(14, 365, 94, 35))
+ self.connect(self.connectLabel, SIGNAL("clicked()"), self.bottomPanel.showConnectDialog)
+
+ self.backButton = customButton(BACK_BUTTON, BACK_BUTTON_CLICKED, self)
+ self.backButton.setGeometry(QRect(411, 39, 15, 15))
+ self.connect(self.backButton, SIGNAL("clicked()"), self.back)
+
+ self.forwardButton = customButton(FORWARD_BUTTON, FORWARD_BUTTON_CLICKED, self)
+ self.forwardButton.setGeometry(QRect(430, 39, 15, 15))
+ self.connect(self.forwardButton, SIGNAL("clicked()"), self.forward)
+
+ self.setStyleSheet(STYLESHEET)
+
+
+ def back(self):
+ print "back"
+
+ def forward(self):
+ print "forward"
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+import sys
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsmenu import *
+from ui.pcsapplicationlist import *
+from ui.pcsdeviceviewer import *
+from ui.pcsuiutils import *
+from pcsdevicemanager import PcsDeviceManager
+from ui.pcscustombuttons import PcsCustomButton as customButton
+from ui.pcsbutton import PcsButton
+from style.styleTabletSuite import *
+
+class PCSuite(QMainWindow):
+
+ ''' Class that creates the main window of Pc Suite. '''
+
+ def __init__(self):
+ QMainWindow.__init__(self)
+
+ self.setWindowIcon(QIcon(TABLET_SUITE_LOGO))
+ self.setWindowTitle(APPLICATION_NAME)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+
+ self.deviceManager = PcsDeviceManager()
+ self.menuBar = PcsMenu(self.deviceManager, self)
+# self.menuBar.setVisible(False)
+ self.setMenuBar(self.menuBar)
+
+ self.topPanel = PcsApplicationList(self.deviceManager)
+ self.bottomPanel = PcsDeviceViewer(self.deviceManager, self)
+
+ layout = QVBoxLayout()
+ spacer = QSpacerItem(0, 70)
+ layout.addItem(spacer)
+ layout.addWidget(self.topPanel)
+ layout.addWidget(self.bottomPanel)
+ layout.setMargin(0)
+ layout.setSpacing(0)
+ centralize(self)
+
+ centralPanel = QFrame()
+ centralPanel.setLayout(layout)
+ self.setCentralWidget(centralPanel)
+
+ self.connectLabel = PcsButton("connect", self)
+ self.connectLabel.setObjectName("tsButton")
+ self.connectLabel.setGeometry(QRect(14, 365, 94, 35))
+ self.connect(self.connectLabel, SIGNAL("clicked()"), self.bottomPanel.showConnectDialog)
+
+ self.backButton = customButton(BACK_BUTTON, BACK_BUTTON_CLICKED, self)
+ self.backButton.setGeometry(QRect(411, 39, 15, 15))
+ self.connect(self.backButton, SIGNAL("clicked()"), self.back)
+
+ self.forwardButton = customButton(FORWARD_BUTTON, FORWARD_BUTTON_CLICKED, self)
+ self.forwardButton.setGeometry(QRect(430, 39, 15, 15))
+ self.connect(self.forwardButton, SIGNAL("clicked()"), self.forward)
+
+ self.setStyleSheet(STYLESHEET)
+
+
+ def back(self):
+ print "back"
+
+ def forward(self):
+ print "forward"
+
--- /dev/null
+import os.path
+
+import commands
+import os
+import pwd
+import settings
+import socket
+import sys
+
+import paramiko
+
+from backup.pcsbackuputils import createFolder
+
+sshPath = os.path.expanduser('~/.ssh/')
+known_hosts = os.path.join(sshPath, 'known_hosts')
+log_file = os.path.expanduser('~/.pcsuite/.ssh_log')
+user = 'root'
+keyName = 'rsa_key'
+
+def create_route(host, port=22):
+ # Verify Auth with privateKey
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(15)
+ sock.connect((host, port))
+ sock.close()
+ return True
+ except:
+ print 'No route to host'
+ return False
+
+def verify_exist_keys(host, port=22):
+ try:
+ transport = _create_transport(host, port)
+ except:
+ return False
+ try:
+ getKey = paramiko.RSAKey.from_private_key_file(sshPath + keyName)
+ transport.start_client()
+ transport.auth_publickey(user, getKey)
+ if transport.is_authenticated():
+ transport.close()
+ return True
+ except:
+ # 'Error in auth with publickey, try with password...'
+ return False
+ return False
+
+def keyExchange(host, passwd, port=22):
+ if not os.path.exists(sshPath):
+ createFolder(sshPath)
+
+ # Clean cached keys in ssh-agent
+ os.system('ssh-add -d')
+
+ try:
+ transport = _create_transport(host, port)
+ except:
+ transport.close()
+ return False
+
+ if not _add_host_fingerprint(host):
+ transport.close()
+ return False
+
+ if not _authenticate(user, passwd, transport):
+ transport.close()
+ return False
+
+ if not _add_key_to_host(host, transport):
+ transport.close()
+ return False
+
+ transport.stop_thread()
+ transport.close()
+ return True
+
+def initDirs():
+ settings.makeDirs()
+
+def _create_transport(host, port):
+ # Create a transport and initiate client mode
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.settimeout(15)
+ sock.connect((host, port))
+ except Exception, msg:
+ print 'Connect failed: ' + str(msg)
+ raise Exception('Error while create sockets.')
+ transport = paramiko.Transport(sock)
+ return transport
+
+def _add_host_fingerprint(host):
+ if not os.path.exists(known_hosts):
+ os.system('touch %s' %known_hosts)
+ if os.system('ssh-keyscan -t rsa %s >> %s' %(host, known_hosts)) != 0:
+ return False
+ return True
+
+def _generate_keys():
+ # Generate public and private RSAKey
+ keyFile = os.path.join(sshPath, keyName)
+ if not os.path.exists(keyFile):
+ privateKey = paramiko.RSAKey.generate(2048)
+ privateKey.write_private_key_file(keyFile)
+ login = pwd.getpwuid(os.geteuid())[0]
+ publicKey = '%s %s %s@%s' %(privateKey.get_name(),
+ privateKey.get_base64(),
+ login , socket.gethostname())
+ try:
+ keyFile = open(keyFile + '.pub','w')
+ keyFile.write(publicKey)
+ keyFile.close()
+ except:
+ print 'Error while save the public key'
+ raise Exception()
+ else:
+ try:
+ privateKey = paramiko.RSAKey.from_private_key_file(keyFile)
+ login = pwd.getpwuid(os.geteuid())[0]
+ publicKey = '%s %s %s@%s' %(privateKey.get_name(),
+ privateKey.get_base64(),
+ login , socket.gethostname())
+ except:
+ print 'Error while read the private key'
+ raise Exception()
+ return publicKey
+
+def _authenticate(user, passwd, transport):
+ # Try Auth with password
+ try:
+ transport.start_client()
+ transport.auth_password(user, passwd)
+ except:
+ print 'Verify user or password.'
+ return False
+ if not transport.is_authenticated():
+ print 'Authentication fail'
+ return False
+
+ try:
+ exception = transport.get_exception()
+ if exception:
+ raise exception
+ except Exception, msg:
+ print 'Error in connection: ' + str(msg)
+ return False
+ return True
+
+def _add_key_to_host(host, transport):
+ # Add publickey in host
+ if not transport.is_active():
+ print 'Channel is not active'
+ return False
+
+ paramiko.util.log_to_file(log_file, 10)
+ channel = transport.open_session()
+ try:
+ channel.exec_command('mkdir -p ~/.ssh; echo %s >> .ssh/authorized_keys' % (_generate_keys()))
+ except Exception, msg:
+ print 'Error while generate or add the keys.'
+ channel.close()
+ return False
+ channel.close()
+ return True
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/plugins
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src/plugins
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-06-30T08:48:39.342304Z
+359
+pauloouriques
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
--- /dev/null
+import os
+import os.path
+
+class Settings:
+ def __init__(self):
+ self.home = os.path.expanduser("~")
+ self.default_folder = os.path.join(self.home, ".pcsuite")
+ self.devices_folder = os.path.join(self.default_folder,
+ "devices")
+ self.backup_config_path = os.path.join(self.default_folder, "config")
+ self.backup_folder = os.path.join(self.default_folder, "Backup")
+
+ def initalize(self):
+
+ """Check the existence of required project folders, creating
+ them if needed. Also gives execution permission to all scripts.
+
+ """
+
+ # This is checking if the default folder exists too, because
+ # if it doesn't exist the mount_point won't exist either
+ if not os.path.exists(self.devices_folder):
+ os.makedirs(self.devices_folder)
+ if not os.path.exists(self.backup_config_path):
+ os.makedirs(self.backup_config_path)
+ if not os.path.exists(self.backup_folder):
+ os.makedirs(self.backup_folder)
+
+def makeDirs():
+ s = Settings()
+ s.initalize()
+
+if __name__ == "__main__":
+ makeDirs()
+
+
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 54
+/svn/pc-suite/!svn/ver/652/trunk/tabletsuite/src/style
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/style/__init__.py
+END
+styleTabletSuite.py
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/652/trunk/tabletsuite/src/style/styleTabletSuite.py
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src/style
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-10-05T11:14:02.602311Z
+652
+pauloouriques
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+__init__.py
+file
+
+
+
+
+2009-09-29T18:30:21.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-08-11T18:25:49.287367Z
+542
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
+styleTabletSuite.py
+file
+
+
+
+
+2009-10-08T18:25:37.000000Z
+7c1ee6b259b399ddeab35930daa946eb
+2009-10-05T11:14:02.602311Z
+652
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+19114
+\f
--- /dev/null
+from ui.pcsuiutils import *
+
+STYLESHEET = '''
+ QPushButton {
+ min-height:33px;
+ min-width:64px;
+ max-height:33px;
+ max-width:64px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy: NoFocus;
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ QPushButton#tsButton {
+ color : #636060;
+ background-image: url(''' + BUTTON_BG +''');
+ min-height:33px;
+ min-width:91px;
+ max-height:32px;
+ max-width:93px;
+ border: none;
+ qproperty-focusPolicy : NoFocus;
+ qproperty-icon: none;
+ }
+
+ QPushButton#tsButton::pressed {
+ background-image: url(''' + BUTTON_BG_CLICKED + ''');
+ }
+
+ QPushButton#smallButton {
+ color : gray;
+ border-image: url(''' + BUTTON_BG +''');
+ min-height:20px;
+ min-width:34px;
+ max-height:20px;
+ max-width:34px;
+ border: none;
+ qproperty-focusPolicy : NoFocus;
+ qproperty-icon: none;
+ background:transparent;
+ }
+
+ QPushButton#smallButton::pressed {
+ border-image: url(''' + BUTTON_BG_CLICKED + ''');
+ background:transparent;
+ }
+
+ QMainWindow {
+ background-image: url(''' + BACKGROUND_IMAGE + ''');
+ }
+
+ PcsBackup {
+ background-image: url('''+ BACKUP_BG +''')
+ }
+
+ PcsRestoreBackupUi {
+ background-image: url('''+ RESTORE_BG +''')
+ }
+
+ PcsBackupManagerUi{
+ background-image: url('''+ MANAGER_BG +''')
+ }
+
+ QListWidget {
+ selection-background-color : transparent;
+ }
+
+ QMenuBar::item {
+ background: transparent;
+ }
+
+ QMenuBar {
+ background: transparent;
+ }
+
+ QRadioButton{
+ qproperty-focusPolicy: NoFocus;
+ border-image: url('''+ CHECKBOX_BORDER +''');
+ min-height: 38px;
+ max-height: 38px;
+ }
+
+ QRadioButton::indicator:unchecked {
+ image: url(''' + CHECKBOX_UNCHECKED + ''');
+ }
+
+ QRadioButton::indicator:checked {
+ image: url('''+ CHECKBOX_CHECKED +''');
+ }
+
+ QCheckBox{
+ border-image: url('''+ CHECKBOX_BORDER +''');
+ qproperty-focusPolicy: NoFocus;
+ spacing: 10px;
+ min-height: 38px;
+ max-height: 38px;
+ min-width: 230px;
+ max-width: 230px;
+ }
+
+ QCheckBox::indicator:unchecked {
+ image: url(''' + CHECKBOX_UNCHECKED + ''');
+ }
+
+ QCheckBox::indicator:checked {
+ image: url('''+ CHECKBOX_CHECKED +''');
+ }
+
+ QScrollArea {
+ background: none;
+ margin-top : 0px;
+ min-width: 270px;
+ max-width: 270px;
+ min-height: 243px;
+ max-height: 243px;
+ border-image :url('''+ COPY_BORDER +''');
+ }
+
+ QScrollArea#restoreScroll {
+ margin-top : 0px;
+ min-width: 270px;
+ max-width: 270px;
+ min-height: 150px;
+ max-height: 150px;
+ border-image :url('''+ COPY_BORDER +''');
+ }
+
+ QListWidget {
+ border-style: inset;
+ }
+
+ QInputDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ }
+
+ QScrollBar::sub-line, QScrollBar::add-line{
+ background:none;
+ }
+
+ QScrollBar::add-page, QScrollBar::sub-page{
+ background:none;
+ }
+
+ QScrollBar:vertical {
+ border-image: url(''' + SCROLL_BASE_V + ''');
+ background:none;
+ margin: 0px;
+ min-width:18px;
+ max-width:18px;
+ border: 1px solid grey;
+ }
+
+ QScrollBar:handle:vertical {
+ border-image: url(''' + SCROLL_HANDLE_V +''');
+ }
+
+ QScrollBar:horizontal{
+ border-image: url(''' + SCROLL_BASE_H + ''');
+ background:none;
+ margin: 0px;
+ min-height:18px;
+ max-height:18px;
+ border: 1px solid grey;
+ }
+
+ QScrollBar:handle:horizontal {
+ border-image: url(''' + SCROLL_HANDLE_H +''');
+ }
+
+ QPushButton#buttonBrowse {
+ min-height:25px;
+ min-width:25px;
+ max-height:25px;
+ max-width:25px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BROWSE_BUTTON +''');
+ }
+
+ QLineEdit {
+ border-image: url(''' + BACKUP_NAME_BORDER +''');
+ color: white;
+ }
+
+ QLineEdit#backupNameField {
+ border-image: url(''' + BACKUP_NAME_BORDER +''');
+ color: white;
+ min-height:20px;
+ min-width:171px;
+ max-height:20px;
+ max-width:171px;
+ }
+
+ QLineEdit#pathField {
+ border-image: url(''' + PATH_BORDER +''');
+ color: white;
+ min-height:22px;
+ min-width:241px;
+ max-height:22px;
+ max-width:241px;
+ }
+
+ QLineEdit#ipField {
+ border-image: url(''' + PATH_BORDER +''');
+ color: white;
+ min-height:22px;
+ min-width:215px;
+ max-height:22px;
+ max-width:215px;
+ }
+
+ QProgressBar#progressBarWizard {
+ min-height: 18px;
+ min-width: 353px;
+ max-height: 18px;
+ max-width: 353px;
+ border-image: url(''' + PROGRESS_BAR_BORDER +''');
+ }
+
+ QProgressBar#progressBarWizard::chunk{
+ background-image:url(''' + PROGRESS_BAR_CHUNK +''');
+ max-height: 18px;
+ margin: 0px;
+ }
+
+ QProgressBar#progressBarDialog {
+ min-height: 18px;
+ min-width: 260px;
+ max-height: 18px;
+ max-width: 260px;
+ border-image: url(''' + PROGRESS_BAR_BORDER +''');
+ }
+
+ QProgressBar#progressBarDialog::chunk{
+ background-image:url(''' + PROGRESS_BAR_CHUNK_DIALOG +''');
+ max-height: 18px;
+ margin: 0px;
+ }
+
+ QProgressDialog#progressDialog{
+ background-image:url(''' + DEFAULT_BG +''');
+ }
+
+ QWidget#DeviceListPanel {
+ background-color: transparent;
+ min-height: 265px;
+ min-width: 370px;
+ max-height: 265px;
+ max-width: 370px;
+ }
+
+ QTabWidget#tabBar::pane {
+ border-top: 10px solid transparent;
+ border-left: 40px solid transparent;
+ background-color: transparent;
+ }
+
+ QTableView#ListView {
+ border-image: url(''' + TABLE_BORDER + ''');
+ background-color: transparent;
+ qproperty-focusPolicy: NoFocus;
+ color: white;
+ alternate-background-color: #afafaf;
+ padding: 0px;
+ selection-background-color: #ced1cc;
+ selection-color: #1d544f;
+ show-decoration-selected: 0;
+ border: 2px;
+ min-height: 200px;
+ max-height: 200px;
+ min-width: 350px;
+ max-width: 350px;
+
+ }
+
+ QTableView#ipList {
+ border-image: url(''' + IP_LIST_BORDER + ''');
+ background-color: transparent;
+ qproperty-focusPolicy: NoFocus;
+ color: white;
+ alternate-background-color: #afafaf;
+ padding: 0px;
+ selection-background-color: #ced1cc;
+ selection-color: #1d544f;
+ show-decoration-selected: 0;
+ border: 2px;
+ min-height: 120px;
+ max-height: 120px;
+ min-width: 248px;
+ max-width: 248px;
+
+ }
+
+ QScrollArea#listScrollArea {
+
+ }
+
+ QHeaderView#listHeader {
+ background-color: gray;
+
+ }
+
+ QHeaderView#listHeader::section {
+ border-top: 10px solid transparent;
+ border-color: transparent;
+ background-color: transparent;
+ color: Black;
+ font: 10px;
+ }
+
+ QTabBar#restoreTabs {
+ qproperty-focusPolicy: NoFocus;
+ }
+
+ QTabBar#restoreTabs::tab {
+ background-color: transparent;
+ border: none;
+ min-width: 215px;
+ max-width: 215px;
+ padding: 0px;
+
+ }
+
+ QTabBar#restoreTabs::tab:selected {
+ color: white;
+ }
+
+ QTabBar#managerTabs {
+ qproperty-focusPolicy: NoFocus;
+ }
+
+ QTabBar#managerTabs::tab {
+ background-color: transparent;
+ border: none;
+ min-width: 215px;
+ max-width: 215px;
+ padding: 0px;
+
+ }
+
+ QTabBar#managerTabs::tab:selected {
+ color: white;
+ }
+
+ QTabBar#managerTabs::tab:!selected {
+ color: black;
+ }
+
+ QDialog#connectDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 289px;
+ max-height: 289px;
+ min-width: 275px;
+ }
+
+ QDialog#viewDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 190px;
+ max-height: 190px;
+ min-width: 300px;
+ max-width: 300px;
+ }
+
+ QDialog#copyDialogToDevice{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 140px;
+ max-height: 140px;
+ min-width: 230px;
+ max-width: 230px;
+ }
+
+ QDialog#copyDialogFromDevice{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 110px;
+ max-height: 110px;
+ min-width: 260px;
+ max-width: 260px;
+ }
+
+ PcsRestoreDialog {
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 250px;
+ max-height: 250px;
+ min-width: 300px;
+ max-width: 300px;
+ }
+
+ QListWidget#viewList{
+ border-image: url(''' + VIEW_BORDER + ''');
+ qproperty-focusPolicy: NoFocus;
+ padding: 5px;
+ }
+
+ PcsProgressDialog {
+ background-image: url('''+ DEFAULT_BG +''');
+ min-height: 150px;
+ max-height: 150px;
+ min-width: 295px;
+ max-width: 295px;
+ }
+
+ '''
+
+
+
+
+BACKUP_BUTTON_STYLE = '''
+
+ QPushButton {
+ color : gray;
+ min-height:35px;
+ min-width:79px;
+ max-height:35px;
+ max-width:79px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BT_NEXT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' +BT_NEXT_CLICKED + ''');
+ }
+
+ '''
+
+DEFAULT_BUTTON_STYLE = '''
+
+ QPushButton {
+ min-height:33px;
+ min-width:64px;
+ max-height:33px;
+ max-width:64px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ '''
+SMALL_DEFAULT_BUTTON_STYLE = '''
+
+ QPushButton {
+ min-height:20px;
+ min-width:34px;
+ max-height:20px;
+ max-width: 34px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + SMALL_DEFAULT_BUTTON + ''')
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + SMALL_DEFAULT_BUTTON_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ '''
+
+SMALL_ICON_NEW_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:125px;
+ max-height:25px;
+ max-width: 125px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_NEW_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_NEW_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:125px;
+ max-height:25px;
+ max-width: 125px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_NEW_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_MANAGER_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:138px;
+ max-height:25px;
+ max-width: 138px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_MANAGER_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_MANAGER_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:138px;
+ max-height:25px;
+ max-width: 138px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_MANAGER_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_RESTORE_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:130px;
+ max-height:25px;
+ max-width: 130px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_RESTORE_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:130px;
+ max-height:25px;
+ max-width: 130px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_RESTORE_BACKUP + ''')
+ }
+ '''
+MESSAGE_BOX_DEFAULT = '''
+
+ QMessageBox {
+ background-image: url('''+ DEFAULT_BG +''');
+ color: black;
+ }
+ ''' + DEFAULT_BUTTON_STYLE
+
+MESSAGE_BOX_APP = '''
+ QMessageBox {
+ background-image: url('''+ DEFAULT_BG +''');
+ color: black;
+ }
+ QAbstractButton {
+ color : #636060;
+ background-image: url(''' + BUTTON_BG +''');
+ min-height:33px;
+ min-width:91px;
+ max-height:32px;
+ max-width:93px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy: NoFocus;
+ }
+ QAbstractButton::pressed {
+ background-image: url(''' + BUTTON_BG_CLICKED + ''');
+ }
+ '''
+
\ No newline at end of file
--- /dev/null
+from ui.pcsuiutils import *
+
+STYLESHEET = '''
+ QPushButton {
+ min-height:33px;
+ min-width:64px;
+ max-height:33px;
+ max-width:64px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy: NoFocus;
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ QPushButton#tsButton {
+ color : #636060;
+ background-image: url(''' + BUTTON_BG +''');
+ min-height:33px;
+ min-width:91px;
+ max-height:32px;
+ max-width:93px;
+ border: none;
+ qproperty-focusPolicy : NoFocus;
+ qproperty-icon: none;
+ }
+
+ QPushButton#tsButton::pressed {
+ background-image: url(''' + BUTTON_BG_CLICKED + ''');
+ }
+
+ QPushButton#smallButton {
+ color : gray;
+ border-image: url(''' + BUTTON_BG +''');
+ min-height:20px;
+ min-width:34px;
+ max-height:20px;
+ max-width:34px;
+ border: none;
+ qproperty-focusPolicy : NoFocus;
+ qproperty-icon: none;
+ background:transparent;
+ }
+
+ QPushButton#smallButton::pressed {
+ border-image: url(''' + BUTTON_BG_CLICKED + ''');
+ background:transparent;
+ }
+
+ QMainWindow {
+ background-image: url(''' + BACKGROUND_IMAGE + ''');
+ }
+
+ PcsBackup {
+ background-image: url('''+ BACKUP_BG +''')
+ }
+
+ PcsRestoreBackupUi {
+ background-image: url('''+ RESTORE_BG +''')
+ }
+
+ PcsBackupManagerUi{
+ background-image: url('''+ MANAGER_BG +''')
+ }
+
+ QListWidget {
+ selection-background-color : transparent;
+ }
+
+ QMenuBar::item {
+ background: transparent;
+ }
+
+ QMenuBar {
+ background: transparent;
+ }
+
+ QRadioButton{
+ qproperty-focusPolicy: NoFocus;
+ border-image: url('''+ CHECKBOX_BORDER +''');
+ min-height: 38px;
+ max-height: 38px;
+ }
+
+ QRadioButton::indicator:unchecked {
+ image: url(''' + CHECKBOX_UNCHECKED + ''');
+ }
+
+ QRadioButton::indicator:checked {
+ image: url('''+ CHECKBOX_CHECKED +''');
+ }
+
+ QCheckBox{
+ border-image: url('''+ CHECKBOX_BORDER +''');
+ qproperty-focusPolicy: NoFocus;
+ spacing: 10px;
+ min-height: 38px;
+ max-height: 38px;
+ min-width: 230px;
+ max-width: 230px;
+ }
+
+ QCheckBox::indicator:unchecked {
+ image: url(''' + CHECKBOX_UNCHECKED + ''');
+ }
+
+ QCheckBox::indicator:checked {
+ image: url('''+ CHECKBOX_CHECKED +''');
+ }
+
+ QScrollArea {
+ background: none;
+ margin-top : 0px;
+ min-width: 270px;
+ max-width: 270px;
+ min-height: 243px;
+ max-height: 243px;
+ border-image :url('''+ COPY_BORDER +''');
+ }
+
+ QScrollArea#restoreScroll {
+ margin-top : 0px;
+ min-width: 270px;
+ max-width: 270px;
+ min-height: 150px;
+ max-height: 150px;
+ border-image :url('''+ COPY_BORDER +''');
+ }
+
+ QListWidget {
+ border-style: inset;
+ }
+
+ QInputDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ }
+
+ QScrollBar::sub-line, QScrollBar::add-line{
+ background:none;
+ }
+
+ QScrollBar::add-page, QScrollBar::sub-page{
+ background:none;
+ }
+
+ QScrollBar:vertical {
+ border-image: url(''' + SCROLL_BASE_V + ''');
+ background:none;
+ margin: 0px;
+ min-width:18px;
+ max-width:18px;
+ border: 1px solid grey;
+ }
+
+ QScrollBar:handle:vertical {
+ border-image: url(''' + SCROLL_HANDLE_V +''');
+ }
+
+ QScrollBar:horizontal{
+ border-image: url(''' + SCROLL_BASE_H + ''');
+ background:none;
+ margin: 0px;
+ min-height:18px;
+ max-height:18px;
+ border: 1px solid grey;
+ }
+
+ QScrollBar:handle:horizontal {
+ border-image: url(''' + SCROLL_HANDLE_H +''');
+ }
+
+ QPushButton#buttonBrowse {
+ min-height:25px;
+ min-width:25px;
+ max-height:25px;
+ max-width:25px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BROWSE_BUTTON +''');
+ }
+
+ QLineEdit {
+ border-image: url(''' + BACKUP_NAME_BORDER +''');
+ color: white;
+ }
+
+ QLineEdit#backupNameField {
+ border-image: url(''' + BACKUP_NAME_BORDER +''');
+ color: white;
+ min-height:20px;
+ min-width:171px;
+ max-height:20px;
+ max-width:171px;
+ }
+
+ QLineEdit#pathField {
+ border-image: url(''' + PATH_BORDER +''');
+ color: white;
+ min-height:22px;
+ min-width:241px;
+ max-height:22px;
+ max-width:241px;
+ }
+
+ QLineEdit#ipField {
+ border-image: url(''' + PATH_BORDER +''');
+ color: white;
+ min-height:22px;
+ min-width:215px;
+ max-height:22px;
+ max-width:215px;
+ }
+
+ QProgressBar#progressBarWizard {
+ min-height: 18px;
+ min-width: 353px;
+ max-height: 18px;
+ max-width: 353px;
+ border-image: url(''' + PROGRESS_BAR_BORDER +''');
+ }
+
+ QProgressBar#progressBarWizard::chunk{
+ background-image:url(''' + PROGRESS_BAR_CHUNK +''');
+ max-height: 18px;
+ margin: 0px;
+ }
+
+ QProgressBar#progressBarDialog {
+ min-height: 18px;
+ min-width: 260px;
+ max-height: 18px;
+ max-width: 260px;
+ border-image: url(''' + PROGRESS_BAR_BORDER +''');
+ }
+
+ QProgressBar#progressBarDialog::chunk{
+ background-image:url(''' + PROGRESS_BAR_CHUNK_DIALOG +''');
+ max-height: 18px;
+ margin: 0px;
+ }
+
+ QProgressDialog#progressDialog{
+ background-image:url(''' + DEFAULT_BG +''');
+ }
+
+ QWidget#DeviceListPanel {
+ background-color: transparent;
+ min-height: 265px;
+ min-width: 370px;
+ max-height: 265px;
+ max-width: 370px;
+ }
+
+ QTabWidget#tabBar::pane {
+ border-top: 10px solid transparent;
+ border-left: 40px solid transparent;
+ background-color: transparent;
+ }
+
+ QTableView#ListView {
+ border-image: url(''' + TABLE_BORDER + ''');
+ background-color: transparent;
+ qproperty-focusPolicy: NoFocus;
+ color: white;
+ alternate-background-color: #afafaf;
+ padding: 0px;
+ selection-background-color: #ced1cc;
+ selection-color: #1d544f;
+ show-decoration-selected: 0;
+ border: 2px;
+ min-height: 200px;
+ max-height: 200px;
+ min-width: 350px;
+ max-width: 350px;
+
+ }
+
+ QTableView#ipList {
+ border-image: url(''' + IP_LIST_BORDER + ''');
+ background-color: transparent;
+ qproperty-focusPolicy: NoFocus;
+ color: white;
+ alternate-background-color: #afafaf;
+ padding: 0px;
+ selection-background-color: #ced1cc;
+ selection-color: #1d544f;
+ show-decoration-selected: 0;
+ border: 2px;
+ min-height: 120px;
+ max-height: 120px;
+ min-width: 248px;
+ max-width: 248px;
+
+ }
+
+ QScrollArea#listScrollArea {
+
+ }
+
+ QHeaderView#listHeader {
+ background-color: gray;
+
+ }
+
+ QHeaderView#listHeader::section {
+ border-top: 10px solid transparent;
+ border-color: transparent;
+ background-color: transparent;
+ color: Black;
+ font: 10px;
+ }
+
+ QTabBar#restoreTabs {
+ qproperty-focusPolicy: NoFocus;
+ }
+
+ QTabBar#restoreTabs::tab {
+ background-color: transparent;
+ border: none;
+ min-width: 215px;
+ max-width: 215px;
+ padding: 0px;
+
+ }
+
+ QTabBar#restoreTabs::tab:selected {
+ color: white;
+ }
+
+ QTabBar#managerTabs {
+ qproperty-focusPolicy: NoFocus;
+ }
+
+ QTabBar#managerTabs::tab {
+ background-color: transparent;
+ border: none;
+ min-width: 215px;
+ max-width: 215px;
+ padding: 0px;
+
+ }
+
+ QTabBar#managerTabs::tab:selected {
+ color: white;
+ }
+
+ QTabBar#managerTabs::tab:!selected {
+ color: black;
+ }
+
+ QDialog#connectDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 289px;
+ max-height: 289px;
+ min-width: 275px;
+ }
+
+ QDialog#viewDialog{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 190px;
+ max-height: 190px;
+ min-width: 300px;
+ max-width: 300px;
+ }
+
+ QDialog#copyDialogToDevice{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 140px;
+ max-height: 140px;
+ min-width: 230px;
+ max-width: 230px;
+ }
+
+ QDialog#copyDialogFromDevice{
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 110px;
+ max-height: 110px;
+ min-width: 260px;
+ max-width: 260px;
+ }
+
+ PcsRestoreDialog {
+ background-image: url(''' + DEFAULT_BG + ''');
+ border: none;
+ min-height: 250px;
+ max-height: 250px;
+ min-width: 300px;
+ max-width: 300px;
+ }
+
+ QListWidget#viewList{
+ border-image: url(''' + VIEW_BORDER + ''');
+ qproperty-focusPolicy: NoFocus;
+ padding: 5px;
+ }
+
+ PcsProgressDialog {
+ background-image: url('''+ DEFAULT_BG +''');
+ min-height: 150px;
+ max-height: 150px;
+ min-width: 295px;
+ max-width: 295px;
+ }
+
+ '''
+
+
+
+
+BACKUP_BUTTON_STYLE = '''
+
+ QPushButton {
+ color : gray;
+ min-height:35px;
+ min-width:79px;
+ max-height:35px;
+ max-width:79px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BT_NEXT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' +BT_NEXT_CLICKED + ''');
+ }
+
+ '''
+
+DEFAULT_BUTTON_STYLE = '''
+
+ QPushButton {
+ min-height:33px;
+ min-width:64px;
+ max-height:33px;
+ max-width:64px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT +''');
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + BACKUP_BUTTON_DEFAULT_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ '''
+SMALL_DEFAULT_BUTTON_STYLE = '''
+
+ QPushButton {
+ min-height:20px;
+ min-width:34px;
+ max-height:20px;
+ max-width: 34px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy : NoFocus;
+ background-image: url(''' + SMALL_DEFAULT_BUTTON + ''')
+ }
+
+ QPushButton::pressed {
+ background-image: url(''' + SMALL_DEFAULT_BUTTON_CLICKED + ''');
+ }
+
+ QPushButton::enabled {
+ color:black;
+ }
+
+ '''
+
+SMALL_ICON_NEW_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:125px;
+ max-height:25px;
+ max-width: 125px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_NEW_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_NEW_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:125px;
+ max-height:25px;
+ max-width: 125px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_NEW_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_MANAGER_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:138px;
+ max-height:25px;
+ max-width: 138px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_MANAGER_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_MANAGER_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:138px;
+ max-height:25px;
+ max-width: 138px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_MANAGER_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_RESTORE_BACKUP_STYLE = '''
+ QPushButton {
+ min-height:25px;
+ min-width:130px;
+ max-height:25px;
+ max-width: 130px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_RESTORE_BACKUP + ''')
+ }
+
+ '''
+
+SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED = '''
+ QPushButton {
+ color: white;
+ min-height:25px;
+ min-width:130px;
+ max-height:25px;
+ max-width: 130px;
+ border: none;
+ qproperty-iconSize: 25px 25px;
+ qproperty-focusPolicy : NoFocus;
+ background: transparent;
+ qproperty-icon: url(''' + SMALL_ICON_RESTORE_BACKUP + ''')
+ }
+ '''
+MESSAGE_BOX_DEFAULT = '''
+
+ QMessageBox {
+ background-image: url('''+ DEFAULT_BG +''');
+ color: black;
+ }
+ ''' + DEFAULT_BUTTON_STYLE
+
+MESSAGE_BOX_APP = '''
+ QMessageBox {
+ background-image: url('''+ DEFAULT_BG +''');
+ color: black;
+ }
+ QAbstractButton {
+ color : #636060;
+ background-image: url(''' + BUTTON_BG +''');
+ min-height:33px;
+ min-width:91px;
+ max-height:32px;
+ max-width:93px;
+ border: none;
+ qproperty-icon: none;
+ qproperty-focusPolicy: NoFocus;
+ }
+ QAbstractButton::pressed {
+ background-image: url(''' + BUTTON_BG_CLICKED + ''');
+ }
+ '''
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python
+
+import sys, os
+import optparse
+from PyQt4.QtGui import *
+
+parser = optparse.OptionParser(usage="%prog [options] [project-file]")
+parser.add_option("-l", "--local-dirs", action="store_true", dest="use_local_dirs",
+ help="Use files from the local directory tree")
+
+(options, args) = parser.parse_args()
+if options.use_local_dirs:
+ PATHS = {"IMAGE_PATH" : os.pardir + "/img/",
+ "BATTERY_PATH" : "./"}
+else:
+ PATHS = {"IMAGE_PATH" : "/usr/share/tabletsuite/",
+ "BATTERY_PATH" : "/usr/lib/python2.6/site-packages/src/"}
+
+for var, path in PATHS.iteritems():
+ os.environ.setdefault(var, path)
+
+
+from pcsuite.pcsuite import PCSuite
+
+app = QApplication(sys.argv)
+ps = PCSuite()
+ps.show()
+
+app.exec_()
--- /dev/null
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svn/pc-suite/!svn/ver/651/trunk/tabletsuite/src/ui
+END
+pcsdevicewidget.py
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/624/trunk/tabletsuite/src/ui/pcsdevicewidget.py
+END
+pcsmenu.py
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/pcsmenu.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/__init__.py
+END
+pcscustombuttons.py
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/pcscustombuttons.py
+END
+pcsbutton.py
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/pcsbutton.py
+END
+pcsdeviceinfoviewer.py
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/pcsdeviceinfoviewer.py
+END
+pcsuiutils.py
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svn/pc-suite/!svn/ver/648/trunk/tabletsuite/src/ui/pcsuiutils.py
+END
+pcsapplicationlist.py
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/pc-suite/!svn/ver/612/trunk/tabletsuite/src/ui/pcsapplicationlist.py
+END
+pcsapp.py
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/ui/pcsapp.py
+END
+tsuigeneralmethods.py
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svn/pc-suite/!svn/ver/616/trunk/tabletsuite/src/ui/tsuigeneralmethods.py
+END
+pcsdeviceviewer.py
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/pc-suite/!svn/ver/651/trunk/tabletsuite/src/ui/pcsdeviceviewer.py
+END
--- /dev/null
+K 13
+svn:mergeinfo
+V 0
+
+END
--- /dev/null
+9
+
+dir
+653
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite/trunk/tabletsuite/src/ui
+http://gforge.embedded.ufcg.edu.br/svn/pc-suite
+
+
+
+2009-10-01T16:05:02.177628Z
+651
+nicholas
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ccd57667-b161-0410-a082-fa92f2fb3e95
+\f
+pcsdevicewidget.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+84f28d53fce52d6be1ce09a14a0a1e82
+2009-09-14T19:20:21.821743Z
+624
+amaury
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3004
+\f
+pcsmenu.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+09b541ed1dd300a729ae68ea9f944498
+2009-08-04T18:37:56.490706Z
+510
+amaury
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4005
+\f
+__init__.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d41d8cd98f00b204e9800998ecf8427e
+2009-04-02T19:30:47.227755Z
+61
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+\f
+pcscustombuttons.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+01c999f11e8e38ac29c05fbe9d8a46d9
+2009-08-05T16:55:19.618241Z
+511
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1052
+\f
+pcsbutton.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+8ceb0be1042061439ab2e971a5439fb5
+2009-08-06T18:40:51.041049Z
+523
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+285
+\f
+pcsdeviceinfoviewer.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+ed5d20e8ba52cfb30cedb4b5697f6aa9
+2009-08-18T14:29:37.615498Z
+566
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7187
+\f
+pcsuiutils.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d92be1dd2821ca8bc135e2666c8be881
+2009-09-28T11:36:33.963218Z
+648
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4522
+\f
+pcsapplicationlist.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+d0164df0e34d095d7e6f7d9203a06cf9
+2009-09-10T20:35:15.948790Z
+612
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1583
+\f
+pcsapp.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+80eef7e5d2a325b436d9e9d71d16aee0
+2009-06-30T10:24:42.195284Z
+364
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+390
+\f
+tsuigeneralmethods.py
+file
+
+
+
+
+2009-09-29T18:30:22.000000Z
+4119124fdd8d0ae371ed717af9785a2d
+2009-09-14T12:31:28.560392Z
+616
+pauloouriques
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1062
+\f
+pcsdeviceviewer.py
+file
+
+
+
+
+2009-10-08T18:25:37.000000Z
+20b23b9e27952b9a6598f9df06993c1d
+2009-10-01T16:05:02.177628Z
+651
+nicholas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11580
+\f
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+
+class PcsApp(QDialog):
+
+ ''' Class that represents an application from Pc Suite'''
+
+ def __init__(self, parent=None):
+ super(PcsApp, self).__init__(parent)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from backup.pcsbackup import *
+from pcsuiutils import *
+from tsuigeneralmethods import *
+
+class PcsApplicationList(QFrame):
+
+ ''' Class that creates buttons on the main frame. Each button
+ represents a Pc Suite Application.'''
+
+ def __init__(self, deviceManager, parent=None):
+ super(PcsApplicationList, self).__init__(parent)
+ self.layout = QHBoxLayout()
+ self.setFixedSize(480,200)
+ self.createList()
+ self.setLayout(self.layout)
+ self.deviceManager = deviceManager
+
+ def createList(self):
+ self.listWidget = QListWidget()
+ self.listWidget.setViewMode(QListView.IconMode)
+ self.listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ # Creates Backup application applet
+ backupButton = QListWidgetItem()
+ backupButton.setIcon(QIcon(BACKUP_IMAGE))
+ backupButton.setText("Backup")
+ backupButton.setToolTip("Backup Application")
+ self.listWidget.addItem(backupButton)
+
+ self.connect(self.listWidget,
+ SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
+ self.openBackupApplication)
+
+ self.layout.addWidget(self.listWidget)
+
+ def openBackupApplication(self):
+ deviceInfo = self.deviceManager.getCurrentDevice()
+ backup = PcsBackup(deviceInfo, self)
+ centralize(backup)
+ backup.show()
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PcsButton(QPushButton):
+ def __init__(self, name = "", parent = None):
+ QPushButton.__init__(self, parent)
+ self.setText(name)
+
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PcsCustomButton(QLabel):
+ def __init__(self, image, pressedImage, text = "", parent = None):
+ super(QLabel, self).__init__(parent)
+
+ self.panel = QLabel()
+ self.layout = QHBoxLayout()
+ self.text = QLabel(text)
+ self.defaultPixmap = QPixmap(image)
+ self.pressedPixmap = QPixmap(pressedImage)
+ self.panel.setPixmap(self.defaultPixmap)
+ self.panel.setGeometry(self.defaultPixmap.rect())
+ self.layout.addWidget(self.panel)
+ if(text <> ""):
+ self.layout.addWidget(self.text)
+ self.setLayout(self.layout)
+
+
+ def mouseReleaseEvent(self,event):
+ self.panel.setPixmap(self.defaultPixmap)
+ self.emit(SIGNAL("clicked()"))
+
+ def mousePressEvent(self, event):
+ self.panel.setPixmap(self.pressedPixmap)
+
+ def setTextVisible(self, flag):
+ if flag:
+ pass
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from time import sleep
+import threading
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from pcsuiutils import *
+from ui.pcscustombuttons import PcsCustomButton as customButton
+
+class PcsDeviceInfoViewer(QHBoxLayout):
+
+ ''' Class that displays how the device is connected with the PC'''
+
+ def __init__(self, pcSuite):
+ super(PcsDeviceInfoViewer,self).__init__()
+
+ self.label = QLabel("")
+ self.label.setText("<font style='color: gray'; size=2>Maemo Release</font>")
+ self.label.setFixedSize(90,20)
+
+ self.pcSuite = pcSuite
+ self.l2 = QLabel()
+ pixmap = QPixmap(SSH_IMAGE)
+ self.l2.setPixmap(pixmap)
+
+ spacer = QSpacerItem(60, 60)
+ maemoLayout = QVBoxLayout()
+ maemoLayout.setMargin(0)
+ maemoLayout.addItem(spacer)
+ maemoLayout.addWidget(self.label)
+ maemoLayout.addWidget(self.l2)
+ maemoLayout.addItem(spacer)
+
+ spacer2 = QSpacerItem(0, 32)
+ spacer3 = QSpacerItem(0, 37.6)
+ self.statusLayout = QGridLayout()
+ self.statusLayout.setColumnStretch(1, 1)
+ self.statusLayout.addItem(spacer2, 0, 0)
+ self._createStatusWidget(self.statusLayout)
+ self.statusLayout.addItem(spacer3, 4, 0)
+
+ self.setMargin(0)
+ self.addLayout(maemoLayout)
+ spacer4 = QSpacerItem(10, 10)
+ self.addItem(spacer4)
+ self.addLayout(self.statusLayout)
+
+ self.modelLabel = QLabel("Model", self.pcSuite)
+ self.modelLabel.setText("<font style='color: white'; size=2>Model</font>")
+ self.modelLabel.setGeometry(QRect(330, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+ self.arrowLabel = QLabel(self.pcSuite)
+ self.arrowLabel.setPixmap(QPixmap(WHITE_ARROW))
+ self.arrowLabel.setGeometry(QRect(365, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+ self.deviceNameLabel = QLabel("None", self.pcSuite)
+ self.deviceNameLabel.setText("<font style='color: white'; size=2>None</font>")
+ self.deviceNameLabel.setGeometry(QRect(380, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+
+ self.deviceNameLabel2 = QLabel(self.pcSuite)
+ self.deviceNameLabel2.setText("<font style='color: #333333'; size=2>None</font>")
+ self.deviceNameLabel2.setGeometry(QRect(10, 39, 50, 15))
+
+ self.arrowLabel = QLabel(self.pcSuite)
+ self.arrowLabel.setPixmap(QPixmap(BLACK_ARROW))
+ self.arrowLabel.setGeometry(QRect(40, 39, 15, 15))
+
+ self.actionLabel = QLabel(self.pcSuite)
+ self.actionLabel.setText("<font style='color: white'; size=2>Select option</font>")
+ self.actionLabel.setGeometry(QRect(55, 36, 100, 20))
+
+ self.chargingThread = None;
+
+ def setDeviceInfo(self, deviceInfo):
+ self.deviceInfo = deviceInfo
+ self.label.setText("<font style='color: grey'; size=2>" + deviceInfo.system +"</font>" )
+
+
+ self.label.repaint()
+ self.deviceNameLabel.setText("<font style='color: white'; size=2>"
+ + deviceInfo.name + "</font>")
+ self.deviceNameLabel2.setText("<font style='color: #333333'; size=2>"
+ + deviceInfo.name + "</font>")
+ if(self.chargingThread != None):
+ if self.deviceInfo.charging:
+ self._batteryBar.setToolTip("Charging...")
+ else:
+ self.emit(SIGNAL("stopThread"))
+ self._batteryBar.setToolTip("Battery: %d%%" % (deviceInfo.battery))
+ self._batteryBar.setValue(deviceInfo.battery)
+ else:
+ if self.deviceInfo.charging:
+ self._batteryBar.setToolTip("Charging...")
+ self.chargingThread = ChargingThread(self)
+ self.connect(self.chargingThread, SIGNAL("charging"), self._charging)
+ self.chargingThread.start()
+ else:
+ self._batteryBar.setValue(deviceInfo.battery)
+ self._batteryBar.setToolTip("Battery: %d%%" % (deviceInfo.battery))
+
+
+ memory = deviceInfo.storage
+ tip = ""
+ total_m1 = 0
+ total_m2 = 0
+ current_m1 = 0
+ current_m2 = 0
+ if memory[1] != -1:
+ value_m1 = float(memory[1][1]) * 100 / float(memory[1][0])
+ current_m1 = float(memory[1][1])/1024
+ total_m1 = float(memory[1][0])/1024
+ tip += "MMC1: %.1fMB / %.1fMB - %d%%\n" % (current_m1, total_m1, value_m1)
+
+ if memory[2] != -1:
+ value_m2 = float(memory[2][1]) * 100 / float(memory[2][0])
+ current_m2 = float(memory[2][1])/1024
+ total_m2 = float(memory[2][0])/1024
+ tip += "MMC2: %.1fMB / %.1fMB - %d%%\n" % (current_m2, total_m2, value_m2)
+
+ if total_m1 == 0 and total_m2 == 0:
+ tip = "No external memory found."
+ else:
+ current = current_m1 + current_m2
+ total = total_m1 + total_m2
+ value = (current_m1 + current_m2) * 100 / total
+ tip += "Total: %.1fMB / %.1fMB - %d%%" % (current, total, value)
+ self._memoryBar.setValue(value)
+ self._memoryBar.setToolTip(tip)
+
+ current = float(memory[0][1])/1024
+ total = float(memory[0][0])/1024
+ value = current * 100 / total
+ self._deviceBar.setValue(value)
+ self._deviceBar.setToolTip("Device Memory: %.1fMB / %.1fMB - %d%%" % (current, total, value))
+
+ def _createStatusWidget(self, layout):
+ self._batteryBar = self._newProgressBar(layout, 1, BATTERY_IMAGE)
+ self._deviceBar = self._newProgressBar(layout, 2, DEVICE_MEMORY_IMAGE)
+ self._memoryBar = self._newProgressBar(layout, 3, MEMORY_IMAGE)
+
+ def _newProgressBar(self, layout, line, image):
+ bar = QProgressBar()
+ bar.setMaximum(100)
+ bar.setMinimum(0)
+ bar.setFixedSize(150,12.9)
+ bar.setTextVisible(False)
+ layout.addWidget(bar, line, 0 )
+
+ label = QLabel()
+ label.setFixedSize(30,15)
+ pixmap = QPixmap(image)
+ label.setPixmap(pixmap)
+ layout.addWidget(label, line, 1)
+
+ return bar
+
+ def _charging(self):
+ currentValue = self._batteryBar.value()
+ if(currentValue == 100):
+ self._batteryBar.setValue(0)
+ self._batteryBar.setValue(currentValue + 1)
+ self._batteryBar.repaint()
+
+
+class ChargingThread(QThread):
+ def __init__(self, infoViewer):
+ QThread.__init__(self)
+ self.flag = True
+ self.connect(infoViewer, SIGNAL("stopThread"), self.stopThread)
+ self.connect(infoViewer, SIGNAL("destroyed()"), self.stopThread)
+
+ def stopThread(self):
+ self.flag = False
+
+ def run(self):
+ while(self.flag):
+ try:
+ sleep(0.02)
+ self.emit(SIGNAL("charging"))
+ except:
+ self.stopThread()
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from functools import partial
+from time import sleep
+
+from pcsdeviceinfoviewer import PcsDeviceInfoViewer
+from pcsdevicewidget import PcsDeviceWidget
+from pcsuiutils import *
+from tsuigeneralmethods import *
+from pcsutils import *
+
+from style.styleTabletSuite import *
+from backup.pcswindowmanager import *
+
+class PcsDeviceViewer(QFrame):
+
+ '''Class that displays the devices which are connected to the PC'''
+
+ _ip = "None"
+ CONNECTION_ERROR_MESSAGE = "Could not connect to device with the given IP " + \
+ "address.\nCheck if device is turned on and is properly " + \
+ "connected to network"
+
+ def __init__(self, deviceManager, pcSuite):
+ super(PcsDeviceViewer, self).__init__()
+ self.deviceManager = deviceManager
+ self.deviceManager.loadDevices()
+# self.pcSuite = pcSuite
+ self.setFixedSize(WINDOW_WIDTH, 150)
+ self.deviceWidget = PcsDeviceWidget(0)
+
+ # Create device connection type
+ self.deviceInfoViewer = PcsDeviceInfoViewer(pcSuite)
+
+ self.mainLayout = QHBoxLayout()
+ self.mainLayout.setMargin(0)
+
+ spacer = QSpacerItem(15, 15)
+ self.mainLayout.addItem(spacer)
+ self.mainLayout.addWidget(self.deviceWidget)
+ self.mainLayout.addItem(QSpacerItem(20,20))
+ self.mainLayout.addLayout(self.deviceInfoViewer)
+ self.mainLayout.addItem(spacer)
+ self.setLayout(self.mainLayout)
+
+ self.connectDialog = None
+
+ def checkIp(self, ip):
+ list = ip.split(".")
+ if len(list) != 4:
+ return False
+ for sublist in list:
+ if len(sublist) < 1 or len(sublist) > 3:
+ return False
+ for element in sublist:
+ if not str(element).isdigit():
+ return False
+ return True
+
+ def showConnectDialog(self):
+ if(self.connectDialog == None):
+ self.connectDialog = QDialog(self, Qt.FramelessWindowHint)
+ self.connectDialog.setObjectName("connectDialog")
+ self.connectDialog.setWindowIcon(QIcon(TABLET_SUITE_LOGO))
+ self.connectDialog.setWindowTitle("Device Selection")
+ connectDialogLayout = QVBoxLayout()
+
+ hLayout = QHBoxLayout()
+ addButton = QPushButton("Add")
+ addButton.setObjectName("smallButton")
+ self.connect(addButton, SIGNAL("clicked()"), self.addIp)
+
+ self.ipField = QLineEdit()
+ self.ipField.setText("IP Number")
+ self.ipField.setObjectName("ipField")
+ hLayout.addWidget(self.ipField)
+ hLayout.addWidget(addButton)
+
+ buttonLayout = QHBoxLayout()
+ self.connectButton = QPushButton("Connect")
+ self.connectButton.setObjectName("tsButton")
+ self.connect(self.connectButton, SIGNAL("clicked()"), self._connect)
+
+ self.deleteButton = QPushButton("Delete")
+ self.deleteButton.setObjectName("tsButton")
+ self.connect(self.deleteButton, SIGNAL("clicked()"), self._deleteSelectedIp)
+
+ cancelButton = QPushButton("Cancel")
+ cancelButton.setObjectName("tsButton")
+ setVisible = partial(self.connectDialog.setVisible, False)
+ self.connect(cancelButton, SIGNAL("clicked()"), setVisible)
+
+ buttonLayout.addWidget(self.connectButton)
+ buttonLayout.addWidget(self.deleteButton)
+ buttonLayout.addWidget(cancelButton)
+
+ vLayout = QVBoxLayout()
+ vLayout.setMargin(15)
+ vLayout.addWidget(QLabel("Select the device IP"))
+ vLayout.addLayout(hLayout)
+ vLayout.addWidget(self._createIpList())
+ connectDialogLayout.addLayout(vLayout)
+ connectDialogLayout.addLayout(buttonLayout)
+ self.connectDialog.setLayout(connectDialogLayout)
+ self._updateIpList()
+ self.connectDialog.exec_()
+
+ else:
+ self._updateIpList()
+ self.connectDialog.setVisible(True)
+
+ def _connect(self):
+ self._ip = self.getSelectedIp()
+ if not create_route(self._ip):
+ showMessageBox(self.CONNECTION_ERROR_MESSAGE,
+ "Error while connecting to device")
+ return False
+ if not verify_exist_keys(self._ip):
+ dialog = QMessageBox()
+ dialog.setText( "Wrong Key, It seems that the device key " + \
+ "changed. Do you want to exchange keys again?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ if not self.showPasswdDialog():
+ return False
+ else:
+ return False
+ self._runAddDevice()
+
+ def _createIpList(self):
+ self.ipList = QTableView(self)
+ self.ipList.setObjectName("ipList")
+ self.ipList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+ self.ipList.setAlternatingRowColors(True)
+ self.ipList.setShowGrid(False)
+ self.ipList.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.model = QStandardItemModel()
+ self.ipList.setModel(self.model)
+ self._updateButtonsState()
+ self.connect(self.ipList.selectionModel(),
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ hHeader = QHeaderView(Qt.Horizontal)
+ hHeader.setVisible(False)
+ hHeader.setResizeMode(QHeaderView.ResizeToContents)
+ hHeader.setMinimumSectionSize(225)
+ self.ipList.setHorizontalHeader(hHeader)
+
+ vHeader = QHeaderView(Qt.Vertical)
+ vHeader.setVisible(False)
+ self.ipList.setVerticalHeader(vHeader)
+
+ return self.ipList
+
+ def _deleteSelectedIp(self):
+ dialog = QMessageBox()
+ dialog.setText("Remove selected ip?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_APP)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+ for index in indexList:
+ if index.isValid():
+ try:
+ ipAdress = self.model.itemData(index)[0].toString()
+ self.deviceManager.removeDevice(ipAdress)
+ except:
+ pass
+ finally:
+ self.model.removeRow(index.row())
+
+ def getSelectedIp(self):
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ for index in indexList:
+ if index.isValid():
+ data = self.model.itemData(index)
+ return data[0].toString()
+
+ def showInvalidIpDialog(self):
+ showMessageBox("Invalid ip adress", "Invalid ip")
+
+ def addIp(self):
+ ip = self.ipField.text()
+
+ if self.checkIp(ip):
+ for i in range(self.model.rowCount()):
+ if(self.model.item(i).text() == ip):
+ self.ipField.setText("IP Number")
+ return
+ item = QStandardItem(ip)
+ self.model.appendRow([item])
+ self.ipField.setText("IP Number")
+ else:
+ self.showInvalidIpDialog()
+
+ def showPasswdDialog(self):
+ (passwd, ok) = QInputDialog.getText(self, "Device Selection",
+ "Root Password:",
+ QLineEdit.Password,
+ QString(),
+ Qt.FramelessWindowHint)
+ if ok and not passwd.isEmpty():
+ self._passwd = passwd
+ if not keyExchange(self._ip, self._passwd):
+ errorMessage = "Could not connect to device with the given IP " + \
+ "Could not exchange keys"
+ showMessageBox(errorMessage, "Error while connecting to device")
+ return False
+ return True
+
+ def _updateButtonsState(self):
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+ if len(indexList) > 1 or len(indexList) <= 0:
+ self.connectButton.setDisabled(True)
+ self.deleteButton.setDisabled(True)
+ else:
+ self.connectButton.setEnabled(True)
+ self.deleteButton.setEnabled(True)
+
+ def _createWindowManager(self, deviceInf):
+ if deviceInf != None:
+ PcsWindowManager(deviceInf, self)
+
+ def _runAddDevice(self):
+ self.connectingThread = connectingThread(self.deviceManager, self._ip)
+ self.connect(self.connectingThread, SIGNAL("connectException"), self._connectException)
+ self.connect(self.connectingThread, SIGNAL("createWindowManager"), self._createWindowManager)
+ self.connectingThread.start()
+
+ self.connectionProgress()
+ self.connect(self.connectingThread, SIGNAL("connectionDone"), self.updateDeviceInformation)
+
+ def updateDeviceInformation(self, deviceInfo):
+ self._progressDialog.cancel()
+ self.deviceInfo = deviceInfo
+ self.deviceManager.setCurrentDevice(self._ip)
+ if self.deviceInfo:
+ self.deviceManager.loadDevices()
+ self.deviceWidget.setDeviceInfo(self.deviceInfo)
+ self.deviceInfoViewer.setDeviceInfo(self.deviceInfo)
+ else:
+ showMessageBox("An error occurred while connect.", "Connection error")
+
+ def _updateIpList(self):
+ self.model.clear()
+ devices = self.deviceManager.getDevices()
+ for device in devices:
+ self.model.appendRow(QStandardItem(str(device)))
+
+ def connectionProgress(self):
+ self.connectDialog.setVisible(False)
+ self._progressDialog = QProgressDialog("Connecting...",
+ QString(), 0, -1, self,
+ Qt.FramelessWindowHint)
+ self._progressDialog.setObjectName("progressDialog")
+ self._progressDialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self._progressDialog.setValue(0)
+ self._progressDialog.show()
+
+ def _connectException(self):
+ showMessageBox("", "Error while connect to device")
+
+
+class connectingThread(QThread):
+ def __init__(self, deviceManager, deviceIp):
+ QThread.__init__(self)
+ self.deviceManager = deviceManager
+ self.deviceIp = deviceIp
+
+ def run(self):
+ try:
+ deviceInf = self.deviceManager._addDevice(self.deviceIp)
+ self.emit(SIGNAL("createWindowManager"), deviceInf)
+ self.emit(SIGNAL("connectionDone"), deviceInf)
+ except:
+ self.emit(SIGNAL("connectException"))
+ self.emit(SIGNAL("connectionDone"), None)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+import sys
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from pcsuiutils import *
+from pcsdeviceinfo import *
+
+class PcsDeviceWidget(QFrame):
+
+ def __init__(self, size):
+ super(PcsDeviceWidget, self).__init__()
+ self.layout = QGridLayout()
+ self.layout.setMargin(0)
+ self.gridLayout = QGridLayout()
+ self.hasDeviceName = False
+ self.size = size
+
+ self.deviceLabel = QLabel()
+ if size == 1:
+ img = DEVICE_DISCONNECTED_BACKUP
+ else:
+ img = DEVICE_DISCONNECTED
+ self.deviceLabel.setPixmap(QPixmap(img))
+ self.gridLayout.addWidget(self.deviceLabel, 0, 0, Qt.AlignCenter)
+
+ self.layout.addLayout(self.gridLayout, 0, 0, Qt.AlignCenter)
+ self.setLayout(self.layout)
+
+ def addBorder(self):
+ devices = [(0, None, (None, None)),
+ (1, DEVICE_BACKUP_BORDER, (208, 205)),
+ (2, DEVICE_CHECKBOX_BORDER, (152, 154)),
+ (3, DEVICE_FILE_BORDER, (112, 125))]
+
+ name = devices[self.size][1]
+ self.borderLabel = QLabel()
+ self.borderLabel.setFixedSize(devices[self.size][2][0], devices[self.size][2][1])
+ self.borderLabel.setPixmap(QPixmap(name))
+ self.layout.addWidget(self.borderLabel, 0, 0, Qt.AlignCenter)
+
+ def addDeviceName(self):
+ devices = [(0, None, (None, None)),
+ (1, DEVICE_NAME_BORDER_BACKUP, (174, 23)),
+ (2, DEVICE_NAME_BORDER_CHECKBOX, (100, 23)),
+ (3, DEVICE_NAME_BORDER_FILE, (91, 23))]
+
+ name = devices[self.size][1]
+ self.hasDeviceName = True
+ self.nameLayout = QGridLayout()
+ self.nameLabel = QLabel("Connect a device ")
+ nameBorderLabel = QLabel()
+ nameBorderLabel.setFixedSize(devices[self.size][2][0], devices[self.size][2][1])
+ nameBorderLabel.setPixmap(QPixmap(name))
+ self.nameLayout.addWidget(self.nameLabel, 0, 0, Qt.AlignCenter)
+ self.nameLayout.addWidget(nameBorderLabel, 0, 0, Qt.AlignCenter)
+
+ self.gridLayout.addLayout(self.nameLayout, 1, 0, Qt.AlignCenter)
+
+ def setImage(self, path):
+ self.deviceLabel.setPixmap(QPixmap(path))
+
+ def setDeviceInfo(self, deviceInfo):
+ devices = [(0, N800_FILE, N810_FILE),
+ (1, N800_BACKUP, N810_BACKUP),
+ (2, N800, N810),
+ (3, N800_FILE, N810_FILE)]
+ if(deviceInfo != None):
+ if deviceInfo.name == "N800":
+ name = devices[self.size][1]
+ elif deviceInfo.name == "N810":
+ name = devices[self.size][2]
+ self.deviceLabel.setPixmap(QPixmap(name))
+ self.deviceLabel.repaint()
+ if self.hasDeviceName:
+ self.nameLabel.setText(deviceInfo.name)
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from backup.pcsbackup import *
+from pcsuiutils import *
+
+class PcsMenu(QMenuBar):
+
+ ''' Class that creates a menu bar for Pc Suite '''
+
+ def __init__(self, device_manager, parent = None):
+ super(PcsMenu,self).__init__(parent)
+ self.deviceManager = device_manager
+ self.create_menu_file()
+ #self.create_menu_web()
+ #self.create_menu_settings()
+ #self.create_menu_help()
+
+ def create_menu_file(self):
+
+ self.menu_file = QMenu("File")
+
+ menu_list = [("Backup", self.show_backup_dialog,
+ BACKUP_IMAGE)]
+# ("Synchronize", self.pass_func, ""),
+# ("Connect to Web", self.pass_func, ""),
+# ("Contacts", self.pass_func, ""),
+# ("Messages", self.pass_func, ""),
+# ("Calendar", self.pass_func, ""),
+# ("File manager", self.pass_func, ""),
+# ("Tranfer music", self.pass_func, ""),
+# ("Store images", self.pass_func, ""),
+# ("Video Transfers", self.pass_func, ""),
+# ("Install Applications", self.pass_func, ""),
+# ("Update Phone's Software", self.pass_func,""),
+# ("Download maps", self.pass_func, ""),
+# ("Quit", self.pass_func, image._nokia_icon)]
+
+ for tuple in menu_list:
+ name = tuple[0]
+ callback = tuple[1]
+ icon = tuple[2]
+
+ action = QAction(name, self.menu_file)
+ self.menu_file.addAction(action)
+ self.connect(action, SIGNAL("triggered()"), callback)
+ action.setIcon(QIcon(icon))
+
+ self.addMenu(self.menu_file)
+
+ def create_menu_web(self):
+ self.menu_web = QMenu("Web")
+
+ self.menu_web_pc_suite = QMenu("PC Suite at web")
+ self.menu_web.addMenu(self.menu_web_pc_suite)
+ self.pc_suite_demonstration = QAction("PC Suite demonstration",
+ self.menu_web)
+ self.menu_web.addAction(self.pc_suite_demonstration)
+
+ self.menu_web.addSeparator()
+
+ self.registration_action = QAction("Registration", self.menu_web)
+ self.menu_web.addAction(self.registration_action)
+ self.browse_updates_action = QAction("Browse updates and complements",
+ self.menu_web)
+ self.menu_web.addAction(self.browse_updates_action)
+
+ self.addMenu(self.menu_web)
+
+ def create_menu_settings(self):
+ self.menu_settings = QMenu("Options")
+
+ self.settings_action = QAction("Settings...", self.menu_settings)
+ self.menu_settings.addAction(self.settings_action)
+ self.manage_connections_action = QAction("Manage Connections",
+ self.menu_settings)
+ self.menu_settings.addAction(self.manage_connections_action)
+ self.add_phones_action = QAction("Add more phones",
+ self.menu_settings)
+ self.menu_settings.addAction(self.add_phones_action)
+ self.rename_phone_action = QAction("Rename Phone", self.menu_settings)
+ self.menu_settings.addAction(self.rename_phone_action)
+
+ self.addMenu(self.menu_settings)
+
+ def create_menu_help(self):
+ self.menu_help = QMenu("?")
+ self.addMenu(self.menu_help)
+
+ def show_backup_dialog(self):
+ deviceInfo = self.deviceManager.getCurrentDevice()
+ backup = PcsBackup(deviceInfo, self)
+ centralize(backup)
+ backup.show()
+
--- /dev/null
+"""Module contaning most used general functions"""
+
+import os
+
+from PyQt4 import QtGui
+
+APPLICATION_NAME = "TabletSuite"
+
+IMG_PATH = os.environ['IMAGE_PATH']
+
+BACKUP_IMAGE = IMG_PATH + "backup.png"
+TABLET_SUITE_LOGO = IMG_PATH + "tabletSuite_logo.png"
+SSH_IMAGE = IMG_PATH + "ssh.png"
+BATTERY_IMAGE = IMG_PATH + "battery_bar.png"
+CHARGING_IMAGE = IMG_PATH + "battery_bar_charging.png"
+MEMORY_IMAGE = IMG_PATH + "memory_bar.png"
+DEVICE_MEMORY_IMAGE = IMG_PATH + "device_memory.png"
+BACKGROUND_IMAGE = IMG_PATH + "bg_geral0.png"
+N800, N810 = IMG_PATH + "N800.png", IMG_PATH + "N810.png"
+DEVICE_DISCONNECTED = IMG_PATH + "disconnected.png"
+DEVICE_DISCONNECTED_BACKUP = IMG_PATH + "disconnected_backup.png"
+DEVICE_BACKUP_BORDER = IMG_PATH + "device_backup_border.png"
+DEVICE_CHECKBOX_BORDER = IMG_PATH + "device_checkbox_border.png"
+DEVICE_FILE_BORDER = IMG_PATH + "device_file_border.png"
+DEVICE_NAME_BORDER_BACKUP = IMG_PATH + "device_name_border_backup.png"
+DEVICE_NAME_BORDER_CHECKBOX = IMG_PATH + "device_name_border_checkbox.png"
+DEVICE_NAME_BORDER_FILE = IMG_PATH + "device_name_border_file.png"
+N800_BACKUP = IMG_PATH + "N800_backup.png"
+N800_FILE = IMG_PATH + "N800_file.png"
+N810_BACKUP = IMG_PATH + "N810_backup.png"
+N810_FILE = IMG_PATH + "N810_file.png"
+BLACK_ARROW = IMG_PATH + "black_arrow.png"
+WHITE_ARROW = IMG_PATH + "white_arrow.png"
+BUTTON_BG = IMG_PATH + "button_bg.png"
+BUTTON_BG_CLICKED = IMG_PATH + "button_bg_clicked.png"
+BUTTON_WITH_ICON_BG = IMG_PATH + "button_with_icon_bg.png"
+BUTTON_WITH_ICON_BG_CLICKED = IMG_PATH + "button_with_icon_bg_clicked.png"
+FORWARD_BUTTON = IMG_PATH + "forward_arrow_off.png"
+FORWARD_BUTTON_CLICKED = IMG_PATH + "forward_arrow_on.png"
+BACK_BUTTON = IMG_PATH + "back_arrow_off.png"
+BACK_BUTTON_CLICKED = IMG_PATH + "back_arrow_on.png"
+SMALL_ICON_NEW_BACKUP = IMG_PATH + "small_icon-ref-newbackup.png"
+SMALL_ICON_MANAGER_BACKUP = IMG_PATH + "small_icon-ref-managebackups.png"
+SMALL_ICON_RESTORE_BACKUP = IMG_PATH + "small_icon-ref-restorebackups.png"
+SMALL_ICON_SETTINGS = IMG_PATH + "small_icon-ref-settings.png"
+ICON_NEW_BACKUP = IMG_PATH + "icon-ref-newbackup.png"
+ICON_MANAGER_BACKUP = IMG_PATH + "icon-ref-managebackups.png"
+ICON_RESTORE_BACKUP = IMG_PATH + "icon-ref-restorebackups.png"
+ICON_SETTINGS = IMG_PATH + "icon-ref-settings.png"
+ICON_ALERT = IMG_PATH + "icon-alert-ref.png"
+BACKUP_BG = IMG_PATH + "bg_backup0.png"
+RESTORE_BG = IMG_PATH + "bg_restore.png"
+MANAGER_BG = IMG_PATH + "bg_manager.png"
+COPY_BORDER = IMG_PATH + "copy_border.png"
+CHECKBOX_UNCHECKED = IMG_PATH + "checkbox_unchecked.png"
+CHECKBOX_CHECKED = IMG_PATH + "checkbox_checked.png"
+CHECKBOX_BORDER = IMG_PATH + "checkbox_border.png"
+BT_NEXT = IMG_PATH + "bt_next.png"
+BT_NEXT_CLICKED = IMG_PATH + "bt_next_clicked.png"
+PC_BORDER_FILE = IMG_PATH + "pc_file_border.png"
+PC_IMAGE = IMG_PATH + "pc_image.png"
+PC_NAME_BORDER_FILE = IMG_PATH + "pc_name_border_file.png"
+LARGE_ARROW_IMAGE = IMG_PATH + "large_arrow_image.png"
+LARGE_ARROW_BORDER = IMG_PATH + "large_arrow_border.png"
+BROWSE_BUTTON = IMG_PATH + "browse_button.png"
+BACKUP_NAME_BORDER = IMG_PATH + "backup_name_border.png"
+BACKUP_NAME_BG = IMG_PATH + "backup_name_bg.png"
+PATH_BG = IMG_PATH + "path_bg.png"
+PATH_BORDER = IMG_PATH + "path_border.png"
+SCROLL_BASE_H = IMG_PATH + "scroll_base_h.png"
+SCROLL_BASE_V = IMG_PATH + "scroll_base_v.png"
+SCROLL_HANDLE_H = IMG_PATH + "scroll_handle_h.png"
+SCROLL_HANDLE_V = IMG_PATH + "scroll_handle_v.png"
+BACKUP_BUTTON_DEFAULT_CLICKED = IMG_PATH + "backup_default_button_clicked.png"
+BACKUP_BUTTON_DEFAULT = IMG_PATH + "backup_default_button.png"
+PROGRESS_BAR_BG = IMG_PATH + "progress_bar_bg.png"
+PROGRESS_BAR_DIALOG_BG = IMG_PATH + "progress_bar_dialog_bg.png"
+PROGRESS_BAR_BORDER = IMG_PATH + "progress_bar_border.png"
+PROGRESS_BAR_CHUNK = IMG_PATH + "progress_bar_chunk.png"
+PROGRESS_BAR_CHUNK_DIALOG = IMG_PATH + "progress_bar_chunk_dialog.png"
+TABLE_BORDER = IMG_PATH + "table_border.png"
+TAB_BG_1 = IMG_PATH + "tab_bg_1.png"
+TAB_BG_2 = IMG_PATH + "tab_bg_3.png"
+SMALL_DEFAULT_BUTTON_CLICKED = IMG_PATH + "small_default_button_clicked.png"
+SMALL_DEFAULT_BUTTON = IMG_PATH + "small_default_button.png"
+IP_LIST_BORDER = IMG_PATH + "ip_list_border.png"
+DEFAULT_BG = IMG_PATH + "default_bg.png"
+VIEW_BORDER = IMG_PATH + "view_border.png"
+OPEN_FILE_ERROR = "Could not open backup files. Maybe file is protected by" + \
+" password"
+OPEN_FILE_ERROR_TITLE = "Error while opening file"
+
+TOP_SPACER = QtGui.QSpacerItem(0,30)
+TOP_BAR_X, TOP_BAR_Y = 10, 39
+WINDOW_WIDTH = 453
+WINDOW_HEIGHT = 400
+
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+
+def centralize(widget):
+ screen = QtGui.QDesktopWidget().screenGeometry()
+ size = widget.geometry()
+ widget.move((screen.width() - size.width())/2, (screen.height() - size.height())/2)
+
+def showMessageBox(message, window_title = ""):
+ """ Creates a QMessageBox object and set its window title and text to the
+ given strings.
+
+ Attributes:
+ String message - Message to be displayed inside the message box.
+ String window_title - String representing the title of the message box.
+
+ """
+ message_box = QtGui.QMessageBox()
+ message_box.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ message_box.setWindowFlags(QtCore.Qt.FramelessWindowHint)
+ message_box.setWindowTitle(window_title)
+ message_box.setWindowIcon(QtGui.QIcon(BACKUP_IMAGE))
+ message_box.setText(message)
+ message_box.exec_()
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+
+class PcsApp(QDialog):
+
+ ''' Class that represents an application from Pc Suite'''
+
+ def __init__(self, parent=None):
+ super(PcsApp, self).__init__(parent)
+ self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from backup.pcsbackup import *
+from pcsuiutils import *
+from tsuigeneralmethods import *
+
+class PcsApplicationList(QFrame):
+
+ ''' Class that creates buttons on the main frame. Each button
+ represents a Pc Suite Application.'''
+
+ def __init__(self, deviceManager, parent=None):
+ super(PcsApplicationList, self).__init__(parent)
+ self.layout = QHBoxLayout()
+ self.setFixedSize(480,200)
+ self.createList()
+ self.setLayout(self.layout)
+ self.deviceManager = deviceManager
+
+ def createList(self):
+ self.listWidget = QListWidget()
+ self.listWidget.setViewMode(QListView.IconMode)
+ self.listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+ # Creates Backup application applet
+ backupButton = QListWidgetItem()
+ backupButton.setIcon(QIcon(BACKUP_IMAGE))
+ backupButton.setText("Backup")
+ backupButton.setToolTip("Backup Application")
+ self.listWidget.addItem(backupButton)
+
+ self.connect(self.listWidget,
+ SIGNAL("itemDoubleClicked(QListWidgetItem *)"),
+ self.openBackupApplication)
+
+ self.layout.addWidget(self.listWidget)
+
+ def openBackupApplication(self):
+ deviceInfo = self.deviceManager.getCurrentDevice()
+ backup = PcsBackup(deviceInfo, self)
+ centralize(backup)
+ backup.show()
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PcsButton(QPushButton):
+ def __init__(self, name = "", parent = None):
+ QPushButton.__init__(self, parent)
+ self.setText(name)
+
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+class PcsCustomButton(QLabel):
+ def __init__(self, image, pressedImage, text = "", parent = None):
+ super(QLabel, self).__init__(parent)
+
+ self.panel = QLabel()
+ self.layout = QHBoxLayout()
+ self.text = QLabel(text)
+ self.defaultPixmap = QPixmap(image)
+ self.pressedPixmap = QPixmap(pressedImage)
+ self.panel.setPixmap(self.defaultPixmap)
+ self.panel.setGeometry(self.defaultPixmap.rect())
+ self.layout.addWidget(self.panel)
+ if(text <> ""):
+ self.layout.addWidget(self.text)
+ self.setLayout(self.layout)
+
+
+ def mouseReleaseEvent(self,event):
+ self.panel.setPixmap(self.defaultPixmap)
+ self.emit(SIGNAL("clicked()"))
+
+ def mousePressEvent(self, event):
+ self.panel.setPixmap(self.pressedPixmap)
+
+ def setTextVisible(self, flag):
+ if flag:
+ pass
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from time import sleep
+import threading
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from ui.pcsuiutils import *
+from pcsuiutils import *
+from ui.pcscustombuttons import PcsCustomButton as customButton
+
+class PcsDeviceInfoViewer(QHBoxLayout):
+
+ ''' Class that displays how the device is connected with the PC'''
+
+ def __init__(self, pcSuite):
+ super(PcsDeviceInfoViewer,self).__init__()
+
+ self.label = QLabel("")
+ self.label.setText("<font style='color: gray'; size=2>Maemo Release</font>")
+ self.label.setFixedSize(90,20)
+
+ self.pcSuite = pcSuite
+ self.l2 = QLabel()
+ pixmap = QPixmap(SSH_IMAGE)
+ self.l2.setPixmap(pixmap)
+
+ spacer = QSpacerItem(60, 60)
+ maemoLayout = QVBoxLayout()
+ maemoLayout.setMargin(0)
+ maemoLayout.addItem(spacer)
+ maemoLayout.addWidget(self.label)
+ maemoLayout.addWidget(self.l2)
+ maemoLayout.addItem(spacer)
+
+ spacer2 = QSpacerItem(0, 32)
+ spacer3 = QSpacerItem(0, 37.6)
+ self.statusLayout = QGridLayout()
+ self.statusLayout.setColumnStretch(1, 1)
+ self.statusLayout.addItem(spacer2, 0, 0)
+ self._createStatusWidget(self.statusLayout)
+ self.statusLayout.addItem(spacer3, 4, 0)
+
+ self.setMargin(0)
+ self.addLayout(maemoLayout)
+ spacer4 = QSpacerItem(10, 10)
+ self.addItem(spacer4)
+ self.addLayout(self.statusLayout)
+
+ self.modelLabel = QLabel("Model", self.pcSuite)
+ self.modelLabel.setText("<font style='color: white'; size=2>Model</font>")
+ self.modelLabel.setGeometry(QRect(330, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+ self.arrowLabel = QLabel(self.pcSuite)
+ self.arrowLabel.setPixmap(QPixmap(WHITE_ARROW))
+ self.arrowLabel.setGeometry(QRect(365, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+ self.deviceNameLabel = QLabel("None", self.pcSuite)
+ self.deviceNameLabel.setText("<font style='color: white'; size=2>None</font>")
+ self.deviceNameLabel.setGeometry(QRect(380, 70, WINDOW_WIDTH, WINDOW_HEIGHT))
+
+
+ self.deviceNameLabel2 = QLabel(self.pcSuite)
+ self.deviceNameLabel2.setText("<font style='color: #333333'; size=2>None</font>")
+ self.deviceNameLabel2.setGeometry(QRect(10, 39, 50, 15))
+
+ self.arrowLabel = QLabel(self.pcSuite)
+ self.arrowLabel.setPixmap(QPixmap(BLACK_ARROW))
+ self.arrowLabel.setGeometry(QRect(40, 39, 15, 15))
+
+ self.actionLabel = QLabel(self.pcSuite)
+ self.actionLabel.setText("<font style='color: white'; size=2>Select option</font>")
+ self.actionLabel.setGeometry(QRect(55, 36, 100, 20))
+
+ self.chargingThread = None;
+
+ def setDeviceInfo(self, deviceInfo):
+ self.deviceInfo = deviceInfo
+ self.label.setText("<font style='color: grey'; size=2>" + deviceInfo.system +"</font>" )
+
+
+ self.label.repaint()
+ self.deviceNameLabel.setText("<font style='color: white'; size=2>"
+ + deviceInfo.name + "</font>")
+ self.deviceNameLabel2.setText("<font style='color: #333333'; size=2>"
+ + deviceInfo.name + "</font>")
+ if(self.chargingThread != None):
+ if self.deviceInfo.charging:
+ self._batteryBar.setToolTip("Charging...")
+ else:
+ self.emit(SIGNAL("stopThread"))
+ self._batteryBar.setToolTip("Battery: %d%%" % (deviceInfo.battery))
+ self._batteryBar.setValue(deviceInfo.battery)
+ else:
+ if self.deviceInfo.charging:
+ self._batteryBar.setToolTip("Charging...")
+ self.chargingThread = ChargingThread(self)
+ self.connect(self.chargingThread, SIGNAL("charging"), self._charging)
+ self.chargingThread.start()
+ else:
+ self._batteryBar.setValue(deviceInfo.battery)
+ self._batteryBar.setToolTip("Battery: %d%%" % (deviceInfo.battery))
+
+
+ memory = deviceInfo.storage
+ tip = ""
+ total_m1 = 0
+ total_m2 = 0
+ current_m1 = 0
+ current_m2 = 0
+ if memory[1] != -1:
+ value_m1 = float(memory[1][1]) * 100 / float(memory[1][0])
+ current_m1 = float(memory[1][1])/1024
+ total_m1 = float(memory[1][0])/1024
+ tip += "MMC1: %.1fMB / %.1fMB - %d%%\n" % (current_m1, total_m1, value_m1)
+
+ if memory[2] != -1:
+ value_m2 = float(memory[2][1]) * 100 / float(memory[2][0])
+ current_m2 = float(memory[2][1])/1024
+ total_m2 = float(memory[2][0])/1024
+ tip += "MMC2: %.1fMB / %.1fMB - %d%%\n" % (current_m2, total_m2, value_m2)
+
+ if total_m1 == 0 and total_m2 == 0:
+ tip = "No external memory found."
+ else:
+ current = current_m1 + current_m2
+ total = total_m1 + total_m2
+ value = (current_m1 + current_m2) * 100 / total
+ tip += "Total: %.1fMB / %.1fMB - %d%%" % (current, total, value)
+ self._memoryBar.setValue(value)
+ self._memoryBar.setToolTip(tip)
+
+ current = float(memory[0][1])/1024
+ total = float(memory[0][0])/1024
+ value = current * 100 / total
+ self._deviceBar.setValue(value)
+ self._deviceBar.setToolTip("Device Memory: %.1fMB / %.1fMB - %d%%" % (current, total, value))
+
+ def _createStatusWidget(self, layout):
+ self._batteryBar = self._newProgressBar(layout, 1, BATTERY_IMAGE)
+ self._deviceBar = self._newProgressBar(layout, 2, DEVICE_MEMORY_IMAGE)
+ self._memoryBar = self._newProgressBar(layout, 3, MEMORY_IMAGE)
+
+ def _newProgressBar(self, layout, line, image):
+ bar = QProgressBar()
+ bar.setMaximum(100)
+ bar.setMinimum(0)
+ bar.setFixedSize(150,12.9)
+ bar.setTextVisible(False)
+ layout.addWidget(bar, line, 0 )
+
+ label = QLabel()
+ label.setFixedSize(30,15)
+ pixmap = QPixmap(image)
+ label.setPixmap(pixmap)
+ layout.addWidget(label, line, 1)
+
+ return bar
+
+ def _charging(self):
+ currentValue = self._batteryBar.value()
+ if(currentValue == 100):
+ self._batteryBar.setValue(0)
+ self._batteryBar.setValue(currentValue + 1)
+ self._batteryBar.repaint()
+
+
+class ChargingThread(QThread):
+ def __init__(self, infoViewer):
+ QThread.__init__(self)
+ self.flag = True
+ self.connect(infoViewer, SIGNAL("stopThread"), self.stopThread)
+ self.connect(infoViewer, SIGNAL("destroyed()"), self.stopThread)
+
+ def stopThread(self):
+ self.flag = False
+
+ def run(self):
+ while(self.flag):
+ try:
+ sleep(0.02)
+ self.emit(SIGNAL("charging"))
+ except:
+ self.stopThread()
+
+
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from functools import partial
+from time import sleep
+
+from pcsdeviceinfoviewer import PcsDeviceInfoViewer
+from pcsdevicewidget import PcsDeviceWidget
+from pcsuiutils import *
+from tsuigeneralmethods import *
+from pcsutils import *
+
+from style.styleTabletSuite import *
+from backup.pcswindowmanager import *
+
+class PcsDeviceViewer(QFrame):
+
+ '''Class that displays the devices which are connected to the PC'''
+
+ _ip = "None"
+ CONNECTION_ERROR_MESSAGE = "Could not connect to device with the given IP " + \
+ "address.\nCheck if device is turned on and is properly " + \
+ "connected to network"
+
+ def __init__(self, deviceManager, pcSuite):
+ super(PcsDeviceViewer, self).__init__()
+ self.deviceManager = deviceManager
+ self.deviceManager.loadDevices()
+# self.pcSuite = pcSuite
+ self.setFixedSize(WINDOW_WIDTH, 150)
+ self.deviceWidget = PcsDeviceWidget(0)
+
+ # Create device connection type
+ self.deviceInfoViewer = PcsDeviceInfoViewer(pcSuite)
+
+ self.mainLayout = QHBoxLayout()
+ self.mainLayout.setMargin(0)
+
+ spacer = QSpacerItem(15, 15)
+ self.mainLayout.addItem(spacer)
+ self.mainLayout.addWidget(self.deviceWidget)
+ self.mainLayout.addItem(QSpacerItem(20,20))
+ self.mainLayout.addLayout(self.deviceInfoViewer)
+ self.mainLayout.addItem(spacer)
+ self.setLayout(self.mainLayout)
+
+ self.connectDialog = None
+
+ def checkIp(self, ip):
+ list = ip.split(".")
+ if len(list) != 4:
+ return False
+ for sublist in list:
+ if len(sublist) < 1 or len(sublist) > 3:
+ return False
+ for element in sublist:
+ if not str(element).isdigit():
+ return False
+ return True
+
+ def showConnectDialog(self):
+ if(self.connectDialog == None):
+ self.connectDialog = QDialog(self, Qt.FramelessWindowHint)
+ self.connectDialog.setObjectName("connectDialog")
+ self.connectDialog.setWindowIcon(QIcon(TABLET_SUITE_LOGO))
+ self.connectDialog.setWindowTitle("Device Selection")
+ connectDialogLayout = QVBoxLayout()
+
+ hLayout = QHBoxLayout()
+ addButton = QPushButton("Add")
+ addButton.setObjectName("smallButton")
+ self.connect(addButton, SIGNAL("clicked()"), self.addIp)
+
+ self.ipField = QLineEdit()
+ self.ipField.setText("IP Number")
+ self.ipField.setObjectName("ipField")
+ hLayout.addWidget(self.ipField)
+ hLayout.addWidget(addButton)
+
+ buttonLayout = QHBoxLayout()
+ self.connectButton = QPushButton("Connect")
+ self.connectButton.setObjectName("tsButton")
+ self.connect(self.connectButton, SIGNAL("clicked()"), self._connect)
+
+ self.deleteButton = QPushButton("Delete")
+ self.deleteButton.setObjectName("tsButton")
+ self.connect(self.deleteButton, SIGNAL("clicked()"), self._deleteSelectedIp)
+
+ cancelButton = QPushButton("Cancel")
+ cancelButton.setObjectName("tsButton")
+ setVisible = partial(self.connectDialog.setVisible, False)
+ self.connect(cancelButton, SIGNAL("clicked()"), setVisible)
+
+ buttonLayout.addWidget(self.connectButton)
+ buttonLayout.addWidget(self.deleteButton)
+ buttonLayout.addWidget(cancelButton)
+
+ vLayout = QVBoxLayout()
+ vLayout.setMargin(15)
+ vLayout.addWidget(QLabel("Select the device IP"))
+ vLayout.addLayout(hLayout)
+ vLayout.addWidget(self._createIpList())
+ connectDialogLayout.addLayout(vLayout)
+ connectDialogLayout.addLayout(buttonLayout)
+ self.connectDialog.setLayout(connectDialogLayout)
+ self._updateIpList()
+ self.connectDialog.exec_()
+
+ else:
+ self._updateIpList()
+ self.connectDialog.setVisible(True)
+
+ def _connect(self):
+ self._ip = self.getSelectedIp()
+ if not create_route(self._ip):
+ showMessageBox(self.CONNECTION_ERROR_MESSAGE,
+ "Error while connecting to device")
+ return False
+ if not verify_exist_keys(self._ip):
+ dialog = QMessageBox()
+ dialog.setText( "Wrong Key, It seems that the device key " + \
+ "changed. Do you want to exchange keys again?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ if not self.showPasswdDialog():
+ return False
+ else:
+ return False
+ self._runAddDevice()
+
+ def _createIpList(self):
+ self.ipList = QTableView(self)
+ self.ipList.setObjectName("ipList")
+ self.ipList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+ self.ipList.setAlternatingRowColors(True)
+ self.ipList.setShowGrid(False)
+ self.ipList.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self.model = QStandardItemModel()
+ self.ipList.setModel(self.model)
+ self._updateButtonsState()
+ self.connect(self.ipList.selectionModel(),
+ SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+ self._updateButtonsState)
+
+ hHeader = QHeaderView(Qt.Horizontal)
+ hHeader.setVisible(False)
+ hHeader.setResizeMode(QHeaderView.ResizeToContents)
+ hHeader.setMinimumSectionSize(225)
+ self.ipList.setHorizontalHeader(hHeader)
+
+ vHeader = QHeaderView(Qt.Vertical)
+ vHeader.setVisible(False)
+ self.ipList.setVerticalHeader(vHeader)
+
+ return self.ipList
+
+ def _deleteSelectedIp(self):
+ dialog = QMessageBox()
+ dialog.setText("Remove selected ip?")
+ dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
+ dialog.setStyleSheet(MESSAGE_BOX_APP)
+ ret = dialog.exec_()
+ if ret == QMessageBox.Yes:
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+ for index in indexList:
+ if index.isValid():
+ try:
+ ipAdress = self.model.itemData(index)[0].toString()
+ self.deviceManager.removeDevice(ipAdress)
+ except:
+ pass
+ finally:
+ self.model.removeRow(index.row())
+
+ def getSelectedIp(self):
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+
+ for index in indexList:
+ if index.isValid():
+ data = self.model.itemData(index)
+ return data[0].toString()
+
+ def showInvalidIpDialog(self):
+ showMessageBox("Invalid ip adress", "Invalid ip")
+
+ def addIp(self):
+ ip = self.ipField.text()
+
+ if self.checkIp(ip):
+ for i in range(self.model.rowCount()):
+ if(self.model.item(i).text() == ip):
+ self.ipField.setText("IP Number")
+ return
+ item = QStandardItem(ip)
+ self.model.appendRow([item])
+ self.ipField.setText("IP Number")
+ else:
+ self.showInvalidIpDialog()
+
+ def showPasswdDialog(self):
+ (passwd, ok) = QInputDialog.getText(self, "Device Selection",
+ "Root Password:",
+ QLineEdit.Password,
+ QString(),
+ Qt.FramelessWindowHint)
+ if ok and not passwd.isEmpty():
+ self._passwd = passwd
+ if not keyExchange(self._ip, self._passwd):
+ errorMessage = "Could not connect to device with the given IP " + \
+ "Could not exchange keys"
+ showMessageBox(errorMessage, "Error while connecting to device")
+ return False
+ return True
+
+ def _updateButtonsState(self):
+ selectionModel = self.ipList.selectionModel()
+ indexList = selectionModel.selectedRows()
+ if len(indexList) > 1 or len(indexList) <= 0:
+ self.connectButton.setDisabled(True)
+ self.deleteButton.setDisabled(True)
+ else:
+ self.connectButton.setEnabled(True)
+ self.deleteButton.setEnabled(True)
+
+ def _createWindowManager(self, deviceInf):
+ if deviceInf != None:
+ PcsWindowManager(deviceInf, self)
+
+ def _runAddDevice(self):
+ self.connectingThread = connectingThread(self.deviceManager, self._ip)
+ self.connect(self.connectingThread, SIGNAL("connectException"), self._connectException)
+ self.connect(self.connectingThread, SIGNAL("createWindowManager"), self._createWindowManager)
+ self.connectingThread.start()
+
+ self.connectionProgress()
+ self.connect(self.connectingThread, SIGNAL("connectionDone"), self.updateDeviceInformation)
+
+ def updateDeviceInformation(self, deviceInfo):
+ self._progressDialog.cancel()
+ self.deviceInfo = deviceInfo
+ self.deviceManager.setCurrentDevice(self._ip)
+ if self.deviceInfo:
+ self.deviceManager.loadDevices()
+ self.deviceWidget.setDeviceInfo(self.deviceInfo)
+ self.deviceInfoViewer.setDeviceInfo(self.deviceInfo)
+ else:
+ showMessageBox("An error occurred while connect.", "Connection error")
+
+ def _updateIpList(self):
+ self.model.clear()
+ devices = self.deviceManager.getDevices()
+ for device in devices:
+ self.model.appendRow(QStandardItem(str(device)))
+
+ def connectionProgress(self):
+ self.connectDialog.setVisible(False)
+ self._progressDialog = QProgressDialog("Connecting...",
+ QString(), 0, -1, self,
+ Qt.FramelessWindowHint)
+ self._progressDialog.setObjectName("progressDialog")
+ self._progressDialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+ self._progressDialog.setValue(0)
+ self._progressDialog.show()
+
+ def _connectException(self):
+ showMessageBox("", "Error while connect to device")
+
+
+class connectingThread(QThread):
+ def __init__(self, deviceManager, deviceIp):
+ QThread.__init__(self)
+ self.deviceManager = deviceManager
+ self.deviceIp = deviceIp
+
+ def run(self):
+ try:
+ deviceInf = self.deviceManager._addDevice(self.deviceIp)
+ self.emit(SIGNAL("createWindowManager"), deviceInf)
+ self.emit(SIGNAL("connectionDone"), deviceInf)
+ except:
+ self.emit(SIGNAL("connectException"))
+ self.emit(SIGNAL("connectionDone"), None)
+
\ No newline at end of file
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+import sys
+from functools import partial
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from pcsuiutils import *
+from pcsdeviceinfo import *
+
+class PcsDeviceWidget(QFrame):
+
+ def __init__(self, size):
+ super(PcsDeviceWidget, self).__init__()
+ self.layout = QGridLayout()
+ self.layout.setMargin(0)
+ self.gridLayout = QGridLayout()
+ self.hasDeviceName = False
+ self.size = size
+
+ self.deviceLabel = QLabel()
+ if size == 1:
+ img = DEVICE_DISCONNECTED_BACKUP
+ else:
+ img = DEVICE_DISCONNECTED
+ self.deviceLabel.setPixmap(QPixmap(img))
+ self.gridLayout.addWidget(self.deviceLabel, 0, 0, Qt.AlignCenter)
+
+ self.layout.addLayout(self.gridLayout, 0, 0, Qt.AlignCenter)
+ self.setLayout(self.layout)
+
+ def addBorder(self):
+ devices = [(0, None, (None, None)),
+ (1, DEVICE_BACKUP_BORDER, (208, 205)),
+ (2, DEVICE_CHECKBOX_BORDER, (152, 154)),
+ (3, DEVICE_FILE_BORDER, (112, 125))]
+
+ name = devices[self.size][1]
+ self.borderLabel = QLabel()
+ self.borderLabel.setFixedSize(devices[self.size][2][0], devices[self.size][2][1])
+ self.borderLabel.setPixmap(QPixmap(name))
+ self.layout.addWidget(self.borderLabel, 0, 0, Qt.AlignCenter)
+
+ def addDeviceName(self):
+ devices = [(0, None, (None, None)),
+ (1, DEVICE_NAME_BORDER_BACKUP, (174, 23)),
+ (2, DEVICE_NAME_BORDER_CHECKBOX, (100, 23)),
+ (3, DEVICE_NAME_BORDER_FILE, (91, 23))]
+
+ name = devices[self.size][1]
+ self.hasDeviceName = True
+ self.nameLayout = QGridLayout()
+ self.nameLabel = QLabel("Connect a device ")
+ nameBorderLabel = QLabel()
+ nameBorderLabel.setFixedSize(devices[self.size][2][0], devices[self.size][2][1])
+ nameBorderLabel.setPixmap(QPixmap(name))
+ self.nameLayout.addWidget(self.nameLabel, 0, 0, Qt.AlignCenter)
+ self.nameLayout.addWidget(nameBorderLabel, 0, 0, Qt.AlignCenter)
+
+ self.gridLayout.addLayout(self.nameLayout, 1, 0, Qt.AlignCenter)
+
+ def setImage(self, path):
+ self.deviceLabel.setPixmap(QPixmap(path))
+
+ def setDeviceInfo(self, deviceInfo):
+ devices = [(0, N800_FILE, N810_FILE),
+ (1, N800_BACKUP, N810_BACKUP),
+ (2, N800, N810),
+ (3, N800_FILE, N810_FILE)]
+ if(deviceInfo != None):
+ if deviceInfo.name == "N800":
+ name = devices[self.size][1]
+ elif deviceInfo.name == "N810":
+ name = devices[self.size][2]
+ self.deviceLabel.setPixmap(QPixmap(name))
+ self.deviceLabel.repaint()
+ if self.hasDeviceName:
+ self.nameLabel.setText(deviceInfo.name)
+
+
--- /dev/null
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from backup.pcsbackup import *
+from pcsuiutils import *
+
+class PcsMenu(QMenuBar):
+
+ ''' Class that creates a menu bar for Pc Suite '''
+
+ def __init__(self, device_manager, parent = None):
+ super(PcsMenu,self).__init__(parent)
+ self.deviceManager = device_manager
+ self.create_menu_file()
+ #self.create_menu_web()
+ #self.create_menu_settings()
+ #self.create_menu_help()
+
+ def create_menu_file(self):
+
+ self.menu_file = QMenu("File")
+
+ menu_list = [("Backup", self.show_backup_dialog,
+ BACKUP_IMAGE)]
+# ("Synchronize", self.pass_func, ""),
+# ("Connect to Web", self.pass_func, ""),
+# ("Contacts", self.pass_func, ""),
+# ("Messages", self.pass_func, ""),
+# ("Calendar", self.pass_func, ""),
+# ("File manager", self.pass_func, ""),
+# ("Tranfer music", self.pass_func, ""),
+# ("Store images", self.pass_func, ""),
+# ("Video Transfers", self.pass_func, ""),
+# ("Install Applications", self.pass_func, ""),
+# ("Update Phone's Software", self.pass_func,""),
+# ("Download maps", self.pass_func, ""),
+# ("Quit", self.pass_func, image._nokia_icon)]
+
+ for tuple in menu_list:
+ name = tuple[0]
+ callback = tuple[1]
+ icon = tuple[2]
+
+ action = QAction(name, self.menu_file)
+ self.menu_file.addAction(action)
+ self.connect(action, SIGNAL("triggered()"), callback)
+ action.setIcon(QIcon(icon))
+
+ self.addMenu(self.menu_file)
+
+ def create_menu_web(self):
+ self.menu_web = QMenu("Web")
+
+ self.menu_web_pc_suite = QMenu("PC Suite at web")
+ self.menu_web.addMenu(self.menu_web_pc_suite)
+ self.pc_suite_demonstration = QAction("PC Suite demonstration",
+ self.menu_web)
+ self.menu_web.addAction(self.pc_suite_demonstration)
+
+ self.menu_web.addSeparator()
+
+ self.registration_action = QAction("Registration", self.menu_web)
+ self.menu_web.addAction(self.registration_action)
+ self.browse_updates_action = QAction("Browse updates and complements",
+ self.menu_web)
+ self.menu_web.addAction(self.browse_updates_action)
+
+ self.addMenu(self.menu_web)
+
+ def create_menu_settings(self):
+ self.menu_settings = QMenu("Options")
+
+ self.settings_action = QAction("Settings...", self.menu_settings)
+ self.menu_settings.addAction(self.settings_action)
+ self.manage_connections_action = QAction("Manage Connections",
+ self.menu_settings)
+ self.menu_settings.addAction(self.manage_connections_action)
+ self.add_phones_action = QAction("Add more phones",
+ self.menu_settings)
+ self.menu_settings.addAction(self.add_phones_action)
+ self.rename_phone_action = QAction("Rename Phone", self.menu_settings)
+ self.menu_settings.addAction(self.rename_phone_action)
+
+ self.addMenu(self.menu_settings)
+
+ def create_menu_help(self):
+ self.menu_help = QMenu("?")
+ self.addMenu(self.menu_help)
+
+ def show_backup_dialog(self):
+ deviceInfo = self.deviceManager.getCurrentDevice()
+ backup = PcsBackup(deviceInfo, self)
+ centralize(backup)
+ backup.show()
+
--- /dev/null
+"""Module contaning most used general functions"""
+
+import os
+
+from PyQt4 import QtGui
+
+APPLICATION_NAME = "TabletSuite"
+
+IMG_PATH = os.environ['IMAGE_PATH']
+
+BACKUP_IMAGE = IMG_PATH + "backup.png"
+TABLET_SUITE_LOGO = IMG_PATH + "tabletSuite_logo.png"
+SSH_IMAGE = IMG_PATH + "ssh.png"
+BATTERY_IMAGE = IMG_PATH + "battery_bar.png"
+CHARGING_IMAGE = IMG_PATH + "battery_bar_charging.png"
+MEMORY_IMAGE = IMG_PATH + "memory_bar.png"
+DEVICE_MEMORY_IMAGE = IMG_PATH + "device_memory.png"
+BACKGROUND_IMAGE = IMG_PATH + "bg_geral0.png"
+N800, N810 = IMG_PATH + "N800.png", IMG_PATH + "N810.png"
+DEVICE_DISCONNECTED = IMG_PATH + "disconnected.png"
+DEVICE_DISCONNECTED_BACKUP = IMG_PATH + "disconnected_backup.png"
+DEVICE_BACKUP_BORDER = IMG_PATH + "device_backup_border.png"
+DEVICE_CHECKBOX_BORDER = IMG_PATH + "device_checkbox_border.png"
+DEVICE_FILE_BORDER = IMG_PATH + "device_file_border.png"
+DEVICE_NAME_BORDER_BACKUP = IMG_PATH + "device_name_border_backup.png"
+DEVICE_NAME_BORDER_CHECKBOX = IMG_PATH + "device_name_border_checkbox.png"
+DEVICE_NAME_BORDER_FILE = IMG_PATH + "device_name_border_file.png"
+N800_BACKUP = IMG_PATH + "N800_backup.png"
+N800_FILE = IMG_PATH + "N800_file.png"
+N810_BACKUP = IMG_PATH + "N810_backup.png"
+N810_FILE = IMG_PATH + "N810_file.png"
+BLACK_ARROW = IMG_PATH + "black_arrow.png"
+WHITE_ARROW = IMG_PATH + "white_arrow.png"
+BUTTON_BG = IMG_PATH + "button_bg.png"
+BUTTON_BG_CLICKED = IMG_PATH + "button_bg_clicked.png"
+BUTTON_WITH_ICON_BG = IMG_PATH + "button_with_icon_bg.png"
+BUTTON_WITH_ICON_BG_CLICKED = IMG_PATH + "button_with_icon_bg_clicked.png"
+FORWARD_BUTTON = IMG_PATH + "forward_arrow_off.png"
+FORWARD_BUTTON_CLICKED = IMG_PATH + "forward_arrow_on.png"
+BACK_BUTTON = IMG_PATH + "back_arrow_off.png"
+BACK_BUTTON_CLICKED = IMG_PATH + "back_arrow_on.png"
+SMALL_ICON_NEW_BACKUP = IMG_PATH + "small_icon-ref-newbackup.png"
+SMALL_ICON_MANAGER_BACKUP = IMG_PATH + "small_icon-ref-managebackups.png"
+SMALL_ICON_RESTORE_BACKUP = IMG_PATH + "small_icon-ref-restorebackups.png"
+SMALL_ICON_SETTINGS = IMG_PATH + "small_icon-ref-settings.png"
+ICON_NEW_BACKUP = IMG_PATH + "icon-ref-newbackup.png"
+ICON_MANAGER_BACKUP = IMG_PATH + "icon-ref-managebackups.png"
+ICON_RESTORE_BACKUP = IMG_PATH + "icon-ref-restorebackups.png"
+ICON_SETTINGS = IMG_PATH + "icon-ref-settings.png"
+ICON_ALERT = IMG_PATH + "icon-alert-ref.png"
+BACKUP_BG = IMG_PATH + "bg_backup0.png"
+RESTORE_BG = IMG_PATH + "bg_restore.png"
+MANAGER_BG = IMG_PATH + "bg_manager.png"
+COPY_BORDER = IMG_PATH + "copy_border.png"
+CHECKBOX_UNCHECKED = IMG_PATH + "checkbox_unchecked.png"
+CHECKBOX_CHECKED = IMG_PATH + "checkbox_checked.png"
+CHECKBOX_BORDER = IMG_PATH + "checkbox_border.png"
+BT_NEXT = IMG_PATH + "bt_next.png"
+BT_NEXT_CLICKED = IMG_PATH + "bt_next_clicked.png"
+PC_BORDER_FILE = IMG_PATH + "pc_file_border.png"
+PC_IMAGE = IMG_PATH + "pc_image.png"
+PC_NAME_BORDER_FILE = IMG_PATH + "pc_name_border_file.png"
+LARGE_ARROW_IMAGE = IMG_PATH + "large_arrow_image.png"
+LARGE_ARROW_BORDER = IMG_PATH + "large_arrow_border.png"
+BROWSE_BUTTON = IMG_PATH + "browse_button.png"
+BACKUP_NAME_BORDER = IMG_PATH + "backup_name_border.png"
+BACKUP_NAME_BG = IMG_PATH + "backup_name_bg.png"
+PATH_BG = IMG_PATH + "path_bg.png"
+PATH_BORDER = IMG_PATH + "path_border.png"
+SCROLL_BASE_H = IMG_PATH + "scroll_base_h.png"
+SCROLL_BASE_V = IMG_PATH + "scroll_base_v.png"
+SCROLL_HANDLE_H = IMG_PATH + "scroll_handle_h.png"
+SCROLL_HANDLE_V = IMG_PATH + "scroll_handle_v.png"
+BACKUP_BUTTON_DEFAULT_CLICKED = IMG_PATH + "backup_default_button_clicked.png"
+BACKUP_BUTTON_DEFAULT = IMG_PATH + "backup_default_button.png"
+PROGRESS_BAR_BG = IMG_PATH + "progress_bar_bg.png"
+PROGRESS_BAR_DIALOG_BG = IMG_PATH + "progress_bar_dialog_bg.png"
+PROGRESS_BAR_BORDER = IMG_PATH + "progress_bar_border.png"
+PROGRESS_BAR_CHUNK = IMG_PATH + "progress_bar_chunk.png"
+PROGRESS_BAR_CHUNK_DIALOG = IMG_PATH + "progress_bar_chunk_dialog.png"
+TABLE_BORDER = IMG_PATH + "table_border.png"
+TAB_BG_1 = IMG_PATH + "tab_bg_1.png"
+TAB_BG_2 = IMG_PATH + "tab_bg_3.png"
+SMALL_DEFAULT_BUTTON_CLICKED = IMG_PATH + "small_default_button_clicked.png"
+SMALL_DEFAULT_BUTTON = IMG_PATH + "small_default_button.png"
+IP_LIST_BORDER = IMG_PATH + "ip_list_border.png"
+DEFAULT_BG = IMG_PATH + "default_bg.png"
+VIEW_BORDER = IMG_PATH + "view_border.png"
+OPEN_FILE_ERROR = "Could not open backup files. Maybe file is protected by" + \
+" password"
+OPEN_FILE_ERROR_TITLE = "Error while opening file"
+
+TOP_SPACER = QtGui.QSpacerItem(0,30)
+TOP_BAR_X, TOP_BAR_Y = 10, 39
+WINDOW_WIDTH = 453
+WINDOW_HEIGHT = 400
+
--- /dev/null
+# Authors: Amaury Medeiros, Nicholas Alexander and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+
+from ui.pcsuiutils import *
+from style.styleTabletSuite import *
+
+def centralize(widget):
+ screen = QtGui.QDesktopWidget().screenGeometry()
+ size = widget.geometry()
+ widget.move((screen.width() - size.width())/2, (screen.height() - size.height())/2)
+
+def showMessageBox(message, window_title = ""):
+ """ Creates a QMessageBox object and set its window title and text to the
+ given strings.
+
+ Attributes:
+ String message - Message to be displayed inside the message box.
+ String window_title - String representing the title of the message box.
+
+ """
+ message_box = QtGui.QMessageBox()
+ message_box.setStyleSheet(MESSAGE_BOX_DEFAULT)
+ message_box.setWindowFlags(QtCore.Qt.FramelessWindowHint)
+ message_box.setWindowTitle(window_title)
+ message_box.setWindowIcon(QtGui.QIcon(BACKUP_IMAGE))
+ message_box.setText(message)
+ message_box.exec_()
+
+
--- /dev/null
+#!/bin/bash
+exec /usr/bin/python /usr/lib/python2.6/site-packages/src/tabletsuite.py