From: Otacilio Freitas de Lacerda Date: Fri, 9 Oct 2009 13:12:23 +0000 (-0300) Subject: Initial commit (Vesion 0.1) X-Git-Url: http://git.maemo.org/git/?p=tablet-suite;a=commitdiff_plain;h=256d6db84797e58f32185f042154a7c0fc54163e Initial commit (Vesion 0.1) --- diff --git a/debian/.svn/all-wcprops b/debian/.svn/all-wcprops new file mode 100644 index 0000000..73104a5 --- /dev/null +++ b/debian/.svn/all-wcprops @@ -0,0 +1,41 @@ +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 diff --git a/debian/.svn/dir-prop-base b/debian/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/debian/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/debian/.svn/entries b/debian/.svn/entries new file mode 100644 index 0000000..c99fd2d --- /dev/null +++ b/debian/.svn/entries @@ -0,0 +1,232 @@ +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 + +control +file + + + + +2009-09-29T18:30:21.000000Z +3f11fa51870d30106bcaba2287c59637 +2009-09-29T15:40:22.681741Z +650 +otacilio + + + + + + + + + + + + + + + + + + + + + +397 + +compat +file + + + + +2009-09-29T18:30:21.000000Z +84bc3da1b3e33a18e8d5e1bdd7a18d7a +2009-07-30T18:46:46.398336Z +495 +otacilio + + + + + + + + + + + + + + + + + + + + + +2 + +changelog +file + + + + +2009-09-29T18:30:21.000000Z +1b9dbce6d0ba853bfec1ac3ed6bb8e2d +2009-09-28T17:26:29.361774Z +649 +melunko + + + + + + + + + + + + + + + + + + + + + +156 + +copyright +file + + + + +2009-09-29T18:30:21.000000Z +dee7a3d70eedde5d9959617122de4083 +2009-07-30T18:46:46.398336Z +495 +otacilio + + + + + + + + + + + + + + + + + + + + + +696 + +docs +file + + + + +2009-09-29T18:30:21.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-07-30T18:46:46.398336Z +495 +otacilio + + + + + + + + + + + + + + + + + + + + + +0 + +rules +file + + + + +2009-09-29T18:30:21.000000Z +bb04c0b837f042492f69dd6a707c39df +2009-08-04T13:54:03.919326Z +505 +otacilio +has-props + + + + + + + + + + + + + + + + + + + + +169 + diff --git a/debian/.svn/format b/debian/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/.svn/format @@ -0,0 +1 @@ +9 diff --git a/debian/.svn/prop-base/rules.svn-base b/debian/.svn/prop-base/rules.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/debian/.svn/prop-base/rules.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/debian/.svn/text-base/changelog.svn-base b/debian/.svn/text-base/changelog.svn-base new file mode 100644 index 0000000..e839256 --- /dev/null +++ b/debian/.svn/text-base/changelog.svn-base @@ -0,0 +1,5 @@ +tablet-suite (0.1) unstable; urgency=low + + * Initial release + + -- Otacilio Freitas de Lacerda Thu, 30 Jul 2009 13:26:51 -0300 diff --git a/debian/.svn/text-base/compat.svn-base b/debian/.svn/text-base/compat.svn-base new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/.svn/text-base/compat.svn-base @@ -0,0 +1 @@ +7 diff --git a/debian/.svn/text-base/control.svn-base b/debian/.svn/text-base/control.svn-base new file mode 100644 index 0000000..cf01246 --- /dev/null +++ b/debian/.svn/text-base/control.svn-base @@ -0,0 +1,13 @@ +Source: tablet-suite +Section: python +Priority: optional +Maintainer: Otacilio Freitas de Lacerda +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: + <. + This package contains the tablet-suite project.> diff --git a/debian/.svn/text-base/copyright.svn-base b/debian/.svn/text-base/copyright.svn-base new file mode 100644 index 0000000..f382bbc --- /dev/null +++ b/debian/.svn/text-base/copyright.svn-base @@ -0,0 +1,24 @@ +This package was debianized by Otacilio Freitas de Lacerda on +Thu, 30 Jul 2009 13:26:51 -0300. + +It was downloaded from + +Upstream Author(s): + + + + +Copyright: + + + + +License: + + + +The Debian packaging is copyright 2009, Otacilio Freitas de Lacerda 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. diff --git a/debian/.svn/text-base/docs.svn-base b/debian/.svn/text-base/docs.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/debian/.svn/text-base/rules.svn-base b/debian/.svn/text-base/rules.svn-base new file mode 100644 index 0000000..329bb2a --- /dev/null +++ b/debian/.svn/text-base/rules.svn-base @@ -0,0 +1,6 @@ +#!/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 + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..e839256 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +tablet-suite (0.1) unstable; urgency=low + + * Initial release + + -- Otacilio Freitas de Lacerda Thu, 30 Jul 2009 13:26:51 -0300 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..cf01246 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: tablet-suite +Section: python +Priority: optional +Maintainer: Otacilio Freitas de Lacerda +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: + <. + This package contains the tablet-suite project.> diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f382bbc --- /dev/null +++ b/debian/copyright @@ -0,0 +1,24 @@ +This package was debianized by Otacilio Freitas de Lacerda on +Thu, 30 Jul 2009 13:26:51 -0300. + +It was downloaded from + +Upstream Author(s): + + + + +Copyright: + + + + +License: + + + +The Debian packaging is copyright 2009, Otacilio Freitas de Lacerda 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. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..329bb2a --- /dev/null +++ b/debian/rules @@ -0,0 +1,6 @@ +#!/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 + diff --git a/fonts/.svn/all-wcprops b/fonts/.svn/all-wcprops new file mode 100644 index 0000000..1a92acc --- /dev/null +++ b/fonts/.svn/all-wcprops @@ -0,0 +1,59 @@ +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 diff --git a/fonts/.svn/entries b/fonts/.svn/entries new file mode 100644 index 0000000..252b795 --- /dev/null +++ b/fonts/.svn/entries @@ -0,0 +1,334 @@ +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 + +pf_tempesta_seven.ttf +file + + + + +2009-09-29T18:30:22.000000Z +9f70908a87757dce7c6e692cd9b6dacb +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +22176 + +pf_tempesta_seven_bold.ttf +file + + + + +2009-09-29T18:30:22.000000Z +31fbb55b275dbdededfc430f50ad9354 +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +21780 + +pf_tempesta_seven_extended.ttf +file + + + + +2009-09-29T18:30:22.000000Z +07b0d01caeb4f8a81ae384119e1c182d +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +22464 + +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 + +pf_tempesta_seven_condensed.ttf +file + + + + +2009-09-29T18:30:22.000000Z +18f38e87a9c2dfd026026d8922d5ce9e +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +21616 + +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 + +BROWA.TTF +file + + + + +2009-09-29T18:30:22.000000Z +558e1f7c26d9405ac41942266ebac11d +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +80392 + +pf_tempesta_seven_compressed.ttf +file + + + + +2009-09-29T18:30:22.000000Z +ff7b35bf8a97fbb416e5d475a6cff55f +2009-09-15T18:22:54.599315Z +632 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +20396 + +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 + diff --git a/fonts/.svn/format b/fonts/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/fonts/.svn/format @@ -0,0 +1 @@ +9 diff --git a/fonts/.svn/prop-base/BROWA.TTF.svn-base b/fonts/.svn/prop-base/BROWA.TTF.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/BROWA.TTF.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_bold.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_bold.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_bold.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_compressed.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_compressed.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_compressed.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_compressed_bold.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_compressed_bold.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_compressed_bold.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_condensed.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_condensed.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_condensed.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_condensed_bold.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_condensed_bold.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_condensed_bold.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_extended.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_extended.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_extended.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/prop-base/pf_tempesta_seven_extended_bold.ttf.svn-base b/fonts/.svn/prop-base/pf_tempesta_seven_extended_bold.ttf.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/fonts/.svn/prop-base/pf_tempesta_seven_extended_bold.ttf.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/fonts/.svn/text-base/BROWA.TTF.svn-base b/fonts/.svn/text-base/BROWA.TTF.svn-base new file mode 100644 index 0000000..dfd6ef5 Binary files /dev/null and b/fonts/.svn/text-base/BROWA.TTF.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven.ttf.svn-base new file mode 100644 index 0000000..90c96f3 Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_bold.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_bold.ttf.svn-base new file mode 100644 index 0000000..8069c6f Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_bold.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_compressed.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_compressed.ttf.svn-base new file mode 100644 index 0000000..f40e35c Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_compressed.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_compressed_bold.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_compressed_bold.ttf.svn-base new file mode 100644 index 0000000..c208390 Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_compressed_bold.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_condensed.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_condensed.ttf.svn-base new file mode 100644 index 0000000..4d25500 Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_condensed.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_condensed_bold.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_condensed_bold.ttf.svn-base new file mode 100644 index 0000000..8f0203f Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_condensed_bold.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_extended.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_extended.ttf.svn-base new file mode 100644 index 0000000..94dbe8e Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_extended.ttf.svn-base differ diff --git a/fonts/.svn/text-base/pf_tempesta_seven_extended_bold.ttf.svn-base b/fonts/.svn/text-base/pf_tempesta_seven_extended_bold.ttf.svn-base new file mode 100644 index 0000000..e3d8ff1 Binary files /dev/null and b/fonts/.svn/text-base/pf_tempesta_seven_extended_bold.ttf.svn-base differ diff --git a/fonts/BROWA.TTF b/fonts/BROWA.TTF new file mode 100644 index 0000000..dfd6ef5 Binary files /dev/null and b/fonts/BROWA.TTF differ diff --git a/fonts/pf_tempesta_seven.ttf b/fonts/pf_tempesta_seven.ttf new file mode 100644 index 0000000..90c96f3 Binary files /dev/null and b/fonts/pf_tempesta_seven.ttf differ diff --git a/fonts/pf_tempesta_seven_bold.ttf b/fonts/pf_tempesta_seven_bold.ttf new file mode 100644 index 0000000..8069c6f Binary files /dev/null and b/fonts/pf_tempesta_seven_bold.ttf differ diff --git a/fonts/pf_tempesta_seven_compressed.ttf b/fonts/pf_tempesta_seven_compressed.ttf new file mode 100644 index 0000000..f40e35c Binary files /dev/null and b/fonts/pf_tempesta_seven_compressed.ttf differ diff --git a/fonts/pf_tempesta_seven_compressed_bold.ttf b/fonts/pf_tempesta_seven_compressed_bold.ttf new file mode 100644 index 0000000..c208390 Binary files /dev/null and b/fonts/pf_tempesta_seven_compressed_bold.ttf differ diff --git a/fonts/pf_tempesta_seven_condensed.ttf b/fonts/pf_tempesta_seven_condensed.ttf new file mode 100644 index 0000000..4d25500 Binary files /dev/null and b/fonts/pf_tempesta_seven_condensed.ttf differ diff --git a/fonts/pf_tempesta_seven_condensed_bold.ttf b/fonts/pf_tempesta_seven_condensed_bold.ttf new file mode 100644 index 0000000..8f0203f Binary files /dev/null and b/fonts/pf_tempesta_seven_condensed_bold.ttf differ diff --git a/fonts/pf_tempesta_seven_extended.ttf b/fonts/pf_tempesta_seven_extended.ttf new file mode 100644 index 0000000..94dbe8e Binary files /dev/null and b/fonts/pf_tempesta_seven_extended.ttf differ diff --git a/fonts/pf_tempesta_seven_extended_bold.ttf b/fonts/pf_tempesta_seven_extended_bold.ttf new file mode 100644 index 0000000..e3d8ff1 Binary files /dev/null and b/fonts/pf_tempesta_seven_extended_bold.ttf differ diff --git a/img/.svn/all-wcprops b/img/.svn/all-wcprops new file mode 100644 index 0000000..be3e401 --- /dev/null +++ b/img/.svn/all-wcprops @@ -0,0 +1,527 @@ +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 diff --git a/img/.svn/dir-prop-base b/img/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/img/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/img/.svn/entries b/img/.svn/entries new file mode 100644 index 0000000..71bb608 --- /dev/null +++ b/img/.svn/entries @@ -0,0 +1,2986 @@ +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 + +checkbox_checked.png +file + + + + +2009-09-29T18:30:22.000000Z +a01bf9fbe352b626b8e5b3484c9e645e +2009-08-13T17:08:11.546686Z +550 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +822 + +scroll_handle_v.png +file + + + + +2009-09-29T18:30:22.000000Z +cfbffd47da519d20e6c645586e1be0fc +2009-09-09T16:10:10.046818Z +610 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3103 + +scroll_base_h.png +file + + + + +2009-09-29T18:30:22.000000Z +23e767ca7a1bf2a2158e52837f6e415b +2009-09-09T16:10:10.046818Z +610 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +844 + +progress_bar_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +342126781b58ecf007b3faad2568af64 +2009-08-21T18:19:06.773534Z +573 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3756 + +ip_list_border.png +file + + + + +2009-09-29T18:30:22.000000Z +eaca0b8358ab0e84df410a39886c9d6f +2009-09-03T16:03:51.683671Z +591 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4841 + +backup_name_border.png +file + + + + +2009-09-29T18:30:22.000000Z +78844d8e12b99fab3f63869565651301 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3410 + +large_arrow_image.png +file + + + + +2009-09-29T18:30:22.000000Z +2957d2a0847d5844f5a130b40d11271a +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +5609 + +progress_bar_connecting_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +00f570e8e6010180c9bd53f241fae029 +2009-09-10T20:35:15.948790Z +612 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3699 + +small_default_button.png +file + + + + +2009-09-29T18:30:22.000000Z +13644f0774d460563f934c46e2cd8056 +2009-09-03T16:03:51.683671Z +591 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3443 + +scroll_base_v.png +file + + + + +2009-09-29T18:30:22.000000Z +3230dc7d26417d0b4d968c9a6f2c71c5 +2009-09-09T16:10:10.046818Z +610 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3597 + +progress_bar_chunk.png +file + + + + +2009-09-29T18:30:22.000000Z +f9a64d04eb7eae7900af543bedf374be +2009-09-08T17:01:54.301655Z +609 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3279 + +bg_geral0.png +file + + + + +2009-09-29T18:30:22.000000Z +91111ff0319924d279c47e55423dec94 +2009-07-28T18:31:05.094742Z +476 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +79464 + +view_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +6d46d6caa3a6ca58e35094b664a39a6b +2009-09-03T22:08:31.931352Z +600 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3281 + +bg_geral2.png +file + + + + +2009-09-29T18:30:22.000000Z +e6e8a6c49810a752be37c0e22f753781 +2009-07-16T17:37:19.503117Z +437 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +52909 + +table_border.png +file + + + + +2009-09-29T18:30:22.000000Z +aec2ba53080f3ffa7ee774e73211b8f5 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4887 + +progress_bar_border.png +file + + + + +2009-09-29T18:30:22.000000Z +d888d82dcd05b6055888ba810fa25799 +2009-08-21T18:19:06.773534Z +573 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3273 + +N810_file.png +file + + + + +2009-09-29T18:30:22.000000Z +de0f0760975780acd73d91f857d05426 +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +10288 + +N800.png +file + + + + +2009-09-29T18:30:22.000000Z +8ed3e9ce544ea2f26a4dbd7657122398 +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +6231 + +small_default_button_clicked.png +file + + + + +2009-09-29T18:30:22.000000Z +a1fa5275ce8a0ec5e68d25b3e9f02883 +2009-09-03T16:03:51.683671Z +591 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3579 + +disconnected_backup.png +file + + + + +2009-09-29T18:30:22.000000Z +7414015bc4afd729f9b54b05ea9c04f7 +2009-09-14T19:20:21.821743Z +624 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +21287 + +white_arrow.png +file + + + + +2009-09-29T18:30:22.000000Z +690dc22ed876c3436a427891a9115362 +2009-07-29T09:45:01.027130Z +482 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2817 + +device_file_border.png +file + + + + +2009-09-29T18:30:22.000000Z +4211e9d5c31659da6d66dad550c9d646 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4224 + +bg_restore.png +file + + + + +2009-09-29T18:30:22.000000Z +460acdb041c97f3b866c48bd01e6dcc4 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +62107 + +icon-ref-restorebackups.png +file + + + + +2009-09-29T18:30:22.000000Z +06caf36fbbacfa1e892c62e6ad6cd104 +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4633 + +default_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +562028809d59ea75c5bb4fc2face91b7 +2009-09-09T16:10:10.046818Z +610 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2396 + +browse_button.png +file + + + + +2009-09-29T18:30:22.000000Z +850dd65278e2b1ab21ad0a9bd34e6c31 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3991 + +bg_backup0.png +file + + + + +2009-09-29T18:30:22.000000Z +71b7252b3021dd09f8ec587549118893 +2009-08-11T16:36:01.916949Z +539 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +48940 + +pc_name_border_file.png +file + + + + +2009-09-29T18:30:22.000000Z +cafe36896b8b58e92d5d351b0c153720 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3468 + +pc_file_border.png +file + + + + +2009-09-29T18:30:22.000000Z +20068b0940926d1110879ab4a59fb44f +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4230 + +checkbox_unchecked.png +file + + + + +2009-09-29T18:30:22.000000Z +118a0f804bcc4d7e90be766910bbc51c +2009-08-13T17:08:11.546686Z +550 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +688 + +icon-ref-settings.png +file + + + + +2009-09-29T18:30:22.000000Z +1a0d9597956dda69c405967db13fed7c +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +5214 + +large_arrow_border.png +file + + + + +2009-09-29T18:30:22.000000Z +0f34a62a541a7caa7aa2f1d4b1d9b112 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +6248 + +disconnected.png +file + + + + +2009-09-29T18:30:22.000000Z +ff9a15db496d8dae6461766710d6686d +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +12211 + +device_name_border_checkbox.png +file + + + + +2009-09-29T18:30:22.000000Z +bd2ca576ffc5981ec2323064d2dadb65 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3324 + +device_checkbox_border.png +file + + + + +2009-09-29T18:30:22.000000Z +cf98ab9a0bb3870789b4853bd1957667 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4304 + +backup.png +file + + + + +2009-09-29T18:30:22.000000Z +870aca33c4343973c09b83e3dfe45ab4 +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4657 + +back_arrow_on.png +file + + + + +2009-09-29T18:30:22.000000Z +d259ebab223ef56773733ce28676fb3e +2009-07-29T12:18:32.451141Z +490 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2954 + +icon-alert-ref.png +file + + + + +2009-09-29T18:30:22.000000Z +36c02dce8980394a63d0716986846db4 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3604 + +view_border.png +file + + + + +2009-09-29T18:30:22.000000Z +07c9e5b9c933aab32c52d83369f1749b +2009-09-03T22:08:31.931352Z +600 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4512 + +forward_arrow_on.png +file + + + + +2009-09-29T18:30:22.000000Z +972f112af726e4cc1048c4957987df5c +2009-07-29T12:18:32.451141Z +490 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2950 + +N800_backup.png +file + + + + +2009-09-29T18:30:22.000000Z +3a755c3c2d6016b103280e1dfac404c3 +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +10860 + +tabletsuite.desktop +file + + + + +2009-09-29T18:30:22.000000Z +57206ed9fbe3ad7e9f6035587fc0a20d +2009-09-24T18:11:29.733195Z +643 +otacilio +has-props + + + + + + + + + + + + + + + + + + + + +269 + +N810_backup.png +file + + + + +2009-09-29T18:30:22.000000Z +f42fa915e09e712f6904561390845c73 +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +19137 + +lista.png +file + + + + +2009-09-29T18:30:22.000000Z +21abea4315d51598bc9493ba74507eb5 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3363 + +bg_backup.png +file + + + + +2009-09-29T18:30:22.000000Z +929064a3d451a8c7e72c8e211401db87 +2009-08-07T19:29:53.557169Z +529 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +74676 + +icon-ref-newbackup.png +file + + + + +2009-09-29T18:30:22.000000Z +207b1bdc88279b56c6755a3841021208 +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4895 + +device_backup_border.png +file + + + + +2009-09-29T18:30:22.000000Z +afb641c1d2d237b8be0b564ed6c979c1 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4792 + +N810.png +file + + + + +2009-09-29T18:30:22.000000Z +24f08a897165cee8770aee6a05e0ed65 +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +12356 + +arrow.png +file + + + + +2009-09-29T18:30:22.000000Z +690dc22ed876c3436a427891a9115362 +2009-07-28T17:43:56.280909Z +474 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2817 + +device_name_border_file.png +file + + + + +2009-09-29T18:30:22.000000Z +d425373982afaea21744991e30f584fe +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3399 + +tab_bg_1.png +file + + + + +2009-09-29T18:30:22.000000Z +5cd4e834dcd5137cf36f48552cb30ef6 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +11985 + +progress_bar_chunk_dialog.png +file + + + + +2009-09-29T18:30:22.000000Z +8201eaae0da8f4f292365a716b4d527a +2009-09-08T17:01:54.301655Z +609 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3228 + +tab_bg_2.png +file + + + + +2009-09-29T18:30:22.000000Z +e822a037236b010e3285fd7c6b0026c2 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +10955 + +tab_bg_3.png +file + + + + +2009-09-29T18:30:22.000000Z +53bb3b054aa1ae191d9a3caf0f3d5cb8 +2009-08-27T10:01:51.549755Z +577 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +7825 + +icon-ref-managebackups.png +file + + + + +2009-09-29T18:30:22.000000Z +1d823eb2520527d96b65d79292c3bfdb +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +5154 + +pc_image.png +file + + + + +2009-09-29T18:30:22.000000Z +8aef2711997e0be150bfb960d4b22f3d +2009-09-10T22:40:29.655655Z +614 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +6196 + +progress_bar_dialog_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +4a2c3ade46963dee17dcf765773e9274 +2009-09-08T17:01:54.301655Z +609 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3903 + +device_name_border_backup.png +file + + + + +2009-09-29T18:30:22.000000Z +845b4976344776d80ab27ef9baf073d4 +2009-08-10T18:42:02.033426Z +532 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3487 + +button_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +8f7e66a13a3d77964b89ecc60062fd8b +2009-08-05T16:55:19.618241Z +511 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +5430 + +checkbox_border.png +file + + + + +2009-09-29T18:30:22.000000Z +335ed6a4799668bd6d0e2e84f69c6f62 +2009-08-12T10:13:12.305172Z +544 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3953 + +N800_file.png +file + + + + +2009-09-29T18:30:22.000000Z +de991fbf0dde3cf6b7bfa3f5bc1dbdad +2009-09-08T14:59:55.898571Z +608 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +5012 + +small_icon-ref-restorebackups.png +file + + + + +2009-09-29T18:30:22.000000Z +822f5e0ed76fb0bb47a8d2f90f375469 +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +3725 + +black_arrow.png +file + + + + +2009-09-29T18:30:22.000000Z +03e716d26ee1913272983b9cfcc199f8 +2009-07-29T09:45:01.027130Z +482 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2824 + +button_with_icon_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +d4ffa3fe7a2f3e2eba14b66936411a85 +2009-08-10T11:25:57.599617Z +531 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3896 + +small_icon-ref-settings.png +file + + + + +2009-09-29T18:30:22.000000Z +1140c565d18d21a1efd190bc1a2ec8dc +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4242 + +memory_bar.png +file + + + + +2009-09-29T18:30:22.000000Z +35fa29ba1087512051d27bf08766942c +2009-07-27T10:04:31.020564Z +466 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3563 + +ssh.png +file + + + + +2009-09-29T18:30:22.000000Z +40dfa113ff4dbf710d29e9c965f94e97 +2009-07-02T12:53:33.231762Z +373 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +3437 + +battery_bar.png +file + + + + +2009-09-29T18:30:22.000000Z +23a300c76eb873d8b2f35a037151a0b7 +2009-07-27T10:04:31.020564Z +466 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3659 + +button_bg_clicked.png +file + + + + +2009-09-29T18:30:22.000000Z +b4331208b1129b52d060a67e9f812335 +2009-08-05T16:55:19.618241Z +511 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +4360 + +bt_next.png +file + + + + +2009-09-29T18:30:22.000000Z +0ea17926855c030924cd0375de12cbe6 +2009-08-11T18:11:13.211844Z +540 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +3705 + +path_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +2e9149e73f319bd8c29b46e4f68bd29b +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3856 + +backup_default_button.png +file + + + + +2009-09-29T18:30:22.000000Z +507a2a81d9894d081cd48286cabc08be +2009-08-27T20:31:13.838494Z +579 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3604 + +back_arrow_off.png +file + + + + +2009-09-29T18:30:22.000000Z +e08a8e19f58dcc1ae9993676fa2d2273 +2009-07-29T12:18:32.451141Z +490 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2954 + +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 + +tabletSuite_logo.png +file + + + + +2009-09-29T18:30:22.000000Z +1a1166670a4205cfd08c1befc674c2bb +2009-08-18T15:36:29.586124Z +570 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +7324 + +copy_border.png +file + + + + +2009-09-29T18:30:22.000000Z +e92a79031af207d5615413f878bcaa27 +2009-08-13T17:08:11.546686Z +550 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4924 + +small_icon-ref-newbackup.png +file + + + + +2009-09-29T18:30:22.000000Z +cf9ba7641b827a058912d9379915ecad +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4003 + +forward_arrow_off.png +file + + + + +2009-09-29T18:30:22.000000Z +3379a96302f63597c319c50a264933a8 +2009-07-29T12:18:32.451141Z +490 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +2950 + +device_selection_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +63b1ba933149d0ffcb6e17edefa09c70 +2009-09-03T22:08:31.931352Z +600 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +5927 + +backup_name_bg.png +file + + + + +2009-09-29T18:30:22.000000Z +abfde4ac92d9205f446eef12a951f024 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3909 + +scroll_handle_h.png +file + + + + +2009-09-29T18:30:22.000000Z +25c1fa8f802f15ba9575b98a6f645346 +2009-09-09T16:10:10.046818Z +610 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +446 + +bt_next_clicked.png +file + + + + +2009-09-29T18:30:22.000000Z +ff7a184854f8fc2301f35393d62102f5 +2009-08-11T18:11:13.211844Z +540 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +3836 + +backup_default_button_clicked.png +file + + + + +2009-09-29T18:30:22.000000Z +df78c1f41a82b17a499c603b5fd4f381 +2009-08-27T20:31:13.838494Z +579 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3732 + +bg_manager.png +file + + + + +2009-09-29T18:30:22.000000Z +460acdb041c97f3b866c48bd01e6dcc4 +2009-09-03T21:14:33.964127Z +596 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +62107 + +device_memory.png +file + + + + +2009-09-29T18:30:22.000000Z +ead62093235e632745d327a6e05fb890 +2009-07-27T10:04:31.020564Z +466 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3715 + +path_border.png +file + + + + +2009-09-29T18:30:22.000000Z +e2bf32a0e2b5b49abd45777ddb597fd0 +2009-08-13T19:38:57.115054Z +551 +pauloouriques +has-props + + + + + + + + + + + + + + + + + + + + +3412 + +small_icon-ref-managebackups.png +file + + + + +2009-09-29T18:30:22.000000Z +35938d68793a64ddc63691a22bbbb912 +2009-09-15T12:07:49.302204Z +626 +amaury +has-props + + + + + + + + + + + + + + + + + + + + +4022 + diff --git a/img/.svn/format b/img/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/img/.svn/format @@ -0,0 +1 @@ +9 diff --git a/img/.svn/prop-base/N800.png.svn-base b/img/.svn/prop-base/N800.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N800.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/N800_backup.png.svn-base b/img/.svn/prop-base/N800_backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N800_backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/N800_file.png.svn-base b/img/.svn/prop-base/N800_file.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N800_file.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/N810.png.svn-base b/img/.svn/prop-base/N810.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N810.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/N810_backup.png.svn-base b/img/.svn/prop-base/N810_backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N810_backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/N810_file.png.svn-base b/img/.svn/prop-base/N810_file.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/N810_file.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/arrow.png.svn-base b/img/.svn/prop-base/arrow.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/arrow.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/back_arrow_off.png.svn-base b/img/.svn/prop-base/back_arrow_off.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/back_arrow_off.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/back_arrow_on.png.svn-base b/img/.svn/prop-base/back_arrow_on.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/back_arrow_on.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/backup.png.svn-base b/img/.svn/prop-base/backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/backup_default_button.png.svn-base b/img/.svn/prop-base/backup_default_button.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/backup_default_button.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/backup_default_button_clicked.png.svn-base b/img/.svn/prop-base/backup_default_button_clicked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/backup_default_button_clicked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/backup_name_bg.png.svn-base b/img/.svn/prop-base/backup_name_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/backup_name_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/backup_name_border.png.svn-base b/img/.svn/prop-base/backup_name_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/backup_name_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/battery_bar.png.svn-base b/img/.svn/prop-base/battery_bar.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/battery_bar.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_backup.png.svn-base b/img/.svn/prop-base/bg_backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_backup0.png.svn-base b/img/.svn/prop-base/bg_backup0.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_backup0.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_geral0.png.svn-base b/img/.svn/prop-base/bg_geral0.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_geral0.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_geral2.png.svn-base b/img/.svn/prop-base/bg_geral2.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_geral2.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_manager.png.svn-base b/img/.svn/prop-base/bg_manager.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_manager.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bg_restore.png.svn-base b/img/.svn/prop-base/bg_restore.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bg_restore.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/black_arrow.png.svn-base b/img/.svn/prop-base/black_arrow.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/black_arrow.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/browse_button.png.svn-base b/img/.svn/prop-base/browse_button.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/browse_button.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bt_next.png.svn-base b/img/.svn/prop-base/bt_next.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bt_next.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/bt_next_clicked.png.svn-base b/img/.svn/prop-base/bt_next_clicked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/bt_next_clicked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/button_bg.png.svn-base b/img/.svn/prop-base/button_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/button_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/button_bg_clicked.png.svn-base b/img/.svn/prop-base/button_bg_clicked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/button_bg_clicked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/button_with_icon_bg.png.svn-base b/img/.svn/prop-base/button_with_icon_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/button_with_icon_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/button_with_icon_bg_clicked.png.svn-base b/img/.svn/prop-base/button_with_icon_bg_clicked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/button_with_icon_bg_clicked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/checkbox_border.png.svn-base b/img/.svn/prop-base/checkbox_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/checkbox_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/checkbox_checked.png.svn-base b/img/.svn/prop-base/checkbox_checked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/checkbox_checked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/checkbox_unchecked.png.svn-base b/img/.svn/prop-base/checkbox_unchecked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/checkbox_unchecked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/copy_border.png.svn-base b/img/.svn/prop-base/copy_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/copy_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/default_bg.png.svn-base b/img/.svn/prop-base/default_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/default_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_backup_border.png.svn-base b/img/.svn/prop-base/device_backup_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_backup_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_checkbox_border.png.svn-base b/img/.svn/prop-base/device_checkbox_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_checkbox_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_file_border.png.svn-base b/img/.svn/prop-base/device_file_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_file_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_memory.png.svn-base b/img/.svn/prop-base/device_memory.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_memory.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_name_border_backup.png.svn-base b/img/.svn/prop-base/device_name_border_backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_name_border_backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_name_border_checkbox.png.svn-base b/img/.svn/prop-base/device_name_border_checkbox.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_name_border_checkbox.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_name_border_file.png.svn-base b/img/.svn/prop-base/device_name_border_file.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_name_border_file.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/device_selection_bg.png.svn-base b/img/.svn/prop-base/device_selection_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/device_selection_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/disconnected.png.svn-base b/img/.svn/prop-base/disconnected.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/disconnected.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/disconnected_backup.png.svn-base b/img/.svn/prop-base/disconnected_backup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/disconnected_backup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/forward_arrow_off.png.svn-base b/img/.svn/prop-base/forward_arrow_off.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/forward_arrow_off.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/forward_arrow_on.png.svn-base b/img/.svn/prop-base/forward_arrow_on.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/forward_arrow_on.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/icon-alert-ref.png.svn-base b/img/.svn/prop-base/icon-alert-ref.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/icon-alert-ref.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/icon-ref-managebackups.png.svn-base b/img/.svn/prop-base/icon-ref-managebackups.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/icon-ref-managebackups.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/icon-ref-newbackup.png.svn-base b/img/.svn/prop-base/icon-ref-newbackup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/icon-ref-newbackup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/icon-ref-restorebackups.png.svn-base b/img/.svn/prop-base/icon-ref-restorebackups.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/icon-ref-restorebackups.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/icon-ref-settings.png.svn-base b/img/.svn/prop-base/icon-ref-settings.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/icon-ref-settings.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/ip_list_border.png.svn-base b/img/.svn/prop-base/ip_list_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/ip_list_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/large_arrow_border.png.svn-base b/img/.svn/prop-base/large_arrow_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/large_arrow_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/large_arrow_image.png.svn-base b/img/.svn/prop-base/large_arrow_image.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/large_arrow_image.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/lista.png.svn-base b/img/.svn/prop-base/lista.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/lista.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/memory_bar.png.svn-base b/img/.svn/prop-base/memory_bar.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/memory_bar.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/path_bg.png.svn-base b/img/.svn/prop-base/path_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/path_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/path_border.png.svn-base b/img/.svn/prop-base/path_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/path_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/pc_file_border.png.svn-base b/img/.svn/prop-base/pc_file_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/pc_file_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/pc_image.png.svn-base b/img/.svn/prop-base/pc_image.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/pc_image.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/pc_name_border_file.png.svn-base b/img/.svn/prop-base/pc_name_border_file.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/pc_name_border_file.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_bg.png.svn-base b/img/.svn/prop-base/progress_bar_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_border.png.svn-base b/img/.svn/prop-base/progress_bar_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_chunk.png.svn-base b/img/.svn/prop-base/progress_bar_chunk.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_chunk.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_chunk_dialog.png.svn-base b/img/.svn/prop-base/progress_bar_chunk_dialog.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_chunk_dialog.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_connecting_bg.png.svn-base b/img/.svn/prop-base/progress_bar_connecting_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_connecting_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/progress_bar_dialog_bg.png.svn-base b/img/.svn/prop-base/progress_bar_dialog_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/progress_bar_dialog_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/scroll_base_h.png.svn-base b/img/.svn/prop-base/scroll_base_h.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/scroll_base_h.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/scroll_base_v.png.svn-base b/img/.svn/prop-base/scroll_base_v.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/scroll_base_v.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/scroll_handle_h.png.svn-base b/img/.svn/prop-base/scroll_handle_h.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/scroll_handle_h.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/scroll_handle_v.png.svn-base b/img/.svn/prop-base/scroll_handle_v.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/scroll_handle_v.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_default_button.png.svn-base b/img/.svn/prop-base/small_default_button.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_default_button.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_default_button_clicked.png.svn-base b/img/.svn/prop-base/small_default_button_clicked.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_default_button_clicked.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_icon-ref-managebackups.png.svn-base b/img/.svn/prop-base/small_icon-ref-managebackups.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_icon-ref-managebackups.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_icon-ref-newbackup.png.svn-base b/img/.svn/prop-base/small_icon-ref-newbackup.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_icon-ref-newbackup.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_icon-ref-restorebackups.png.svn-base b/img/.svn/prop-base/small_icon-ref-restorebackups.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_icon-ref-restorebackups.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/small_icon-ref-settings.png.svn-base b/img/.svn/prop-base/small_icon-ref-settings.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/small_icon-ref-settings.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/ssh.png.svn-base b/img/.svn/prop-base/ssh.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/ssh.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/tab_bg_1.png.svn-base b/img/.svn/prop-base/tab_bg_1.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/tab_bg_1.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/tab_bg_2.png.svn-base b/img/.svn/prop-base/tab_bg_2.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/tab_bg_2.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/tab_bg_3.png.svn-base b/img/.svn/prop-base/tab_bg_3.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/tab_bg_3.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/table_border.png.svn-base b/img/.svn/prop-base/table_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/table_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/tabletSuite_logo.png.svn-base b/img/.svn/prop-base/tabletSuite_logo.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/tabletSuite_logo.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/tabletsuite.desktop.svn-base b/img/.svn/prop-base/tabletsuite.desktop.svn-base new file mode 100644 index 0000000..8d28d86 --- /dev/null +++ b/img/.svn/prop-base/tabletsuite.desktop.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mergeinfo +V 0 + +END diff --git a/img/.svn/prop-base/view_bg.png.svn-base b/img/.svn/prop-base/view_bg.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/view_bg.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/view_border.png.svn-base b/img/.svn/prop-base/view_border.png.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/img/.svn/prop-base/view_border.png.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/prop-base/white_arrow.png.svn-base b/img/.svn/prop-base/white_arrow.png.svn-base new file mode 100644 index 0000000..dbc918b --- /dev/null +++ b/img/.svn/prop-base/white_arrow.png.svn-base @@ -0,0 +1,9 @@ +K 14 +svn:executable +V 1 +* +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/img/.svn/text-base/N800.png.svn-base b/img/.svn/text-base/N800.png.svn-base new file mode 100644 index 0000000..48df145 Binary files /dev/null and b/img/.svn/text-base/N800.png.svn-base differ diff --git a/img/.svn/text-base/N800_backup.png.svn-base b/img/.svn/text-base/N800_backup.png.svn-base new file mode 100644 index 0000000..43fbb85 Binary files /dev/null and b/img/.svn/text-base/N800_backup.png.svn-base differ diff --git a/img/.svn/text-base/N800_file.png.svn-base b/img/.svn/text-base/N800_file.png.svn-base new file mode 100644 index 0000000..edfa13b Binary files /dev/null and b/img/.svn/text-base/N800_file.png.svn-base differ diff --git a/img/.svn/text-base/N810.png.svn-base b/img/.svn/text-base/N810.png.svn-base new file mode 100644 index 0000000..0a869b6 Binary files /dev/null and b/img/.svn/text-base/N810.png.svn-base differ diff --git a/img/.svn/text-base/N810_backup.png.svn-base b/img/.svn/text-base/N810_backup.png.svn-base new file mode 100644 index 0000000..02c60e8 Binary files /dev/null and b/img/.svn/text-base/N810_backup.png.svn-base differ diff --git a/img/.svn/text-base/N810_file.png.svn-base b/img/.svn/text-base/N810_file.png.svn-base new file mode 100644 index 0000000..fb7d138 Binary files /dev/null and b/img/.svn/text-base/N810_file.png.svn-base differ diff --git a/img/.svn/text-base/arrow.png.svn-base b/img/.svn/text-base/arrow.png.svn-base new file mode 100644 index 0000000..4dbf148 Binary files /dev/null and b/img/.svn/text-base/arrow.png.svn-base differ diff --git a/img/.svn/text-base/back_arrow_off.png.svn-base b/img/.svn/text-base/back_arrow_off.png.svn-base new file mode 100644 index 0000000..48c68a8 Binary files /dev/null and b/img/.svn/text-base/back_arrow_off.png.svn-base differ diff --git a/img/.svn/text-base/back_arrow_on.png.svn-base b/img/.svn/text-base/back_arrow_on.png.svn-base new file mode 100644 index 0000000..99d8986 Binary files /dev/null and b/img/.svn/text-base/back_arrow_on.png.svn-base differ diff --git a/img/.svn/text-base/backup.png.svn-base b/img/.svn/text-base/backup.png.svn-base new file mode 100644 index 0000000..b5dc1fd Binary files /dev/null and b/img/.svn/text-base/backup.png.svn-base differ diff --git a/img/.svn/text-base/backup_default_button.png.svn-base b/img/.svn/text-base/backup_default_button.png.svn-base new file mode 100644 index 0000000..eded036 Binary files /dev/null and b/img/.svn/text-base/backup_default_button.png.svn-base differ diff --git a/img/.svn/text-base/backup_default_button_clicked.png.svn-base b/img/.svn/text-base/backup_default_button_clicked.png.svn-base new file mode 100644 index 0000000..45b0e71 Binary files /dev/null and b/img/.svn/text-base/backup_default_button_clicked.png.svn-base differ diff --git a/img/.svn/text-base/backup_name_bg.png.svn-base b/img/.svn/text-base/backup_name_bg.png.svn-base new file mode 100644 index 0000000..6ec151a Binary files /dev/null and b/img/.svn/text-base/backup_name_bg.png.svn-base differ diff --git a/img/.svn/text-base/backup_name_border.png.svn-base b/img/.svn/text-base/backup_name_border.png.svn-base new file mode 100644 index 0000000..76baec9 Binary files /dev/null and b/img/.svn/text-base/backup_name_border.png.svn-base differ diff --git a/img/.svn/text-base/battery_bar.png.svn-base b/img/.svn/text-base/battery_bar.png.svn-base new file mode 100644 index 0000000..b2b632f Binary files /dev/null and b/img/.svn/text-base/battery_bar.png.svn-base differ diff --git a/img/.svn/text-base/bg_backup.png.svn-base b/img/.svn/text-base/bg_backup.png.svn-base new file mode 100644 index 0000000..701d70d Binary files /dev/null and b/img/.svn/text-base/bg_backup.png.svn-base differ diff --git a/img/.svn/text-base/bg_backup0.png.svn-base b/img/.svn/text-base/bg_backup0.png.svn-base new file mode 100644 index 0000000..da7b3c0 Binary files /dev/null and b/img/.svn/text-base/bg_backup0.png.svn-base differ diff --git a/img/.svn/text-base/bg_geral0.png.svn-base b/img/.svn/text-base/bg_geral0.png.svn-base new file mode 100644 index 0000000..506b9a7 Binary files /dev/null and b/img/.svn/text-base/bg_geral0.png.svn-base differ diff --git a/img/.svn/text-base/bg_geral2.png.svn-base b/img/.svn/text-base/bg_geral2.png.svn-base new file mode 100644 index 0000000..6a49225 Binary files /dev/null and b/img/.svn/text-base/bg_geral2.png.svn-base differ diff --git a/img/.svn/text-base/bg_manager.png.svn-base b/img/.svn/text-base/bg_manager.png.svn-base new file mode 100644 index 0000000..11c0671 Binary files /dev/null and b/img/.svn/text-base/bg_manager.png.svn-base differ diff --git a/img/.svn/text-base/bg_restore.png.svn-base b/img/.svn/text-base/bg_restore.png.svn-base new file mode 100644 index 0000000..11c0671 Binary files /dev/null and b/img/.svn/text-base/bg_restore.png.svn-base differ diff --git a/img/.svn/text-base/black_arrow.png.svn-base b/img/.svn/text-base/black_arrow.png.svn-base new file mode 100644 index 0000000..536644d Binary files /dev/null and b/img/.svn/text-base/black_arrow.png.svn-base differ diff --git a/img/.svn/text-base/browse_button.png.svn-base b/img/.svn/text-base/browse_button.png.svn-base new file mode 100644 index 0000000..990e6d4 Binary files /dev/null and b/img/.svn/text-base/browse_button.png.svn-base differ diff --git a/img/.svn/text-base/bt_next.png.svn-base b/img/.svn/text-base/bt_next.png.svn-base new file mode 100644 index 0000000..48297fe Binary files /dev/null and b/img/.svn/text-base/bt_next.png.svn-base differ diff --git a/img/.svn/text-base/bt_next_clicked.png.svn-base b/img/.svn/text-base/bt_next_clicked.png.svn-base new file mode 100644 index 0000000..8a747c8 Binary files /dev/null and b/img/.svn/text-base/bt_next_clicked.png.svn-base differ diff --git a/img/.svn/text-base/button_bg.png.svn-base b/img/.svn/text-base/button_bg.png.svn-base new file mode 100644 index 0000000..fe8f537 Binary files /dev/null and b/img/.svn/text-base/button_bg.png.svn-base differ diff --git a/img/.svn/text-base/button_bg_clicked.png.svn-base b/img/.svn/text-base/button_bg_clicked.png.svn-base new file mode 100644 index 0000000..97fbdb3 Binary files /dev/null and b/img/.svn/text-base/button_bg_clicked.png.svn-base differ diff --git a/img/.svn/text-base/button_with_icon_bg.png.svn-base b/img/.svn/text-base/button_with_icon_bg.png.svn-base new file mode 100644 index 0000000..cf6fc2c Binary files /dev/null and b/img/.svn/text-base/button_with_icon_bg.png.svn-base differ diff --git a/img/.svn/text-base/button_with_icon_bg_clicked.png.svn-base b/img/.svn/text-base/button_with_icon_bg_clicked.png.svn-base new file mode 100644 index 0000000..8ceb603 Binary files /dev/null and b/img/.svn/text-base/button_with_icon_bg_clicked.png.svn-base differ diff --git a/img/.svn/text-base/checkbox_border.png.svn-base b/img/.svn/text-base/checkbox_border.png.svn-base new file mode 100644 index 0000000..ae4ae02 Binary files /dev/null and b/img/.svn/text-base/checkbox_border.png.svn-base differ diff --git a/img/.svn/text-base/checkbox_checked.png.svn-base b/img/.svn/text-base/checkbox_checked.png.svn-base new file mode 100644 index 0000000..6774a97 Binary files /dev/null and b/img/.svn/text-base/checkbox_checked.png.svn-base differ diff --git a/img/.svn/text-base/checkbox_unchecked.png.svn-base b/img/.svn/text-base/checkbox_unchecked.png.svn-base new file mode 100644 index 0000000..10576e9 Binary files /dev/null and b/img/.svn/text-base/checkbox_unchecked.png.svn-base differ diff --git a/img/.svn/text-base/copy_border.png.svn-base b/img/.svn/text-base/copy_border.png.svn-base new file mode 100644 index 0000000..d5e140c Binary files /dev/null and b/img/.svn/text-base/copy_border.png.svn-base differ diff --git a/img/.svn/text-base/default_bg.png.svn-base b/img/.svn/text-base/default_bg.png.svn-base new file mode 100644 index 0000000..b96ca03 Binary files /dev/null and b/img/.svn/text-base/default_bg.png.svn-base differ diff --git a/img/.svn/text-base/device_backup_border.png.svn-base b/img/.svn/text-base/device_backup_border.png.svn-base new file mode 100644 index 0000000..44b2c65 Binary files /dev/null and b/img/.svn/text-base/device_backup_border.png.svn-base differ diff --git a/img/.svn/text-base/device_checkbox_border.png.svn-base b/img/.svn/text-base/device_checkbox_border.png.svn-base new file mode 100644 index 0000000..e6793cc Binary files /dev/null and b/img/.svn/text-base/device_checkbox_border.png.svn-base differ diff --git a/img/.svn/text-base/device_file_border.png.svn-base b/img/.svn/text-base/device_file_border.png.svn-base new file mode 100644 index 0000000..3043002 Binary files /dev/null and b/img/.svn/text-base/device_file_border.png.svn-base differ diff --git a/img/.svn/text-base/device_memory.png.svn-base b/img/.svn/text-base/device_memory.png.svn-base new file mode 100644 index 0000000..8164cbd Binary files /dev/null and b/img/.svn/text-base/device_memory.png.svn-base differ diff --git a/img/.svn/text-base/device_name_border_backup.png.svn-base b/img/.svn/text-base/device_name_border_backup.png.svn-base new file mode 100644 index 0000000..9e233d4 Binary files /dev/null and b/img/.svn/text-base/device_name_border_backup.png.svn-base differ diff --git a/img/.svn/text-base/device_name_border_checkbox.png.svn-base b/img/.svn/text-base/device_name_border_checkbox.png.svn-base new file mode 100644 index 0000000..5dbf5f9 Binary files /dev/null and b/img/.svn/text-base/device_name_border_checkbox.png.svn-base differ diff --git a/img/.svn/text-base/device_name_border_file.png.svn-base b/img/.svn/text-base/device_name_border_file.png.svn-base new file mode 100644 index 0000000..3f0ee83 Binary files /dev/null and b/img/.svn/text-base/device_name_border_file.png.svn-base differ diff --git a/img/.svn/text-base/device_selection_bg.png.svn-base b/img/.svn/text-base/device_selection_bg.png.svn-base new file mode 100644 index 0000000..e6d525f Binary files /dev/null and b/img/.svn/text-base/device_selection_bg.png.svn-base differ diff --git a/img/.svn/text-base/disconnected.png.svn-base b/img/.svn/text-base/disconnected.png.svn-base new file mode 100644 index 0000000..ed10736 Binary files /dev/null and b/img/.svn/text-base/disconnected.png.svn-base differ diff --git a/img/.svn/text-base/disconnected_backup.png.svn-base b/img/.svn/text-base/disconnected_backup.png.svn-base new file mode 100644 index 0000000..edab272 Binary files /dev/null and b/img/.svn/text-base/disconnected_backup.png.svn-base differ diff --git a/img/.svn/text-base/forward_arrow_off.png.svn-base b/img/.svn/text-base/forward_arrow_off.png.svn-base new file mode 100644 index 0000000..4cb19bf Binary files /dev/null and b/img/.svn/text-base/forward_arrow_off.png.svn-base differ diff --git a/img/.svn/text-base/forward_arrow_on.png.svn-base b/img/.svn/text-base/forward_arrow_on.png.svn-base new file mode 100644 index 0000000..48c5e9e Binary files /dev/null and b/img/.svn/text-base/forward_arrow_on.png.svn-base differ diff --git a/img/.svn/text-base/icon-alert-ref.png.svn-base b/img/.svn/text-base/icon-alert-ref.png.svn-base new file mode 100644 index 0000000..c6494d9 Binary files /dev/null and b/img/.svn/text-base/icon-alert-ref.png.svn-base differ diff --git a/img/.svn/text-base/icon-ref-managebackups.png.svn-base b/img/.svn/text-base/icon-ref-managebackups.png.svn-base new file mode 100644 index 0000000..e610e38 Binary files /dev/null and b/img/.svn/text-base/icon-ref-managebackups.png.svn-base differ diff --git a/img/.svn/text-base/icon-ref-newbackup.png.svn-base b/img/.svn/text-base/icon-ref-newbackup.png.svn-base new file mode 100644 index 0000000..fae0e89 Binary files /dev/null and b/img/.svn/text-base/icon-ref-newbackup.png.svn-base differ diff --git a/img/.svn/text-base/icon-ref-restorebackups.png.svn-base b/img/.svn/text-base/icon-ref-restorebackups.png.svn-base new file mode 100644 index 0000000..2ff5139 Binary files /dev/null and b/img/.svn/text-base/icon-ref-restorebackups.png.svn-base differ diff --git a/img/.svn/text-base/icon-ref-settings.png.svn-base b/img/.svn/text-base/icon-ref-settings.png.svn-base new file mode 100644 index 0000000..2227abf Binary files /dev/null and b/img/.svn/text-base/icon-ref-settings.png.svn-base differ diff --git a/img/.svn/text-base/ip_list_border.png.svn-base b/img/.svn/text-base/ip_list_border.png.svn-base new file mode 100644 index 0000000..9a099fc Binary files /dev/null and b/img/.svn/text-base/ip_list_border.png.svn-base differ diff --git a/img/.svn/text-base/large_arrow_border.png.svn-base b/img/.svn/text-base/large_arrow_border.png.svn-base new file mode 100644 index 0000000..f6b955f Binary files /dev/null and b/img/.svn/text-base/large_arrow_border.png.svn-base differ diff --git a/img/.svn/text-base/large_arrow_image.png.svn-base b/img/.svn/text-base/large_arrow_image.png.svn-base new file mode 100644 index 0000000..7e2db57 Binary files /dev/null and b/img/.svn/text-base/large_arrow_image.png.svn-base differ diff --git a/img/.svn/text-base/lista.png.svn-base b/img/.svn/text-base/lista.png.svn-base new file mode 100644 index 0000000..376f33e Binary files /dev/null and b/img/.svn/text-base/lista.png.svn-base differ diff --git a/img/.svn/text-base/memory_bar.png.svn-base b/img/.svn/text-base/memory_bar.png.svn-base new file mode 100644 index 0000000..c0d0305 Binary files /dev/null and b/img/.svn/text-base/memory_bar.png.svn-base differ diff --git a/img/.svn/text-base/path_bg.png.svn-base b/img/.svn/text-base/path_bg.png.svn-base new file mode 100644 index 0000000..ac7d1af Binary files /dev/null and b/img/.svn/text-base/path_bg.png.svn-base differ diff --git a/img/.svn/text-base/path_border.png.svn-base b/img/.svn/text-base/path_border.png.svn-base new file mode 100644 index 0000000..b978d66 Binary files /dev/null and b/img/.svn/text-base/path_border.png.svn-base differ diff --git a/img/.svn/text-base/pc_file_border.png.svn-base b/img/.svn/text-base/pc_file_border.png.svn-base new file mode 100644 index 0000000..5d87a65 Binary files /dev/null and b/img/.svn/text-base/pc_file_border.png.svn-base differ diff --git a/img/.svn/text-base/pc_image.png.svn-base b/img/.svn/text-base/pc_image.png.svn-base new file mode 100644 index 0000000..09693c6 Binary files /dev/null and b/img/.svn/text-base/pc_image.png.svn-base differ diff --git a/img/.svn/text-base/pc_name_border_file.png.svn-base b/img/.svn/text-base/pc_name_border_file.png.svn-base new file mode 100644 index 0000000..a37d5b2 Binary files /dev/null and b/img/.svn/text-base/pc_name_border_file.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_bg.png.svn-base b/img/.svn/text-base/progress_bar_bg.png.svn-base new file mode 100644 index 0000000..6193ec7 Binary files /dev/null and b/img/.svn/text-base/progress_bar_bg.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_border.png.svn-base b/img/.svn/text-base/progress_bar_border.png.svn-base new file mode 100644 index 0000000..252ead2 Binary files /dev/null and b/img/.svn/text-base/progress_bar_border.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_chunk.png.svn-base b/img/.svn/text-base/progress_bar_chunk.png.svn-base new file mode 100644 index 0000000..b8c8b60 Binary files /dev/null and b/img/.svn/text-base/progress_bar_chunk.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_chunk_dialog.png.svn-base b/img/.svn/text-base/progress_bar_chunk_dialog.png.svn-base new file mode 100644 index 0000000..bde0ce5 Binary files /dev/null and b/img/.svn/text-base/progress_bar_chunk_dialog.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_connecting_bg.png.svn-base b/img/.svn/text-base/progress_bar_connecting_bg.png.svn-base new file mode 100644 index 0000000..942f14b Binary files /dev/null and b/img/.svn/text-base/progress_bar_connecting_bg.png.svn-base differ diff --git a/img/.svn/text-base/progress_bar_dialog_bg.png.svn-base b/img/.svn/text-base/progress_bar_dialog_bg.png.svn-base new file mode 100644 index 0000000..0123b36 Binary files /dev/null and b/img/.svn/text-base/progress_bar_dialog_bg.png.svn-base differ diff --git a/img/.svn/text-base/scroll_base_h.png.svn-base b/img/.svn/text-base/scroll_base_h.png.svn-base new file mode 100644 index 0000000..e1a9c7c Binary files /dev/null and b/img/.svn/text-base/scroll_base_h.png.svn-base differ diff --git a/img/.svn/text-base/scroll_base_v.png.svn-base b/img/.svn/text-base/scroll_base_v.png.svn-base new file mode 100644 index 0000000..d6066c8 Binary files /dev/null and b/img/.svn/text-base/scroll_base_v.png.svn-base differ diff --git a/img/.svn/text-base/scroll_handle_h.png.svn-base b/img/.svn/text-base/scroll_handle_h.png.svn-base new file mode 100644 index 0000000..ed561e4 Binary files /dev/null and b/img/.svn/text-base/scroll_handle_h.png.svn-base differ diff --git a/img/.svn/text-base/scroll_handle_v.png.svn-base b/img/.svn/text-base/scroll_handle_v.png.svn-base new file mode 100644 index 0000000..3a2ad73 Binary files /dev/null and b/img/.svn/text-base/scroll_handle_v.png.svn-base differ diff --git a/img/.svn/text-base/small_default_button.png.svn-base b/img/.svn/text-base/small_default_button.png.svn-base new file mode 100644 index 0000000..8d4017c Binary files /dev/null and b/img/.svn/text-base/small_default_button.png.svn-base differ diff --git a/img/.svn/text-base/small_default_button_clicked.png.svn-base b/img/.svn/text-base/small_default_button_clicked.png.svn-base new file mode 100644 index 0000000..a304368 Binary files /dev/null and b/img/.svn/text-base/small_default_button_clicked.png.svn-base differ diff --git a/img/.svn/text-base/small_icon-ref-managebackups.png.svn-base b/img/.svn/text-base/small_icon-ref-managebackups.png.svn-base new file mode 100644 index 0000000..f9ffe78 Binary files /dev/null and b/img/.svn/text-base/small_icon-ref-managebackups.png.svn-base differ diff --git a/img/.svn/text-base/small_icon-ref-newbackup.png.svn-base b/img/.svn/text-base/small_icon-ref-newbackup.png.svn-base new file mode 100644 index 0000000..97d8166 Binary files /dev/null and b/img/.svn/text-base/small_icon-ref-newbackup.png.svn-base differ diff --git a/img/.svn/text-base/small_icon-ref-restorebackups.png.svn-base b/img/.svn/text-base/small_icon-ref-restorebackups.png.svn-base new file mode 100644 index 0000000..23e2534 Binary files /dev/null and b/img/.svn/text-base/small_icon-ref-restorebackups.png.svn-base differ diff --git a/img/.svn/text-base/small_icon-ref-settings.png.svn-base b/img/.svn/text-base/small_icon-ref-settings.png.svn-base new file mode 100644 index 0000000..abc454c Binary files /dev/null and b/img/.svn/text-base/small_icon-ref-settings.png.svn-base differ diff --git a/img/.svn/text-base/ssh.png.svn-base b/img/.svn/text-base/ssh.png.svn-base new file mode 100644 index 0000000..d4ce558 Binary files /dev/null and b/img/.svn/text-base/ssh.png.svn-base differ diff --git a/img/.svn/text-base/tab_bg_1.png.svn-base b/img/.svn/text-base/tab_bg_1.png.svn-base new file mode 100644 index 0000000..f5de942 Binary files /dev/null and b/img/.svn/text-base/tab_bg_1.png.svn-base differ diff --git a/img/.svn/text-base/tab_bg_2.png.svn-base b/img/.svn/text-base/tab_bg_2.png.svn-base new file mode 100644 index 0000000..0c376ea Binary files /dev/null and b/img/.svn/text-base/tab_bg_2.png.svn-base differ diff --git a/img/.svn/text-base/tab_bg_3.png.svn-base b/img/.svn/text-base/tab_bg_3.png.svn-base new file mode 100644 index 0000000..2188df2 Binary files /dev/null and b/img/.svn/text-base/tab_bg_3.png.svn-base differ diff --git a/img/.svn/text-base/table_border.png.svn-base b/img/.svn/text-base/table_border.png.svn-base new file mode 100644 index 0000000..a4bae53 Binary files /dev/null and b/img/.svn/text-base/table_border.png.svn-base differ diff --git a/img/.svn/text-base/tabletSuite_logo.png.svn-base b/img/.svn/text-base/tabletSuite_logo.png.svn-base new file mode 100644 index 0000000..57b8571 Binary files /dev/null and b/img/.svn/text-base/tabletSuite_logo.png.svn-base differ diff --git a/img/.svn/text-base/tabletsuite.desktop.svn-base b/img/.svn/text-base/tabletsuite.desktop.svn-base new file mode 100644 index 0000000..1262354 --- /dev/null +++ b/img/.svn/text-base/tabletsuite.desktop.svn-base @@ -0,0 +1,12 @@ +#!/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 diff --git a/img/.svn/text-base/view_bg.png.svn-base b/img/.svn/text-base/view_bg.png.svn-base new file mode 100644 index 0000000..4a9743d Binary files /dev/null and b/img/.svn/text-base/view_bg.png.svn-base differ diff --git a/img/.svn/text-base/view_border.png.svn-base b/img/.svn/text-base/view_border.png.svn-base new file mode 100644 index 0000000..b289586 Binary files /dev/null and b/img/.svn/text-base/view_border.png.svn-base differ diff --git a/img/.svn/text-base/white_arrow.png.svn-base b/img/.svn/text-base/white_arrow.png.svn-base new file mode 100644 index 0000000..4dbf148 Binary files /dev/null and b/img/.svn/text-base/white_arrow.png.svn-base differ diff --git a/img/N800.png b/img/N800.png new file mode 100644 index 0000000..48df145 Binary files /dev/null and b/img/N800.png differ diff --git a/img/N800_backup.png b/img/N800_backup.png new file mode 100644 index 0000000..43fbb85 Binary files /dev/null and b/img/N800_backup.png differ diff --git a/img/N800_file.png b/img/N800_file.png new file mode 100644 index 0000000..edfa13b Binary files /dev/null and b/img/N800_file.png differ diff --git a/img/N810.png b/img/N810.png new file mode 100644 index 0000000..0a869b6 Binary files /dev/null and b/img/N810.png differ diff --git a/img/N810_backup.png b/img/N810_backup.png new file mode 100644 index 0000000..02c60e8 Binary files /dev/null and b/img/N810_backup.png differ diff --git a/img/N810_file.png b/img/N810_file.png new file mode 100644 index 0000000..fb7d138 Binary files /dev/null and b/img/N810_file.png differ diff --git a/img/arrow.png b/img/arrow.png new file mode 100755 index 0000000..4dbf148 Binary files /dev/null and b/img/arrow.png differ diff --git a/img/back_arrow_off.png b/img/back_arrow_off.png new file mode 100755 index 0000000..48c68a8 Binary files /dev/null and b/img/back_arrow_off.png differ diff --git a/img/back_arrow_on.png b/img/back_arrow_on.png new file mode 100755 index 0000000..99d8986 Binary files /dev/null and b/img/back_arrow_on.png differ diff --git a/img/backup.png b/img/backup.png new file mode 100644 index 0000000..b5dc1fd Binary files /dev/null and b/img/backup.png differ diff --git a/img/backup_default_button.png b/img/backup_default_button.png new file mode 100644 index 0000000..eded036 Binary files /dev/null and b/img/backup_default_button.png differ diff --git a/img/backup_default_button_clicked.png b/img/backup_default_button_clicked.png new file mode 100644 index 0000000..45b0e71 Binary files /dev/null and b/img/backup_default_button_clicked.png differ diff --git a/img/backup_name_bg.png b/img/backup_name_bg.png new file mode 100644 index 0000000..6ec151a Binary files /dev/null and b/img/backup_name_bg.png differ diff --git a/img/backup_name_border.png b/img/backup_name_border.png new file mode 100644 index 0000000..76baec9 Binary files /dev/null and b/img/backup_name_border.png differ diff --git a/img/battery_bar.png b/img/battery_bar.png new file mode 100644 index 0000000..b2b632f Binary files /dev/null and b/img/battery_bar.png differ diff --git a/img/bg_backup.png b/img/bg_backup.png new file mode 100644 index 0000000..701d70d Binary files /dev/null and b/img/bg_backup.png differ diff --git a/img/bg_backup0.png b/img/bg_backup0.png new file mode 100644 index 0000000..da7b3c0 Binary files /dev/null and b/img/bg_backup0.png differ diff --git a/img/bg_geral0.png b/img/bg_geral0.png new file mode 100644 index 0000000..506b9a7 Binary files /dev/null and b/img/bg_geral0.png differ diff --git a/img/bg_geral2.png b/img/bg_geral2.png new file mode 100644 index 0000000..6a49225 Binary files /dev/null and b/img/bg_geral2.png differ diff --git a/img/bg_manager.png b/img/bg_manager.png new file mode 100644 index 0000000..11c0671 Binary files /dev/null and b/img/bg_manager.png differ diff --git a/img/bg_restore.png b/img/bg_restore.png new file mode 100644 index 0000000..11c0671 Binary files /dev/null and b/img/bg_restore.png differ diff --git a/img/black_arrow.png b/img/black_arrow.png new file mode 100644 index 0000000..536644d Binary files /dev/null and b/img/black_arrow.png differ diff --git a/img/browse_button.png b/img/browse_button.png new file mode 100644 index 0000000..990e6d4 Binary files /dev/null and b/img/browse_button.png differ diff --git a/img/bt_next.png b/img/bt_next.png new file mode 100644 index 0000000..48297fe Binary files /dev/null and b/img/bt_next.png differ diff --git a/img/bt_next_clicked.png b/img/bt_next_clicked.png new file mode 100644 index 0000000..8a747c8 Binary files /dev/null and b/img/bt_next_clicked.png differ diff --git a/img/button_bg.png b/img/button_bg.png new file mode 100644 index 0000000..fe8f537 Binary files /dev/null and b/img/button_bg.png differ diff --git a/img/button_bg_clicked.png b/img/button_bg_clicked.png new file mode 100644 index 0000000..97fbdb3 Binary files /dev/null and b/img/button_bg_clicked.png differ diff --git a/img/button_with_icon_bg.png b/img/button_with_icon_bg.png new file mode 100644 index 0000000..cf6fc2c Binary files /dev/null and b/img/button_with_icon_bg.png differ diff --git a/img/button_with_icon_bg_clicked.png b/img/button_with_icon_bg_clicked.png new file mode 100644 index 0000000..8ceb603 Binary files /dev/null and b/img/button_with_icon_bg_clicked.png differ diff --git a/img/checkbox_border.png b/img/checkbox_border.png new file mode 100644 index 0000000..ae4ae02 Binary files /dev/null and b/img/checkbox_border.png differ diff --git a/img/checkbox_checked.png b/img/checkbox_checked.png new file mode 100644 index 0000000..6774a97 Binary files /dev/null and b/img/checkbox_checked.png differ diff --git a/img/checkbox_unchecked.png b/img/checkbox_unchecked.png new file mode 100644 index 0000000..10576e9 Binary files /dev/null and b/img/checkbox_unchecked.png differ diff --git a/img/copy_border.png b/img/copy_border.png new file mode 100644 index 0000000..d5e140c Binary files /dev/null and b/img/copy_border.png differ diff --git a/img/default_bg.png b/img/default_bg.png new file mode 100644 index 0000000..b96ca03 Binary files /dev/null and b/img/default_bg.png differ diff --git a/img/device_backup_border.png b/img/device_backup_border.png new file mode 100644 index 0000000..44b2c65 Binary files /dev/null and b/img/device_backup_border.png differ diff --git a/img/device_checkbox_border.png b/img/device_checkbox_border.png new file mode 100644 index 0000000..e6793cc Binary files /dev/null and b/img/device_checkbox_border.png differ diff --git a/img/device_file_border.png b/img/device_file_border.png new file mode 100644 index 0000000..3043002 Binary files /dev/null and b/img/device_file_border.png differ diff --git a/img/device_memory.png b/img/device_memory.png new file mode 100644 index 0000000..8164cbd Binary files /dev/null and b/img/device_memory.png differ diff --git a/img/device_name_border_backup.png b/img/device_name_border_backup.png new file mode 100644 index 0000000..9e233d4 Binary files /dev/null and b/img/device_name_border_backup.png differ diff --git a/img/device_name_border_checkbox.png b/img/device_name_border_checkbox.png new file mode 100644 index 0000000..5dbf5f9 Binary files /dev/null and b/img/device_name_border_checkbox.png differ diff --git a/img/device_name_border_file.png b/img/device_name_border_file.png new file mode 100644 index 0000000..3f0ee83 Binary files /dev/null and b/img/device_name_border_file.png differ diff --git a/img/device_selection_bg.png b/img/device_selection_bg.png new file mode 100644 index 0000000..e6d525f Binary files /dev/null and b/img/device_selection_bg.png differ diff --git a/img/disconnected.png b/img/disconnected.png new file mode 100644 index 0000000..ed10736 Binary files /dev/null and b/img/disconnected.png differ diff --git a/img/disconnected_backup.png b/img/disconnected_backup.png new file mode 100644 index 0000000..edab272 Binary files /dev/null and b/img/disconnected_backup.png differ diff --git a/img/forward_arrow_off.png b/img/forward_arrow_off.png new file mode 100755 index 0000000..4cb19bf Binary files /dev/null and b/img/forward_arrow_off.png differ diff --git a/img/forward_arrow_on.png b/img/forward_arrow_on.png new file mode 100755 index 0000000..48c5e9e Binary files /dev/null and b/img/forward_arrow_on.png differ diff --git a/img/icon-alert-ref.png b/img/icon-alert-ref.png new file mode 100644 index 0000000..c6494d9 Binary files /dev/null and b/img/icon-alert-ref.png differ diff --git a/img/icon-ref-managebackups.png b/img/icon-ref-managebackups.png new file mode 100644 index 0000000..e610e38 Binary files /dev/null and b/img/icon-ref-managebackups.png differ diff --git a/img/icon-ref-newbackup.png b/img/icon-ref-newbackup.png new file mode 100644 index 0000000..fae0e89 Binary files /dev/null and b/img/icon-ref-newbackup.png differ diff --git a/img/icon-ref-restorebackups.png b/img/icon-ref-restorebackups.png new file mode 100644 index 0000000..2ff5139 Binary files /dev/null and b/img/icon-ref-restorebackups.png differ diff --git a/img/icon-ref-settings.png b/img/icon-ref-settings.png new file mode 100644 index 0000000..2227abf Binary files /dev/null and b/img/icon-ref-settings.png differ diff --git a/img/ip_list_border.png b/img/ip_list_border.png new file mode 100644 index 0000000..9a099fc Binary files /dev/null and b/img/ip_list_border.png differ diff --git a/img/large_arrow_border.png b/img/large_arrow_border.png new file mode 100644 index 0000000..f6b955f Binary files /dev/null and b/img/large_arrow_border.png differ diff --git a/img/large_arrow_image.png b/img/large_arrow_image.png new file mode 100644 index 0000000..7e2db57 Binary files /dev/null and b/img/large_arrow_image.png differ diff --git a/img/lista.png b/img/lista.png new file mode 100644 index 0000000..376f33e Binary files /dev/null and b/img/lista.png differ diff --git a/img/memory_bar.png b/img/memory_bar.png new file mode 100644 index 0000000..c0d0305 Binary files /dev/null and b/img/memory_bar.png differ diff --git a/img/path_bg.png b/img/path_bg.png new file mode 100644 index 0000000..ac7d1af Binary files /dev/null and b/img/path_bg.png differ diff --git a/img/path_border.png b/img/path_border.png new file mode 100644 index 0000000..b978d66 Binary files /dev/null and b/img/path_border.png differ diff --git a/img/pc_file_border.png b/img/pc_file_border.png new file mode 100644 index 0000000..5d87a65 Binary files /dev/null and b/img/pc_file_border.png differ diff --git a/img/pc_image.png b/img/pc_image.png new file mode 100644 index 0000000..09693c6 Binary files /dev/null and b/img/pc_image.png differ diff --git a/img/pc_name_border_file.png b/img/pc_name_border_file.png new file mode 100644 index 0000000..a37d5b2 Binary files /dev/null and b/img/pc_name_border_file.png differ diff --git a/img/progress_bar_bg.png b/img/progress_bar_bg.png new file mode 100644 index 0000000..6193ec7 Binary files /dev/null and b/img/progress_bar_bg.png differ diff --git a/img/progress_bar_border.png b/img/progress_bar_border.png new file mode 100644 index 0000000..252ead2 Binary files /dev/null and b/img/progress_bar_border.png differ diff --git a/img/progress_bar_chunk.png b/img/progress_bar_chunk.png new file mode 100644 index 0000000..b8c8b60 Binary files /dev/null and b/img/progress_bar_chunk.png differ diff --git a/img/progress_bar_chunk_dialog.png b/img/progress_bar_chunk_dialog.png new file mode 100644 index 0000000..bde0ce5 Binary files /dev/null and b/img/progress_bar_chunk_dialog.png differ diff --git a/img/progress_bar_connecting_bg.png b/img/progress_bar_connecting_bg.png new file mode 100644 index 0000000..942f14b Binary files /dev/null and b/img/progress_bar_connecting_bg.png differ diff --git a/img/progress_bar_dialog_bg.png b/img/progress_bar_dialog_bg.png new file mode 100644 index 0000000..0123b36 Binary files /dev/null and b/img/progress_bar_dialog_bg.png differ diff --git a/img/scroll_base_h.png b/img/scroll_base_h.png new file mode 100644 index 0000000..e1a9c7c Binary files /dev/null and b/img/scroll_base_h.png differ diff --git a/img/scroll_base_v.png b/img/scroll_base_v.png new file mode 100644 index 0000000..d6066c8 Binary files /dev/null and b/img/scroll_base_v.png differ diff --git a/img/scroll_handle_h.png b/img/scroll_handle_h.png new file mode 100644 index 0000000..ed561e4 Binary files /dev/null and b/img/scroll_handle_h.png differ diff --git a/img/scroll_handle_v.png b/img/scroll_handle_v.png new file mode 100644 index 0000000..3a2ad73 Binary files /dev/null and b/img/scroll_handle_v.png differ diff --git a/img/small_default_button.png b/img/small_default_button.png new file mode 100644 index 0000000..8d4017c Binary files /dev/null and b/img/small_default_button.png differ diff --git a/img/small_default_button_clicked.png b/img/small_default_button_clicked.png new file mode 100644 index 0000000..a304368 Binary files /dev/null and b/img/small_default_button_clicked.png differ diff --git a/img/small_icon-ref-managebackups.png b/img/small_icon-ref-managebackups.png new file mode 100644 index 0000000..f9ffe78 Binary files /dev/null and b/img/small_icon-ref-managebackups.png differ diff --git a/img/small_icon-ref-newbackup.png b/img/small_icon-ref-newbackup.png new file mode 100644 index 0000000..97d8166 Binary files /dev/null and b/img/small_icon-ref-newbackup.png differ diff --git a/img/small_icon-ref-restorebackups.png b/img/small_icon-ref-restorebackups.png new file mode 100644 index 0000000..23e2534 Binary files /dev/null and b/img/small_icon-ref-restorebackups.png differ diff --git a/img/small_icon-ref-settings.png b/img/small_icon-ref-settings.png new file mode 100644 index 0000000..abc454c Binary files /dev/null and b/img/small_icon-ref-settings.png differ diff --git a/img/ssh.png b/img/ssh.png new file mode 100644 index 0000000..d4ce558 Binary files /dev/null and b/img/ssh.png differ diff --git a/img/tab_bg_1.png b/img/tab_bg_1.png new file mode 100644 index 0000000..f5de942 Binary files /dev/null and b/img/tab_bg_1.png differ diff --git a/img/tab_bg_2.png b/img/tab_bg_2.png new file mode 100644 index 0000000..0c376ea Binary files /dev/null and b/img/tab_bg_2.png differ diff --git a/img/tab_bg_3.png b/img/tab_bg_3.png new file mode 100644 index 0000000..2188df2 Binary files /dev/null and b/img/tab_bg_3.png differ diff --git a/img/table_border.png b/img/table_border.png new file mode 100644 index 0000000..a4bae53 Binary files /dev/null and b/img/table_border.png differ diff --git a/img/tabletSuite_logo.png b/img/tabletSuite_logo.png new file mode 100644 index 0000000..57b8571 Binary files /dev/null and b/img/tabletSuite_logo.png differ diff --git a/img/tabletsuite.desktop b/img/tabletsuite.desktop new file mode 100755 index 0000000..1262354 --- /dev/null +++ b/img/tabletsuite.desktop @@ -0,0 +1,12 @@ +#!/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 diff --git a/img/view_bg.png b/img/view_bg.png new file mode 100644 index 0000000..4a9743d Binary files /dev/null and b/img/view_bg.png differ diff --git a/img/view_border.png b/img/view_border.png new file mode 100644 index 0000000..b289586 Binary files /dev/null and b/img/view_border.png differ diff --git a/img/white_arrow.png b/img/white_arrow.png new file mode 100755 index 0000000..4dbf148 Binary files /dev/null and b/img/white_arrow.png differ diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..86371ef --- /dev/null +++ b/setup.py @@ -0,0 +1,21 @@ +#!/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/*'))], +) diff --git a/src/.svn/all-wcprops b/src/.svn/all-wcprops new file mode 100644 index 0000000..cd218cf --- /dev/null +++ b/src/.svn/all-wcprops @@ -0,0 +1,53 @@ +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 diff --git a/src/.svn/dir-prop-base b/src/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/entries b/src/.svn/entries new file mode 100644 index 0000000..f231a9d --- /dev/null +++ b/src/.svn/entries @@ -0,0 +1,315 @@ +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 + +style +dir + +plugins +dir + +battery.py +file + + + + +2009-09-29T18:30:22.000000Z +9e4cc0a1ebba665c2fe12b76ba889647 +2009-09-14T12:56:51.357750Z +617 +otacilio + + + + + + + + + + + + + + + + + + + + + +1811 + +backup +dir + +__init__.py +file + + + + +2009-09-29T18:30:22.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-03-29T21:16:15.145020Z +24 +nicholas + + + + + + + + + + + + + + + + + + + + + +0 + +pcsdevicemanager.py +file + + + + +2009-09-29T18:30:22.000000Z +c759b16ea11f886c17310a1daa147d15 +2009-09-24T17:39:24.743743Z +642 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +4001 + +settings.py +file + + + + +2009-09-29T18:30:22.000000Z +a624870d9c3018ae79cfc67d37fa1abf +2009-06-23T17:46:40.723124Z +346 +melunko + + + + + + + + + + + + + + + + + + + + + +1158 + +pcsdeviceinfo.py +file + + + + +2009-09-29T18:30:22.000000Z +027acaec3db77d7c557936ef39ae9e75 +2009-07-08T15:53:48.428567Z +394 +nicholas + + + + + + + + + + + + + + + + + + + + + +417 + +pcsuite +dir + +tabletsuite.py +file + + + + +2009-09-29T18:30:22.000000Z +0e1bae3cfc483abe88238c96c4ac1798 +2009-09-03T11:08:46.919187Z +588 +otacilio +has-props + + + + + + + + + + + + + + + + + + + + +775 + +ui +dir + +pcsdeviceutils.py +file + + + + +2009-09-29T18:30:22.000000Z +99e1f832b7dab66b04bd0742b4f90423 +2009-09-24T18:11:29.733195Z +643 +otacilio + + + + + + + + + + + + + + + + + + + + + +5128 + +pcsutils.py +file + + + + +2009-09-29T18:30:22.000000Z +6bac19aba73e3f938e4cdb3aea339c13 +2009-09-10T18:11:56.305145Z +611 +nicholas +has-props + + + + + + + + + + + + + + + + + + + + +4727 + diff --git a/src/.svn/format b/src/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/.svn/prop-base/pcsutils.py.svn-base b/src/.svn/prop-base/pcsutils.py.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/src/.svn/prop-base/pcsutils.py.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/src/.svn/prop-base/tabletsuite.py.svn-base b/src/.svn/prop-base/tabletsuite.py.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/.svn/prop-base/tabletsuite.py.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/.svn/text-base/__init__.py.svn-base b/src/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/src/.svn/text-base/battery.py.svn-base b/src/.svn/text-base/battery.py.svn-base new file mode 100644 index 0000000..0404ab0 --- /dev/null +++ b/src/.svn/text-base/battery.py.svn-base @@ -0,0 +1,73 @@ +#!/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) + diff --git a/src/.svn/text-base/pcsdeviceinfo.py.svn-base b/src/.svn/text-base/pcsdeviceinfo.py.svn-base new file mode 100644 index 0000000..5e913eb --- /dev/null +++ b/src/.svn/text-base/pcsdeviceinfo.py.svn-base @@ -0,0 +1,15 @@ +# 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 = "" diff --git a/src/.svn/text-base/pcsdevicemanager.py.svn-base b/src/.svn/text-base/pcsdevicemanager.py.svn-base new file mode 100644 index 0000000..a63160f --- /dev/null +++ b/src/.svn/text-base/pcsdevicemanager.py.svn-base @@ -0,0 +1,131 @@ +# 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) + diff --git a/src/.svn/text-base/pcsdeviceutils.py.svn-base b/src/.svn/text-base/pcsdeviceutils.py.svn-base new file mode 100644 index 0000000..efe8da0 --- /dev/null +++ b/src/.svn/text-base/pcsdeviceutils.py.svn-base @@ -0,0 +1,155 @@ +# 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 diff --git a/src/.svn/text-base/pcsutils.py.svn-base b/src/.svn/text-base/pcsutils.py.svn-base new file mode 100644 index 0000000..7d8a930 --- /dev/null +++ b/src/.svn/text-base/pcsutils.py.svn-base @@ -0,0 +1,165 @@ +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 diff --git a/src/.svn/text-base/settings.py.svn-base b/src/.svn/text-base/settings.py.svn-base new file mode 100644 index 0000000..d5b0325 --- /dev/null +++ b/src/.svn/text-base/settings.py.svn-base @@ -0,0 +1,36 @@ +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() + + diff --git a/src/.svn/text-base/tabletsuite.py.svn-base b/src/.svn/text-base/tabletsuite.py.svn-base new file mode 100644 index 0000000..531c1e8 --- /dev/null +++ b/src/.svn/text-base/tabletsuite.py.svn-base @@ -0,0 +1,29 @@ +#!/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_() diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backup/.svn/all-wcprops b/src/backup/.svn/all-wcprops new file mode 100644 index 0000000..b3ad112 --- /dev/null +++ b/src/backup/.svn/all-wcprops @@ -0,0 +1,125 @@ +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 diff --git a/src/backup/.svn/dir-prop-base b/src/backup/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/backup/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/backup/.svn/entries b/src/backup/.svn/entries new file mode 100644 index 0000000..7857140 --- /dev/null +++ b/src/backup/.svn/entries @@ -0,0 +1,708 @@ +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 + +pcsopenfilewizard.py +file + + + + +2009-09-29T18:30:21.000000Z +bd7d89e9e75d7a71828842740bf96bc9 +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +9749 + +pcsbackupparser.py +file + + + + +2009-09-29T18:30:21.000000Z +cb732e14b18419973e32171f4ab44586 +2009-08-20T18:08:50.977477Z +571 +nicholas + + + + + + + + + + + + + + + + + + + + + +4071 + +pcspcbackupmanager.py +file + + + + +2009-09-29T18:30:21.000000Z +ce87348b076ca74e6cb7c6453cae7683 +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +19153 + +pcsprogressdialog.py +file + + + + +2009-09-29T18:30:21.000000Z +8f8ede17cf9c329d29af777bae73a556 +2009-09-18T09:51:12.321968Z +639 +nicholas + + + + + + + + + + + + + + + + + + + + + +4432 + +pcsprogresswizard.py +file + + + + +2009-09-29T18:30:21.000000Z +3982df75bf944d1b5b8eb49df76460f7 +2009-09-17T14:38:23.185224Z +636 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +9496 + +pcsbackupxml.py +file + + + + +2009-09-29T18:30:21.000000Z +cfc2951c78dbc548e271022d230fa645 +2009-09-14T16:31:07.677300Z +620 +nicholas + + + + + + + + + + + + + + + + + + + + + +3174 + +pcsbackupwizard.py +file + + + + +2009-10-08T18:25:37.000000Z +3171ca50afa16f0dcaf44c048cfa62c6 +2009-10-06T17:00:03.678569Z +653 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +6759 + +pcsbackuputils.py +file + + + + +2009-09-29T18:30:21.000000Z +9f9b1db376f86057eb1dac85a386e05c +2009-09-28T11:36:33.963218Z +648 +nicholas +has-props + + + + + + + + + + + + + + + + + + + + +5583 + +__init__.py +file + + + + +2009-09-29T18:30:21.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-03-30T19:44:37.661351Z +26 +amaury + + + + + + + + + + + + + + + + + + + + + +0 + +pcsbackupmanagerui.py +file + + + + +2009-10-08T18:25:37.000000Z +9c5a36ddecd9d79d7d7988c6b8fd673a +2009-10-05T11:14:02.602311Z +652 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +19623 + +pcsbackuplocation.py +file + + + + +2009-09-29T18:30:21.000000Z +dd0ceb1377ef5b46c6dc79c44dcee7ba +2009-06-23T16:10:35.956172Z +345 +melunko +has-props + + + + + + + + + + + + + + + + + + + + +337 + +pcsbackuplistui.py +file + + + + +2009-09-29T18:30:21.000000Z +313275d8fa5de6a6a67dcc3a0b75bf7a +2009-08-27T10:01:51.549755Z +577 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +3915 + +pcsbackupmanager.py +file + + + + +2009-09-29T18:30:21.000000Z +d61dc11dd6cfdfe3d2eec0b7ebd3a643 +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +6801 + +pcswindowmanager.py +file + + + + +2009-09-29T18:30:21.000000Z +8f77ded896d07d7f62d101b3f70ba23d +2009-09-15T17:59:33.111110Z +630 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +1279 + +pcsrestoredialog.py +file + + + + +2009-09-29T18:30:21.000000Z +44f071048e2ac8dd3e4944866fa857c4 +2009-09-08T13:49:13.253249Z +606 +amaury + + + + + + + + + + + + + + + + + + + + + +7658 + +pcsbackup.py +file + + + + +2009-10-08T18:25:37.000000Z +6b5f22c2382885b7cd8d0f3d468c2597 +2009-10-05T11:14:02.602311Z +652 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +4784 + +pcscheckboxwizard.py +file + + + + +2009-09-29T18:30:21.000000Z +c7bce3b7fe62f58f2c84b72690008619 +2009-09-24T16:33:15.553218Z +641 +nicholas + + + + + + + + + + + + + + + + + + + + + +11024 + +pcsrestorebackupui.py +file + + + + +2009-09-29T18:30:21.000000Z +6229aa92dec31b2d6350a936e4f05849 +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +16050 + +pcsdevicebackupmanager.py +file + + + + +2009-09-29T18:30:21.000000Z +a6eca97d9d73c00c79d1afa06a79c98d +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +3340 + +pcsbackupinfo.py +file + + + + +2009-09-29T18:30:21.000000Z +227e4c627b4f06fb55da1e3d9e59ec4d +2009-08-12T12:26:15.094255Z +548 +nicholas + + + + + + + + + + + + + + + + + + + + + +2055 + diff --git a/src/backup/.svn/format b/src/backup/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/backup/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/backup/.svn/prop-base/pcsbackuplocation.py.svn-base b/src/backup/.svn/prop-base/pcsbackuplocation.py.svn-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/backup/.svn/prop-base/pcsbackuplocation.py.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/backup/.svn/prop-base/pcsbackuputils.py.svn-base b/src/backup/.svn/prop-base/pcsbackuputils.py.svn-base new file mode 100644 index 0000000..869ac71 --- /dev/null +++ b/src/backup/.svn/prop-base/pcsbackuputils.py.svn-base @@ -0,0 +1,5 @@ +K 14 +svn:executable +V 1 +* +END diff --git a/src/backup/.svn/text-base/__init__.py.svn-base b/src/backup/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/src/backup/.svn/text-base/pcsbackup.py.svn-base b/src/backup/.svn/text-base/pcsbackup.py.svn-base new file mode 100644 index 0000000..92d5f2a --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackup.py.svn-base @@ -0,0 +1,124 @@ +# 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("Main") + 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(""\ + "Select an action.") + 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) + diff --git a/src/backup/.svn/text-base/pcsbackupinfo.py.svn-base b/src/backup/.svn/text-base/pcsbackupinfo.py.svn-base new file mode 100644 index 0000000..a76e11e --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupinfo.py.svn-base @@ -0,0 +1,73 @@ +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 diff --git a/src/backup/.svn/text-base/pcsbackuplistui.py.svn-base b/src/backup/.svn/text-base/pcsbackuplistui.py.svn-base new file mode 100644 index 0000000..daca374 --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackuplistui.py.svn-base @@ -0,0 +1,110 @@ +# 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]) diff --git a/src/backup/.svn/text-base/pcsbackuplocation.py.svn-base b/src/backup/.svn/text-base/pcsbackuplocation.py.svn-base new file mode 100644 index 0000000..ab5d942 --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackuplocation.py.svn-base @@ -0,0 +1,11 @@ +# 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 diff --git a/src/backup/.svn/text-base/pcsbackupmanager.py.svn-base b/src/backup/.svn/text-base/pcsbackupmanager.py.svn-base new file mode 100644 index 0000000..92a5cc7 --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupmanager.py.svn-base @@ -0,0 +1,168 @@ +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 diff --git a/src/backup/.svn/text-base/pcsbackupmanagerui.py.svn-base b/src/backup/.svn/text-base/pcsbackupmanagerui.py.svn-base new file mode 100644 index 0000000..2fdc32b --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupmanagerui.py.svn-base @@ -0,0 +1,502 @@ +# 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("Main") + restore = QLabel(" Manage backups") + 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(""\ + "Select the backup you wish to manipulate.") + 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(" Backup copy destination: ") + 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")) + + + + diff --git a/src/backup/.svn/text-base/pcsbackupparser.py.svn-base b/src/backup/.svn/text-base/pcsbackupparser.py.svn-base new file mode 100644 index 0000000..c950a6e --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupparser.py.svn-base @@ -0,0 +1,115 @@ +# 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 + diff --git a/src/backup/.svn/text-base/pcsbackuputils.py.svn-base b/src/backup/.svn/text-base/pcsbackuputils.py.svn-base new file mode 100644 index 0000000..8dfa7fe --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackuputils.py.svn-base @@ -0,0 +1,184 @@ + +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 + diff --git a/src/backup/.svn/text-base/pcsbackupwizard.py.svn-base b/src/backup/.svn/text-base/pcsbackupwizard.py.svn-base new file mode 100644 index 0000000..bd16fc5 --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupwizard.py.svn-base @@ -0,0 +1,180 @@ +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 diff --git a/src/backup/.svn/text-base/pcsbackupxml.py.svn-base b/src/backup/.svn/text-base/pcsbackupxml.py.svn-base new file mode 100644 index 0000000..0bf3905 --- /dev/null +++ b/src/backup/.svn/text-base/pcsbackupxml.py.svn-base @@ -0,0 +1,87 @@ +''' +@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 diff --git a/src/backup/.svn/text-base/pcscheckboxwizard.py.svn-base b/src/backup/.svn/text-base/pcscheckboxwizard.py.svn-base new file mode 100644 index 0000000..7745894 --- /dev/null +++ b/src/backup/.svn/text-base/pcscheckboxwizard.py.svn-base @@ -0,0 +1,292 @@ +# 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(""\ + "Select the types of file you wish to backup.") + 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("Main") + arrow = self._arrow() + arrow2 = self._arrow() + spc = QSpacerItem(5, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + 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 diff --git a/src/backup/.svn/text-base/pcsdevicebackupmanager.py.svn-base b/src/backup/.svn/text-base/pcsdevicebackupmanager.py.svn-base new file mode 100644 index 0000000..095bfd7 --- /dev/null +++ b/src/backup/.svn/text-base/pcsdevicebackupmanager.py.svn-base @@ -0,0 +1,102 @@ + +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 diff --git a/src/backup/.svn/text-base/pcsopenfilewizard.py.svn-base b/src/backup/.svn/text-base/pcsopenfilewizard.py.svn-base new file mode 100644 index 0000000..313aac4 --- /dev/null +++ b/src/backup/.svn/text-base/pcsopenfilewizard.py.svn-base @@ -0,0 +1,264 @@ +# 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("Main") + arrow = self._arrow() + arrow2 = self._arrow() + arrow3 = self._arrow() + spc = QSpacerItem(2, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + folder = QLabel("Folder") + 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(""\ + "Do backup from Device to your PC.") + 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()) + diff --git a/src/backup/.svn/text-base/pcspcbackupmanager.py.svn-base b/src/backup/.svn/text-base/pcspcbackupmanager.py.svn-base new file mode 100644 index 0000000..35bcfe3 --- /dev/null +++ b/src/backup/.svn/text-base/pcspcbackupmanager.py.svn-base @@ -0,0 +1,475 @@ +# 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 diff --git a/src/backup/.svn/text-base/pcsprogressdialog.py.svn-base b/src/backup/.svn/text-base/pcsprogressdialog.py.svn-base new file mode 100644 index 0000000..cf9038f --- /dev/null +++ b/src/backup/.svn/text-base/pcsprogressdialog.py.svn-base @@ -0,0 +1,117 @@ +# 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(""\ + +str(action).capitalize()+ + " in progress...") + + self.actionLabel.setText(''' + '''+ message +'''''') + + 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(""+\ + str(self.action).capitalize() + +" finished.") + if not cancel: + totalSize = "%.2f" % (self.totalSize/(1024.0**2)) + + self.progressReport.setText(""\ + + str(self.numberOfFiles) +\ + " Files - " + totalSize + " MB") + else: + self.progressReport.setText(" 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(""\ + + progress +\ + "% Complete") + + def setCategory(self, catogory): + self.categoryLabel.setText(" Category name: "\ + + catogory +"") + + + \ No newline at end of file diff --git a/src/backup/.svn/text-base/pcsprogresswizard.py.svn-base b/src/backup/.svn/text-base/pcsprogresswizard.py.svn-base new file mode 100644 index 0000000..6afb6af --- /dev/null +++ b/src/backup/.svn/text-base/pcsprogresswizard.py.svn-base @@ -0,0 +1,237 @@ +# 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("Main") + arrow1 = self._arrow() + arrow2 = self._arrow() + arrow3 = self._arrow() + arrow4 = self._arrow() + spc = QSpacerItem(2, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + folder = QLabel("Folder") + if name != "": + loading = QLabel("loading") + else: + loading = QLabel("loading") + 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(""+ name +"") + 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(""\ + "Do backup from Device to your PC.") + 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(""\ + "Backup starting...") + + def _createCenterLayout(self): + gridLayout = QGridLayout() + gridLayout.setMargin(27) + + self.categoryLabel = QLabel(""\ + "Backup starting...") + + 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(""\ + "Backup finished.") + if not cancel: + totalSize = "%.2f" % (self.totalSize/(1024.0**2)) + + self.progressReport.setText(""\ + + str(self.backedUpNumber) +\ + " Files - " + totalSize + " MB") + else: + self.progressReport.setText(" Canceled") + self.categoryLabel.setText("") + self.progressBar.setValue(100) + + + self.infLabel.setText(""\ + "Select an action") + + def updateInfo(self, totalSize, backedUpNumber): + self.totalSize = totalSize + self.backedUpNumber = backedUpNumber + + def setProgress(self, progress): + self.progressBar.setValue(progress) + + self.progressReport.setText(""\ + + str(int(progress))+\ + "% Complete") + + def setCategory(self, category): + self.categoryLabel.setText(" Category name: "\ + + category +"") + + \ No newline at end of file diff --git a/src/backup/.svn/text-base/pcsrestorebackupui.py.svn-base b/src/backup/.svn/text-base/pcsrestorebackupui.py.svn-base new file mode 100644 index 0000000..dc9733a --- /dev/null +++ b/src/backup/.svn/text-base/pcsrestorebackupui.py.svn-base @@ -0,0 +1,412 @@ +# 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("Main") + restore = QLabel(" Restore backups") + 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(""\ + "Select the backup you wish to restore.") + 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")) + diff --git a/src/backup/.svn/text-base/pcsrestoredialog.py.svn-base b/src/backup/.svn/text-base/pcsrestoredialog.py.svn-base new file mode 100644 index 0000000..dbef514 --- /dev/null +++ b/src/backup/.svn/text-base/pcsrestoredialog.py.svn-base @@ -0,0 +1,199 @@ +# 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 + diff --git a/src/backup/.svn/text-base/pcswindowmanager.py.svn-base b/src/backup/.svn/text-base/pcswindowmanager.py.svn-base new file mode 100644 index 0000000..a0aa565 --- /dev/null +++ b/src/backup/.svn/text-base/pcswindowmanager.py.svn-base @@ -0,0 +1,36 @@ +# 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 diff --git a/src/backup/__init__.py b/src/backup/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backup/pcsbackup.py b/src/backup/pcsbackup.py new file mode 100644 index 0000000..92d5f2a --- /dev/null +++ b/src/backup/pcsbackup.py @@ -0,0 +1,124 @@ +# 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("Main") + 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(""\ + "Select an action.") + 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) + diff --git a/src/backup/pcsbackupinfo.py b/src/backup/pcsbackupinfo.py new file mode 100644 index 0000000..a76e11e --- /dev/null +++ b/src/backup/pcsbackupinfo.py @@ -0,0 +1,73 @@ +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 diff --git a/src/backup/pcsbackuplistui.py b/src/backup/pcsbackuplistui.py new file mode 100644 index 0000000..daca374 --- /dev/null +++ b/src/backup/pcsbackuplistui.py @@ -0,0 +1,110 @@ +# 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]) diff --git a/src/backup/pcsbackuplocation.py b/src/backup/pcsbackuplocation.py new file mode 100644 index 0000000..ab5d942 --- /dev/null +++ b/src/backup/pcsbackuplocation.py @@ -0,0 +1,11 @@ +# 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 diff --git a/src/backup/pcsbackupmanager.py b/src/backup/pcsbackupmanager.py new file mode 100644 index 0000000..92a5cc7 --- /dev/null +++ b/src/backup/pcsbackupmanager.py @@ -0,0 +1,168 @@ +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 diff --git a/src/backup/pcsbackupmanagerui.py b/src/backup/pcsbackupmanagerui.py new file mode 100644 index 0000000..2fdc32b --- /dev/null +++ b/src/backup/pcsbackupmanagerui.py @@ -0,0 +1,502 @@ +# 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("Main") + restore = QLabel(" Manage backups") + 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(""\ + "Select the backup you wish to manipulate.") + 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(" Backup copy destination: ") + 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")) + + + + diff --git a/src/backup/pcsbackupparser.py b/src/backup/pcsbackupparser.py new file mode 100644 index 0000000..c950a6e --- /dev/null +++ b/src/backup/pcsbackupparser.py @@ -0,0 +1,115 @@ +# 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 + diff --git a/src/backup/pcsbackuputils.py b/src/backup/pcsbackuputils.py new file mode 100755 index 0000000..8dfa7fe --- /dev/null +++ b/src/backup/pcsbackuputils.py @@ -0,0 +1,184 @@ + +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 + diff --git a/src/backup/pcsbackupwizard.py b/src/backup/pcsbackupwizard.py new file mode 100644 index 0000000..bd16fc5 --- /dev/null +++ b/src/backup/pcsbackupwizard.py @@ -0,0 +1,180 @@ +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 diff --git a/src/backup/pcsbackupxml.py b/src/backup/pcsbackupxml.py new file mode 100644 index 0000000..0bf3905 --- /dev/null +++ b/src/backup/pcsbackupxml.py @@ -0,0 +1,87 @@ +''' +@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 diff --git a/src/backup/pcscheckboxwizard.py b/src/backup/pcscheckboxwizard.py new file mode 100644 index 0000000..7745894 --- /dev/null +++ b/src/backup/pcscheckboxwizard.py @@ -0,0 +1,292 @@ +# 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(""\ + "Select the types of file you wish to backup.") + 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("Main") + arrow = self._arrow() + arrow2 = self._arrow() + spc = QSpacerItem(5, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + 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 diff --git a/src/backup/pcsdevicebackupmanager.py b/src/backup/pcsdevicebackupmanager.py new file mode 100644 index 0000000..095bfd7 --- /dev/null +++ b/src/backup/pcsdevicebackupmanager.py @@ -0,0 +1,102 @@ + +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 diff --git a/src/backup/pcsopenfilewizard.py b/src/backup/pcsopenfilewizard.py new file mode 100644 index 0000000..313aac4 --- /dev/null +++ b/src/backup/pcsopenfilewizard.py @@ -0,0 +1,264 @@ +# 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("Main") + arrow = self._arrow() + arrow2 = self._arrow() + arrow3 = self._arrow() + spc = QSpacerItem(2, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + folder = QLabel("Folder") + 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(""\ + "Do backup from Device to your PC.") + 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()) + diff --git a/src/backup/pcspcbackupmanager.py b/src/backup/pcspcbackupmanager.py new file mode 100644 index 0000000..35bcfe3 --- /dev/null +++ b/src/backup/pcspcbackupmanager.py @@ -0,0 +1,475 @@ +# 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 diff --git a/src/backup/pcsprogressdialog.py b/src/backup/pcsprogressdialog.py new file mode 100644 index 0000000..cf9038f --- /dev/null +++ b/src/backup/pcsprogressdialog.py @@ -0,0 +1,117 @@ +# 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(""\ + +str(action).capitalize()+ + " in progress...") + + self.actionLabel.setText(''' + '''+ message +'''''') + + 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(""+\ + str(self.action).capitalize() + +" finished.") + if not cancel: + totalSize = "%.2f" % (self.totalSize/(1024.0**2)) + + self.progressReport.setText(""\ + + str(self.numberOfFiles) +\ + " Files - " + totalSize + " MB") + else: + self.progressReport.setText(" 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(""\ + + progress +\ + "% Complete") + + def setCategory(self, catogory): + self.categoryLabel.setText(" Category name: "\ + + catogory +"") + + + \ No newline at end of file diff --git a/src/backup/pcsprogresswizard.py b/src/backup/pcsprogresswizard.py new file mode 100644 index 0000000..6afb6af --- /dev/null +++ b/src/backup/pcsprogresswizard.py @@ -0,0 +1,237 @@ +# 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("Main") + arrow1 = self._arrow() + arrow2 = self._arrow() + arrow3 = self._arrow() + arrow4 = self._arrow() + spc = QSpacerItem(2, 0) + newBackup = QLabel(" New Backup") + files = QLabel("Files") + folder = QLabel("Folder") + if name != "": + loading = QLabel("loading") + else: + loading = QLabel("loading") + 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(""+ name +"") + 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(""\ + "Do backup from Device to your PC.") + 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(""\ + "Backup starting...") + + def _createCenterLayout(self): + gridLayout = QGridLayout() + gridLayout.setMargin(27) + + self.categoryLabel = QLabel(""\ + "Backup starting...") + + 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(""\ + "Backup finished.") + if not cancel: + totalSize = "%.2f" % (self.totalSize/(1024.0**2)) + + self.progressReport.setText(""\ + + str(self.backedUpNumber) +\ + " Files - " + totalSize + " MB") + else: + self.progressReport.setText(" Canceled") + self.categoryLabel.setText("") + self.progressBar.setValue(100) + + + self.infLabel.setText(""\ + "Select an action") + + def updateInfo(self, totalSize, backedUpNumber): + self.totalSize = totalSize + self.backedUpNumber = backedUpNumber + + def setProgress(self, progress): + self.progressBar.setValue(progress) + + self.progressReport.setText(""\ + + str(int(progress))+\ + "% Complete") + + def setCategory(self, category): + self.categoryLabel.setText(" Category name: "\ + + category +"") + + \ No newline at end of file diff --git a/src/backup/pcsrestorebackupui.py b/src/backup/pcsrestorebackupui.py new file mode 100644 index 0000000..dc9733a --- /dev/null +++ b/src/backup/pcsrestorebackupui.py @@ -0,0 +1,412 @@ +# 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("Main") + restore = QLabel(" Restore backups") + 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(""\ + "Select the backup you wish to restore.") + 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")) + diff --git a/src/backup/pcsrestoredialog.py b/src/backup/pcsrestoredialog.py new file mode 100644 index 0000000..dbef514 --- /dev/null +++ b/src/backup/pcsrestoredialog.py @@ -0,0 +1,199 @@ +# 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 + diff --git a/src/backup/pcswindowmanager.py b/src/backup/pcswindowmanager.py new file mode 100644 index 0000000..a0aa565 --- /dev/null +++ b/src/backup/pcswindowmanager.py @@ -0,0 +1,36 @@ +# 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 diff --git a/src/battery.py b/src/battery.py new file mode 100644 index 0000000..0404ab0 --- /dev/null +++ b/src/battery.py @@ -0,0 +1,73 @@ +#!/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) + diff --git a/src/pcsdeviceinfo.py b/src/pcsdeviceinfo.py new file mode 100644 index 0000000..5e913eb --- /dev/null +++ b/src/pcsdeviceinfo.py @@ -0,0 +1,15 @@ +# 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 = "" diff --git a/src/pcsdevicemanager.py b/src/pcsdevicemanager.py new file mode 100644 index 0000000..a63160f --- /dev/null +++ b/src/pcsdevicemanager.py @@ -0,0 +1,131 @@ +# 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) + diff --git a/src/pcsdeviceutils.py b/src/pcsdeviceutils.py new file mode 100644 index 0000000..efe8da0 --- /dev/null +++ b/src/pcsdeviceutils.py @@ -0,0 +1,155 @@ +# 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 diff --git a/src/pcsuite/.svn/all-wcprops b/src/pcsuite/.svn/all-wcprops new file mode 100644 index 0000000..b956fd7 --- /dev/null +++ b/src/pcsuite/.svn/all-wcprops @@ -0,0 +1,17 @@ +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 diff --git a/src/pcsuite/.svn/dir-prop-base b/src/pcsuite/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/pcsuite/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/pcsuite/.svn/entries b/src/pcsuite/.svn/entries new file mode 100644 index 0000000..cf0dc6d --- /dev/null +++ b/src/pcsuite/.svn/entries @@ -0,0 +1,96 @@ +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 + +pcsuite.py +file + + + + +2009-09-29T18:30:21.000000Z +1762e558bf43ba18c805db6698bf3945 +2009-09-10T20:35:15.948790Z +612 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +2373 + +__init__.py +file + + + + +2009-09-29T18:30:21.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-04-02T19:30:47.227755Z +61 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +0 + diff --git a/src/pcsuite/.svn/format b/src/pcsuite/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/pcsuite/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/pcsuite/.svn/text-base/__init__.py.svn-base b/src/pcsuite/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/src/pcsuite/.svn/text-base/pcsuite.py.svn-base b/src/pcsuite/.svn/text-base/pcsuite.py.svn-base new file mode 100644 index 0000000..f4026c8 --- /dev/null +++ b/src/pcsuite/.svn/text-base/pcsuite.py.svn-base @@ -0,0 +1,71 @@ +# 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" + diff --git a/src/pcsuite/__init__.py b/src/pcsuite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcsuite/pcsuite.py b/src/pcsuite/pcsuite.py new file mode 100644 index 0000000..f4026c8 --- /dev/null +++ b/src/pcsuite/pcsuite.py @@ -0,0 +1,71 @@ +# 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" + diff --git a/src/pcsutils.py b/src/pcsutils.py new file mode 100755 index 0000000..7d8a930 --- /dev/null +++ b/src/pcsutils.py @@ -0,0 +1,165 @@ +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 diff --git a/src/plugins/.svn/all-wcprops b/src/plugins/.svn/all-wcprops new file mode 100644 index 0000000..87e0384 --- /dev/null +++ b/src/plugins/.svn/all-wcprops @@ -0,0 +1,5 @@ +K 25 +svn:wc:ra_dav:version-url +V 56 +/svn/pc-suite/!svn/ver/590/trunk/tabletsuite/src/plugins +END diff --git a/src/plugins/.svn/entries b/src/plugins/.svn/entries new file mode 100644 index 0000000..08f5fb3 --- /dev/null +++ b/src/plugins/.svn/entries @@ -0,0 +1,28 @@ +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 + diff --git a/src/plugins/.svn/format b/src/plugins/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/plugins/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/settings.py b/src/settings.py new file mode 100644 index 0000000..d5b0325 --- /dev/null +++ b/src/settings.py @@ -0,0 +1,36 @@ +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() + + diff --git a/src/style/.svn/all-wcprops b/src/style/.svn/all-wcprops new file mode 100644 index 0000000..7c9e76f --- /dev/null +++ b/src/style/.svn/all-wcprops @@ -0,0 +1,17 @@ +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 diff --git a/src/style/.svn/entries b/src/style/.svn/entries new file mode 100644 index 0000000..6757ffc --- /dev/null +++ b/src/style/.svn/entries @@ -0,0 +1,96 @@ +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 + +__init__.py +file + + + + +2009-09-29T18:30:21.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-08-11T18:25:49.287367Z +542 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +0 + +styleTabletSuite.py +file + + + + +2009-10-08T18:25:37.000000Z +7c1ee6b259b399ddeab35930daa946eb +2009-10-05T11:14:02.602311Z +652 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +19114 + diff --git a/src/style/.svn/format b/src/style/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/style/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/style/.svn/text-base/__init__.py.svn-base b/src/style/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/src/style/.svn/text-base/styleTabletSuite.py.svn-base b/src/style/.svn/text-base/styleTabletSuite.py.svn-base new file mode 100644 index 0000000..493cdd5 --- /dev/null +++ b/src/style/.svn/text-base/styleTabletSuite.py.svn-base @@ -0,0 +1,606 @@ +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 diff --git a/src/style/__init__.py b/src/style/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/style/styleTabletSuite.py b/src/style/styleTabletSuite.py new file mode 100644 index 0000000..493cdd5 --- /dev/null +++ b/src/style/styleTabletSuite.py @@ -0,0 +1,606 @@ +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 diff --git a/src/tabletsuite.py b/src/tabletsuite.py new file mode 100644 index 0000000..531c1e8 --- /dev/null +++ b/src/tabletsuite.py @@ -0,0 +1,29 @@ +#!/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_() diff --git a/src/ui/.svn/all-wcprops b/src/ui/.svn/all-wcprops new file mode 100644 index 0000000..266eecc --- /dev/null +++ b/src/ui/.svn/all-wcprops @@ -0,0 +1,71 @@ +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 diff --git a/src/ui/.svn/dir-prop-base b/src/ui/.svn/dir-prop-base new file mode 100644 index 0000000..3160658 --- /dev/null +++ b/src/ui/.svn/dir-prop-base @@ -0,0 +1,5 @@ +K 13 +svn:mergeinfo +V 0 + +END diff --git a/src/ui/.svn/entries b/src/ui/.svn/entries new file mode 100644 index 0000000..b193a34 --- /dev/null +++ b/src/ui/.svn/entries @@ -0,0 +1,402 @@ +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 + +pcsdevicewidget.py +file + + + + +2009-09-29T18:30:22.000000Z +84f28d53fce52d6be1ce09a14a0a1e82 +2009-09-14T19:20:21.821743Z +624 +amaury + + + + + + + + + + + + + + + + + + + + + +3004 + +pcsmenu.py +file + + + + +2009-09-29T18:30:22.000000Z +09b541ed1dd300a729ae68ea9f944498 +2009-08-04T18:37:56.490706Z +510 +amaury + + + + + + + + + + + + + + + + + + + + + +4005 + +__init__.py +file + + + + +2009-09-29T18:30:22.000000Z +d41d8cd98f00b204e9800998ecf8427e +2009-04-02T19:30:47.227755Z +61 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +0 + +pcscustombuttons.py +file + + + + +2009-09-29T18:30:22.000000Z +01c999f11e8e38ac29c05fbe9d8a46d9 +2009-08-05T16:55:19.618241Z +511 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +1052 + +pcsbutton.py +file + + + + +2009-09-29T18:30:22.000000Z +8ceb0be1042061439ab2e971a5439fb5 +2009-08-06T18:40:51.041049Z +523 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +285 + +pcsdeviceinfoviewer.py +file + + + + +2009-09-29T18:30:22.000000Z +ed5d20e8ba52cfb30cedb4b5697f6aa9 +2009-08-18T14:29:37.615498Z +566 +nicholas + + + + + + + + + + + + + + + + + + + + + +7187 + +pcsuiutils.py +file + + + + +2009-09-29T18:30:22.000000Z +d92be1dd2821ca8bc135e2666c8be881 +2009-09-28T11:36:33.963218Z +648 +nicholas + + + + + + + + + + + + + + + + + + + + + +4522 + +pcsapplicationlist.py +file + + + + +2009-09-29T18:30:22.000000Z +d0164df0e34d095d7e6f7d9203a06cf9 +2009-09-10T20:35:15.948790Z +612 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +1583 + +pcsapp.py +file + + + + +2009-09-29T18:30:22.000000Z +80eef7e5d2a325b436d9e9d71d16aee0 +2009-06-30T10:24:42.195284Z +364 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +390 + +tsuigeneralmethods.py +file + + + + +2009-09-29T18:30:22.000000Z +4119124fdd8d0ae371ed717af9785a2d +2009-09-14T12:31:28.560392Z +616 +pauloouriques + + + + + + + + + + + + + + + + + + + + + +1062 + +pcsdeviceviewer.py +file + + + + +2009-10-08T18:25:37.000000Z +20b23b9e27952b9a6598f9df06993c1d +2009-10-01T16:05:02.177628Z +651 +nicholas + + + + + + + + + + + + + + + + + + + + + +11580 + diff --git a/src/ui/.svn/format b/src/ui/.svn/format new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/src/ui/.svn/format @@ -0,0 +1 @@ +9 diff --git a/src/ui/.svn/text-base/__init__.py.svn-base b/src/ui/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/.svn/text-base/pcsapp.py.svn-base b/src/ui/.svn/text-base/pcsapp.py.svn-base new file mode 100644 index 0000000..f901392 --- /dev/null +++ b/src/ui/.svn/text-base/pcsapp.py.svn-base @@ -0,0 +1,16 @@ +# 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 diff --git a/src/ui/.svn/text-base/pcsapplicationlist.py.svn-base b/src/ui/.svn/text-base/pcsapplicationlist.py.svn-base new file mode 100644 index 0000000..bfc3b54 --- /dev/null +++ b/src/ui/.svn/text-base/pcsapplicationlist.py.svn-base @@ -0,0 +1,48 @@ +# 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() + + diff --git a/src/ui/.svn/text-base/pcsbutton.py.svn-base b/src/ui/.svn/text-base/pcsbutton.py.svn-base new file mode 100644 index 0000000..8175c81 --- /dev/null +++ b/src/ui/.svn/text-base/pcsbutton.py.svn-base @@ -0,0 +1,13 @@ +# 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) + + + diff --git a/src/ui/.svn/text-base/pcscustombuttons.py.svn-base b/src/ui/.svn/text-base/pcscustombuttons.py.svn-base new file mode 100644 index 0000000..cdbe15f --- /dev/null +++ b/src/ui/.svn/text-base/pcscustombuttons.py.svn-base @@ -0,0 +1,35 @@ +# 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 + + diff --git a/src/ui/.svn/text-base/pcsdeviceinfoviewer.py.svn-base b/src/ui/.svn/text-base/pcsdeviceinfoviewer.py.svn-base new file mode 100644 index 0000000..4a5959b --- /dev/null +++ b/src/ui/.svn/text-base/pcsdeviceinfoviewer.py.svn-base @@ -0,0 +1,189 @@ +# 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("Maemo Release") + 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("Model") + 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("None") + self.deviceNameLabel.setGeometry(QRect(380, 70, WINDOW_WIDTH, WINDOW_HEIGHT)) + + + self.deviceNameLabel2 = QLabel(self.pcSuite) + self.deviceNameLabel2.setText("None") + 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("Select option") + self.actionLabel.setGeometry(QRect(55, 36, 100, 20)) + + self.chargingThread = None; + + def setDeviceInfo(self, deviceInfo): + self.deviceInfo = deviceInfo + self.label.setText("" + deviceInfo.system +"" ) + + + self.label.repaint() + self.deviceNameLabel.setText("" + + deviceInfo.name + "") + self.deviceNameLabel2.setText("" + + deviceInfo.name + "") + 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 diff --git a/src/ui/.svn/text-base/pcsdeviceviewer.py.svn-base b/src/ui/.svn/text-base/pcsdeviceviewer.py.svn-base new file mode 100644 index 0000000..17495a0 --- /dev/null +++ b/src/ui/.svn/text-base/pcsdeviceviewer.py.svn-base @@ -0,0 +1,292 @@ +# 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 diff --git a/src/ui/.svn/text-base/pcsdevicewidget.py.svn-base b/src/ui/.svn/text-base/pcsdevicewidget.py.svn-base new file mode 100644 index 0000000..927316b --- /dev/null +++ b/src/ui/.svn/text-base/pcsdevicewidget.py.svn-base @@ -0,0 +1,81 @@ +# 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) + + diff --git a/src/ui/.svn/text-base/pcsmenu.py.svn-base b/src/ui/.svn/text-base/pcsmenu.py.svn-base new file mode 100644 index 0000000..fcc7809 --- /dev/null +++ b/src/ui/.svn/text-base/pcsmenu.py.svn-base @@ -0,0 +1,98 @@ +# 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() + diff --git a/src/ui/.svn/text-base/pcsuiutils.py.svn-base b/src/ui/.svn/text-base/pcsuiutils.py.svn-base new file mode 100644 index 0000000..db97929 --- /dev/null +++ b/src/ui/.svn/text-base/pcsuiutils.py.svn-base @@ -0,0 +1,97 @@ +"""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 + diff --git a/src/ui/.svn/text-base/tsuigeneralmethods.py.svn-base b/src/ui/.svn/text-base/tsuigeneralmethods.py.svn-base new file mode 100644 index 0000000..1535527 --- /dev/null +++ b/src/ui/.svn/text-base/tsuigeneralmethods.py.svn-base @@ -0,0 +1,32 @@ +# 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_() + + diff --git a/src/ui/__init__.py b/src/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/pcsapp.py b/src/ui/pcsapp.py new file mode 100644 index 0000000..f901392 --- /dev/null +++ b/src/ui/pcsapp.py @@ -0,0 +1,16 @@ +# 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 diff --git a/src/ui/pcsapplicationlist.py b/src/ui/pcsapplicationlist.py new file mode 100644 index 0000000..bfc3b54 --- /dev/null +++ b/src/ui/pcsapplicationlist.py @@ -0,0 +1,48 @@ +# 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() + + diff --git a/src/ui/pcsbutton.py b/src/ui/pcsbutton.py new file mode 100644 index 0000000..8175c81 --- /dev/null +++ b/src/ui/pcsbutton.py @@ -0,0 +1,13 @@ +# 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) + + + diff --git a/src/ui/pcscustombuttons.py b/src/ui/pcscustombuttons.py new file mode 100644 index 0000000..cdbe15f --- /dev/null +++ b/src/ui/pcscustombuttons.py @@ -0,0 +1,35 @@ +# 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 + + diff --git a/src/ui/pcsdeviceinfoviewer.py b/src/ui/pcsdeviceinfoviewer.py new file mode 100644 index 0000000..4a5959b --- /dev/null +++ b/src/ui/pcsdeviceinfoviewer.py @@ -0,0 +1,189 @@ +# 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("Maemo Release") + 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("Model") + 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("None") + self.deviceNameLabel.setGeometry(QRect(380, 70, WINDOW_WIDTH, WINDOW_HEIGHT)) + + + self.deviceNameLabel2 = QLabel(self.pcSuite) + self.deviceNameLabel2.setText("None") + 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("Select option") + self.actionLabel.setGeometry(QRect(55, 36, 100, 20)) + + self.chargingThread = None; + + def setDeviceInfo(self, deviceInfo): + self.deviceInfo = deviceInfo + self.label.setText("" + deviceInfo.system +"" ) + + + self.label.repaint() + self.deviceNameLabel.setText("" + + deviceInfo.name + "") + self.deviceNameLabel2.setText("" + + deviceInfo.name + "") + 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 diff --git a/src/ui/pcsdeviceviewer.py b/src/ui/pcsdeviceviewer.py new file mode 100644 index 0000000..17495a0 --- /dev/null +++ b/src/ui/pcsdeviceviewer.py @@ -0,0 +1,292 @@ +# 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 diff --git a/src/ui/pcsdevicewidget.py b/src/ui/pcsdevicewidget.py new file mode 100644 index 0000000..927316b --- /dev/null +++ b/src/ui/pcsdevicewidget.py @@ -0,0 +1,81 @@ +# 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) + + diff --git a/src/ui/pcsmenu.py b/src/ui/pcsmenu.py new file mode 100644 index 0000000..fcc7809 --- /dev/null +++ b/src/ui/pcsmenu.py @@ -0,0 +1,98 @@ +# 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() + diff --git a/src/ui/pcsuiutils.py b/src/ui/pcsuiutils.py new file mode 100644 index 0000000..db97929 --- /dev/null +++ b/src/ui/pcsuiutils.py @@ -0,0 +1,97 @@ +"""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 + diff --git a/src/ui/tsuigeneralmethods.py b/src/ui/tsuigeneralmethods.py new file mode 100644 index 0000000..1535527 --- /dev/null +++ b/src/ui/tsuigeneralmethods.py @@ -0,0 +1,32 @@ +# 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_() + + diff --git a/tabletsuite b/tabletsuite new file mode 100644 index 0000000..609bd76 --- /dev/null +++ b/tabletsuite @@ -0,0 +1,2 @@ +#!/bin/bash +exec /usr/bin/python /usr/lib/python2.6/site-packages/src/tabletsuite.py diff --git a/welcome b/welcome deleted file mode 100644 index e69de29..0000000