From 9cf4ca47a1c59e7a60edac91d41a61c1f6592152 Mon Sep 17 00:00:00 2001 From: Paul S Date: Tue, 4 May 2021 18:10:32 +0200 Subject: [PATCH 01/11] initial version of graphical installer - Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) --- .gitignore | 1 + README.md | 25 +- backup.py | 268 ++++++++++++++++++ changelog.MD | 16 ++ install.sh | 4 +- .../english.txt => languages/english.py | 19 +- .languages/german.txt => languages/german.py | 25 +- 7 files changed, 343 insertions(+), 15 deletions(-) create mode 100644 .gitignore create mode 100644 backup.py create mode 100644 changelog.MD rename .languages/english.txt => languages/english.py (76%) rename .languages/german.txt => languages/german.py (55%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/README.md b/README.md index c1c7e67..5f3d97f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ Name: Backuppy Description: Make daily backups with Backuppy to avoid losing your data. -Usage: start it with: 'backuppy' +Usage: +- start it with: `backuppy` +- start gui version with: `python backup.py` (install pip package 'PySide2' first) Author: Joël Schurter @@ -16,13 +18,28 @@ More infos: see constants and readme.md # ToDo -- make a graphical installer & Tool - add a log-file for the rsync errors # Dependencies +- rsync (because Backuppy makes its backups with rsync) -rsync - 'sudo apt install' rsync or 'sudo pacman -S rsync' # because Backuppy makes its bakups with rsync + execute `sudo apt install rsync` on Debian/Ubuntu + + execute `sudo pacman -S rsync` on Arch/Manjaro + +# Dependencies for the graphical installer: +- pip (the python package manager) + + execute `sudo apt install python3-pip` on Debian/Ubuntu + + execute `sudo pacman -S pip` on Arch/Manjaro + +- pip package 'PySide2' + + execute `pip3 install pyside2` on Debian/Ubuntu + + execute `pip install pyside2` on Arch/Manjaro # IMPORTANT -You have to remove the "backuppy" alias in your .bashrc or .zshrc before reinstall Backuppy. \ No newline at end of file +You have to remove the "backuppy" alias in your .bashrc or .zshrc before reinstall Backuppy. diff --git a/backup.py b/backup.py new file mode 100644 index 0000000..d2f6938 --- /dev/null +++ b/backup.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python3 +""" +project: Backuppy +version: 1.01.000 +file: backup.py +summary: main entry python file +""" + +# Standard library imports +import os + +# Third party imports +from PySide2 import QtCore +from PySide2 import QtGui +from PySide2 import QtCore, QtWidgets + +# local imports +from languages import english +from languages import german + +# local globals +VERSION: str = "1.01.000" +EMAIL: str = "fotocoder@joschu.ch" +LANG_EN: str = "English" +LANG_DE: str = "German" +LANGUAGE: str = LANG_EN +MYDIR: str = os.getcwd() +SOURCEDIR: str = None +EXCLUDE: bool = True +TARGETDIR: str = None + +def get_lang_text(search_str: str): + return_str: str = eval("english." + search_str) + global LANGUAGE + if LANGUAGE == LANG_DE: + return_str = eval("german." + search_str) + return return_str + + +class BackuppyWizard(QtWidgets.QWizard): + def __init__(self, parent=None): + super().__init__(parent) + + self.addPage(Page01(self)) + self.addPage(Page02(self)) + self.addPage(Page03(self)) + self.addPage(Page04(self)) + self.addPage(Page05(self)) + self.addPage(Page06(self)) + self.addPage(Page07(self)) + self.addPage(Page08(self)) + self.addPage(Page09(self)) + self.addPage(Page10(self)) + + self.setWindowTitle(english.intromsg1) + self.resize(640, 480) + +class Page01(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel("Hello, first of all, which language do you prefer: English or German?") + # self.comboBox = QIComboBox(self) + self.comboBox = QtWidgets.QComboBox(self) + self.comboBox.addItem("English", LANG_DE) + self.comboBox.addItem("German", LANG_EN) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.comboBox) + self.setLayout(layout) + + def validatePage(self): + global LANGUAGE + if self.comboBox.currentText() == LANG_DE: + LANGUAGE = LANG_DE + else: + LANGUAGE = LANG_EN + return True + + +class Page02(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("languagepack")) + self.label2.setText(get_lang_text("intromsg2")) + + +class Page03(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel() + self.groupbox = QtWidgets.QGroupBox() + self.groupbox.setFlat(True) + self.radio1 = QtWidgets.QRadioButton() + self.radio2 = QtWidgets.QRadioButton() + + vbox = QtWidgets.QVBoxLayout() + vbox.addWidget(self.radio1) + vbox.addWidget(self.radio2) + vbox.addStretch(1) + self.groupbox.setLayout(vbox) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.groupbox) + self.setLayout(layout) + + def initializePage(self): + self.label.setText(get_lang_text("excludefile1")) + self.radio1.setText(get_lang_text("Yes")) + self.radio2.setText(get_lang_text("No")) + self.radio1.setChecked(True) + + def validatePage(self): + global EXCLUDE + if self.radio1.isChecked(): + EXCLUDE = True + else: + EXCLUDE = False + return True + +class Page04(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + self.setLayout(layout) + + def initializePage(self): + global EXCLUDE + if EXCLUDE: + self.label.setText(get_lang_text("excludefile2")) + else: + self.label.setText(get_lang_text("excludefile3")) + +class Page05(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.edit = QtWidgets.QLineEdit() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.edit) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("srcdir1")) + self.label2.setText(get_lang_text("srcdir2")) + + def validatePage(self): + global SOURCEDIR + SOURCEDIR = self.edit.text() + + return True + + +class Page06(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("srcdir3_1")) + self.label2.setText(SOURCEDIR) + self.label3.setText(get_lang_text("srcdir3_2")) + + +class Page07(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.edit = QtWidgets.QLineEdit() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.edit) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("targetdir1")) + + def validatePage(self): + global TARGETDIR + TARGETDIR = self.edit.text() + + return True + + +class Page08(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("targetdir2_1")) + self.label2.setText(TARGETDIR) + self.label3.setText(get_lang_text("targetdir2_2")) + + +class Page09(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("collect")) + global SOURCEDIR, TARGETDIR + self.label2.setText(f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {SOURCEDIR} {TARGETDIR}") + + +class Page10(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + self.setFinalPage(True) + + def initializePage(self): + self.label1.setText(get_lang_text("outro1")) + self.label2.setText(get_lang_text("outro2")) + urlLink = "fotocoder@joschu.ch" + self.label3.setText(urlLink) + self.label3.setOpenExternalLinks(True) + + +if __name__ == '__main__': + print(f"Starting backup.py v{VERSION}") + app = QtWidgets.QApplication() + wizard = BackuppyWizard() + wizard.show() + app.exec_() + print("Ending backup.py") diff --git a/changelog.MD b/changelog.MD new file mode 100644 index 0000000..0b581e8 --- /dev/null +++ b/changelog.MD @@ -0,0 +1,16 @@ +# Changelog Backuppy + +## [1.01.000] - 2021-05-04 +### Added + - Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) + + ### Changed + - Directory ".languages" renamed to "languages" due to python module import syntax constraints + - Files "english.txt" and "german.txt" renamed to .-py due to follow the python filename schema + +# Changelog Backuppy + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/install.sh b/install.sh index f28fc48..ab6e3fc 100755 --- a/install.sh +++ b/install.sh @@ -2,8 +2,8 @@ # Variables mydir=$PWD -langDE=".languages/german.txt" -langEN=".languages/english.txt" +langDE="languages/german.py" +langEN="languages/english.py" # Intro # language diff --git a/.languages/english.txt b/languages/english.py similarity index 76% rename from .languages/english.txt rename to languages/english.py index 29c8869..891ef03 100644 --- a/.languages/english.txt +++ b/languages/english.py @@ -1,10 +1,23 @@ +#!/usr/bin/env python3 +""" +project: Backuppy +file: languages/english.py +summary: english language file +""" + +Yes="Yes" + +No="No" + +languagepack="Perfect, the English language package is now activated. Welcome!" + intromsg1="Thanks for using Backuppy to make your backups!" intromsg2="The installer will now ask you a few things to adapt your backup script to your requirements." rsyncopt="rsync offers various options, but to simplify the installation process, I have activated the options -a, -q and -p. \n If you want to set more options, you can do thjat in the file 'Backuppy.sh'." -excludefile1="Now I need to know if you want to exclude one or more files/directories from your backups. Then you can adjust this in the 'exclude.txt'. \There you can exclude directories and files in the format '/directory' '/file.txt'.\n Do you want to exclude files/directories or not? [Y/N]" +excludefile1="Now I need to know if you want to exclude one or more files/directories from your backups.\nThen you can adjust this in the 'exclude.txt'.\nThere you can exclude directories and files in the format '/directory' '/file.txt'.\nDo you want to exclude files/directories or not?" excludefile2="Perfect, then you can enter your files/directories to be excluded in the file 'exclude.txt' after completing the installation of Backuppy." @@ -22,8 +35,8 @@ targetdir1="Now I need to know where Backuppy should save your backups, i.e. the targetdir2_1="you have typed in the following destination path:" targetdir2_2="if this path is not correct, adjust it in the file 'backuppy.sh'." -collect="Now we have almost reached the end of the installer. I will now create the rsync command for you and show it to you.\n If you notice a mistake, just cancel the installer and start again from the beginning. \n Note: I recommend that you download Backuppy completely again in this case." +collect="Now we have almost reached the end of the installer. I will now create the rsync command for you and show it to you.\n If you notice a mistake, just cancel the installer and start again from the beginning.\nNote: I recommend that you download Backuppy completely again in this case." outro1="Now we have reached the end. Now you can start Backuppy in the terminal with the command 'backuppy'. You may then have to type in your password so that Backuppy can work properly." -outro2="Backuppy is now installed, have fun with it! If you have any questions, just write to me: fotocoder@joschu.ch" +outro2="Backuppy is now installed, have fun with it! If you have any questions, just write to me." diff --git a/.languages/german.txt b/languages/german.py similarity index 55% rename from .languages/german.txt rename to languages/german.py index d185c03..bf4081e 100644 --- a/.languages/german.txt +++ b/languages/german.py @@ -1,12 +1,25 @@ +#!/usr/bin/env python3 +""" +project: Backuppy +file: languages/german.py +summary: german language file +""" + +Yes="Ja" + +No="Nein" + +languagepack="Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen!" + intromsg1="Danke, dass du Backuppy nutzt, um deine Backups zu erstellen!" intromsg2="Der Installer wird dich nun einige Dinge abfragen, um dein Backup-Skript an deine Anforderungen anzupassen." rsyncopt="rsync bietet verschiedene Optionen an, um das Ganze jedoch zu vereinfachen, habe ich die Optionen -a, -q und -p aktiviert. \n Wenn du mehr einstellen willst, kannst du das in der Datei 'Backuppy.sh' machen." -excludefile1="Nun muss ich noch wissen, ob du ein oder mehrere Dateien/Verzeichnisse vom Backup ausschliessen möchtest. Dann kannst du das in der 'exclude.txt' anpassen. \n Dort kannst du dann im Format '/Verzeichnis' '/Datei.txt' Verzeichnisse und Dateien ausschliessen.\n Möchtest du Dateien/Verzeichnisse ausschliessen oder nicht? [J/N]" +excludefile1="Nun muss ich noch wissen, ob du ein oder mehrere Dateien/Verzeichnisse vom Backup ausschliessen möchtest.\nDann kannst du das in der 'exclude.txt' anpassen.\nDort kannst du dann im Format '/Verzeichnis' '/Datei.txt' Verzeichnisse und Dateien ausschliessen.\nMöchtest du Dateien/Verzeichnisse ausschliessen oder nicht?" -excludefile2="Perfekt, dann kannst du nach der Fertigstellung der Installation von Backuppy deine auszuschliessenden Dateien/Verzeichnisse in der Datei 'exclude.txt eintragen." +excludefile2="Perfekt, dann kannst du nach der Fertigstellung der Installation von Backuppy deine auszuschliessenden\nDateien/Verzeichnisse in der Datei 'exclude.txt eintragen." excludefile3="Gut, dann erstelle ich die Datei 'exclude.txt' gar nicht erst, da du sie ja nicht brauchst." @@ -17,13 +30,13 @@ srcdir2="Welches Verzeichnis möchtest du sichern (z.B. das Homeverzeichnis)? Bi srcdir3_1="du hast folgenden Quellpfad eingetippt: " srcdir3_2="wenn dieser Pfad nicht stimmen sollte, dann passe ihn in der Datei 'Backuppy.sh' an." -targetdir1="Nun muss ich noch wissen, wo Backuppy dein Backup ablegen soll, das Zielverzeichnis also. \n Bitte tippe dieses gewissenhaft und auf die Weise wie beim Quellverzeichnis ein." +targetdir1="Nun muss ich noch wissen, wo Backuppy dein Backup ablegen soll, das Zielverzeichnis also.\nBitte tippe dieses gewissenhaft und auf die Weise wie beim Quellverzeichnis ein." targetdir2_1="du hast folgenden Zielpfad eingetippt:" targetdir2_2="wenn dieser Pfad nicht stimmen sollte, dann passe ihn in der Datei 'backuppy.sh' an." -collect="Nun sind wir fast am Ende des Installers angelangt. Ich erstelle nun den rsync-Befehl für dich und zeige ihn dir nachher nochmal. \n Wenn dir da etwas auffallen sollte, brich den Installer einfach ab und fange nochmal von Vorne an. \n Achtung: ich empfehle dir, Backuppy in diesem Fall nochmal komplett neu zu installieren." +collect="Nun sind wir fast am Ende des Installers angelangt. Ich erstelle nun den rsync-Befehl für dich und zeige ihn\ndir nachher nochmal.\nWenn dir da etwas auffallen sollte, brich den Installer einfach ab und fange nochmal von Vorne an.\nAchtung: ich empfehle dir, Backuppy in diesem Fall nochmal komplett neu zu installieren." -outro1="Perfekt, jetzt sind wir fertig. Nun kannst du Backuppy im Terminal mit dem Befehl 'backuppy' starten. Möglicherweise musst du dann noch dein Passwort eintippen, damit Backuppy ordnungsgemäss arbeiten kann." +outro1="Perfekt, jetzt sind wir fertig. Nun kannst du Backuppy im Terminal mit dem Befehl 'backuppy' starten.\nMöglicherweise musst du dann noch dein Passwort eintippen, damit Backuppy ordnungsgemäss arbeiten kann." -outro2="Backuppy ist nun installiert, viel Spass damit! Bei Fragen schreib mir einfach: fotocoder@joschu.ch" +outro2="Backuppy ist nun installiert, viel Spass damit! Bei Fragen schreib mir einfach." From 5d5477e3e8cc181538457bcc64f14af45aacde3d Mon Sep 17 00:00:00 2001 From: Paul S Date: Tue, 4 May 2021 18:14:22 +0200 Subject: [PATCH 02/11] Update changelog.MD --- changelog.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.MD b/changelog.MD index 0b581e8..61fc7fc 100644 --- a/changelog.MD +++ b/changelog.MD @@ -3,6 +3,7 @@ ## [1.01.000] - 2021-05-04 ### Added - Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) + - Changelog.MD ### Changed - Directory ".languages" renamed to "languages" due to python module import syntax constraints From c281a0a588c37ac4874e7255b177424c160054d6 Mon Sep 17 00:00:00 2001 From: Paul S Date: Tue, 4 May 2021 18:25:28 +0200 Subject: [PATCH 03/11] Use defined E-MAIL constant --- backup.py | 6 +++--- changelog.MD | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backup.py b/backup.py index d2f6938..266dc56 100644 --- a/backup.py +++ b/backup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ project: Backuppy -version: 1.01.000 +version: 1.01.001 file: backup.py summary: main entry python file """ @@ -19,7 +19,7 @@ from languages import english from languages import german # local globals -VERSION: str = "1.01.000" +VERSION: str = "1.01.001" EMAIL: str = "fotocoder@joschu.ch" LANG_EN: str = "English" LANG_DE: str = "German" @@ -254,7 +254,7 @@ class Page10(QtWidgets.QWizardPage): def initializePage(self): self.label1.setText(get_lang_text("outro1")) self.label2.setText(get_lang_text("outro2")) - urlLink = "fotocoder@joschu.ch" + urlLink = f"{EMAIL}" self.label3.setText(urlLink) self.label3.setOpenExternalLinks(True) diff --git a/changelog.MD b/changelog.MD index 61fc7fc..51721aa 100644 --- a/changelog.MD +++ b/changelog.MD @@ -1,13 +1,17 @@ # Changelog Backuppy +## [1.01.001] - 2021-05-04 +### Changed +- Use E-MAIL constant + ## [1.01.000] - 2021-05-04 ### Added - - Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) - - Changelog.MD +- Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) +- Changelog.MD - ### Changed - - Directory ".languages" renamed to "languages" due to python module import syntax constraints - - Files "english.txt" and "german.txt" renamed to .-py due to follow the python filename schema +### Changed +- Directory ".languages" renamed to "languages" due to python module import syntax constraints +- Files "english.txt" and "german.txt" renamed to .-py due to follow the python filename schema # Changelog Backuppy From 898f4b5809371c4ea5016d4be280e80471d7b666 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 12:33:17 +0200 Subject: [PATCH 04/11] fixed problem with the Bash/ZSH config --- install.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index ab6e3fc..2852df2 100755 --- a/install.sh +++ b/install.sh @@ -66,15 +66,24 @@ echo -e "$targetdir2_1 $targetdir $targetdir2_2" sleep 1 # alias entry in .bashrc or .zshrc -#zshrc +# .zshrc case 1 echo $SHELL if [ $SHELL = "/usr/bin/zsh" ]; then echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc fi -#bashrc +# zshrc case 2 +echo $SHELL +if [ $SHELL = "/bin/zsh" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc +fi +#bashrc case 1 if [ $SHELL = "/usr/bin/bash" ]; then echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc fi +# bashrc case 2 +if [ $SHELL = "/bin/bash" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc +fi # collects all the information needed to execute the rsync command and creates it. echo -e "$collect \n" From e2c03559b6a1a5faa53652addc34adcd3c2e0f19 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:18:36 +0200 Subject: [PATCH 05/11] Updated README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5f3d97f..fae01e5 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,17 @@ Name: Backuppy Description: Make daily backups with Backuppy to avoid losing your data. -Usage: -- start it with: `backuppy` -- start gui version with: `python backup.py` (install pip package 'PySide2' first) +Installation: execute `chmod +x install.sh && .\install.sh` + +Install. GUI: execute `chmod +x install.sh && .\install.sh --gui` + +Usage: execute `backuppy` Author: Joël Schurter Licence: GPL3 -More infos: see constants and readme.md +More infos: see constants and README.md # ToDo From eeeabbbbf9d25dc315a875d5973b14c9050aa57d Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:20:04 +0200 Subject: [PATCH 06/11] Updates language-files to be used in GUI-installer --- languages/english.py | 12 ++++++------ languages/german.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/languages/english.py b/languages/english.py index 891ef03..e04cfe2 100644 --- a/languages/english.py +++ b/languages/english.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -""" -project: Backuppy -file: languages/english.py -summary: english language file -""" +# """ +# project: Backuppy +# file: languages/english.py +# summary: english language file +# """ Yes="Yes" @@ -17,7 +17,7 @@ intromsg2="The installer will now ask you a few things to adapt your backup scri rsyncopt="rsync offers various options, but to simplify the installation process, I have activated the options -a, -q and -p. \n If you want to set more options, you can do thjat in the file 'Backuppy.sh'." -excludefile1="Now I need to know if you want to exclude one or more files/directories from your backups.\nThen you can adjust this in the 'exclude.txt'.\nThere you can exclude directories and files in the format '/directory' '/file.txt'.\nDo you want to exclude files/directories or not?" +excludefile1="Now I need to know if you want to exclude one or more files/directories from your backups.\nThen you can adjust this in the 'exclude.txt'.\nThere you can exclude directories and files in the format '/directory' '/file.txt'.\nDo you want to exclude files/directories or not? [Y/N]" excludefile2="Perfect, then you can enter your files/directories to be excluded in the file 'exclude.txt' after completing the installation of Backuppy." diff --git a/languages/german.py b/languages/german.py index bf4081e..07508c9 100644 --- a/languages/german.py +++ b/languages/german.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -""" -project: Backuppy -file: languages/german.py -summary: german language file -""" +# """ +# project: Backuppy +# file: languages/german.py +# summary: german language file +# """ Yes="Ja" @@ -17,7 +17,7 @@ intromsg2="Der Installer wird dich nun einige Dinge abfragen, um dein Backup-Skr rsyncopt="rsync bietet verschiedene Optionen an, um das Ganze jedoch zu vereinfachen, habe ich die Optionen -a, -q und -p aktiviert. \n Wenn du mehr einstellen willst, kannst du das in der Datei 'Backuppy.sh' machen." -excludefile1="Nun muss ich noch wissen, ob du ein oder mehrere Dateien/Verzeichnisse vom Backup ausschliessen möchtest.\nDann kannst du das in der 'exclude.txt' anpassen.\nDort kannst du dann im Format '/Verzeichnis' '/Datei.txt' Verzeichnisse und Dateien ausschliessen.\nMöchtest du Dateien/Verzeichnisse ausschliessen oder nicht?" +excludefile1="Nun muss ich noch wissen, ob du ein oder mehrere Dateien/Verzeichnisse vom Backup ausschliessen möchtest.\nDann kannst du das in der 'exclude.txt' anpassen.\nDort kannst du dann im Format '/Verzeichnis' '/Datei.txt' Verzeichnisse und Dateien ausschliessen.\nMöchtest du Dateien/Verzeichnisse ausschliessen oder nicht? [J/N]" excludefile2="Perfekt, dann kannst du nach der Fertigstellung der Installation von Backuppy deine auszuschliessenden\nDateien/Verzeichnisse in der Datei 'exclude.txt eintragen." From 67a03607270e6262efc8ce19f4cd7602411b9a19 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:21:06 +0200 Subject: [PATCH 07/11] Updated CHANGELOG.md --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e975aa4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,32 @@ +# Changelog Backuppy + +## [1.02.000] - 2021-05-05 +### Added +- Now fully functional as the shell version + +### Changed +- Updated "README.md" concerning installation and usage +- Changed filename "Changelog.MD" to "CHANGELOG.md" + +### Fixed +- Fixed problem with the Bash/ZSH config + +## [1.01.001] - 2021-05-04 +### Changed +- Use E-MAIL constant + +## [1.01.000] - 2021-05-04 +### Added +- Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) +- Changelog.MD + +### Changed +- Directory ".languages" renamed to "languages" due to python module import syntax constraints +- Files "english.txt" and "german.txt" renamed to .-py due to follow the python filename schema + +# Changelog Backuppy + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). From d4327b64dbaa8d01c06b14b513f4a3c191601995 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:21:54 +0200 Subject: [PATCH 08/11] Implemented same functionality as in install.sh --- install.py | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 install.py diff --git a/install.py b/install.py new file mode 100644 index 0000000..e99284f --- /dev/null +++ b/install.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python3 +""" +project: Backuppy +version: 1.02.000 +file: install.py +summary: main entry python file +""" + +# Standard library imports +import os + +# Third party imports +from PySide2 import QtCore +from PySide2 import QtGui +from PySide2 import QtCore, QtWidgets + +# local imports +from languages import english +from languages import german + +# local globals +VERSION: str = "1.02.000" +EMAIL: str = "fotocoder@joschu.ch" +TARGET_SCRIPT: str = "Backuppy.sh" +EXCLUDE_FILE: str = "exclude.txt" +LANG_EN: str = "English" +LANG_DE: str = "German" +LANGUAGE: str = LANG_EN +MYDIR: str = os.environ.get("mydir") +if not MYDIR: + MYDIR = os.getcwd() +SOURCEDIR: str = None +EXCLUDE: bool = True +TARGETDIR: str = None +RSYNC_CMD: str = None + +def get_lang_text(search_str: str): + """ Returns a string from the appropriate language file. """ + return_str: str = eval("english." + search_str) + global LANGUAGE + if LANGUAGE == LANG_DE: + return_str = eval("german." + search_str) + return return_str + +def trace(message_txt: str): + """ Print a formatted message to std out. """ + print(f"[ OK ]", message_txt) + +class BackuppyWizard(QtWidgets.QWizard): + def __init__(self, parent=None): + super().__init__(parent) + + self.addPage(Page01(self)) + self.addPage(Page02(self)) + self.addPage(Page03(self)) + self.addPage(Page04(self)) + self.addPage(Page05(self)) + self.addPage(Page06(self)) + self.addPage(Page07(self)) + self.addPage(Page08(self)) + self.addPage(Page09(self)) + self.addPage(Page10(self)) + + self.setWindowTitle(english.intromsg1) + self.resize(640, 480) + +class Page01(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel("Hello, first of all, which language do you prefer: English or German?") + # self.comboBox = QIComboBox(self) + self.comboBox = QtWidgets.QComboBox(self) + self.comboBox.addItem(LANG_EN, LANG_EN) + self.comboBox.addItem(LANG_DE, LANG_DE) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.comboBox) + self.setLayout(layout) + + def validatePage(self): + global LANGUAGE + if self.comboBox.currentText() == LANG_DE: + LANGUAGE = LANG_DE + else: + LANGUAGE = LANG_EN + return True + + +class Page02(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("languagepack")) + self.label2.setText(get_lang_text("intromsg2")) + + +class Page03(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel() + self.groupbox = QtWidgets.QGroupBox() + self.groupbox.setFlat(True) + self.radio1 = QtWidgets.QRadioButton() + self.radio2 = QtWidgets.QRadioButton() + + vbox = QtWidgets.QVBoxLayout() + vbox.addWidget(self.radio1) + vbox.addWidget(self.radio2) + vbox.addStretch(1) + self.groupbox.setLayout(vbox) + + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.groupbox) + self.setLayout(layout) + + def initializePage(self): + self.label.setText(get_lang_text("excludefile1")) + self.radio1.setText(get_lang_text("Yes")) + self.radio2.setText(get_lang_text("No")) + self.radio1.setChecked(True) + + def validatePage(self): + global EXCLUDE + if self.radio1.isChecked(): + EXCLUDE = True + else: + EXCLUDE = False + return True + +class Page04(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + self.setLayout(layout) + + def initializePage(self): + global EXCLUDE + if EXCLUDE: + self.label.setText(get_lang_text("excludefile2")) + else: + self.label.setText(get_lang_text("excludefile3")) + +class Page05(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.edit = QtWidgets.QLineEdit() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.edit) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("srcdir1")) + self.label2.setText(get_lang_text("srcdir2")) + + def validatePage(self): + global SOURCEDIR + SOURCEDIR = self.edit.text() + + return True + + +class Page06(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("srcdir3_1")) + bold_text = f"

{SOURCEDIR}

" + self.label2.setText(bold_text) + self.label3.setText(get_lang_text("srcdir3_2")) + + +class Page07(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.edit = QtWidgets.QLineEdit() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.edit) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("targetdir1")) + + def validatePage(self): + global TARGETDIR + TARGETDIR = self.edit.text() + + return True + + +class Page08(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("targetdir2_1")) + bold_text = f"

{TARGETDIR}

" + self.label2.setText(bold_text) + self.label3.setText(get_lang_text("targetdir2_2")) + + def validatePage(self): + global RSYNC_CMD, MYDIR, SOURCEDIR, TARGETDIR + RSYNC_CMD = f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {SOURCEDIR} {TARGETDIR}" + + return True + + +class Page09(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + self.setLayout(layout) + + def initializePage(self): + self.label1.setText(get_lang_text("collect")) + global RSYNC_CMD + #self.label2.setText(f"{RSYNC_CMD}") + bold_text = f"

{RSYNC_CMD}

" + self.label2.setText(bold_text) + + +class Page10(QtWidgets.QWizardPage): + def __init__(self, parent=None): + super().__init__(parent) + self.label1 = QtWidgets.QLabel() + self.label2 = QtWidgets.QLabel() + self.label3 = QtWidgets.QLabel() + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label1) + layout.addWidget(self.label2) + layout.addWidget(self.label3) + self.setLayout(layout) + self.setFinalPage(True) + + def initializePage(self): + self.label1.setText(get_lang_text("outro1")) + self.label2.setText(get_lang_text("outro2")) + urlLink = f"{EMAIL}" + self.label3.setText(urlLink) + self.label3.setOpenExternalLinks(True) + + def validatePage(self): + # create shell script with rsync command + create_shell_script(RSYNC_CMD) + + return True + + +def create_shell_script(command_str: str): + rc_filepath: str = None + + global MYDIR, EXCLUDE, TARGET_SCRIPT + + TARGET_SCRIPT = os.path.join(MYDIR, TARGET_SCRIPT) + ALIAS_STR = f"alias backuppy='sudo {TARGET_SCRIPT}'" + current_shell = os.environ.get("SHELL") + user_home = os.environ.get("HOME") + + ## STEP 1: update shell config scripts with alias for backuppy + # .zshrc case1 and case2 + if current_shell in ("/usr/bin/zsh", "/bin/zsh"): + # Appending to bash config file + rc_filepath = os.path.join(user_home, ".zshrc") + + # .bashrc case1 and case2 + elif current_shell in ("/usr/bin/bash", "/bin/bash"): + # Appending to zsh config file + rc_filepath = os.path.join(user_home, ".bashrc") + + if os.path.isfile(rc_filepath): + with open(rc_filepath, 'a') as file1: + trace(f"Writing {ALIAS_STR} to config file '{rc_filepath}'.") + file1.write("\n# Following line was created by Backuppy\n" + ALIAS_STR + "\n") + + ## STEP 2: Create the exclude script if desired + if EXCLUDE: + global EXCLUDE_FILE + EXCLUDE_FILE = os.path.join(MYDIR, EXCLUDE_FILE) + with open(EXCLUDE_FILE, "w") as file2: + trace(f"creating exclude-file '{EXCLUDE_FILE}'.") + file2.writelines("\n") + + ## STEP 3: enter the rsync command in Backuppy.sh + with open(TARGET_SCRIPT, "w") as file3: + trace(f"Writing rsync-command to file '{TARGET_SCRIPT}':\n {command_str}") + file3.writelines("#!/bin/bash" + "\n") + file3.writelines(command_str + "\n") + + +if __name__ == '__main__': + trace(f"Starting Backuppy install.py v{VERSION}") + app = QtWidgets.QApplication() + wizard = BackuppyWizard() + wizard.show() + + app.exec_() + + trace("Ending Backuppy install.py") From 4bc87b96423dd84d8ed484e2ae11f8e1ac8f9648 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:22:57 +0200 Subject: [PATCH 09/11] Implemented option "--gui" for graphical installer --- install.sh | 183 +++++++++++++++++++++++++++-------------------------- 1 file changed, 95 insertions(+), 88 deletions(-) diff --git a/install.sh b/install.sh index 2852df2..ba8f1da 100755 --- a/install.sh +++ b/install.sh @@ -2,99 +2,106 @@ # Variables mydir=$PWD -langDE="languages/german.py" -langEN="languages/english.py" +langDE="./languages/german.py" +langEN="./languages/english.py" -# Intro -# language -echo -e "Hello, first of all, which language do you prefer: German [DE] or English [EN]?" -read language -if [ $language = "DE" ]; then - echo -e "Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen! \n" - . $langDE +# Check if graphical installer should be executed +if [ "$1" == "--gui" ]; then + python3 -B install.py + exit 0 +else + # Intro + # language + echo -e "Hello, first of all, which language do you prefer: German [DE] or English [EN]?" + read language + if [ $language = "DE" ]; then + echo -e "Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen! \n" + . $langDE + sleep 1 + fi + if [ $language = "EN" ]; then + echo -e "Perfect, the English language package is now activated. Welcome!. \n" + . $langEN + sleep 1 + fi + + echo -e "\n$intromsg1 \n" sleep 1 -fi -if [ $language = "EN" ]; then - echo -e "Perfect, the English language package is now activated. Welcome!. \n" - . $langEN + echo -e " \n$intromsg2\n" sleep 1 -fi + # Installer -echo -e "\n$intromsg1 \n" -sleep 1 -echo -e " \n$intromsg2\n" -sleep 1 -# Installer - -# creates the file 'Backuppy.sh' -touch Backuppy.sh -echo "#!/bin/bash" >> Backuppy.sh -chmod +x Backuppy.sh -# which Rsync options are available and which one you want to use -echo -e "$rsyncopt \n" -sleep 1 - -# asks if you want to exclude files/directories from backup and creates an exclude file in case of Yes -echo -e "$excludefile1" -read exclude -if [ $exclude = "J" ]; then - echo -e "$excludefile2 \n" - touch exclude.txt + # creates the file 'Backuppy.sh' + touch Backuppy.sh + echo "#!/bin/bash" >> Backuppy.sh + chmod +x Backuppy.sh + # which Rsync options are available and which one you want to use + echo -e "$rsyncopt \n" sleep 1 -elif [ $exclude = "Y" ]; then - echo -e "$excludefile2 \n" - touch exclude.txt + + # asks if you want to exclude files/directories from backup and creates an exclude file in case of Yes + echo -e "$excludefile1" + read exclude + if [ $exclude = "J" ]; then + echo -e "$excludefile2 \n" + touch exclude.txt + sleep 1 + elif [ $exclude = "Y" ]; then + echo -e "$excludefile2 \n" + touch exclude.txt + sleep 1 + fi + if [ $exclude = "N" ]; then + echo -e "$excludefile3 \n" + sleep 1 + fi + + # Asks for the source directory which should be saved + echo -e "$srcdir1" sleep 1 -fi -if [ $exclude = "N" ]; then - echo -e "$excludefile3 \n" + echo -e "$srcdir2" + read sourcedir + echo -e "$srcdir3_1 $sourcedir $srcdir3_2" sleep 1 + + # asks for the destination directory in which the backup should be saved + echo -e "$targetdir1" + read targetdir + echo -e "$targetdir2_1 $targetdir $targetdir2_2" + sleep 1 + + # alias entry in .bashrc or .zshrc + # .zshrc case 1 + echo $SHELL + if [ $SHELL = "/usr/bin/zsh" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc + fi + # zshrc case 2 + echo $SHELL + if [ $SHELL = "/bin/zsh" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc + fi + #bashrc case 1 + if [ $SHELL = "/usr/bin/bash" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc + fi + # bashrc case 2 + if [ $SHELL = "/bin/bash" ]; then + echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc + fi + + # collects all the information needed to execute the rsync command and creates it. + echo -e "$collect \n" + sleep 1 + echo -e "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir \n" + sleep 1 + + # enter the rsync command in Backuppy.sh + echo "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir" >> Backuppy.sh + + # Outro + echo -e "$outro1" + sleep 2 + echo "$outro2" + exit 0 fi - -# Asks for the source directory which should be saved -echo -e "$srcdir1" -sleep 1 -echo -e "$srcdir2" -read sourcedir -echo -e "$srcdir3_1 $sourcedir $srcdir3_2" -sleep 1 - -# asks for the destination directory in which the backup should be saved -echo -e "$targetdir1" -read targetdir -echo -e "$targetdir2_1 $targetdir $targetdir2_2" -sleep 1 - -# alias entry in .bashrc or .zshrc -# .zshrc case 1 -echo $SHELL -if [ $SHELL = "/usr/bin/zsh" ]; then - echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc -fi -# zshrc case 2 -echo $SHELL -if [ $SHELL = "/bin/zsh" ]; then - echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc -fi -#bashrc case 1 -if [ $SHELL = "/usr/bin/bash" ]; then - echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc -fi -# bashrc case 2 -if [ $SHELL = "/bin/bash" ]; then - echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc -fi - -# collects all the information needed to execute the rsync command and creates it. -echo -e "$collect \n" -sleep 1 -echo -e "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir \n" -sleep 1 - -# enter the rsync command in Backuppy.sh -echo "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir" >> Backuppy.sh - -# Outro -echo -e "$outro1" -sleep 2 -echo "$outro2" From 00fa691116315ba093e1e2a7143f8b13e519ca41 Mon Sep 17 00:00:00 2001 From: Paul S Date: Wed, 5 May 2021 17:54:06 +0200 Subject: [PATCH 10/11] Renamed "changelog.MD" to "CHANGELOG.md" --- changelog.MD | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 changelog.MD diff --git a/changelog.MD b/changelog.MD deleted file mode 100644 index 51721aa..0000000 --- a/changelog.MD +++ /dev/null @@ -1,21 +0,0 @@ -# Changelog Backuppy - -## [1.01.001] - 2021-05-04 -### Changed -- Use E-MAIL constant - -## [1.01.000] - 2021-05-04 -### Added -- Graphical installer based on Python3 with PySide2 GUI framework (Qt-bindings for Python) -- Changelog.MD - -### Changed -- Directory ".languages" renamed to "languages" due to python module import syntax constraints -- Files "english.txt" and "german.txt" renamed to .-py due to follow the python filename schema - -# Changelog Backuppy - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). From e3bccb0715c5b34688c6fb6210d8b659824752bc Mon Sep 17 00:00:00 2001 From: PhotoLinux Date: Wed, 5 May 2021 19:15:25 +0200 Subject: [PATCH 11/11] deleted backupp.py deleted backup.py because we don't need it anymore. --- backup.py | 268 ------------------------------------------------------ 1 file changed, 268 deletions(-) delete mode 100644 backup.py diff --git a/backup.py b/backup.py deleted file mode 100644 index 266dc56..0000000 --- a/backup.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python3 -""" -project: Backuppy -version: 1.01.001 -file: backup.py -summary: main entry python file -""" - -# Standard library imports -import os - -# Third party imports -from PySide2 import QtCore -from PySide2 import QtGui -from PySide2 import QtCore, QtWidgets - -# local imports -from languages import english -from languages import german - -# local globals -VERSION: str = "1.01.001" -EMAIL: str = "fotocoder@joschu.ch" -LANG_EN: str = "English" -LANG_DE: str = "German" -LANGUAGE: str = LANG_EN -MYDIR: str = os.getcwd() -SOURCEDIR: str = None -EXCLUDE: bool = True -TARGETDIR: str = None - -def get_lang_text(search_str: str): - return_str: str = eval("english." + search_str) - global LANGUAGE - if LANGUAGE == LANG_DE: - return_str = eval("german." + search_str) - return return_str - - -class BackuppyWizard(QtWidgets.QWizard): - def __init__(self, parent=None): - super().__init__(parent) - - self.addPage(Page01(self)) - self.addPage(Page02(self)) - self.addPage(Page03(self)) - self.addPage(Page04(self)) - self.addPage(Page05(self)) - self.addPage(Page06(self)) - self.addPage(Page07(self)) - self.addPage(Page08(self)) - self.addPage(Page09(self)) - self.addPage(Page10(self)) - - self.setWindowTitle(english.intromsg1) - self.resize(640, 480) - -class Page01(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label = QtWidgets.QLabel("Hello, first of all, which language do you prefer: English or German?") - # self.comboBox = QIComboBox(self) - self.comboBox = QtWidgets.QComboBox(self) - self.comboBox.addItem("English", LANG_DE) - self.comboBox.addItem("German", LANG_EN) - - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label) - layout.addWidget(self.comboBox) - self.setLayout(layout) - - def validatePage(self): - global LANGUAGE - if self.comboBox.currentText() == LANG_DE: - LANGUAGE = LANG_DE - else: - LANGUAGE = LANG_EN - return True - - -class Page02(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("languagepack")) - self.label2.setText(get_lang_text("intromsg2")) - - -class Page03(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label = QtWidgets.QLabel() - self.groupbox = QtWidgets.QGroupBox() - self.groupbox.setFlat(True) - self.radio1 = QtWidgets.QRadioButton() - self.radio2 = QtWidgets.QRadioButton() - - vbox = QtWidgets.QVBoxLayout() - vbox.addWidget(self.radio1) - vbox.addWidget(self.radio2) - vbox.addStretch(1) - self.groupbox.setLayout(vbox) - - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label) - layout.addWidget(self.groupbox) - self.setLayout(layout) - - def initializePage(self): - self.label.setText(get_lang_text("excludefile1")) - self.radio1.setText(get_lang_text("Yes")) - self.radio2.setText(get_lang_text("No")) - self.radio1.setChecked(True) - - def validatePage(self): - global EXCLUDE - if self.radio1.isChecked(): - EXCLUDE = True - else: - EXCLUDE = False - return True - -class Page04(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label = QtWidgets.QLabel() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label) - self.setLayout(layout) - - def initializePage(self): - global EXCLUDE - if EXCLUDE: - self.label.setText(get_lang_text("excludefile2")) - else: - self.label.setText(get_lang_text("excludefile3")) - -class Page05(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - self.edit = QtWidgets.QLineEdit() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - layout.addWidget(self.edit) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("srcdir1")) - self.label2.setText(get_lang_text("srcdir2")) - - def validatePage(self): - global SOURCEDIR - SOURCEDIR = self.edit.text() - - return True - - -class Page06(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - self.label3 = QtWidgets.QLabel() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - layout.addWidget(self.label3) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("srcdir3_1")) - self.label2.setText(SOURCEDIR) - self.label3.setText(get_lang_text("srcdir3_2")) - - -class Page07(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.edit = QtWidgets.QLineEdit() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.edit) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("targetdir1")) - - def validatePage(self): - global TARGETDIR - TARGETDIR = self.edit.text() - - return True - - -class Page08(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - self.label3 = QtWidgets.QLabel() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - layout.addWidget(self.label3) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("targetdir2_1")) - self.label2.setText(TARGETDIR) - self.label3.setText(get_lang_text("targetdir2_2")) - - -class Page09(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - self.setLayout(layout) - - def initializePage(self): - self.label1.setText(get_lang_text("collect")) - global SOURCEDIR, TARGETDIR - self.label2.setText(f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {SOURCEDIR} {TARGETDIR}") - - -class Page10(QtWidgets.QWizardPage): - def __init__(self, parent=None): - super().__init__(parent) - self.label1 = QtWidgets.QLabel() - self.label2 = QtWidgets.QLabel() - self.label3 = QtWidgets.QLabel() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label1) - layout.addWidget(self.label2) - layout.addWidget(self.label3) - self.setLayout(layout) - self.setFinalPage(True) - - def initializePage(self): - self.label1.setText(get_lang_text("outro1")) - self.label2.setText(get_lang_text("outro2")) - urlLink = f"{EMAIL}" - self.label3.setText(urlLink) - self.label3.setOpenExternalLinks(True) - - -if __name__ == '__main__': - print(f"Starting backup.py v{VERSION}") - app = QtWidgets.QApplication() - wizard = BackuppyWizard() - wizard.show() - app.exec_() - print("Ending backup.py")