├── .github └── FUNDING.yml ├── .idea ├── .gitignore ├── .name ├── encodings.xml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── timemachine.iml └── vcs.xml ├── LICENSE ├── README.md ├── install.py ├── requirements.txt ├── src ├── __init__.py ├── __pycache__ │ ├── analyse.cpython-310.pyc │ ├── backup_flatpak.cpython-310.pyc │ ├── backup_flatpak.cpython-311.pyc │ ├── backup_now.cpython-310.pyc │ ├── backup_pip_packages.cpython-310.pyc │ ├── backup_pip_packages.cpython-311.pyc │ ├── backup_status.cpython-310.pyc │ ├── backup_status.cpython-311.pyc │ ├── backup_wallpaper.cpython-310.pyc │ ├── backup_wallpaper.cpython-311.pyc │ ├── calculate_time_left_to_backup.cpython-310.pyc │ ├── calculate_time_left_to_backup.cpython-311.pyc │ ├── calculate_time_left_to_backup.cpython-312.pyc │ ├── check_connection.cpython-310.pyc │ ├── check_connection.cpython-311.pyc │ ├── check_connection.cpython-312.pyc │ ├── create_backup_checker_desktop.cpython-310.pyc │ ├── create_backup_checker_desktop.cpython-311.pyc │ ├── create_backup_checker_desktop.cpython-312.pyc │ ├── create_directory.cpython-310.pyc │ ├── create_directory.cpython-311.pyc │ ├── create_directory.cpython-312.pyc │ ├── device_location.cpython-310.pyc │ ├── device_location.cpython-311.pyc │ ├── device_location.cpython-312.pyc │ ├── error_catcher.cpython-310.pyc │ ├── error_catcher.cpython-311.pyc │ ├── error_catcher.cpython-312.pyc │ ├── get_backup_date.cpython-310.pyc │ ├── get_backup_date.cpython-311.pyc │ ├── get_backup_date.cpython-312.pyc │ ├── get_backup_time.cpython-310.pyc │ ├── get_backup_time.cpython-311.pyc │ ├── get_folders_to_be_backup.cpython-310.pyc │ ├── get_folders_to_be_backup.cpython-311.pyc │ ├── get_home_folders.cpython-310.pyc │ ├── get_home_folders.cpython-311.pyc │ ├── get_home_folders.cpython-312.pyc │ ├── get_latest_backup_date.cpython-310.pyc │ ├── get_latest_backup_date.cpython-311.pyc │ ├── get_sizes.cpython-310.pyc │ ├── get_sizes.cpython-311.pyc │ ├── get_sizes.cpython-312.pyc │ ├── get_users_de.cpython-310.pyc │ ├── get_users_de.cpython-311.pyc │ ├── get_users_de.cpython-312.pyc │ ├── handle_spaces.cpython-310.pyc │ ├── handle_spaces.cpython-311.pyc │ ├── handle_spaces.cpython-312.pyc │ ├── next_backup_label.cpython-310.pyc │ ├── next_backup_label.cpython-311.pyc │ ├── next_backup_label.cpython-312.pyc │ ├── notification_massage.cpython-310.pyc │ ├── notification_massage.cpython-311.pyc │ ├── notification_massage.cpython-312.pyc │ ├── package_manager.cpython-310.pyc │ ├── package_manager.cpython-311.pyc │ ├── package_manager.cpython-312.pyc │ ├── prepare_backup.cpython-310.pyc │ ├── prepare_backup.cpython-311.pyc │ ├── prepare_backup.cpython-312.pyc │ ├── read_ini_file.cpython-310.pyc │ ├── read_ini_file.cpython-311.pyc │ ├── read_ini_file.cpython-312.pyc │ ├── restore_backup_flatpaks_applications.cpython-310.pyc │ ├── restore_backup_flatpaks_applications.cpython-311.pyc │ ├── restore_backup_flatpaks_data.cpython-310.pyc │ ├── restore_backup_flatpaks_data.cpython-311.pyc │ ├── restore_backup_home.cpython-310.pyc │ ├── restore_backup_home.cpython-311.pyc │ ├── restore_backup_package_applications.cpython-310.pyc │ ├── restore_backup_package_applications.cpython-311.pyc │ ├── restore_backup_wallpaper.cpython-310.pyc │ ├── restore_backup_wallpaper.cpython-311.pyc │ ├── restore_kde_config.cpython-310.pyc │ ├── restore_kde_config.cpython-311.pyc │ ├── restore_kde_local_share.cpython-310.pyc │ ├── restore_kde_local_share.cpython-311.pyc │ ├── restore_kde_share_config.cpython-310.pyc │ ├── restore_kde_share_config.cpython-311.pyc │ ├── save_info.cpython-310.pyc │ ├── save_info.cpython-311.pyc │ ├── save_info.cpython-312.pyc │ ├── setup.cpython-310.pyc │ ├── setup.cpython-311.pyc │ ├── setup.cpython-312.pyc │ ├── stylesheet.cpython-310.pyc │ ├── stylesheet.cpython-311.pyc │ ├── stylesheet.cpython-312.pyc │ ├── update.cpython-310.pyc │ ├── update.cpython-311.pyc │ └── update.cpython-312.pyc ├── analyse.py ├── at_boot.py ├── backup_checker.py ├── backup_flatpak.py ├── backup_now.py ├── backup_pip_packages.py ├── backup_status.py ├── backup_wallpaper.py ├── browser_in_time_machine.py ├── calculate_time_left_to_backup.py ├── call_migration_assistant.py ├── check_connection.py ├── create_backup_checker_desktop.py ├── create_directory.py ├── desktop │ ├── backup_check.desktop │ ├── migration_assistant.desktop │ └── timemachine.desktop ├── device_location.py ├── error_catcher.py ├── get_backup_date.py ├── get_backup_home_name_and_size.py ├── get_backup_time.py ├── get_days_name.py ├── get_flatpaks_data_size.py ├── get_flatpaks_folders_size.py ├── get_folders_to_be_backup.py ├── get_home_folders.py ├── get_kde_icon_name.py ├── get_latest_backup_date.py ├── get_packages_size.py ├── get_sizes.py ├── get_system_settings_size.py ├── get_users_de.py ├── handle_spaces.py ├── icons │ ├── backup_128px.png │ ├── backup_150px.png │ ├── backup_icon.svg │ ├── check.png │ ├── migration_assistant_212px.png │ ├── resources.qrc │ ├── restore_64px.svg │ ├── systemtrayiconerror.png │ ├── systemtrayiconrestore.png │ └── systemtrayiconrun.png ├── ini │ └── config.db ├── main_window.py ├── make_first_backup.py ├── migration_assistant.py ├── new_enter_time_machine.py ├── next_backup_label.py ├── notification_massage.py ├── old_analyse.py ├── options.py ├── package_manager.py ├── prepare_backup.py ├── read_ini_file.py ├── restore_backup_flatpaks_applications.py ├── restore_backup_flatpaks_data.py ├── restore_backup_home.py ├── restore_backup_package_applications.py ├── restore_kde_config.py ├── restore_kde_local_share.py ├── restore_kde_share_config.py ├── save_info.py ├── screenshots │ ├── img_3.png │ └── img_4.png ├── setup.py ├── stylesheet.py ├── systemtray.py ├── test │ ├── pgbar.py │ ├── preview_img.py │ ├── preview_txt.py │ ├── preview_txt_img.py │ ├── previw_test.py │ ├── sql_guides.py │ └── test_feedback.py ├── translate │ └── en.po ├── ui │ ├── __pycache__ │ │ ├── __init__.cpython-310.pyc │ │ ├── ui_dialog.cpython-310.pyc │ │ ├── ui_dialog.cpython-311.pyc │ │ ├── ui_dialog.cpython-312.pyc │ │ ├── ui_enter_time_machine.cpython-310.pyc │ │ ├── ui_enter_time_machine.cpython-311.pyc │ │ ├── ui_form.cpython-310.pyc │ │ ├── ui_form.cpython-311.pyc │ │ ├── ui_mainwindow.cpython-310.pyc │ │ ├── ui_mainwindow.cpython-311.pyc │ │ ├── ui_mainwindow.cpython-312.pyc │ │ ├── ui_mainwindow_test.cpython-310.pyc │ │ ├── ui_migration.cpython-310.pyc │ │ ├── ui_migration.cpython-311.pyc │ │ ├── ui_new_2mainwindow.cpython-310.pyc │ │ ├── ui_new_mainwindow.cpython-310.pyc │ │ ├── ui_options.cpython-310.pyc │ │ ├── ui_options.cpython-311.pyc │ │ ├── ui_options.cpython-312.pyc │ │ ├── ui_untitled.cpython-310.pyc │ │ ├── ui_untitled.cpython-311.pyc │ │ └── ui_windows.cpython-310.pyc │ ├── dialog.ui │ ├── enter_time_machine.ui │ ├── mainwindow.ui │ ├── migration.ui │ ├── options.ui │ ├── resources.qrc │ ├── ui.cflags │ ├── ui.config │ ├── ui.creator │ ├── ui.creator.user │ ├── ui.creator.user.23c7f7e │ ├── ui.creator.user.696af12 │ ├── ui.creator.user.a7fe446 │ ├── ui.cxxflags │ ├── ui.files │ ├── ui.includes │ ├── ui_dialog.py │ ├── ui_enter_time_machine.py │ ├── ui_mainwindow.py │ ├── ui_migration.py │ └── ui_options.py └── update.py └── uninstall.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | Paypal: ["https://www.paypal.com/paypalme/geovanejeff", paypal.com] 4 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | install.py -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/timemachine.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Attention! 2 | * This project (Time Machine) is not affiliated with Apple. 3 | * This is a backup application created using PySide6 for Linux. 4 | * Time Machine WILL NOT ERASE OR FORMAT YOUR EXTERNAL DEVICE! 5 | 6 |

7 | 8 |

Automatic PC Backups with Time Machine

9 |

10 | 11 | Ensure the safety of your essential files by learning how to set up automatic backups for your PC using Time Machine. 12 | Safeguard your personal data, cherished music, precious photos, and vital documents effortlessly. 13 | Having a reliable backup system in place grants you the power to recover mistakenly deleted files or access data 14 | that might otherwise be out of reach. 15 | 16 | ## Getting Started: Connecting Your Backup Storage 17 | 18 | Begin by linking an external storage device, such as a USB drive, hard disk, or SSD, to your PC. 19 | 20 | - For optimal results, aim to have a backup disk with at least twice the storage capacity of every disk or volume you 21 | intend to back up. If your chosen backup disk falls short on space to accommodate a full backup, Time Machine will 22 | promptly notify you. 23 | 24 | 25 | - It's recommended to have a backup disk with at least twice the storage capacity of your target disks/volumes to ensure 26 | comprehensive coverage. Time Machine will alert you if your backup disk lacks the space needed for a complete backup. 27 | 28 | 29 | ## Crafting Your Backup 30 | 31 | - Automated Backups: Once you've designated your storage device within the Time Machine settings, the automated backup 32 | process initiates seamlessly at regular intervals. 33 | 34 | 35 | - Manual Backups: To take charge and initiate a backup manually, without waiting for the next automated cycle, simply opt 36 | for "Back Up Now" from the Time Machine menu bar. 37 | 38 | 39 | - Real-time Backup Status: Keep tabs on the ongoing backup activities by utilizing the Time Machine menu bar. 40 | For instance, if a backup is on the brink of commencement, a notification will appear in the menu bar, indicating which 41 | files or folders are currently being backed up. 42 | When no backup is in progress, the menu bar will display the timestamp of the most recent backup along with other 43 | relevant details. As your backup disk 44 | reaches its storage limit, the earliest backups will be automatically purged to create space for new ones. 45 | 46 | ## Backup Frequency and Retention 47 | 48 | - Time Machine follows a comprehensive backup strategy: 49 | 50 | Hourly Backups: Time Machine automatically creates backups every hour, preserving the last 24 hours of your selected home's data. This ensures that you can quickly recover files or data from the past day. 51 | 52 | Efficient Storage Management: When your backup disk reaches its capacity, Time Machine intelligently manages your backups. It automatically deletes the oldest backups to make room for new ones, maintaining an efficient storage balance. 53 | 54 | Minimal Disruption: The initial backup may take some time to complete, but you can continue using your computer without interruption. Subsequent backups are much faster since Time Machine only copies files that have changed since the last backup. 55 | 56 | Time Machine's backup strategy combines convenience and efficiency to safeguard your data without disrupting your workflow. 57 | 58 | ### Backups 59 | - [x] Files/Folders 60 | - [x] Flatpak 61 | - [ ] Flatpak Data 62 | - [x] PIP packages 63 | - [x] .Deb or .RPM (from Downloads folder) 64 | 65 | ## Monitoring Backup Status 66 | 67 | - **Color Indicators:** Keep an eye on your system tray's color changes to stay informed about your backup status: 68 | - Green dot, a backup is been made right now. 69 | 70 | Time Machine is currently in the process of backing up your files. Once the backup is complete, it will revert to the 71 | normal icon. 72 | 73 | 74 | - **Error Alerts:** If automatic backup is ON but your backup device becomes disconnected or is not mounted, you'll see 75 | a red dot. 76 | This could also indicate an issue 77 | encountered during the backup process. In such cases, open the Time Machine main window and refer to the provided report 78 | for details. 79 | 80 | 81 | ## Installation 82 | During the installation process, you will need to provide your system password. Follow these steps: 83 | 84 | 1. Open a terminal. 85 | 2. Copy and paste the following command: 86 | 87 | 88 | #### Command: 89 | 90 | git clone -b dev https://github.com/geovanejefferson/timemachine; cd timemachine/; python3 install.py 91 | 92 | 93 | 94 | ## Uninstall 95 | To uninstall the application, use the following steps: 96 | 97 | 1. Open a terminal. 98 | 2. Copy and paste the following command to navigate to the uninstallation directory: 99 | 100 | #### Command: 101 | 102 | cd .local/share/timemachine/; python3 uninstall.py 103 | 104 | ### Screenshoots 105 | ![Screenshot](https://raw.githubusercontent.com/GeovaneJefferson/timemachine/dev/src/screenshots/img_4.png) 106 | 107 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import subprocess as sub 2 | import os 3 | import shutil 4 | import pathlib 5 | from pathlib import Path 6 | 7 | 8 | # Remember to change setup too! 9 | HOME_USER = str(Path.home()) 10 | GET_CURRENT_LOCATION = pathlib.Path().resolve() 11 | 12 | APP_NAME_CLOSE = "timemachine" 13 | APP_NAME = "Time Machine" 14 | APP_VERSION = "v1.1.6.102 dev" 15 | 16 | DST_FOLDER_INSTALL = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}" 17 | DST_APPLICATIONS_LOCATION = f"{HOME_USER}/.local/share/applications" 18 | DST_FILE_EXE_DESKTOP = f"{HOME_USER}/.local/share/applications/{APP_NAME_CLOSE}.desktop" 19 | SRC_AUTOSTARTFOLDER_LOCATION=f"{HOME_USER}/.config/autostart" 20 | 21 | SRC_MAIN_WINDOW_PY = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/main_window.py" 22 | SRC_CALL_MIGRATION_ASSISTANT_PY = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/call_migration_assistant.py" 23 | SRC_MIGRATION_ASSISTANT_PY = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/migration_assistant.py" 24 | 25 | SRC_MIGRATION_ASSISTANT_ICON_212PX = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/icons/migration_assistant_212px.png" 26 | 27 | DST_BACKUP_CHECK_DESKTOP = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/desktop/backup_check.desktop" 28 | SRC_TIMEMACHINE_DESKTOP = f"{HOME_USER}/.local/share/applications/{APP_NAME_CLOSE}.desktop" 29 | DST_MIGRATION_ASSISTANT_DESKTOP = f"{HOME_USER}/.local/share/applications/migration_assistant.desktop" 30 | 31 | SRC_RESTORE_ICON = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/icons/restore_64px.svg" 32 | SRC_BACKUP_ICON = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/icons/backup_128px.png" 33 | SRC_ANALYSE_PY = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/analyse.py" 34 | 35 | 36 | def install_dependencies(user_distro_name): 37 | # sudo apt install libxcb-* 38 | # sudo apt-get install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev 39 | # Depedencies 40 | if distribution_info: 41 | if ( 42 | 'debian' in user_distro_name or 43 | 'ubuntu' in user_distro_name or 44 | 'mint' in user_distro_name): 45 | commands = ['python3-pip', 'flatpak'] 46 | sub.run( 47 | ['sudo', 'apt', 'install', '-y'] + commands, check=True) 48 | 49 | elif 'fedora' in user_distro_name: 50 | commands = ['python3-pip', 'flatpak'] 51 | sub.run( 52 | ['sudo', 'dnf', 'install', '-y'] + commands, check=True) 53 | 54 | elif 'opensuse' in user_distro_name: 55 | commands = ['python3-pip', 'flatpak'] 56 | sub.run( 57 | ['sudo', 'zypper', 'install', '-y'] + commands, check=True) 58 | 59 | elif 'arch' in user_distro_name: 60 | commands = ["python-pip", "qt6-wayland", "flatpak"] 61 | for command in commands: 62 | try: 63 | sub.run( 64 | ["pacman", "-Qq", command], check=True) 65 | except sub.CalledProcessError: 66 | sub.run( 67 | ['sudo', 'pacman', '-S', command], check=True) 68 | 69 | try: 70 | command = f"{GET_CURRENT_LOCATION}/requirements.txt" 71 | sub.run( 72 | ["pip", "install", "-r", command], 73 | check=True) 74 | except: 75 | pass 76 | 77 | # Install Flathub remote 78 | sub.run( 79 | ['flatpak', 'remote-add', 80 | '--if-not-exists', 81 | 'flathub', 82 | 'https://dl.flathub.org/repo/flathub.flatpakrepo'], check=True) 83 | else: 84 | print('Could not install the dependencies!') 85 | print('Manual install all the dependencies, you can see them in requirements.txt') 86 | print('Copying files...') 87 | 88 | def copy_files(): 89 | try: 90 | # Copy current folder to the destination folder 91 | print('-----[COPYING]-----') 92 | print('From:', GET_CURRENT_LOCATION) 93 | print('To:', DST_FOLDER_INSTALL) 94 | print() 95 | shutil.copytree( 96 | GET_CURRENT_LOCATION, 97 | DST_FOLDER_INSTALL, dirs_exist_ok=True) 98 | except Exception as error: 99 | print(error) 100 | # Remove 101 | os.remove(DST_FOLDER_INSTALL) 102 | 103 | def create_application_files(): 104 | # Create .local/share/applications 105 | if not os.path.exists(DST_APPLICATIONS_LOCATION): 106 | command = DST_APPLICATIONS_LOCATION 107 | os.makedirs(command, exist_ok=True) 108 | # sub.run(["mkdir", command]) 109 | 110 | # Send to DST_FILE_EXE_DESKTOP 111 | with open(SRC_TIMEMACHINE_DESKTOP, "w") as writer: 112 | writer.write( 113 | f"[Desktop Entry]\n " 114 | f"Version={APP_VERSION}\n " 115 | f"Type=Application\n " 116 | f"Name={APP_NAME}\n " 117 | f"Comment=Backup your files with {APP_NAME}\n " 118 | f"GenericName=Backup Tool\n " 119 | f"Icon={SRC_BACKUP_ICON}\n " 120 | f"Exec=python3 {SRC_MAIN_WINDOW_PY}\n " 121 | f"Path={HOME_USER}/.local/share/{APP_NAME_CLOSE}/\n " 122 | f"Categories=System\n " 123 | f"StartupWMClass={SRC_MAIN_WINDOW_PY.split('/')[-1]}\n " 124 | f"Actions=backup-now;\n " 125 | f"Terminal=false\n\n" 126 | 127 | f"[Desktop Action backup-now]\n " 128 | f"Name=Backup Now\n " 129 | f"Exec=python3 {SRC_ANALYSE_PY} %F\n ") 130 | 131 | # Migration_assistant .desktop 132 | with open(DST_MIGRATION_ASSISTANT_DESKTOP, "w") as writer: 133 | writer.write( 134 | f"[Desktop Entry]\n " 135 | f"Version={APP_VERSION}\n " 136 | f"Type=Application\n " 137 | f"Name=Migration Assistant\n " 138 | f"Comment=Restore files/folders etc. from a {APP_NAME}'s backup\n " 139 | f"Icon={SRC_MIGRATION_ASSISTANT_ICON_212PX}\n " 140 | f"Exec=python3 {SRC_CALL_MIGRATION_ASSISTANT_PY}\n " 141 | # f"Exec=python3 {SRC_MIGRATION_ASSISTANT_PY}\n " 142 | f"Path={HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/\n " 143 | f"Categories=System\n " 144 | f"StartupWMClass={(SRC_MIGRATION_ASSISTANT_PY).split('/')[-1]}\n " 145 | f"Terminal=false") 146 | 147 | def create_backup_checker_desktop(): 148 | try: 149 | # Create autostart folder if necessary 150 | if not os.path.exists(SRC_AUTOSTARTFOLDER_LOCATION): 151 | os.makedirs(SRC_AUTOSTARTFOLDER_LOCATION, exist_ok=True) 152 | 153 | # Edit file startup with system 154 | with open(DST_BACKUP_CHECK_DESKTOP, "w") as writer: 155 | writer.write( 156 | f"[Desktop Entry]\n " 157 | f"Type=Application\n " 158 | f"Exec=/bin/python3 {HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/at_boot.py\n " 159 | f"Hidden=false\n " 160 | f"NoDisplay=false\n " 161 | f"Name={APP_NAME}\n " 162 | f"Comment={APP_NAME}'s manager before boot.\n " 163 | f"Icon={SRC_RESTORE_ICON}") 164 | except: 165 | pass 166 | 167 | def detect_linux_distribution(): 168 | distribution_info = {} 169 | if os.path.isfile('/etc/os-release'): 170 | with open('/etc/os-release', 'r') as f: 171 | for line in f: 172 | key, value = line.strip().split('=', 1) 173 | # Remove quotes from value 174 | value = value.strip('"') 175 | distribution_info[key] = value 176 | return distribution_info 177 | 178 | 179 | if __name__ == '__main__': 180 | distribution_info = detect_linux_distribution() 181 | if distribution_info: 182 | USERS_DISTRO_NAME = distribution_info.get('NAME') 183 | print() 184 | print("Detected Linux distribution:", USERS_DISTRO_NAME) 185 | print("Version:", distribution_info.get('VERSION')) 186 | print() 187 | else: 188 | print("Unable to detect Linux distribution.") 189 | exit() 190 | 191 | try: 192 | # Install dependencies 193 | print("Installing dependencies...") 194 | install_dependencies(user_distro_name=str(USERS_DISTRO_NAME).lower()) 195 | except Exception as e: 196 | print('Error while trying to install the dependencies.') 197 | exit() 198 | try: 199 | # Begin installation 200 | print() 201 | print(f"Copyng files to {HOME_USER}/.local/share/{APP_NAME_CLOSE}/...") 202 | copy_files() 203 | except Exception as e: 204 | print('Error while trying to copy the files.') 205 | exit() 206 | try: 207 | # Create exe files 208 | print(f"Creating {APP_NAME_CLOSE}.desktop...") 209 | create_application_files() 210 | 211 | # Create backup checker.dekstop 212 | print(f"Creating backup_checker.desktop...") 213 | create_backup_checker_desktop() 214 | except Exception as e: 215 | print('Error while trying to creating .desktop files.') 216 | exit() 217 | 218 | print() 219 | print("Program was successfully installed!") 220 | exit() 221 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PySide6 2 | setproctitle -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__init__.py -------------------------------------------------------------------------------- /src/__pycache__/analyse.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/analyse.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_flatpak.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_flatpak.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_flatpak.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_flatpak.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_now.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_now.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_pip_packages.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_pip_packages.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_pip_packages.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_pip_packages.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_status.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_status.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_status.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_status.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_wallpaper.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_wallpaper.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/backup_wallpaper.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/backup_wallpaper.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/calculate_time_left_to_backup.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/calculate_time_left_to_backup.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/calculate_time_left_to_backup.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/calculate_time_left_to_backup.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/calculate_time_left_to_backup.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/calculate_time_left_to_backup.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/check_connection.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/check_connection.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/check_connection.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/check_connection.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/check_connection.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/check_connection.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_backup_checker_desktop.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_backup_checker_desktop.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_backup_checker_desktop.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_backup_checker_desktop.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_backup_checker_desktop.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_backup_checker_desktop.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_directory.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_directory.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_directory.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_directory.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/create_directory.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/create_directory.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/device_location.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/device_location.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/device_location.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/device_location.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/device_location.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/device_location.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/error_catcher.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/error_catcher.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/error_catcher.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/error_catcher.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/error_catcher.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/error_catcher.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_backup_date.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_backup_date.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_backup_date.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_backup_date.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_backup_date.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_backup_date.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_backup_time.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_backup_time.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_backup_time.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_backup_time.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_folders_to_be_backup.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_folders_to_be_backup.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_folders_to_be_backup.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_folders_to_be_backup.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_home_folders.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_home_folders.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_home_folders.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_home_folders.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_home_folders.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_home_folders.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_latest_backup_date.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_latest_backup_date.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_latest_backup_date.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_latest_backup_date.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_sizes.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_sizes.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_sizes.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_sizes.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_sizes.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_sizes.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_users_de.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_users_de.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_users_de.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_users_de.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/get_users_de.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/get_users_de.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/handle_spaces.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/handle_spaces.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/handle_spaces.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/handle_spaces.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/handle_spaces.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/handle_spaces.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/next_backup_label.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/next_backup_label.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/next_backup_label.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/next_backup_label.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/next_backup_label.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/next_backup_label.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/notification_massage.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/notification_massage.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/notification_massage.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/notification_massage.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/notification_massage.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/notification_massage.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/package_manager.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/package_manager.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/package_manager.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/package_manager.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/package_manager.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/package_manager.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/prepare_backup.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/prepare_backup.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/prepare_backup.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/prepare_backup.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/prepare_backup.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/prepare_backup.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/read_ini_file.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/read_ini_file.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/read_ini_file.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/read_ini_file.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/read_ini_file.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/read_ini_file.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_flatpaks_applications.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_flatpaks_applications.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_flatpaks_applications.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_flatpaks_applications.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_flatpaks_data.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_flatpaks_data.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_flatpaks_data.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_flatpaks_data.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_home.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_home.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_home.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_home.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_package_applications.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_package_applications.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_package_applications.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_package_applications.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_wallpaper.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_wallpaper.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_backup_wallpaper.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_backup_wallpaper.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_config.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_config.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_config.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_config.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_local_share.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_local_share.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_local_share.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_local_share.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_share_config.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_share_config.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/restore_kde_share_config.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/restore_kde_share_config.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/save_info.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/save_info.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/save_info.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/save_info.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/save_info.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/save_info.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/setup.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/setup.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/setup.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/setup.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/setup.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/setup.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/stylesheet.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/stylesheet.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/stylesheet.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/stylesheet.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/stylesheet.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/stylesheet.cpython-312.pyc -------------------------------------------------------------------------------- /src/__pycache__/update.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/update.cpython-310.pyc -------------------------------------------------------------------------------- /src/__pycache__/update.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/update.cpython-311.pyc -------------------------------------------------------------------------------- /src/__pycache__/update.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/__pycache__/update.cpython-312.pyc -------------------------------------------------------------------------------- /src/at_boot.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def system_tray(): 8 | # Update DB 9 | MAIN_INI_FILE.set_database_value( 10 | 'STATUS', 'first_startup', 'True') 11 | 12 | if MAIN_INI_FILE.get_database_value( 13 | 'SYSTEMTRAY', 'system_tray'): 14 | # System tray 15 | sub.Popen( 16 | ['python3', SRC_SYSTEM_TRAY_PY], 17 | stdout=sub.PIPE, 18 | stderr=sub.PIPE) 19 | 20 | if MAIN_INI_FILE.hd_name() is not None: 21 | if MAIN_INI_FILE.get_database_value( 22 | 'STATUS', 'automatically_backup'): 23 | 24 | # Unfinished backup 25 | if MAIN_INI_FILE.get_database_value( 26 | 'STATUS', 'unfinished_backup'): 27 | 28 | # Start backup checker 29 | sub.Popen( 30 | ['python3', SRC_BACKUP_NOW_PY], 31 | stdout=sub.PIPE, 32 | stderr=sub.PIPE) 33 | else: 34 | # Start backup checker 35 | sub.Popen( 36 | ['python3', SRC_BACKUP_CHECKER_PY], 37 | stdout=sub.PIPE, 38 | stderr=sub.PIPE) 39 | 40 | 41 | # Delay startup for x seconds 42 | try: 43 | time.sleep(0) 44 | system_tray() 45 | except Exception as error: 46 | # Save error log 47 | MAIN_INI_FILE.report_error(error) -------------------------------------------------------------------------------- /src/backup_checker.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from prepare_backup import PREPAREBACKUP 4 | from check_connection import is_connected 5 | 6 | # Found packages list 7 | list_of_found_deb_pakages = [] 8 | list_of_found_rpm_packages = [] 9 | 10 | MAIN_INI_FILE = UPDATEINIFILE() 11 | MAIN_PREPARE = PREPAREBACKUP() 12 | DOWNLOADS_FOLDER_LOCATION = f"{HOME_USER}/Downloads" 13 | 14 | 15 | # Check for new .deb, .rpm etc. inside Downloads folder and back up 16 | def check_for_new_packages(): 17 | print("Searching new packages inside Downloads folder...") 18 | 19 | # Search for .deb packages inside Downloads folder 20 | for package in os.listdir(DOWNLOADS_FOLDER_LOCATION): 21 | if package.endswith(".deb"): 22 | # Check if the found .deb is has not alredy been back up 23 | if package.split("_")[0] in ( 24 | f"{MAIN_INI_FILE.deb_main_folder()}/{(package).split('_')[0]}"): 25 | # Add to list, so it wont back up every time the same file 26 | if package not in list_of_found_deb_pakages: 27 | list_of_found_deb_pakages.append(package) 28 | 29 | # Delete the old version before back up 30 | for old_package in os.listdir(MAIN_INI_FILE.deb_main_folder()): 31 | if old_package.startswith(f"{package.split('_')[0]}"): 32 | # Delete old package 33 | dst = os.path.join(MAIN_INI_FILE.deb_main_folder(), old_package) 34 | os.remove(dst) 35 | 36 | # backup the found package 37 | src = os.path.join(DOWNLOADS_FOLDER_LOCATION, package) 38 | dst = MAIN_INI_FILE.deb_main_folder() 39 | shutil.copy2(src, dst) 40 | 41 | # print(src) 42 | # print(dst) 43 | print('Backing up new package:', src) 44 | 45 | # Search for .rpm packages inside Downloads folder 46 | if package.endswith(".rpm"): 47 | # Check if the found .rpm is has not alredy been back up 48 | if package.split("_")[0] in ( 49 | f"{MAIN_INI_FILE.rpm_main_folder()}/{(package).split('_')[0]}"): 50 | # Add to list, so it wont back up every time the same file 51 | if package not in list_of_found_rpm_packages: 52 | list_of_found_rpm_packages.append(package) 53 | 54 | # Delete the old version before back up 55 | for deleteOutput in os.listdir(MAIN_INI_FILE.rpm_main_folder()): 56 | if deleteOutput.startswith(f"{package.split('_')[0]}"): 57 | # Delete old package 58 | dst = os.path.join(MAIN_INI_FILE.deb_main_folder(), old_package) 59 | os.remove(dst) 60 | 61 | # backup the found package 62 | src = os.path.join(DOWNLOADS_FOLDER_LOCATION, package) 63 | dst = MAIN_INI_FILE.rpm_main_folder() 64 | shutil.copy2(src, dst) 65 | 66 | print(src) 67 | print(dst) 68 | print('Backing up new package:', src) 69 | 70 | def time_to_backup(current_time): 71 | # Save current time of check 72 | MAIN_INI_FILE.set_database_value( 73 | 'INFO', 'latest_backup_time_check', current_time) 74 | 75 | print("Calling analyses...") 76 | 77 | x = sub.Popen( 78 | ['python3', SRC_ANALYSE_PY], 79 | stdout=sub.PIPE, 80 | stderr=sub.PIPE) 81 | 82 | output, error = x.communicate() 83 | 84 | # Check the return code 85 | if x.returncode == 0: 86 | print(f"Backup process completed successfully. Output: {output}") 87 | else: 88 | print(f"Error in backup process. Output: {output}, Error: {error}") 89 | 90 | exit() 91 | 92 | # Set the process name 93 | setproctitle.setproctitle("Time Machine - Backup Checker") 94 | 95 | if is_connected(MAIN_INI_FILE.hd_hd()): 96 | # Create the main backup folder 97 | if not os.path.exists(MAIN_INI_FILE.create_base_folder()): 98 | if MAIN_PREPARE.prepare_the_backup(): 99 | # Set backup now to True 100 | MAIN_INI_FILE.set_database_value( 101 | 'STATUS', 'backing_up_now', 'True') 102 | 103 | # Backup now 104 | sub.Popen( 105 | ['python3', SRC_BACKUP_NOW_PY], 106 | stdout=sub.PIPE, 107 | stderr=sub.PIPE) 108 | exit() 109 | 110 | 111 | while True: 112 | try: 113 | # Not current backing up 114 | if not MAIN_INI_FILE.current_backing_up(): 115 | 116 | # Turn on/off backup checker 117 | if not MAIN_INI_FILE.automatically_backup(): 118 | print("Automatically backup is OFF.") 119 | break 120 | 121 | print('Backup checker : ON') 122 | 123 | # Has connection to the backup device 124 | if is_connected(MAIN_INI_FILE.hd_hd()): 125 | print('Backup connection: ON') 126 | 127 | # Check for a new backup 128 | # Get the current time 129 | current_time = str(MAIN_INI_FILE.current_time()) 130 | 131 | print('Current time:', current_time) 132 | print('Backup time:', MILITARY_TIME_OPTION) 133 | print() 134 | 135 | # Time to backup 136 | if current_time in MILITARY_TIME_OPTION: 137 | # Time to backup 138 | time_to_backup(current_time) 139 | 140 | # Check for new packages to backup 141 | check_for_new_packages() 142 | else: 143 | print('Backup connection: OFF') 144 | else: 145 | print('Backup checker: PAUSED') 146 | 147 | time.sleep(5) 148 | except BrokenPipeError: 149 | # Ignore Broken pipe error 150 | pass 151 | except Exception as e: 152 | # Save error log 153 | MAIN_INI_FILE.report_error(e) -------------------------------------------------------------------------------- /src/backup_flatpak.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from notification_massage import notification_message 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | def backup_flatpak(): 9 | flatpak_list= [] 10 | 11 | try: 12 | # Open flatpak file 13 | with open(MAIN_INI_FILE.flatpak_txt_location(), 'w') as configfile: 14 | for flatpak in os.popen(GET_FLATPAKS_APPLICATIONS_NAME): 15 | flatpak = str(flatpak).strip() 16 | 17 | # Filter list to remove dupli 18 | if flatpak not in flatpak_list: 19 | flatpak_list.append(flatpak) 20 | 21 | # Write to file 22 | configfile.write(flatpak + '\n') 23 | 24 | notification_message(f'Backing up: {flatpak}') 25 | except Exception: 26 | pass 27 | 28 | 29 | # # Backup flatpak data 30 | # if MAIN_INI_FILE.get_database_value('STATUS', 'allow_flatpak_data'): 31 | # try: 32 | # # .var/app 33 | # for counter in range(len(flatpak_var_list())): 34 | # # Copy the Flatpak var/app folders 35 | # src = flatpak_var_list()[counter] 36 | # dst = MAIN_INI_FILE.flatpak_var_folder() 37 | # command = src + ' ' + dst 38 | 39 | # notification_message( 40 | # f'Backing up: {flatpak_var_list()[counter]}') 41 | 42 | # print(f'Backing up: {flatpak_var_list()[counter]}') 43 | 44 | # sub.run( 45 | # ['cp', '-rvf', command], 46 | # stdout=sub.PIPE, 47 | # stderr=sub.PIPE) 48 | 49 | 50 | # # .local/share/flatpak 51 | # for counter in range(len(flatpak_local_list())): 52 | # # Copy the Flatpak var/app folders 53 | # src = flatpak_local_list()[counter] 54 | # dst = MAIN_INI_FILE.flatpak_local_folder() 55 | # command = src + ' ' + dst 56 | 57 | # notification_message( 58 | # f'Backing up: {flatpak_local_list()[counter]}') 59 | 60 | # print(f'Backing up: {flatpak_local_list()[counter]}') 61 | 62 | # sub.run( 63 | # ['cp', '-rvf', command], 64 | # stdout=sub.PIPE, 65 | # stderr=sub.PIPE) 66 | 67 | # except: 68 | # pass 69 | 70 | 71 | if __name__ == '__main__': 72 | pass -------------------------------------------------------------------------------- /src/backup_pip_packages.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from notification_massage import notification_message 4 | from create_directory import create_directory, create_file 5 | 6 | 7 | MAIN_INI_FILE = UPDATEINIFILE() 8 | 9 | def backup_pip_packages(): 10 | ################################################################################ 11 | # Create pip text file 12 | ################################################################################ 13 | pip_packages_txt_location = MAIN_INI_FILE.pip_packages_txt_location() 14 | 15 | # Check if the directory exists, and create it if necessary 16 | create_directory(pip_packages_txt_location) 17 | # Check if the file exists, and create it if necessary 18 | create_file(pip_packages_txt_location) 19 | 20 | ################################################################################ 21 | # Get pip packages list 22 | ################################################################################ 23 | try: 24 | pip_freeze_output = sub.check_output( 25 | ['pip', 'freeze']).decode( 26 | 'utf-8') 27 | 28 | lenght_of_packages = len(str(pip_freeze_output).split()) 29 | 30 | # Remove paskages versions numbers 31 | count = 0 32 | with open(MAIN_INI_FILE.pip_packages_txt_location(), 'w') as file: 33 | for line in str(pip_freeze_output).split(): 34 | line = pip_freeze_output.split()[count].split('==')[0] 35 | 36 | # Do not use '\n' at the last number 37 | if (lenght_of_packages - 1) != count: 38 | file.write(line + '\n') 39 | 40 | else: 41 | file.write(line) 42 | 43 | # Notification 44 | notification_message(f'Backing up PIP: {line}') 45 | 46 | count += 1 47 | 48 | except Exception as e: 49 | # Save error log 50 | pass 51 | # MAIN_INI_FILE.report_error(e) -------------------------------------------------------------------------------- /src/backup_status.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def progress_bar_status(): 8 | try: 9 | progress_value = MAIN_INI_FILE.get_database_value('STATUS', 'progress_bar') 10 | 11 | if progress_value is not None: 12 | return f'{progress_value:.1f}% done.' 13 | else: 14 | return None 15 | except Exception as e: 16 | return None 17 | # # Save error log 18 | # MAIN_INI_FILE.report_error(e) -------------------------------------------------------------------------------- /src/backup_wallpaper.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from handle_spaces import handle_spaces 4 | from get_users_de import get_user_de 5 | 6 | 7 | MAIN_INI_FILE = UPDATEINIFILE() 8 | 9 | def get_wallpaper_full_location(): 10 | # Detect color scheme 11 | get_color_scheme = os.popen( 12 | DETECT_THEME_MODE).read().replace("'", "").strip() 13 | ## Set XDG_CURRENT_DESKTOP environment variable 14 | #os.environ['XDG_CURRENT_DESKTOP'] 15 | 16 | ## Execute the command and print the output 17 | #output = os.popen('echo $XDG_CURRENT_DESKTOP').read().strip().lower() 18 | 19 | ################################## 20 | # Compatibility 21 | ################################## 22 | ################################## 23 | # Gnome 24 | ################################### 25 | # If users os name is found in DB 26 | if 'gnome' in get_user_de() or 'unity' in get_user_de(): 27 | # Light theme 28 | if get_color_scheme == "prefer-light": 29 | # Get current wallpaper 30 | wallpaper = os.popen( 31 | GET_GNOME_WALLPAPER).read().replace( 32 | "file://", "").replace("'", "").strip() 33 | else: 34 | # Get current wallpaper (Dark) 35 | wallpaper = os.popen( 36 | GET_GNOME_WALLPAPER_DARK).read().strip().replace( 37 | "file://", "").replace("'", "") 38 | 39 | # If exist, remove "/" at the end 40 | if wallpaper.endswith("/"): 41 | wallpaper = wallpaper.rsplit("/", 1) 42 | wallpaper = "".join(wallpaper) 43 | wallpaper = wallpaper.strip().replace("[", "").replace("'", "") 44 | wallpaper = wallpaper.replace("]", "").replace(",", "") 45 | 46 | # Handle spaces 47 | wallpaper = handle_spaces(wallpaper) 48 | 49 | # Return wallpapers full location 50 | return wallpaper 51 | 52 | ################################## 53 | # Kde 54 | ################################### 55 | elif 'kde' in get_user_de(): 56 | # Search wallaper inside plasma-org.kde.plasma.desktop-appletsrc 57 | with open(f"{HOME_USER}/.config/plasma-org.kde.plasma.desktop-appletsrc", "r") as file: 58 | # Strips the newline character 59 | for line in file.readlines(): 60 | line = line.strip() 61 | 62 | # Search for 63 | if line.startswith('Image='): 64 | # Replace line 65 | line = line.replace('Image=', '') 66 | 67 | # Remove file:// 68 | line = line.replace('file://', '') 69 | 70 | # Handle spaces 71 | # line = handle_spaces(line) 72 | # Return lines full location 73 | return line 74 | 75 | def backup_wallpaper(): 76 | wallpaper_folder = MAIN_INI_FILE.wallpaper_main_folder() 77 | 78 | # Get a list of wallpapers in the specified folder 79 | wallpapers = os.listdir(wallpaper_folder) 80 | 81 | # Check if there are any wallpapers to delete 82 | if wallpapers: 83 | # Iterate over each wallpaper and delete it 84 | for wallpaper in wallpapers: 85 | wallpaper_path = os.path.join(wallpaper_folder, wallpaper) 86 | print('Deleting', wallpaper_path) 87 | 88 | # Execute the command to delete the wallpaper 89 | os.remove(wallpaper_path) 90 | 91 | # Backup wallpaper 92 | if get_wallpaper_full_location() is not None: 93 | src = get_wallpaper_full_location() 94 | dst = MAIN_INI_FILE.wallpaper_main_folder() 95 | 96 | print('Copying', src, dst) 97 | shutil.copy2(src, dst) 98 | 99 | # Write to file 100 | update_db() 101 | 102 | def update_db(): 103 | CONFIG = configparser.ConfigParser() 104 | CONFIG.read(MAIN_INI_FILE.restore_settings_location()) 105 | with open(MAIN_INI_FILE.restore_settings_location(), 'w') as configfile: 106 | if not CONFIG.has_section('INFO'): 107 | CONFIG.add_section('INFO') 108 | 109 | if get_wallpaper_full_location() is not None: 110 | CONFIG.set( 111 | 'INFO', 'wallpaper', f'{get_wallpaper_full_location().split("/")[-1]}') 112 | 113 | # Write to file 114 | CONFIG.write(configfile) 115 | 116 | 117 | if __name__ == '__main__': 118 | pass 119 | -------------------------------------------------------------------------------- /src/calculate_time_left_to_backup.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def calculate_time_left_to_backup(): 8 | # Current time 9 | current_time = datetime.now() 10 | 11 | # Next hour 12 | next_hour = int(MAIN_INI_FILE.current_hour()) + 1 13 | 14 | # Time of the next backup 15 | next_backup_time = current_time.replace( 16 | hour=next_hour, minute=0, second=0) 17 | 18 | # Calculate the time left 19 | time_left = next_backup_time - current_time 20 | 21 | # Extract hours and minutes from the time left 22 | # hours_left = time_left.seconds // 3600 23 | time_left = (time_left.seconds // 60) % 60 24 | 25 | # Return calculation 26 | return calculation(int(time_left) + 1) 27 | 28 | def calculation(time_left): 29 | return f"In Approx. {str(time_left)} minutes..." 30 | 31 | 32 | if __name__ == '__main__': 33 | pass -------------------------------------------------------------------------------- /src/call_migration_assistant.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from PySide6.QtCore import QProcess, QProcessEnvironment 3 | from PySide6.QtWidgets import QApplication, QWidget, QMessageBox 4 | 5 | # Message 6 | print('Migration Assistant needs to run as root.') 7 | # Request users password 8 | sub.run(['sudo', 'python3', *sys.argv], stdout=sub.PIPE, stderr=sub.PIPE) 9 | # sub.run(['pkexec', 'python3', *sys.argv], stdout=sub.PIPE, stderr=sub.PIPE) 10 | # Clear terminal 11 | sub.run(['clear'], stdout=sub.PIPE, stderr=sub.PIPE) 12 | # Open Migration Assistant 13 | sub.run(['python3', SRC_MIGRATION_ASSISTANT_PY], stdout=sub.PIPE, stderr=sub.PIPE) 14 | 15 | # class CallMigrationTool(QWidget): 16 | # def __init__(self): 17 | # super(CallMigrationTool, self).__init__() 18 | 19 | # # Call for root 20 | # if not self.access_root(): 21 | # print('Exiting...') 22 | # sys.exit() 23 | # else: 24 | # # Ask for user's password 25 | # #command = ['pkexec', 'python3'] 26 | # #auth_process = sub.run(command, stdout=sub.PIPE, stderr=sub.PIPE, input=b'password_here'.decode(), text=True, check=False) 27 | # directory_path = str(SRC_MIGRATION_ASSISTANT_PY.split('/')[:-1]) 28 | # directory_path = '/home/macbook/.local/share/timemachine/src' 29 | # #print(os.path.join(directory_path)) 30 | # #exit() 31 | 32 | # auth_process = sub.run(['pkexec', 'python3', SRC_MIGRATION_ASSISTANT_PY], stdout=sub.PIPE, stderr=sub.PIPE, text=True, check=False, cwd=directory_path) 33 | 34 | # print("stdout:", auth_process.stdout) 35 | # print("stderr:", auth_process.stderr) 36 | 37 | # def access_root(self): 38 | # reply = QMessageBox.question(self, 'Confirmation', 'Are you sure you want to execute the command?', QMessageBox.Yes | QMessageBox.No) 39 | # if reply == QMessageBox.Yes: 40 | # return True 41 | # else: 42 | # return False 43 | 44 | # if __name__ == '__main__': 45 | # app = QApplication(sys.argv) 46 | # MAIN = CallMigrationTool() 47 | # MAIN.show() 48 | # sys.exit(app.exec()) 49 | 50 | ## Message 51 | #print('Migration Assistant needs to run as root.') 52 | 53 | ## Request user's password and execute the script with pkexec 54 | #auth_process = sub.run(['pkexec', 'python3', *sys.argv], stdout=sub.PIPE, stderr=sub.PIPE) 55 | 56 | ## Print stdout and stderr of the authentication process for debugging 57 | #print("stdout:", auth_process.stdout.decode()) 58 | #print("stderr:", auth_process.stderr.decode()) 59 | #print("stderr:", type(auth_process.stderr.decode())) 60 | 61 | #if 'Error' in auth_process.stderr.decode(): 62 | #print('ø***') 63 | ## Clear terminal 64 | #sub.run(['clear'], stdout=sub.PIPE, stderr=sub.PIPE) 65 | ## Open Migration Assistant 66 | #sub.run(['python3', SRC_MIGRATION_ASSISTANT_PY], stdout=sub.PIPE, stderr=sub.PIPE) 67 | -------------------------------------------------------------------------------- /src/check_connection.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def is_connected(ini_hd_name): 5 | # External availability 6 | try: 7 | os.listdir(ini_hd_name) 8 | return True 9 | # No connection to backup device 10 | except FileNotFoundError: 11 | return False 12 | except PermissionError: 13 | return False 14 | 15 | if __name__ == '__main__': 16 | pass -------------------------------------------------------------------------------- /src/create_backup_checker_desktop.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from create_directory import create_directory 3 | 4 | 5 | # Remember to change INSTALL too!!! 6 | def create_backup_checker_desktop(): 7 | # Create autostart folder if necessary 8 | if not os.path.exists(SRC_AUTOSTART_FOLDER_LOCATION): 9 | command = SRC_AUTOSTART_FOLDER_LOCATION 10 | 11 | create_directory(command) 12 | 13 | # Edit file startup with system 14 | with open(DST_BACKUP_CHECK_DESKTOP, "w") as writer: 15 | writer.write( 16 | f"[Desktop Entry]\n " 17 | f"Type=Application\n " 18 | f"Exec=/bin/python3 {HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/at_boot.py\n " 19 | f"Hidden=false\n " 20 | f"NoDisplay=false\n " 21 | f"Name={APP_NAME}\n " 22 | f"Comment={APP_NAME}'s manager before boot.\n " 23 | f"Icon={SRC_RESTORE_ICON}") 24 | 25 | 26 | if __name__ == '__main__': 27 | pass 28 | -------------------------------------------------------------------------------- /src/create_directory.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def create_directory(location): 5 | # Is a directory to a file 6 | if '.' in str(location).split('/')[-1]: 7 | # Extract the directory path from the file path 8 | directory = os.path.dirname(location) 9 | else: 10 | # Extract the directory path from the file path 11 | directory = location 12 | 13 | # Check if the directory exists, and create it if necessary 14 | if not os.path.exists(directory): 15 | print(f"Directory '{directory}' does not exist. Creating...") 16 | try: 17 | os.makedirs(directory, exist_ok=True) 18 | print(f"Directory '{directory}' created successfully.") 19 | except Exception as e: 20 | print(f"Error creating directory: {e}") 21 | 22 | def create_file(location): 23 | # Check if the file already exists 24 | if not os.path.exists(location): 25 | print(f'File "{location}" does not exist. Creating...') 26 | 27 | # Create the file 28 | try: 29 | with open(location, 'w'): 30 | pass # This creates an empty file 31 | print(f'File "{location}" created successfully.') 32 | except Exception as e: 33 | print(f"Error creating file: {e}") 34 | else: 35 | print('File already exists.') -------------------------------------------------------------------------------- /src/desktop/backup_check.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Exec=/bin/python3 /home/geovane/.local/share/timemachine/src/at_boot.py 4 | Hidden=false 5 | NoDisplay=false 6 | Name=Time Machine 7 | Comment=Time Machine's manager before boot. 8 | Icon=/home/geovane/.local/share/timemachine/src/icons/restore_64px.svg -------------------------------------------------------------------------------- /src/desktop/migration_assistant.desktop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/desktop/migration_assistant.desktop -------------------------------------------------------------------------------- /src/desktop/timemachine.desktop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/desktop/timemachine.desktop -------------------------------------------------------------------------------- /src/device_location.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def device_location(): 5 | # Search external inside media 6 | try: 7 | if len(os.listdir(f'{MEDIA}/{USERNAME}')) != 0: 8 | return True 9 | 10 | except FileNotFoundError: 11 | try: 12 | if len(os.listdir(f'{RUN}/{USERNAME}')) != 0: 13 | return False 14 | 15 | except: 16 | print(f"No devices found.") 17 | return None 18 | 19 | 20 | if __name__=='__main__': 21 | pass 22 | -------------------------------------------------------------------------------- /src/error_catcher.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from create_directory import create_directory, create_file 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | def signal_exit(*args): 9 | # Set unafineshed backup to Yes 10 | # MAIN_INI_FILE.set_database_value('STATUS', 'unfinished_backup', 'Yes') 11 | 12 | if args: 13 | messages = args # Use the entire args tuple as a list 14 | print("All messages are:", messages) 15 | 16 | else: 17 | print("No messages provided.") 18 | 19 | # Check if the directory exists, and create it if necessary 20 | create_directory(LOG_LOCATION) 21 | # Check if the file exists, and create it if necessary 22 | create_file(LOG_LOCATION) 23 | 24 | # Write bug in to it 25 | with open(LOG_LOCATION, 'w') as writer: 26 | writer.write(str(messages)) 27 | 28 | def error_trying_to_backup(e): 29 | MAIN_INI_FILE.set_database_value('INFO', 'saved_notification', f'{e}') 30 | exit() -------------------------------------------------------------------------------- /src/get_backup_date.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def get_backup_date(): 8 | backup_date_list = [] 9 | 10 | try: 11 | for date_folder in os.listdir(f"{str(MAIN_INI_FILE.backup_folder_name())}"): 12 | # Only date folders 13 | if '-' in date_folder: 14 | backup_date_list.append(date_folder) 15 | backup_date_list.sort( 16 | reverse = True, 17 | key = lambda date: datetime.strptime(date, "%d-%m-%y")) 18 | 19 | # Has date in list 20 | if backup_date_list: 21 | return backup_date_list 22 | 23 | else: 24 | return None 25 | 26 | except: 27 | pass 28 | 29 | def last_backup_date(): 30 | # Grab last date folder 31 | return get_backup_date()[0] 32 | 33 | def last_backup_time(): 34 | loc = MAIN_INI_FILE.backup_dates_location() 35 | search = loc + '/' + last_backup_date() 36 | 37 | # Grab last time folder 38 | for time_folder in os.listdir(search): 39 | # Exclude hidden files/folder 40 | if '.' not in time_folder: 41 | break 42 | 43 | # Time folder found 44 | if time_folder: 45 | return time_folder 46 | 47 | def has_backup_dates(): 48 | # Last date/time folder 49 | for has_date_folder in os.listdir(MAIN_INI_FILE.backup_dates_location()): 50 | # Exlude hidden files/folders 51 | if '.' not in has_date_folder: 52 | break 53 | 54 | return bool(has_date_folder) 55 | 56 | 57 | if __name__ == '__main__': 58 | print(last_backup_time()) 59 | pass -------------------------------------------------------------------------------- /src/get_backup_home_name_and_size.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from get_latest_backup_date import latest_backup_date 4 | from get_backup_time import get_latest_backup_time 5 | from handle_spaces import handle_spaces 6 | 7 | 8 | MAIN_INI_FILE = UPDATEINIFILE() 9 | 10 | 11 | list_home_folder_to_restore = [] 12 | list_home_folder_size_to_restore = [] 13 | list_home_folder_size_to_restore_pretty = [] 14 | 15 | def get_backup_home_folders_name(): 16 | print("Getting folders name...") 17 | 18 | for folder in os.listdir(f"{MAIN_INI_FILE.get_backup_home_folders()}"): 19 | folder = folder.capitalize() 20 | 21 | # Check folder isUpper or not 22 | if not os.path.exists(f"{HOME_USER}/{folder}"): 23 | folder = folder.lower() 24 | 25 | # Add to the list after handle spaces 26 | list_home_folder_to_restore.append(handle_spaces(folder)) 27 | 28 | try: 29 | get_size = os.popen(f"du -s {MAIN_INI_FILE.backup_folder_name()}/{latest_backup_date()}/{(get_latest_backup_time()[0])}/") 30 | get_size = get_size.read().strip("\t").strip("\n").replace(f"{MAIN_INI_FILE.backup_folder_name()}/" 31 | f"{latest_backup_date()}/{(get_latest_backup_time()[0])}/", "").replace("\t", "") 32 | 33 | # Add to the list 34 | list_home_folder_size_to_restore.append(int(get_size)) 35 | except: 36 | pass 37 | 38 | try: 39 | get_size = os.popen(f"du -hs {MAIN_INI_FILE.backup_folder_name()}/{latest_backup_date()}/{(get_latest_backup_time()[0])}/") 40 | get_size = get_size.read().strip("\t").strip("\n").replace(f"{MAIN_INI_FILE.backup_folder_name()}/" 41 | f"{latest_backup_date()}/{(get_latest_backup_time()[0])}/", "").replace("\t", "") 42 | 43 | # Add to the list 44 | list_home_folder_size_to_restore_pretty.append(int(get_size)) 45 | except: 46 | pass 47 | 48 | # Return all sizes 49 | return list_home_folder_to_restore 50 | 51 | def get_backup_folders_size(): 52 | get_backup_home_folders_name() 53 | 54 | # Return first size from list 55 | return list_home_folder_size_to_restore[0] 56 | 57 | def get_backup_folders_size_pretty(): 58 | get_backup_home_folders_name() 59 | 60 | try: 61 | # Return first size from list, pretty way 62 | return list_home_folder_size_to_restore_pretty[0] 63 | except IndexError: 64 | return None 65 | 66 | 67 | if __name__ == '__main__': 68 | pass -------------------------------------------------------------------------------- /src/get_backup_time.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from get_backup_date import * 3 | from read_ini_file import UPDATEINIFILE 4 | from get_latest_backup_date import latest_backup_date 5 | 6 | 7 | MAIN_INI_FILE = UPDATEINIFILE() 8 | 9 | 10 | def get_latest_backup_time(): 11 | list_of_time_folder = [] 12 | 13 | try: 14 | for output in os.listdir(f'{MAIN_INI_FILE.backup_dates_location()}/{latest_backup_date()}'): 15 | list_of_time_folder.append(output) 16 | 17 | # Sort list 18 | list_of_time_folder.sort(reverse=True) 19 | # Return list 20 | return list_of_time_folder[0] 21 | except: 22 | pass 23 | 24 | 25 | if __name__ == '__main__': 26 | pass -------------------------------------------------------------------------------- /src/get_days_name.py: -------------------------------------------------------------------------------- 1 | import locale 2 | import datetime 3 | 4 | 5 | def get_days_name(): 6 | # Set the locale for the current session to English (United States) 7 | locale.setlocale(locale.LC_TIME, 'en_US.utf8') 8 | # Get the abbreviated day name (e.g., "Mon", "Tue", etc.) for the current day 9 | abbreviated_day_name = datetime.datetime.today().strftime('%a') 10 | # Return days abreviated 11 | return str(abbreviated_day_name) -------------------------------------------------------------------------------- /src/get_flatpaks_data_size.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | flatpak_var_size_list = [] 5 | flatpak_var_to_be_restore = [] 6 | flatpak_local_to_be_restore = [] 7 | 8 | def restore_backup_flatpaks_data(): 9 | print("Checking size of flatpak (var)...") 10 | 11 | try: 12 | for output in os.listdir(SRC_FLATPAK_VAR_FOLDER_LOCATION): 13 | get_size = os.popen(f"du -s {SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}") 14 | get_size = get_size.read().strip("\t").strip("\n").replace( 15 | f"{SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}", "").replace("\t", "") 16 | 17 | ################################################################################ 18 | # Add to list 19 | # If current folder (output inside var/app) is not higher than X MB 20 | # Add to list to be backup 21 | ################################################################################ 22 | # Add to flatpak_var_size_list KBytes size of the current output (folder inside var/app) 23 | # inside external device 24 | flatpak_var_size_list.append(int(get_size)) 25 | # Add current output (folder inside var/app) to be backup later 26 | flatpak_var_to_be_restore.append(f"{SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}") 27 | 28 | ################################################################################ 29 | # Get flatpak (.local/share/flatpak) folders size 30 | ################################################################################ 31 | # Get .local/share/flatpak size before back up to external 32 | for output in os.listdir(SRC_FLATPAK_LOCAL_FOLDER_LOCATION): 33 | # Get size of flatpak folder inside var/app/ 34 | get_size = os.popen(f"du -s {SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}") 35 | get_size = get_size.read().strip("\t").strip("\n").replace( 36 | f"{SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}", "").replace("\t", "") 37 | 38 | # Add to list to be backup 39 | flatpak_var_size_list.append(int(get_size)) 40 | # Add current output (folder inside var/app) to be backup later 41 | flatpak_local_to_be_restore.append(f"{SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}") 42 | except Exception: 43 | pass 44 | 45 | 46 | if __name__ == '__main__': 47 | pass -------------------------------------------------------------------------------- /src/get_flatpaks_folders_size.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from device_location import device_location 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | 9 | flatpak_var_size_list = [] 10 | flatpak_var_to_be_backup = [] 11 | flatpak_local_to_be_backup = [] 12 | flatpak_local_size_list = [] 13 | 14 | def flatpak_var_size(): 15 | ################################################################################ 16 | # Get flatpak (var/app) folders size 17 | ################################################################################ 18 | for output in os.listdir(SRC_FLATPAK_VAR_FOLDER_LOCATION): # Get folders size before back up to external 19 | get_size = os.popen(f"du -s {SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}").read().strip("\t").strip("\n").replace( 20 | f"{SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}", "").replace("\t", "") 21 | 22 | ################################################################################ 23 | # Add to list 24 | # If current folder (output inside var/app) is not higher than X MB 25 | # Add to list to be backup 26 | ################################################################################ 27 | # Add to flatpak_var_size_list KBytes size of the current output (folder inside var/app) 28 | # inside external device 29 | flatpak_var_size_list.append(int(get_size)) 30 | # Add current output (folder inside var/app) to be backup later 31 | flatpak_var_to_be_backup.append(f"{SRC_FLATPAK_VAR_FOLDER_LOCATION}/{output}") 32 | 33 | # Return sum of all var sizes 34 | return sum(flatpak_var_size_list) 35 | 36 | def flatpak_var_list(): 37 | # Get flapatk var size 38 | flatpak_var_size() 39 | 40 | return flatpak_var_to_be_backup 41 | 42 | def flatpak_local_size(): 43 | try: 44 | ################################################################################ 45 | # Get flatpak (.local/share/flatpak) folders size 46 | ################################################################################ 47 | for output in os.listdir(SRC_FLATPAK_LOCAL_FOLDER_LOCATION): # Get .local/share/flatpak size before back up to external 48 | # Get size of flatpak folder inside var/app/ 49 | get_size = os.popen(f"du -s {SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}") 50 | get_size = get_size.read().strip("\t").strip("\n").replace( 51 | f"{SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}", "").replace("\t", "") 52 | 53 | # Add to list to be backup 54 | flatpak_local_size_list.append(int(get_size)) 55 | # Add current output (folder inside var/app) to be backup later 56 | flatpak_local_to_be_backup.append(f"{SRC_FLATPAK_LOCAL_FOLDER_LOCATION}/{output}") 57 | 58 | # Return sum of all local sizes 59 | return sum(flatpak_local_size_list) 60 | except: 61 | pass 62 | 63 | def flatpak_local_list(): 64 | flatpak_local_size() 65 | 66 | return flatpak_local_to_be_backup 67 | 68 | 69 | if __name__ == '__main__': 70 | pass -------------------------------------------------------------------------------- /src/get_folders_to_be_backup.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def get_folders(): 8 | list_of_folders = [] 9 | list_of_folders_to_return = [] 10 | 11 | # Connect to the SQLite database 12 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 13 | cursor = conn.cursor() 14 | 15 | # Query all keys from the specified table 16 | cursor.execute(f"SELECT key FROM FOLDER") 17 | keys = [row[0] for row in cursor.fetchall()] 18 | 19 | # Close the connection 20 | conn.close() 21 | 22 | for key in keys: 23 | list_of_folders.append(key) 24 | 25 | # Get Backup Folders 26 | for folder in list_of_folders: 27 | folder = str(folder).capitalize() 28 | 29 | # Check folder isUpper or not 30 | if not os.path.exists(f"{HOME_USER}/{folder}"): 31 | folder = folder.lower() 32 | 33 | list_of_folders_to_return.append(folder) 34 | list_of_folders_to_return.sort() 35 | 36 | return list_of_folders_to_return 37 | 38 | def home_folders_size(): 39 | home_folder_to_backup_size_list = [] 40 | 41 | for folder in get_folders(): 42 | try: 43 | # Get folder size 44 | get_size = os.popen(f"du -s {HOME_USER}/{folder}") 45 | get_size = int(get_size.read().strip("\t").strip("\n").replace( 46 | f"{HOME_USER}/{folder}", "").replace("\t", "")) 47 | 48 | # Add to list 49 | home_folder_to_backup_size_list.append(get_size) 50 | except Exception: 51 | pass 52 | 53 | return sum(home_folder_to_backup_size_list) 54 | 55 | def may_create_date_time_folder(): 56 | # Read the include file and process each item's information 57 | with open(MAIN_INI_FILE.include_to_backup(), "r") as f: 58 | lines = f.readlines() 59 | 60 | for i in range(0, len(lines), 5): 61 | try: 62 | filename = lines[i + 0].split(':')[-1].strip() 63 | size_string = lines[i + 1].split(':')[-1].strip() 64 | # size = int(size_string.split()[0]) 65 | location = lines[i + 2].split(':')[-1].strip() 66 | status = lines[i + 3].split(':')[-1].strip() 67 | 68 | ########################################################## 69 | # .MAIN BACKUP 70 | ########################################################## 71 | if status == 'UPDATED': 72 | # Latest date/time with only close file location 73 | # Remove home name 74 | remove_home_name = location.replace(f'{HOME_USER}', ' ').strip() 75 | 76 | # Fx. /Desktop/test.txt 77 | destination_location = f'{MAIN_INI_FILE.time_folder_format()}{remove_home_name}' 78 | 79 | # One is necessary to create date/time folder 80 | return True 81 | 82 | except IndexError: 83 | pass 84 | 85 | return False 86 | 87 | 88 | if __name__ == '__main__': 89 | # print(get_folders()) 90 | pass -------------------------------------------------------------------------------- /src/get_home_folders.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | home_folders_list = [] 5 | 6 | def get_home_folders(): 7 | for folder in GET_HOME_FOLDERS: 8 | if not "." in folder: 9 | home_folders_list.append(folder) 10 | 11 | # Sort list 12 | home_folders_list.sort() 13 | 14 | # Return list 15 | return home_folders_list 16 | 17 | 18 | if __name__ == '__main__': 19 | pass 20 | -------------------------------------------------------------------------------- /src/get_kde_icon_name.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def get_kde_icon_name(): 5 | with open(f"{HOME_USER}/.config/kdeglobals", "r") as read: 6 | read = read.readlines() 7 | 8 | for counter in range(len(read)): 9 | try: 10 | if '[Icons]' in read[counter]: 11 | break 12 | except: 13 | pass 14 | 15 | return read[counter+1].split()[0].replace('Theme=','') 16 | 17 | 18 | if __name__ == '__main__': 19 | pass 20 | -------------------------------------------------------------------------------- /src/get_latest_backup_date.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | all_date_folder_list = [] 7 | 8 | def has_date_folder(): 9 | # Get all dates folders 10 | for date in os.listdir(str(MAIN_INI_FILE.backup_folder_name())): 11 | # Only date folders 12 | if '-' in date: 13 | all_date_folder_list.append(date) 14 | 15 | if all_date_folder_list: 16 | # Has date folder inside 17 | return True 18 | 19 | else: 20 | return False 21 | 22 | def latest_backup_date_label(): 23 | # Has date folder inside 24 | if has_date_folder(): 25 | # Sort list to get the latest 26 | all_date_folder_list.sort( 27 | reverse = True, 28 | key = lambda date: 29 | datetime.strptime(date, "%d-%m-%y")) 30 | 31 | # Get latest backup time 32 | from get_backup_time import get_latest_backup_time 33 | if get_latest_backup_time is not None: 34 | latest_backup = str( 35 | get_latest_backup_time()).replace("-",":") 36 | 37 | # Return 'Today', 'yesterday' or Nothing '' 38 | if not date_timeframe() == '': 39 | return date_timeframe() + latest_backup 40 | 41 | else: 42 | return MAIN_INI_FILE.latest_backup_date() 43 | 44 | else: 45 | # check date timeframe 46 | # Return latest backup to main folder 47 | return date_timeframe() + MAIN_INI_FILE.latest_backup_date() 48 | 49 | def latest_backup_date(): 50 | # Has date folder inside 51 | if has_date_folder(): 52 | # Sort list to get the latest 53 | all_date_folder_list.sort( 54 | reverse=True, 55 | key=lambda 56 | date: datetime.strptime(date, "%d-%m-%y")) 57 | 58 | # No date/time folders found 59 | return all_date_folder_list[0] 60 | 61 | else: 62 | # Return latest 'checked' backup date 63 | ''' 64 | This will return last time a new file was backup to main. 65 | No date/time folder was created yet. 66 | ''' 67 | 68 | # Return latest backup to main folder 69 | return MAIN_INI_FILE.latest_backup_date() 70 | 71 | def date_timeframe(): 72 | todays_full_date = ( 73 | MAIN_INI_FILE.current_date() + '-' + 74 | MAIN_INI_FILE.current_month() + '-' + 75 | MAIN_INI_FILE.current_year()) 76 | 77 | # Date/time 78 | if has_date_folder(): 79 | # Last backup date match with todays date 80 | if todays_full_date in MAIN_INI_FILE.latest_backup_date(): 81 | return 'Today, ' 82 | 83 | # Yesterday 84 | # Last backup date match with yesterdays date 85 | else: 86 | # Check todays date, if last backup was Yesterday, return Yesterday 87 | if int(MAIN_INI_FILE.current_date()) - int(all_date_folder_list[0][:2]) == 1: 88 | # return 'Yesterday,', latest_backup 89 | return 'Yesterday, ' 90 | 91 | # Main 92 | else: 93 | if MAIN_INI_FILE.latest_backup_date() != 'None': 94 | # Latest backup to main match with todays date 95 | if todays_full_date in MAIN_INI_FILE.latest_backup_date(): 96 | return 'Today, ' 97 | 98 | # Check todays date, if last backup was Yesterday, return Yesterday 99 | elif int(MAIN_INI_FILE.current_date()) - int(all_date_folder_list[0][:2]) == 1: 100 | # return 'Yesterday,', latest_backup 101 | return 'Yesterday, ' 102 | 103 | return '' 104 | 105 | if __name__ == '__main__': 106 | pass -------------------------------------------------------------------------------- /src/get_packages_size.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from package_manager import package_manager 3 | from read_ini_file import UPDATEINIFILE 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | 9 | def get_packages_size(): 10 | try: 11 | if package_manager() == DEB_FOLDER_NAME: 12 | application_Size = os.popen(f"du -hs {MAIN_INI_FILE.deb_main_folder()}/") 13 | application_Size = application_Size.read().strip("\t").strip("\n") 14 | application_Size = application_Size.replace(f"{MAIN_INI_FILE.deb_main_folder()}", "").replace("\t", "").replace("/", "") 15 | 16 | elif package_manager() == RPM_FOLDER_NAME: 17 | application_Size = os.popen(f"du -hs {MAIN_INI_FILE.rpm_main_folder()}/") 18 | application_Size = application_Size.read().strip("\t").strip("\n") 19 | application_Size = application_Size.replace(f"{MAIN_INI_FILE.rpm_main_folder()}", "").replace("\t", "").replace("/", "") 20 | 21 | if "M" in application_Size: 22 | return application_Size + "B" 23 | else: 24 | return application_Size 25 | 26 | except: 27 | return None 28 | 29 | 30 | if __name__=='__main__': 31 | pass -------------------------------------------------------------------------------- /src/get_sizes.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from device_location import device_location 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | def get_external_device_max_size(): 9 | # Get external max size 10 | external_max_size = os.popen( 11 | f"df --output=size -h {MAIN_INI_FILE.hd_hd()}") 12 | external_max_size = external_max_size.read().strip()\ 13 | .replace("1K-blocks", "")\ 14 | .replace("Size", "")\ 15 | .replace("\n", "")\ 16 | .replace(" ", "") 17 | 18 | return str(external_max_size) 19 | 20 | def get_external_device_used_size(): 21 | used_space = os.popen( 22 | f'df --output=avail -h {MAIN_INI_FILE.hd_hd()}').read().strip()\ 23 | .replace('1K-blocks', '')\ 24 | .replace('Avail', '')\ 25 | .replace('\n', '')\ 26 | .replace(' ', '') 27 | 28 | return str(used_space) 29 | 30 | def get_external_device_free_size(): 31 | try: 32 | # External free space 33 | available_device_space = os.popen( 34 | f"df --output=avail -B1 {MAIN_INI_FILE.hd_hd()}") 35 | available_device_space = available_device_space.read().strip()\ 36 | .replace("1K-blocks", "")\ 37 | .replace("Avail", "")\ 38 | .replace("\n", "")\ 39 | .replace(" ", "") 40 | 41 | return int(available_device_space) 42 | 43 | except ValueError: 44 | print("Device is probably not connected.") 45 | exit() 46 | 47 | def get_external_device_string_size(device): 48 | # Get external max size 49 | external_max_size=os.popen( 50 | f"df --output=size -h {device}").read().strip().replace( 51 | "1K-blocks", "").replace( 52 | "Size", "").replace( 53 | "\n", "").replace( 54 | " ", "") 55 | 56 | # Get external usded size 57 | used_space = os.popen(f"df --output=used -h {device}") 58 | used_space = used_space.read().strip().replace("1K-blocks", "").replace( 59 | "Used", "").replace("\n", "").replace(" ", "") 60 | 61 | return used_space + "/" + external_max_size 62 | 63 | def get_all_used_backup_device_space(device): 64 | # MEDIA 65 | if device_location(): 66 | used_space = os.popen( 67 | f"df --output=avail -h {MAIN_INI_FILE.hd_hd()}").read().\ 68 | strip().replace( 69 | "1K-blocks", "").replace( 70 | "Avail", "").replace( 71 | "\n", "").replace( 72 | " ", "") 73 | else: 74 | # RUN 75 | used_space = os.popen(f"df --output=avail -h {RUN}/{USERNAME}/{device}").read().\ 76 | strip().replace( 77 | "1K-blocks", "").replace( 78 | "Avail", "").replace( 79 | "\n", "").replace( 80 | " ", "") 81 | 82 | return str(used_space) 83 | 84 | def get_used_backup_space(): 85 | x = get_all_max_backup_device_space() 86 | y = get_external_device_used_size() 87 | value = [] 88 | 89 | # Filter max space 90 | filter1 = [] 91 | for i in x: 92 | if i.isdigit(): 93 | filter1.append(i) 94 | else: 95 | # Add str to value 96 | value.append(i) 97 | 98 | # Filter total devices space 99 | total_device_space = int(''.join(filter1)) 100 | 101 | # Filter used space 102 | filter2 = [] 103 | for i in y: 104 | if i.isdigit(): 105 | filter2.append(i) 106 | 107 | # Filter used device space 108 | used_device_space = int(''.join(filter2)) 109 | 110 | value = ''.join(value) 111 | result = total_device_space - used_device_space 112 | return str(result) + value 113 | 114 | def get_all_max_backup_device_space(): 115 | external_max_size=os.popen(f"df --output=size -h {MAIN_INI_FILE.hd_hd()}").read().strip().replace( 116 | "1K-blocks", "").replace( 117 | "Size", "").replace( 118 | "\n", "").replace( 119 | " ", "") 120 | 121 | return str(external_max_size) 122 | 123 | def needeed_size_to_backup_home(): 124 | global lines 125 | 126 | # Read the file and initialize a total size variable 127 | total_size = 0 128 | 129 | # Read each line from the input file 130 | with open(MAIN_INI_FILE.include_to_backup(), "r") as f: 131 | lines = f.readlines() 132 | for i in range(1, len(lines), 5): 133 | try: 134 | size = int(lines[i].split()[1]) # Extract the size (convert to int) 135 | total_size += size 136 | except (ValueError, IndexError): 137 | pass 138 | 139 | # Conver to GB 140 | gb_value = total_size / 1024**3 141 | 142 | print() 143 | print(f"Total size of all items: {total_size} bytes") 144 | print(f"Total size of all items: {gb_value:.2f} GB") 145 | 146 | return int(total_size) 147 | 148 | def number_of_item_to_backup(): 149 | # Grab "lines" value 150 | needeed_size_to_backup_home() 151 | 152 | try: 153 | count_filename = 0 154 | count_new_file = 0 155 | count_updated_file = 0 156 | with open(MAIN_INI_FILE.include_to_backup(), "r") as f: 157 | for line in f: 158 | # Assuming each entry starts with "Filename:" 159 | if line.startswith("Filename:"): 160 | count_filename += 1 161 | 162 | # New file count 163 | if line.startswith("Status: NEW"): 164 | count_new_file += 1 165 | 166 | # Updated file count 167 | if line.startswith("Status: UPDATED"): 168 | count_updated_file += 1 169 | 170 | print(f'Total items to be backup: {count_filename}') 171 | print(f'NEW Items: {count_new_file}') 172 | print(f'UPDATED Items: {count_updated_file}') 173 | return count_filename 174 | except: 175 | return 0 176 | 177 | def get_directory_size(directory): 178 | total_size = 0 179 | 180 | # Function to recursively calculate total size of a directory 181 | for dirpath, dirnames, filenames in os.walk(directory): 182 | for filename in filenames: 183 | file_path = os.path.join(dirpath, filename) 184 | total_size += os.path.getsize(file_path) 185 | 186 | return total_size 187 | 188 | def get_item_size(item_path): 189 | item_size = 0 190 | 191 | # Add the new item to date, and time folders 192 | if os.path.isdir(item_path): 193 | item_size = get_directory_size(item_path) 194 | elif os.path.isfile(item_path): 195 | item_size = os.path.getsize(item_path) 196 | 197 | try: 198 | # In bytes 199 | return item_size 200 | except UnboundLocalError: 201 | return 0 202 | 203 | 204 | if __name__ == '__main__': 205 | print(get_all_max_backup_device_space()) 206 | pass 207 | -------------------------------------------------------------------------------- /src/get_system_settings_size.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from package_manager import package_manager 3 | from read_ini_file import UPDATEINIFILE 4 | 5 | dummySystemSettingsSizeList=[] 6 | dummy=[] 7 | result=[] 8 | 9 | def get_system_settings_size(): 10 | MAININIFILE=UPDATEINIFILE() 11 | 12 | try: 13 | # Icons size 14 | systemSettingsIcon=os.popen(f"du -hs {MAININIFILE.icon_main_folder()} 2>/dev/null") 15 | systemSettingsIcon=systemSettingsIcon.read().strip("\t") 16 | systemSettingsIcon=systemSettingsIcon.strip("\n") 17 | systemSettingsIcon=systemSettingsIcon.replace(f"{MAININIFILE.icon_main_folder()}", "") 18 | 19 | if systemSettingsIcon != "": 20 | for string in systemSettingsIcon: 21 | if string.isdigit(): 22 | dummy.append(string) 23 | 24 | systemSettingsIcon=''.join(dummy) 25 | dummy.clear() 26 | systemSettingsIcon=int(systemSettingsIcon) 27 | dummySystemSettingsSizeList.append(systemSettingsIcon) 28 | 29 | #################################### 30 | # Plasma 31 | #################################### 32 | # systemSettingsTheme=os.popen(f"du -hs {MAININIFILE.plasma_main_folder()} 2>/dev/null") 33 | # systemSettingsTheme=systemSettingsTheme.read().strip("\t") 34 | # systemSettingsTheme=systemSettingsTheme.strip("\n") 35 | # systemSettingsTheme=systemSettingsTheme.replace(f"{PLASMA_FOLDER_NAME}", "") 36 | 37 | # if systemSettingsTheme != "": 38 | # for string in systemSettingsTheme: 39 | # if string.isdigit(): 40 | # dummy.append(string) 41 | 42 | # systemSettingsTheme=''.join(dummy) 43 | # dummy.clear() 44 | # systemSettingsTheme=int(systemSettingsTheme) 45 | # dummySystemSettingsSizeList.append(systemSettingsTheme) 46 | 47 | #################################### 48 | # GTK Theme 49 | #################################### 50 | systemSettingsTheme=os.popen(f"du -hs {MAININIFILE.gtk_theme_main_folder()} 2>/dev/null") 51 | systemSettingsTheme=systemSettingsTheme.read().strip("\t") 52 | systemSettingsTheme=systemSettingsTheme.strip("\n") 53 | systemSettingsTheme=systemSettingsTheme.replace(f"{GTK_THEME_FOLDER_NAME}", "") 54 | 55 | if systemSettingsTheme != "": 56 | for string in systemSettingsTheme: 57 | if string.isdigit(): 58 | dummy.append(string) 59 | 60 | systemSettingsTheme=''.join(dummy) 61 | dummy.clear() 62 | systemSettingsTheme=int(systemSettingsTheme) 63 | dummySystemSettingsSizeList.append(systemSettingsTheme) 64 | 65 | #################################### 66 | # Aurorae 67 | #################################### 68 | systemSettingsTheme=os.popen(f"du -hs {MAININIFILE.aurorae_main_folder()} 2>/dev/null") 69 | systemSettingsTheme=systemSettingsTheme.read().strip("\t") 70 | systemSettingsTheme=systemSettingsTheme.strip("\n") 71 | systemSettingsTheme=systemSettingsTheme.replace(f"{AURORAEFOLDERNAME}", "") 72 | 73 | if systemSettingsTheme != "": 74 | for string in systemSettingsTheme: 75 | if string.isdigit(): 76 | dummy.append(string) 77 | 78 | systemSettingsTheme=''.join(dummy) 79 | dummy.clear() 80 | systemSettingsTheme=int(systemSettingsTheme) 81 | dummySystemSettingsSizeList.append(systemSettingsTheme) 82 | 83 | if len(dummySystemSettingsSizeList) > 1: 84 | if sum(dummySystemSettingsSizeList) < 1000: 85 | return f"{sum(dummySystemSettingsSizeList)} MB" 86 | else: 87 | if len(dummySystemSettingsSizeList) == 4: 88 | x=sum(dummySystemSettingsSizeList) 89 | 90 | value=0 91 | for count in range(len(str(x))): 92 | #print(str(x)[count]) 93 | result.append(str(x)[count]) 94 | if value == 0: 95 | result.append(".") 96 | value += 1 97 | else: 98 | value += 1 99 | 100 | y=" ".join(result).replace(" ","") 101 | if int(y[3]) > 1: 102 | return f"{y[0]}G" 103 | else: 104 | return f"{y[:3]}G" 105 | 106 | except Exception as error: 107 | print(error) 108 | return "None" 109 | 110 | if __name__ == '__main__': 111 | pass -------------------------------------------------------------------------------- /src/get_users_de.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | USER_DE = os.environ.get(GET_USER_DE).lower().strip() 4 | 5 | def get_user_de(): 6 | if ':' in USER_DE: 7 | return USER_DE.split(':')[1] 8 | else: 9 | return USER_DE 10 | 11 | 12 | if __name__ == '__main__': 13 | pass -------------------------------------------------------------------------------- /src/handle_spaces.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def handle_spaces(string): 5 | string = str(string) 6 | 7 | # Handle spaces 8 | if " " in string: 9 | return string.replace(' ', '\ ') 10 | 11 | else: 12 | return string 13 | 14 | 15 | if __name__ == '__main__': 16 | pass -------------------------------------------------------------------------------- /src/icons/backup_128px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/backup_128px.png -------------------------------------------------------------------------------- /src/icons/backup_150px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/backup_150px.png -------------------------------------------------------------------------------- /src/icons/backup_icon.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/backup_icon.svg -------------------------------------------------------------------------------- /src/icons/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/check.png -------------------------------------------------------------------------------- /src/icons/migration_assistant_212px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/migration_assistant_212px.png -------------------------------------------------------------------------------- /src/icons/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | backup_128px.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/icons/systemtrayiconerror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/systemtrayiconerror.png -------------------------------------------------------------------------------- /src/icons/systemtrayiconrestore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/systemtrayiconrestore.png -------------------------------------------------------------------------------- /src/icons/systemtrayiconrun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/icons/systemtrayiconrun.png -------------------------------------------------------------------------------- /src/ini/config.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ini/config.db -------------------------------------------------------------------------------- /src/make_first_backup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from PySide6.QtCore import Qt, QObject, Signal, Slot 4 | from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QProgressBar, QLabel 5 | from setup import * 6 | from get_folders_to_be_backup import get_folders 7 | 8 | class BackupApp(QMainWindow): 9 | def __init__(self): 10 | super().__init__() 11 | self.setWindowTitle("File Backup App") 12 | self.setGeometry(100, 100, 400, 200) 13 | 14 | self.central_widget = QWidget() 15 | self.setCentralWidget(self.central_widget) 16 | 17 | self.layout = QVBoxLayout() 18 | 19 | self.backup_button = QPushButton("Start Backup") 20 | self.backup_button.clicked.connect(self.start_backup) 21 | self.layout.addWidget(self.backup_button) 22 | 23 | self.progress_bar = QProgressBar() 24 | self.layout.addWidget(self.progress_bar) 25 | 26 | self.file_label = QLabel("Backing up: ") 27 | self.layout.addWidget(self.file_label) 28 | 29 | self.central_widget.setLayout(self.layout) 30 | 31 | 32 | @Slot() 33 | def start_backup(self): 34 | # Get a list of subdirectories to back up 35 | subdirectories = get_folders() 36 | copied_files = 0 37 | #target_folder = "/media/macbook/Backup_Drive/TMB/test" 38 | 39 | for i in subdirectories: 40 | source_folder = os.path.join(HOME_USER, i) 41 | total_files = count_files(source_folder) 42 | 43 | 44 | #for root, dirs, files in os.walk(source_folder): 45 | #for file in files: 46 | #source_path = os.path.join(root, file) 47 | #relative_path = os.path.relpath(source_path, source_folder) 48 | #target_path = os.path.join(target_folder, i, relative_path) 49 | #os.makedirs(os.path.dirname(target_path), exist_ok=True) 50 | 51 | #try: 52 | #shutil.copy(source_path, target_path) 53 | #print(f"Backed up: {source_path}") 54 | #except Exception as e: 55 | #print(f"Error while backing up {source_path}: {e}") 56 | 57 | copied_files += 1 58 | progress = int(copied_files / total_files * 100) 59 | self.progress_bar.setValue(progress) 60 | 61 | def count_files(folder_path): 62 | file_count = 0 63 | for root, dirs, files in os.walk(folder_path): 64 | file_count += len(files) 65 | return file_count 66 | 67 | 68 | if __name__ == "__main__": 69 | app = QApplication([]) 70 | window = BackupApp() 71 | window.show() 72 | app.exec() 73 | -------------------------------------------------------------------------------- /src/next_backup_label.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | MAIN_INI_FILE = UPDATEINIFILE() 5 | 6 | def next_backup_label(): 7 | int_list = [] 8 | 9 | # Current hour + 1 10 | next_backup_time = int(MAIN_INI_FILE.current_hour()) + 1 11 | 12 | # Under 10:00 13 | for i in str(next_backup_time): 14 | int_list.append(i) 15 | 16 | # Add 0 at the begin 17 | if len(int_list) == 1: 18 | int_list.insert(0, '0') 19 | # Join 20 | next_backup_time = ''.join(int_list) 21 | 22 | return f'Today, {str(next_backup_time)}:00' 23 | 24 | 25 | if __name__ == '__main__': 26 | pass -------------------------------------------------------------------------------- /src/notification_massage.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | 8 | def notification_message(message): 9 | MAIN_INI_FILE.set_database_value('INFO', 'current_backing_up', str(message)) 10 | 11 | def notification_message_current_backing_up(message): 12 | MAIN_INI_FILE.set_database_value('INFO', 'saved_notification', str(message)) 13 | 14 | 15 | if __name__ == '__main__': 16 | pass -------------------------------------------------------------------------------- /src/options.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from ui.ui_options import Ui_Options 3 | 4 | 5 | class Options(QWidget): 6 | def __init__(self, parent=None): 7 | super(Options, self).__init__() 8 | self.ui = Ui_Options() 9 | self.ui.setupUi(self) 10 | 11 | def auto_select_stackwidget(self): 12 | # Auto check the first stack button 13 | self.ui.backup_stack_button.setChecked(True) 14 | 15 | 16 | if __name__ == "__main__": 17 | app = QApplication(sys.argv) 18 | 19 | stackedWidget = QStackedWidget() 20 | 21 | main = Options() 22 | 23 | stackedWidget.addWidget(main) 24 | stackedWidget.setCurrentIndex(0) 25 | stackedWidget.setFixedSize(400, 300) 26 | stackedWidget.show() 27 | 28 | sys.exit(app.exec()) 29 | 30 | -------------------------------------------------------------------------------- /src/package_manager.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | 4 | def package_manager(): 5 | user_package_manager = os.popen(GET_USER_PACKAGE_MANAGER).read().strip().lower() 6 | 7 | # Distros 8 | if 'ubuntu' in user_package_manager: 9 | return 'deb' 10 | elif 'debian' in user_package_manager: 11 | return 'deb' 12 | elif 'fedora' in user_package_manager: 13 | return 'rpm' 14 | elif 'opensuse' in user_package_manager: 15 | return 'rpm' 16 | elif 'arch' in user_package_manager: 17 | return 'pacman' 18 | else: 19 | return 'None' 20 | 21 | 22 | if __name__=='__main__': 23 | pass 24 | -------------------------------------------------------------------------------- /src/restore_backup_flatpaks_applications.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from notification_massage import notification_message_current_backing_up 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | async def restore_backup_flatpaks_applications(): 9 | print("Installing flatpaks apps...") 10 | 11 | with open(f"{MAIN_INI_FILE.flatpak_txt_location()}", "r") as read_flatpak_file: 12 | read_flatpak_file = read_flatpak_file.readlines() 13 | 14 | for flatpak in read_flatpak_file: 15 | flatpak = flatpak.strip() 16 | 17 | if flatpak not in read_exclude: 18 | # Install only if flatpak if not in the exclude app list 19 | try: 20 | # Update DB 21 | MAIN_INI_FILE.set_database_value('INFO', 'current_backing_up', f'{flatpak}') 22 | 23 | print(f'Installing: {flatpak}...') 24 | 25 | notification_message_current_backing_up(f'Installing: {flatpak}...') 26 | 27 | # Install them 28 | sub.run( 29 | ["flatpak", "install", "--system", 30 | "--noninteractive", "--assumeyes", "--or-update", 31 | flatpak], stdout=sub.PIPE, stderr=sub.PIPE) 32 | 33 | except Exception as e: 34 | print(e) 35 | pass 36 | 37 | 38 | if __name__ == '__main__': 39 | pass 40 | -------------------------------------------------------------------------------- /src/restore_backup_flatpaks_data.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from notification_massage import notification_message_current_backing_up 4 | from handle_spaces import handle_spaces 5 | 6 | 7 | MAIN_INI_FILE = UPDATEINIFILE() 8 | 9 | async def restore_backup_flatpaks_data(): 10 | print('Restoring flatpaks data...') 11 | 12 | for data in os.listdir(MAIN_INI_FILE.flatpak_var_folder()): 13 | # Handle spaces 14 | data = handle_spaces(data) 15 | 16 | notification_message_current_backing_up(f'Restoring: {data}...') 17 | 18 | # Restore flatpak data (var) folders from external device 19 | src = MAIN_INI_FILE.flatpak_var_folder() + '/' + data 20 | dst = SRC_FLATPAK_VAR_FOLDER_LOCATION 21 | 22 | sub.run( 23 | ['cp', '-rvf', 24 | src, dst]) 25 | 26 | for data in os.listdir(MAIN_INI_FILE.flatpak_local_folder()): 27 | # Handle spaces 28 | data = handle_spaces(data) 29 | 30 | notification_message_current_backing_up(f'Restoring: {data}...') 31 | 32 | # Restore flatpak data (Local) folders from external device 33 | src = MAIN_INI_FILE.flatpak_local_folder() + '/' + data 34 | dst = SRC_FLATPAK_LOCAL_FOLDER_LOCATION 35 | 36 | sub.run( 37 | ['cp', '-rvf', 38 | src, dst]) 39 | 40 | 41 | if __name__ == '__main__': 42 | pass -------------------------------------------------------------------------------- /src/restore_backup_home.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from get_backup_date import get_backup_date 4 | from get_backup_time import get_latest_backup_time 5 | from notification_massage import notification_message_current_backing_up 6 | from handle_spaces import handle_spaces 7 | from create_directory import create_directory 8 | 9 | 10 | MAIN_INI_FILE = UPDATEINIFILE() 11 | 12 | 13 | async def restore_backup_home(): 14 | print("Restoring Home folders...") 15 | 16 | # location = (f'{MAIN_INI_FILE.backup_folder_name()}/'\ 17 | # f'{get_backup_date()[0]}/'\ 18 | # f'{get_latest_backup_time()[0]}/') 19 | 20 | location = MAIN_INI_FILE.main_backup_folder() 21 | 22 | for folder in os.listdir(location): 23 | # EXclude hidden files/folder 24 | if not folder.startswith('.'): 25 | # Handle spaces 26 | folder = handle_spaces(folder) 27 | 28 | print('Restoring:', folder) 29 | 30 | notification_message_current_backing_up( 31 | f'Restoring: {HOME_USER}/{folder}...') 32 | 33 | # If folder folder do not exist, create it 34 | if not os.path.exists(f"{HOME_USER}/{folder}"): 35 | dst = HOME_USER + "/" + folder 36 | 37 | sub.run( 38 | ["mkdir", dst], 39 | stdout=sub.PIPE, 40 | stderr=sub.PIPE) 41 | 42 | # Restore Home folders 43 | # Restore the latest backup 44 | # src = MAIN_INI_FILE.backup_folder_name() + "/" + get_backup_date()[0] + "/" + get_latest_backup_time()[0] + "/" + folder + "/" 45 | 46 | # Source from main backup folder 47 | src = location + '/' + folder + '/' 48 | dst = HOME_USER + '/' + folder + '/' 49 | 50 | print(src) 51 | print(dst) 52 | print() 53 | 54 | # Copy everything from src to dst folder 55 | for i in os.listdir(src): 56 | x = src + i 57 | 58 | sub.run( 59 | ['cp', '-rvf', x, dst], 60 | stdout=sub.PIPE, 61 | stderr=sub.PIPE, 62 | text=True) 63 | 64 | 65 | if __name__ == '__main__': 66 | pass -------------------------------------------------------------------------------- /src/restore_backup_package_applications.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from notification_massage import notification_message_current_backing_up 4 | 5 | 6 | MAIN_INI_FILE = UPDATEINIFILE() 7 | 8 | async def restore_backup_package_applications(): 9 | print("Installing applications packages...") 10 | 11 | try: 12 | with open(MAIN_INI_FILE.exclude_applications_location(), 'r') as read_exclude: 13 | read_exclude = read_exclude.read().split("\n") 14 | except: 15 | pass 16 | 17 | try: 18 | package_manager = MAIN_INI_FILE.get_database_value('INFO', 'packagermanager') 19 | 20 | if package_manager == DEB_FOLDER_NAME: 21 | ################################################################################ 22 | # Restore DEBS 23 | ################################################################################ 24 | for package in os.listdir(MAIN_INI_FILE.deb_main_folder()): 25 | print(f"Installing {MAIN_INI_FILE.deb_main_folder()}/{package}") 26 | 27 | # Install only if package if not in the exclude app list 28 | if package not in read_exclude: 29 | # Install it 30 | command = MAIN_INI_FILE.deb_main_folder() + "/" + package 31 | 32 | sub.run( 33 | ["sudo", "dpkg", "-i", command], 34 | stdout=sub.PIPE, 35 | stderr=sub.PIPE) 36 | 37 | # Update notification 38 | notification_message_current_backing_up( 39 | f'Installing: {package}...') 40 | 41 | # Fix packages installation 42 | sub.run( 43 | ["sudo", "apt", "install", "-f"], 44 | stdout=sub.PIPE, 45 | stderr=sub.PIPE) 46 | 47 | elif package_manager == RPM_FOLDER_NAME: 48 | ################################################################################ 49 | # Restore RPMS 50 | ################################################################################ 51 | for package in os.listdir(MAIN_INI_FILE.rpm_main_folder()): 52 | print(f"Installing {MAIN_INI_FILE.rpm_main_folder()}/{package}") 53 | 54 | # Install only if package if not in the exclude app list 55 | if package not in read_exclude: 56 | # Install rpms applications 57 | command = f"{MAIN_INI_FILE.rpm_main_folder()}/{package}" 58 | 59 | sub.run( 60 | ["sudo", "rpm", "-ivh", "--replacepkgs", command], 61 | stdout=sub.PIPE, 62 | stderr=sub.PIPE) 63 | 64 | # Update notification 65 | notification_message_current_backing_up( 66 | f'Restoring: {package}...') 67 | 68 | except Exception as e: 69 | print(e) 70 | pass 71 | 72 | 73 | if __name__ == '__main__': 74 | pass -------------------------------------------------------------------------------- /src/restore_kde_config.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def restore_kde_config(): 8 | try: 9 | src = MAIN_INI_FILE.kde_config_main_folder() + '/' 10 | dst = HOME_USER + '/.config/' 11 | 12 | print('-----[.CONFIG]-----') 13 | print('From:', src) 14 | print('To:', dst) 15 | 16 | shutil.copytree(src, dst, dirs_exist_ok= True) 17 | except Exception as error: 18 | print(error) 19 | # Save error log 20 | # MAIN_INI_FILE.report_error(error) 21 | 22 | 23 | if __name__ == '__main__': 24 | pass 25 | -------------------------------------------------------------------------------- /src/restore_kde_local_share.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def restore_kde_local_share(): 8 | try: 9 | src = MAIN_INI_FILE.kde_local_share_main_folder() + '/' 10 | dst = os.path.join(HOME_USER, '.local/share/') 11 | 12 | print('-----[.LOCAL/SHARE]-----') 13 | print('From:', src) 14 | print('To:', dst) 15 | 16 | shutil.copytree(src, dst, dirs_exist_ok = True) 17 | except Exception as error: 18 | print(error) 19 | # Save error log 20 | MAIN_INI_FILE.report_error(error) 21 | 22 | 23 | if __name__ == '__main__': 24 | pass 25 | -------------------------------------------------------------------------------- /src/restore_kde_share_config.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | 4 | 5 | MAIN_INI_FILE = UPDATEINIFILE() 6 | 7 | def restore_kde_share_config(): 8 | try: 9 | src = MAIN_INI_FILE.kde_share_config_main_folder() 10 | dst = os.path.join(HOME_USER, '.kde/share/') 11 | 12 | print('-----[.KDE/SHARE]-----') 13 | print('From:', src) 14 | print('To:', dst) 15 | 16 | shutil.copytree(src, dst, dirs_exist_ok= True) 17 | except Exception as error: 18 | print(error) 19 | # Save error log 20 | MAIN_INI_FILE.report_error(error) 21 | 22 | 23 | if __name__ == '__main__': 24 | pass 25 | -------------------------------------------------------------------------------- /src/save_info.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | from read_ini_file import UPDATEINIFILE 3 | from package_manager import package_manager 4 | from get_users_de import get_user_de 5 | from device_location import device_location 6 | 7 | 8 | MAIN_INI_FILE = UPDATEINIFILE() 9 | 10 | 11 | def save_info(device): 12 | # .deb 13 | if DEB_FOLDER_NAME in package_manager(): 14 | MAIN_INI_FILE.set_database_value( 15 | 'INFO', 'packageManager', DEB_FOLDER_NAME) 16 | 17 | # .rpm 18 | elif RPM_FOLDER_NAME in package_manager(): 19 | MAIN_INI_FILE.set_database_value( 20 | 'INFO', 'packageManager', RPM_FOLDER_NAME) 21 | 22 | # Update db 23 | MAIN_INI_FILE.set_database_value('INFO', 'os', get_user_de()) 24 | 25 | # Users OS language 26 | # config.set('INFO', 'language', f'{str(system_language())}') 27 | 28 | # Device location 29 | if device_location(): 30 | MAIN_INI_FILE.set_database_value( 31 | 'EXTERNAL', 'hd', f'{MEDIA}/{USERNAME}/{device}') 32 | 33 | elif not device_location(): 34 | MAIN_INI_FILE.set_database_value( 35 | 'EXTERNAL', 'hd', f'{RUN}/{USERNAME}/{device}') 36 | 37 | # External name 38 | MAIN_INI_FILE.set_database_value( 39 | 'EXTERNAL', 'name', device) 40 | 41 | 42 | if __name__ == '__main__': 43 | pass -------------------------------------------------------------------------------- /src/screenshots/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/screenshots/img_3.png -------------------------------------------------------------------------------- /src/screenshots/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/screenshots/img_4.png -------------------------------------------------------------------------------- /src/stylesheet.py: -------------------------------------------------------------------------------- 1 | # from setup import * 2 | 3 | # Font 4 | MAIN_FONT = "Ubuntu" 5 | titleFontSize = 10 6 | titleFontSizeCompact = 8 7 | 8 | temperatureFont = "Ubuntu" 9 | temperatureFontSize = 22 10 | temperatureSmallFontSize = 9 11 | 12 | # Button 13 | BUTTONHEIGHT_SIZE = 24 14 | BUTTON_FONT_SIZE = 10 15 | 16 | # Migration Assistant 17 | MIGRATION_ASSISTANT_TITLE = 28 18 | 19 | FONT_SIZE_11PX = 11 20 | fontSize24px = 24 21 | 22 | boldText = (""" 23 | font-weight: bold; 24 | border:transparent; 25 | background-color:transparent; 26 | color:white; 27 | """) 28 | 29 | boldTextBlack = (""" 30 | font-weight: bold; 31 | border:transparent; 32 | background-color:transparent; 33 | color:black; 34 | """) 35 | 36 | newsBoldText = (""" 37 | color:rgb(247,63,95); 38 | font-weight: bold; 39 | border:transparent; 40 | background-color:transparent; 41 | """) 42 | 43 | normalText = (""" 44 | border:transparent; 45 | background-color:transparent; 46 | color:white; 47 | """) 48 | 49 | applicationBackgroundBox = (""" 50 | background-color:white; 51 | color:black; 52 | border:0px; 53 | """) 54 | 55 | applicationBackgroundBoxDark = (""" 56 | background-color:red; 57 | border-right:1px solid rgba(14,14,14,0.1); 58 | """) 59 | 60 | separetorLine = (""" 61 | border-top:1px solid rgba(14,14,14,0.1); 62 | """) 63 | 64 | separetorLineDark = (""" 65 | border-top:1px solid rgba(110, 109, 112, 1); 66 | """) 67 | 68 | separetorLineLeftbackground = (""" 69 | border-right:1px solid rgba(14,14,14,0.1); 70 | """) 71 | 72 | separetorLineLeftbackgroundDark = (""" 73 | border-right:1px solid rgba(110, 109, 112, 1); 74 | """) 75 | 76 | timeBox = ( 77 | """ 78 | border-color: transparent; 79 | border:1px solid rgba(14,14,14,0.2); 80 | border-radius:4px; 81 | """) 82 | 83 | leftBackgroundColorStylesheet = ( 84 | """ 85 | background-color:rgba(240, 241, 243, 1); 86 | border-right:1px solid rgba(14,14,14,0.1); 87 | """) 88 | 89 | leftBackgroundColorStylesheetDark = ( 90 | """ 91 | background-color:rgba(45, 45, 45, 1); 92 | border-right:1px solid rgba(14,14,14,0.1); 93 | """) 94 | 95 | buttonStylesheet = ( 96 | "QPushButton" 97 | "{" 98 | "border-radius:6px;" 99 | "background-color:rgb(255,255,255);" 100 | "border:1px solid rgba(14,14,14,0.2);" 101 | "color:black;" 102 | "}" 103 | "QPushButton:hover" 104 | "{" 105 | "background-color:rgba(245,245,245,1);" 106 | "}" 107 | "QPushButton:disabled" 108 | "{" 109 | "background-color:rgb(255,255,255);" 110 | "color:rgba(223,222,223,1);" 111 | "border:0px;" 112 | "}" 113 | "QPushButton:checked" 114 | "{" 115 | "background-color:rgba(213,213,213,1);" 116 | "}") 117 | 118 | buttonStylesheetDark = ( 119 | "QPushButton" 120 | "{" 121 | "border-radius:6px;" 122 | "background-color:rgba(110, 109, 112, 1);" 123 | "border:1px solid rgba(14,14,14,0.2);" 124 | "color:rgba(223, 222, 223, 1);" 125 | "}" 126 | "QPushButton:hover" 127 | "{" 128 | "background-color:rgba(76,75,78,1);" 129 | "}" 130 | "QPushButton:disabled " 131 | "{" 132 | "background-color:rgba(69, 69, 70, 1);" 133 | "color:rgba(99, 99, 99, 1);" 134 | "}") 135 | 136 | useDiskButtonStylesheet = ( 137 | "QPushButton" 138 | "{" 139 | "border-radius:6px;" 140 | "background-color:rgba(75,145,247,1);" 141 | "border:1px solid rgba(14,14,14,0.2);" 142 | "color:rgba(255, 255, 255, 1);" 143 | "}" 144 | "QPushButton:hover" 145 | "{" 146 | "background-color:rgba(76,75,78,1);" 147 | "color:rgba(255, 255, 255,1);" 148 | "}" 149 | "QPushButton:disabled " 150 | "{" 151 | "background-color:rgb(255,255,255);" 152 | "color:rgba(223,222,223,1);" 153 | "border:0px;" 154 | "}") 155 | 156 | availableDeviceButtonStylesheet = ( 157 | "QPushButton" 158 | "{" 159 | "border-radius:6px;" 160 | "background-color:rgb(255,255,255);" 161 | "border:1px solid rgba(14,14,14,0.2);" 162 | "color:black;" 163 | "padding-left:45px;" 164 | "text-align:left;" 165 | "}" 166 | "QPushButton:hover" 167 | "{" 168 | "background-color:rgba(245,245,245,1);" 169 | "}" 170 | "QPushButton:disabled" 171 | "{" 172 | "background-color:rgb(255,255,255);" 173 | "color:rgba(223,222,223,1);" 174 | "border:0px;" 175 | "}" 176 | "QPushButton:checked" 177 | "{" 178 | "background-color:rgba(213,213,213,1);" 179 | "}") 180 | 181 | availableDeviceButtonStylesheetDark = ( 182 | "QPushButton" 183 | "{" 184 | "border-radius:6px;" 185 | "background-color:rgba(110, 109, 112, 1);" 186 | "border:1px solid rgba(14,14,14,0.2);" 187 | "color:white;" 188 | "padding-left:45px;" 189 | "text-align:left;" 190 | "}" 191 | "QPushButton:hover" 192 | "{" 193 | "background-color:rgba(76,75,78,1);" 194 | "}" 195 | "QPushButton:disabled" 196 | "{" 197 | "background-color:rgb(255,255,255);" 198 | "color:rgba(223,222,223,1);" 199 | "border:0px;" 200 | "}" 201 | "QPushButton:checked" 202 | "{" 203 | "background-color:rgba(37, 37, 37, 1);" 204 | "border:1px solid rgba(98, 98, 98, 1);" 205 | "}") 206 | 207 | externalWindowbackgroundStylesheet = ( 208 | "QWidget" 209 | "{" 210 | "background-color:white;" 211 | "border:1px solid rgba(14,14,14,0.1);" 212 | "border-radius: 8px;" 213 | "}") 214 | 215 | externalWindowbackgroundStylesheetDark = ( 216 | "QWidget" 217 | "{" 218 | "background-color:rgba(69, 69, 70, 1);" 219 | "border:1px solid rgba(14,14,14,0.1);" 220 | "border-radius: 8px;" 221 | "color:white;" 222 | "}") 223 | 224 | # WEATHER WIDGETS COLOR 225 | clouds = (""" 226 | background-color:rgb(208,204,204); 227 | border-radius:9px; 228 | border:0px solid rgba(51,51,51,1); 229 | """) 230 | 231 | transparentBackground = (""" 232 | background-color:0px; 233 | border-radius:0px; 234 | border:0px solid rgba(51,51,51,1); 235 | """) 236 | 237 | -------------------------------------------------------------------------------- /src/test/pgbar.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PySide6.QtCore import QTimer 3 | from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QProgressBar 4 | 5 | 6 | class Window(QWidget): 7 | def __init__(self, *args, **kwargs): 8 | super(Window, self).__init__(*args, **kwargs) 9 | self.resize(800, 600) 10 | layout = QVBoxLayout(self) 11 | # layout.addWidget(ProgressBar(self, minimum=0, maximum=100)) 12 | layout.addWidget(QProgressBar(self, minimum=0, maximum=0)) 13 | # layout.addWidget(ProgressBar(self, minimum=0, maximum=100, textVisible=False)) 14 | # layout.addWidget(ProgressBar(self, minimum=0, maximum=0, textVisible=False)) 15 | # layout.addWidget(ProgressBar(self, minimum=0, maximum=100, textVisible=False)) 16 | # layout.addWidget(ProgressBar(self, minimum=0, maximum=0, textVisible=False)) 17 | 18 | if __name__ == "__main__": 19 | app = QApplication(sys.argv) 20 | w = Window() 21 | w.show() 22 | sys.exit(app.exec()) 23 | -------------------------------------------------------------------------------- /src/test/preview_img.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PySide6.QtWidgets import QApplication, QMainWindow, QTreeView, QFileSystemModel, QVBoxLayout, QWidget, QLabel 4 | from PySide6.QtGui import QPixmap, QImageReader, QImage 5 | from PySide6.QtCore import Qt 6 | 7 | class FileManager(QMainWindow): 8 | def __init__(self): 9 | super().__init__() 10 | 11 | self.setWindowTitle("File Manager") 12 | self.setGeometry(100, 100, 800, 600) 13 | 14 | self.initUI() 15 | 16 | def initUI(self): 17 | layout = QVBoxLayout() 18 | 19 | self.model = QFileSystemModel() 20 | self.model.setRootPath(os.path.expanduser("~")) 21 | self.tree_view = QTreeView() 22 | self.tree_view.setModel(self.model) 23 | self.tree_view.setRootIndex(self.model.index(os.path.expanduser("~"))) 24 | self.tree_view.selectionModel().currentChanged.connect(self.preview_file) 25 | 26 | self.image_label = QLabel() 27 | self.image_label.setAlignment(Qt.AlignCenter) 28 | 29 | self.splitter = QWidget() 30 | splitter_layout = QVBoxLayout() 31 | splitter_layout.addWidget(self.tree_view) 32 | splitter_layout.addWidget(self.image_label) 33 | self.splitter.setLayout(splitter_layout) 34 | 35 | layout.addWidget(self.splitter) 36 | 37 | central_widget = QWidget() 38 | central_widget.setLayout(layout) 39 | self.setCentralWidget(central_widget) 40 | 41 | def resize_image(self, pixmap, max_size): 42 | if pixmap.width() > max_size or pixmap.height() > max_size: 43 | pixmap = pixmap.scaled(max_size, max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) 44 | return pixmap 45 | 46 | def preview_file(self, current, previous): 47 | file_path = self.model.filePath(current) 48 | print(current) 49 | print(previous) 50 | print(file_path) 51 | 52 | if os.path.isfile(file_path) and file_path.lower().endswith((".png", ".jpg", ".jpeg", ".gif")): 53 | image_reader = QImageReader(file_path) 54 | pixmap = QPixmap.fromImageReader(image_reader) 55 | max_size = 300 # Set your maximum image size here 56 | pixmap = self.resize_image(pixmap, max_size) 57 | self.image_label.setPixmap(pixmap) 58 | else: 59 | self.image_label.clear() 60 | 61 | def main(): 62 | app = QApplication(sys.argv) 63 | file_manager = FileManager() 64 | file_manager.show() 65 | sys.exit(app.exec_()) 66 | 67 | if __name__ == "__main__": 68 | main() 69 | -------------------------------------------------------------------------------- /src/test/preview_txt.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PySide6.QtWidgets import QApplication, QMainWindow, QTreeView, QFileSystemModel, QVBoxLayout, QWidget, QTextBrowser 4 | from PySide6.QtCore import Qt 5 | from PySide6.QtGui import QTextCursor 6 | 7 | class FileManager(QMainWindow): 8 | def __init__(self): 9 | super().__init__() 10 | 11 | self.setWindowTitle("File Manager") 12 | self.setGeometry(100, 100, 800, 600) 13 | 14 | self.initUI() 15 | 16 | def initUI(self): 17 | layout = QVBoxLayout() 18 | 19 | self.model = QFileSystemModel() 20 | self.model.setRootPath(os.path.expanduser("~")) 21 | self.tree_view = QTreeView() 22 | self.tree_view.setModel(self.model) 23 | self.tree_view.setRootIndex(self.model.index(os.path.expanduser("~"))) 24 | self.tree_view.selectionModel().currentChanged.connect(self.preview_file) 25 | 26 | self.text_browser = QTextBrowser() 27 | 28 | self.splitter = QWidget() 29 | splitter_layout = QVBoxLayout() 30 | splitter_layout.addWidget(self.tree_view) 31 | splitter_layout.addWidget(self.text_browser) 32 | self.splitter.setLayout(splitter_layout) 33 | 34 | layout.addWidget(self.splitter) 35 | 36 | central_widget = QWidget() 37 | central_widget.setLayout(layout) 38 | self.setCentralWidget(central_widget) 39 | 40 | def preview_file(self, current, previous): 41 | file_path = self.model.filePath(current) 42 | 43 | if os.path.isfile(file_path): 44 | with open(file_path, "r") as file: 45 | content = file.read() 46 | self.text_browser.setPlainText(content) 47 | self.text_browser.moveCursor(QTextCursor.Start) 48 | 49 | def main(): 50 | app = QApplication(sys.argv) 51 | file_manager = FileManager() 52 | file_manager.show() 53 | sys.exit(app.exec_()) 54 | 55 | if __name__ == "__main__": 56 | main() 57 | -------------------------------------------------------------------------------- /src/test/preview_txt_img.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PySide6.QtCore import Qt, QDir, QSize 4 | from PySide6.QtGui import QIcon, QPixmap, QImageReader, QImage 5 | from PySide6.QtWidgets import QApplication, QMainWindow, QListView, QVBoxLayout, QWidget, QLabel, QFileDialog, QFileSystemModel 6 | 7 | class FileManager(QMainWindow): 8 | def __init__(self): 9 | super().__init__() 10 | 11 | self.setWindowTitle("File Manager") 12 | self.setGeometry(100, 100, 800, 600) 13 | 14 | self.central_widget = QWidget(self) 15 | self.setCentralWidget(self.central_widget) 16 | 17 | self.layout = QVBoxLayout() 18 | self.central_widget.setLayout(self.layout) 19 | 20 | self.file_list_view = QListView() 21 | self.layout.addWidget(self.file_list_view) 22 | 23 | self.file_list_view.setIconSize(QSize(64, 64)) 24 | self.file_list_view.setViewMode(QListView.IconMode) 25 | self.file_list_view.setResizeMode(QListView.Adjust) 26 | self.file_list_view.setSelectionMode(QListView.SingleSelection) 27 | self.file_list_view.setSpacing(10) 28 | 29 | self.file_list_view.clicked.connect(self.show_preview) 30 | 31 | self.preview_label = QLabel() 32 | self.layout.addWidget(self.preview_label) 33 | 34 | self.load_downloads_folder() 35 | 36 | def load_downloads_folder(self): 37 | downloads_path = QDir.homePath() + "/Documents" 38 | self.model = QFileSystemModel() 39 | self.model.setRootPath(downloads_path) 40 | self.file_list_view.setModel(self.model) 41 | self.file_list_view.setRootIndex(self.model.index(downloads_path)) 42 | 43 | def show_preview(self, index): 44 | file_info = self.model.fileInfo(index) 45 | file_path = file_info.filePath() 46 | 47 | if file_info.isDir(): 48 | self.preview_label.clear() 49 | else: 50 | mime_type = QImageReader.imageFormat(file_path) 51 | if mime_type: 52 | pixmap = QPixmap(file_path) 53 | self.preview_label.setPixmap(pixmap.scaledToWidth(300)) 54 | else: 55 | self.preview_label.clear() 56 | 57 | def main(): 58 | app = QApplication(sys.argv) 59 | file_manager = FileManager() 60 | file_manager.show() 61 | sys.exit(app.exec_()) 62 | 63 | if __name__ == "__main__": 64 | main() 65 | -------------------------------------------------------------------------------- /src/test/previw_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PySide6 import QtCore, QtWidgets, QtGui 4 | from PySide6.QtCore import ( 5 | Qt, QSize, QRect, QPropertyAnimation, 6 | QEasingCurve, QPoint, QSocketNotifier,QDir) 7 | from PySide6.QtGui import (QFont, QPixmap , QIcon, QMovie, QAction, 8 | QPalette, QColor,QCursor,QImage,QImageReader,QTextCursor,QScreen,QGuiApplication) 9 | from PySide6.QtWidgets import (QMainWindow, QWidget, QApplication, 10 | QPushButton, QLabel, QCheckBox, QLineEdit, 11 | QWidget, QFrame, QGridLayout, QHBoxLayout, 12 | QVBoxLayout, QMessageBox, QRadioButton, 13 | QScrollArea, QSpacerItem, QSizePolicy, 14 | QSpinBox, QComboBox, QGraphicsBlurEffect, 15 | QSystemTrayIcon, QMenu, QStackedWidget,QDialog, 16 | QListView,QFileSystemModel,QTextBrowser) 17 | 18 | 19 | class PreviewWindow(QDialog): 20 | def __init__(self, parent=None): 21 | super().__init__(parent) 22 | self.setWindowTitle("Preview") 23 | self.setModal(True) 24 | self.setWindowFlag(Qt.FramelessWindowHint) 25 | 26 | self.preview_label = QLabel(self) 27 | self.text_browser = QTextBrowser() 28 | self.layout = QVBoxLayout(self) 29 | 30 | self.layout.addWidget(self.preview_label) 31 | self.layout.addWidget(self.text_browser) 32 | 33 | def set_preview(self, pixmap): 34 | self.preview_label.setPixmap(pixmap) 35 | 36 | def keyPressEvent(self, event): 37 | if event.key() == Qt.Key_Return: 38 | self.close() 39 | 40 | class FileManager(QMainWindow): 41 | def __init__(self): 42 | super().__init__() 43 | self.loc = [] 44 | self.opened = False 45 | 46 | self.setWindowTitle("File Manager") 47 | self.setGeometry(100, 100, 800, 600) 48 | 49 | self.central_widget = QWidget(self) 50 | self.setCentralWidget(self.central_widget) 51 | 52 | self.layout = QVBoxLayout() 53 | self.central_widget.setLayout(self.layout) 54 | 55 | self.file_list_view = QListView() 56 | self.file_list_view.setWordWrap(True) 57 | self.layout.addWidget(self.file_list_view) 58 | 59 | self.file_list_view.setIconSize(QSize(64, 64)) 60 | self.file_list_view.setViewMode(QListView.IconMode) 61 | self.file_list_view.setResizeMode(QListView.Adjust) 62 | self.file_list_view.setSelectionMode(QListView.MultiSelection) 63 | self.file_list_view.setSpacing(10) 64 | 65 | self.file_list_view.clicked.connect(self.selected_item) 66 | self.file_list_view.viewport().installEventFilter(self) 67 | 68 | self.preview_window = None 69 | 70 | self.load_downloads_folder() 71 | 72 | def load_downloads_folder(self): 73 | 74 | # downloads_path = QDir.homePath() + "/Downloads" 75 | downloads_path = "/media/geovane/" 76 | self.model = QFileSystemModel() 77 | self.model.setRootPath(downloads_path) 78 | self.file_list_view.setModel(self.model) 79 | self.file_list_view.setRootIndex(self.model.index(downloads_path)) 80 | 81 | def selected_item(self, index): 82 | self.image_type = ['png', 'jpg', 'jpeg', 'webp', 'svg', 'pdf'] 83 | self.text_type = ['txt', 'py', 'cpp', 'h'] 84 | 85 | file_info = self.model.fileInfo(index) 86 | file_path = file_info.filePath() 87 | 88 | print(file_path) 89 | 90 | if file_path.split(".")[-1] in self.image_type or file_path.split(".")[-1] in self.text_type: 91 | if file_path in self.loc: 92 | self.loc.remove(file_path) 93 | else: 94 | self.loc.append(file_path) 95 | else: 96 | self.loc.clear() 97 | 98 | def keyPressEvent(self, event): 99 | if event.key() == Qt.Key_Return: 100 | # Has value inside list 101 | if self.loc: 102 | last_item = self.loc[-1] 103 | last_item_extension = str(last_item).split(".")[-1] 104 | 105 | if not self.preview_window: 106 | self.preview_window = PreviewWindow(self) 107 | 108 | if last_item_extension in self.image_type: 109 | pixmap = QPixmap(self.loc[-1]) 110 | 111 | self.preview_window.text_browser.setFixedSize(0, 0) 112 | self.preview_window.text_browser.clear() 113 | 114 | self.preview_window.set_preview(pixmap.scaledToWidth(round(900/2))) 115 | self.preview_window.show() 116 | 117 | elif last_item_extension in self.text_type: 118 | with open(last_item, "r") as file: 119 | self.preview_window.preview_label.clear() 120 | 121 | self.preview_window.text_browser.setFixedSize(round(900/2), round(1080/2)) 122 | self.preview_window.text_browser.adjustSize() 123 | self.preview_window.text_browser.setPlainText(file.read()) 124 | self.preview_window.text_browser.moveCursor(QTextCursor.Start) 125 | 126 | # Open preview 127 | self.preview_window.show() 128 | 129 | def main(): 130 | app = QApplication(sys.argv) 131 | file_manager = FileManager() 132 | file_manager.show() 133 | sys.exit(app.exec()) 134 | 135 | 136 | if __name__ == "__main__": 137 | main() 138 | -------------------------------------------------------------------------------- /src/test/sql_guides.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | from pathlib import Path 3 | 4 | APP_NAME_CLOSE = "timemachine" 5 | HOME_USER = str(Path.home()) 6 | SRC_USER_CONFIG_DB = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/ini/config.db" 7 | 8 | 9 | def connect_to_database(): 10 | # Connect to the SQLite database 11 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 12 | cursor = conn.cursor() 13 | 14 | def update_database(section, key, value): 15 | # Connect to the SQLite database 16 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 17 | cursor = conn.cursor() 18 | 19 | cursor.execute(''' 20 | UPDATE app_settings 21 | SET value = ? 22 | WHERE section = ? AND key = ? 23 | ''', (value, section, key)) 24 | 25 | # Commit changes and close the connection 26 | conn.commit() 27 | conn.close() 28 | 29 | def get_ini_folders(section, key, value): 30 | # Insert or replace data into the table 31 | cursor.execute(f''' 32 | INSERT OR REPLACE INTO {section} ({key}, {value}) 33 | VALUES (?, ?) 34 | ''', (key, value)) 35 | 36 | # Commit changes and close the connection 37 | conn.commit() 38 | conn.close() 39 | 40 | 41 | def create_table(table): 42 | # Connect to the SQLite database 43 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 44 | cursor = conn.cursor() 45 | 46 | # Create table STATUS 47 | cursor.execute(f''' 48 | CREATE TABLE IF NOT EXISTS {table} ( 49 | key TEXT PRIMARY KEY, 50 | value TEXT 51 | ) 52 | ''') 53 | 54 | def add_to_table(table, key, value): 55 | # Connect to the SQLite database 56 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 57 | cursor = conn.cursor() 58 | 59 | cursor.execute(f''' 60 | INSERT OR REPLACE INTO {table} (key, value) 61 | VALUES (?, ?) 62 | ''', (f'{key}', f'{value}')) 63 | 64 | conn.commit() 65 | # conn.close() 66 | 67 | def print_status_data(table): 68 | # Connect to the SQLite database 69 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 70 | cursor = conn.cursor() 71 | 72 | # Execute a query to fetch all rows from the table 73 | query = f"SELECT * FROM {table}" 74 | cursor.execute(query) 75 | 76 | # Fetch all rows 77 | rows = cursor.fetchall() 78 | 79 | # Fetch column names 80 | column_names = [description[0] for description in cursor.description] 81 | 82 | # Close the connection 83 | conn.close() 84 | 85 | # Print the keys and values for each row 86 | for row in rows: 87 | print("Row:") 88 | for col_name, value in zip(column_names, row): 89 | print(f"{col_name}: {value}")(f"{column_names}: {value}") 90 | 91 | def clear_db(): 92 | if os.path.exists(SRC_USER_CONFIG_DB): 93 | os.remove(SRC_USER_CONFIG_DB) 94 | 95 | def remove_key(table, key): 96 | # Connect to the SQLite database 97 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 98 | cursor = conn.cursor() 99 | 100 | # Call the function to print 'STATUS' data 101 | # Key to remove 102 | 103 | # Delete the key-value pair from the 'STATUS' table 104 | cursor.execute(f'DELETE FROM {table} WHERE key = ?', (f'{key}',)) 105 | 106 | # Commit changes and close the connection 107 | conn.commit() 108 | conn.close() 109 | 110 | 111 | def print_all_tables_data(): 112 | # Connect to the SQLite database 113 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 114 | cursor = conn.cursor() 115 | 116 | # Get the list of all table names in the database 117 | cursor.execute("SELECT name FROM sqlite_master WHERE type='table'") 118 | table_names = cursor.fetchall() 119 | 120 | # Loop through each table 121 | for table_name in table_names: 122 | table_name = table_name[0] # Extract the table name from the tuple 123 | 124 | print(f"Table: {table_name}") 125 | 126 | # Query all data from the current table 127 | cursor.execute(f"SELECT key, value FROM {table_name}") 128 | table_data = cursor.fetchall() 129 | 130 | # Print data for the current table 131 | for key, value in table_data: 132 | print(f" {key}: {value}") 133 | 134 | # Close the connection 135 | conn.close() 136 | 137 | def get_database_value(table, key): 138 | # Connect to the SQLite database 139 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 140 | cursor = conn.cursor() 141 | 142 | # Query the value from the specified table and key 143 | cursor.execute(f"SELECT value FROM {table} WHERE key = ?", (key,)) 144 | result = cursor.fetchone() 145 | 146 | # Close the connection 147 | conn.close() 148 | 149 | if result: 150 | return result[0] # The value is the first element in the result tuple 151 | else: 152 | return None # Return None if the key doesn't exist 153 | 154 | # create_table('RESTORE') 155 | # add_to_table('RESTORE', 'system_settings', 'False') 156 | # print_status_data('RESTORE') 157 | # print(get_database_value('RESTORE', 'applications_packages')) 158 | print(print_all_tables_data()) 159 | 160 | # True 161 | # False 162 | # None 163 | def get_keys_from_table(): 164 | # Connect to the SQLite database 165 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 166 | cursor = conn.cursor() 167 | 168 | # Query all keys from the specified table 169 | cursor.execute(f"SELECT key FROM RESTORE") 170 | keys = [row[0] for row in cursor.fetchall()] 171 | 172 | # Close the connection 173 | conn.close() 174 | 175 | 176 | for key in keys: 177 | print(key) 178 | 179 | # get_keys_from_table() 180 | 181 | # import sqlite3 182 | # import configparser 183 | 184 | # # Load INI data 185 | # config = configparser.ConfigParser() 186 | # config.read('config.ini') 187 | 188 | # # Connect to the SQLite database 189 | # conn = sqlite3.connect('config.db') 190 | # cursor = conn.cursor() 191 | 192 | # # Create a table to store the INI data 193 | # cursor.execute(''' 194 | # CREATE TABLE IF NOT EXISTS config ( 195 | # section TEXT, 196 | # key TEXT, 197 | # value TEXT 198 | # ) 199 | # ''') 200 | 201 | # # Insert INI data into the database 202 | # for section in config.sections(): 203 | # for key, value in config.items(section): 204 | # cursor.execute(''' 205 | # INSERT INTO config (section, key, value) 206 | # VALUES (?, ?, ?) 207 | # ''', (section, key, value)) 208 | 209 | # # Commit changes and close the connection 210 | # conn.commit() 211 | # conn.close() 212 | 213 | # # ################################# 214 | # # Connect to the SQLite database 215 | # conn = sqlite3.connect('config.db') 216 | # cursor = conn.cursor() 217 | 218 | # # Query the database for the value of 'unfinished_backup' in the 'STATUS' section 219 | # section = 'STATUS' 220 | # key = 'unfinished_backup' 221 | 222 | # cursor.execute(''' 223 | # SELECT value 224 | # FROM config 225 | # WHERE section = ? AND key = ? 226 | # ''', (section, key)) 227 | 228 | 229 | # print(cursor.fetchone()[0]) 230 | 231 | # # Close the connection 232 | # conn.close() 233 | 234 | -------------------------------------------------------------------------------- /src/test/test_feedback.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from PySide6.QtCore import Qt, QProcess, QTextStream 3 | from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QTextEdit 4 | 5 | class UpdateApp(QMainWindow): 6 | def __init__(self): 7 | super().__init__() 8 | 9 | self.init_ui() 10 | 11 | def init_ui(self): 12 | self.setWindowTitle('Update App') 13 | self.setGeometry(100, 100, 600, 400) 14 | 15 | self.central_widget = QWidget(self) 16 | self.setCentralWidget(self.central_widget) 17 | 18 | self.layout = QVBoxLayout(self.central_widget) 19 | 20 | self.update_button = QPushButton('Run sudo apt update', self) 21 | self.update_button.clicked.connect(self.run_update) 22 | self.layout.addWidget(self.update_button) 23 | 24 | self.command_output = QTextEdit(self) 25 | self.command_output.setReadOnly(True) 26 | self.layout.addWidget(self.command_output) 27 | 28 | self.process = QProcess(self) 29 | self.process.setProcessChannelMode(QProcess.MergedChannels) 30 | self.process.readyReadStandardOutput.connect(self.handle_output) 31 | 32 | def run_update(self): 33 | self.process.start('sudo', ['apt', 'update']) 34 | self.update_button.setDisabled(True) 35 | 36 | def handle_output(self): 37 | output_stream = QTextStream(self.process) 38 | while not output_stream.atEnd(): 39 | line = output_stream.readLine() 40 | self.command_output.append(line) 41 | 42 | def closeEvent(self, event): 43 | # Make sure to kill the process if the application is closed. 44 | if self.process.state() == QProcess.Running: 45 | self.process.kill() 46 | event.accept() 47 | 48 | if __name__ == '__main__': 49 | app = QApplication(sys.argv) 50 | window = UpdateApp() 51 | window.show() 52 | sys.exit(app.exec_()) 53 | -------------------------------------------------------------------------------- /src/translate/en.po: -------------------------------------------------------------------------------- 1 | # Translation of plasmaConfSaver in LANGUAGE 2 | # Copyright (C) 2020 3 | # This file is distributed under the same license as the plasmaConfSaver package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: plasmaConfSaver \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2020-05-20 19:20+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: ../contents/ui/FullRepresentation.qml:89 21 | msgid "Enter customization title" 22 | msgstr "" 23 | 24 | #: ../contents/ui/FullRepresentation.qml:105 25 | msgid "Save" 26 | msgstr "" 27 | 28 | #: ../contents/ui/FullRepresentation.qml:106 29 | msgid "Save your current customization" 30 | msgstr "" 31 | 32 | #: ../contents/ui/FullRepresentation.qml:192 33 | msgid "Import" 34 | msgstr "" 35 | 36 | #: ../contents/ui/FullRepresentation.qml:193 37 | msgid "Import a customization" 38 | msgstr "" 39 | 40 | #: ../contents/ui/FullRepresentation.qml:291 41 | msgid "Load" 42 | msgstr "" 43 | 44 | #: ../contents/ui/FullRepresentation.qml:292 45 | msgid "Load this customization" 46 | msgstr "" 47 | 48 | #: ../contents/ui/FullRepresentation.qml:324 49 | msgid "Update" 50 | msgstr "" 51 | 52 | #: ../contents/ui/FullRepresentation.qml:325 53 | msgid "Save this customization again" 54 | msgstr "" 55 | 56 | #: ../contents/ui/FullRepresentation.qml:358 57 | msgid "Export" 58 | msgstr "" 59 | 60 | #: ../contents/ui/FullRepresentation.qml:359 61 | msgid "Export this customization" 62 | msgstr "" 63 | 64 | #: ../contents/ui/FullRepresentation.qml:382 65 | msgid "Delete" 66 | msgstr "" 67 | 68 | #: ../contents/ui/FullRepresentation.qml:383 69 | msgid "Delete this customization" 70 | msgstr "" 71 | -------------------------------------------------------------------------------- /src/ui/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_dialog.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_dialog.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_dialog.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_dialog.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_dialog.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_dialog.cpython-312.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_enter_time_machine.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_enter_time_machine.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_enter_time_machine.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_enter_time_machine.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_form.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_form.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_form.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_form.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_mainwindow.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_mainwindow.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_mainwindow.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_mainwindow.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_mainwindow.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_mainwindow.cpython-312.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_mainwindow_test.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_mainwindow_test.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_migration.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_migration.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_migration.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_migration.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_new_2mainwindow.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_new_2mainwindow.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_new_mainwindow.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_new_mainwindow.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_options.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_options.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_options.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_options.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_options.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_options.cpython-312.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_untitled.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_untitled.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_untitled.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_untitled.cpython-311.pyc -------------------------------------------------------------------------------- /src/ui/__pycache__/ui_windows.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/__pycache__/ui_windows.cpython-310.pyc -------------------------------------------------------------------------------- /src/ui/dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 500 10 | 360 11 | 12 | 13 | 14 | 15 | 500 16 | 360 17 | 18 | 19 | 20 | 21 | 500 22 | 360 23 | 24 | 25 | 26 | Dialog 27 | 28 | 29 | 30 | 0 31 | 32 | 33 | 0 34 | 35 | 36 | 0 37 | 38 | 39 | 0 40 | 41 | 42 | 0 43 | 44 | 45 | 46 | 47 | 9 48 | 49 | 50 | 9 51 | 52 | 53 | 9 54 | 55 | 56 | 9 57 | 58 | 59 | 9 60 | 61 | 62 | 63 | 64 | true 65 | 66 | 67 | 68 | 69 | 0 70 | 0 71 | 480 72 | 303 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 12 81 | true 82 | 83 | 84 | 85 | Choose a device 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 10 94 | false 95 | 96 | 97 | 98 | color: rgb(128, 128, 128); 99 | 100 | 101 | Backup your Home with a local device. 102 | 103 | 104 | 105 | 106 | 107 | 108 | Qt::Horizontal 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | Qt::Vertical 119 | 120 | 121 | 122 | 20 123 | 40 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | Qt::Horizontal 138 | 139 | 140 | 141 | 40 142 | 20 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 0 152 | 0 153 | 154 | 155 | 156 | 157 | true 158 | 159 | 160 | 161 | Cancel 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 0 170 | 0 171 | 172 | 173 | 174 | background-color: #2196f3; 175 | color: white; 176 | 177 | 178 | Use Disk 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /src/ui/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 500 10 | 360 11 | 12 | 13 | 14 | 15 | 500 16 | 360 17 | 18 | 19 | 20 | 21 | 500 22 | 360 23 | 24 | 25 | 26 | MainWindow 27 | 28 | 29 | 30 | 31 | 4 32 | 33 | 34 | 9 35 | 36 | 37 | 9 38 | 39 | 40 | 9 41 | 42 | 43 | 0 44 | 45 | 46 | 47 | 48 | 49 | false 50 | 51 | 52 | 53 | Backup Device 54 | 55 | 56 | 57 | 58 | 59 | 60 | QFrame::StyledPanel 61 | 62 | 63 | QFrame::Raised 64 | 65 | 66 | 67 | 68 | 69 | 0 70 | 71 | 72 | 73 | 74 | 75 | 10 76 | false 77 | false 78 | false 79 | true 80 | 81 | 82 | 83 | Backup's devices name 84 | 85 | 86 | 87 | 88 | 89 | None 90 | 91 | 92 | 93 | 94 | 95 | 96 | Last Backup Date 97 | 98 | 99 | Last Backup: 100 | 101 | 102 | 103 | 104 | 105 | 106 | Next Backup Date 107 | 108 | 109 | Next Backup: 110 | 111 | 112 | 113 | 114 | 115 | 116 | Remove 117 | 118 | 119 | 120 | 121 | 122 | 123 | IMAGE 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | false 137 | 138 | 139 | 140 | Storage Space 141 | 142 | 143 | 144 | 145 | 146 | 147 | QFrame::StyledPanel 148 | 149 | 150 | QFrame::Raised 151 | 152 | 153 | 154 | 155 | 156 | true 157 | 158 | 159 | 160 | 16777215 161 | 16 162 | 163 | 164 | 165 | 166 | 10 167 | 168 | 169 | 170 | 100 171 | 172 | 173 | 0 174 | 175 | 176 | true 177 | 178 | 179 | 180 | 181 | 182 | 183 | Available Space 184 | 185 | 186 | Available Space: 187 | 188 | 189 | 190 | 191 | 192 | 193 | 39 194 | 195 | 196 | false 197 | 198 | 199 | 200 | 201 | 202 | 203 | Browser Backup Storage 204 | 205 | 206 | Browser 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | Qt::Vertical 217 | 218 | 219 | 220 | 20 221 | 40 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 9 230 | 231 | 232 | 0 233 | 234 | 235 | 9 236 | 237 | 238 | 0 239 | 240 | 241 | 9 242 | 243 | 244 | 245 | 246 | Qt::Horizontal 247 | 248 | 249 | 250 | 40 251 | 20 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 10 261 | 262 | 263 | 264 | background-color: #2196f3; 265 | color: white; 266 | 267 | 268 | Update Available 269 | 270 | 271 | 272 | 273 | 274 | 275 | Add Backup Device 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 10 284 | 285 | 286 | 287 | 288 | 289 | 290 | Options... 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 26 299 | 16777215 300 | 301 | 302 | 303 | 304 | 10 305 | 306 | 307 | 308 | 309 | 310 | 311 | ? 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /src/ui/options.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options 4 | 5 | 6 | 7 | 0 8 | 0 9 | 500 10 | 360 11 | 12 | 13 | 14 | 15 | 500 16 | 360 17 | 18 | 19 | 20 | 21 | 500 22 | 360 23 | 24 | 25 | 26 | Dialog 27 | 28 | 29 | 30 | 31 | 32 | 0 33 | 34 | 35 | 36 | Settings 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | 47 | Startup Applications Preferences: 48 | 49 | 50 | 51 | 52 | 53 | 54 | true 55 | 56 | 57 | Back Up Automatically 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | true 66 | 67 | 68 | 69 | System Tray: 70 | 71 | 72 | 73 | 74 | 75 | 76 | true 77 | 78 | 79 | Show Time Machine in System Tray 80 | 81 | 82 | 83 | 84 | 85 | 86 | Qt::Vertical 87 | 88 | 89 | 90 | 20 91 | 40 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Backup 101 | 102 | 103 | 104 | 105 | 106 | 107 | true 108 | 109 | 110 | 111 | Backup folders: 112 | 113 | 114 | 115 | 116 | 117 | 118 | true 119 | 120 | 121 | 122 | 123 | 0 124 | 0 125 | 458 126 | 223 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | Experimental 142 | 143 | 144 | 145 | 146 | 147 | 148 | true 149 | 150 | 151 | 152 | Experimental Features: 153 | 154 | 155 | 156 | 157 | 158 | 159 | true 160 | 161 | 162 | Browser In Time Machine (System Tray Option) 163 | 164 | 165 | 166 | 167 | 168 | 169 | Qt::Vertical 170 | 171 | 172 | 173 | 20 174 | 40 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | Others 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | true 193 | 194 | 195 | 196 | Flatpak Settings: 197 | 198 | 199 | 200 | 201 | 202 | 203 | false 204 | 205 | 206 | Back up flatpaks Data 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | true 215 | 216 | 217 | 218 | Reset: 219 | 220 | 221 | 222 | 223 | 224 | 225 | <html><head/><body><p>If something seems broken, click on Reset, to reset all settings.</p></body></html> 226 | 227 | 228 | false 229 | 230 | 231 | true 232 | 233 | 234 | 235 | 236 | 237 | 238 | Reset 239 | 240 | 241 | 242 | 243 | 244 | 245 | Qt::Vertical 246 | 247 | 248 | 249 | 20 250 | 40 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 9 265 | 266 | 267 | 9 268 | 269 | 270 | 9 271 | 272 | 273 | 9 274 | 275 | 276 | 9 277 | 278 | 279 | 280 | 281 | Version 282 | 283 | 284 | 285 | 286 | 287 | 288 | Qt::Horizontal 289 | 290 | 291 | 292 | 40 293 | 20 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | -------------------------------------------------------------------------------- /src/ui/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | arrow.png 4 | ../icons/backup_128px.png 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/ui/ui.cflags: -------------------------------------------------------------------------------- 1 | -std=c17 -------------------------------------------------------------------------------- /src/ui/ui.config: -------------------------------------------------------------------------------- 1 | // Add predefined macros for your project here. For example: 2 | // #define THE_ANSWER 42 3 | -------------------------------------------------------------------------------- /src/ui/ui.creator: -------------------------------------------------------------------------------- 1 | [General] 2 | -------------------------------------------------------------------------------- /src/ui/ui.cxxflags: -------------------------------------------------------------------------------- 1 | -std=c++17 -------------------------------------------------------------------------------- /src/ui/ui.files: -------------------------------------------------------------------------------- 1 | __pycache__/ui_dialog.cpython-310.pyc 2 | __pycache__/ui_dialog.cpython-311.pyc 3 | __pycache__/ui_form.cpython-310.pyc 4 | __pycache__/ui_form.cpython-311.pyc 5 | __pycache__/ui_mainwindow.cpython-310.pyc 6 | __pycache__/ui_mainwindow.cpython-311.pyc 7 | __pycache__/ui_migration.cpython-310.pyc 8 | __pycache__/ui_migration.cpython-311.pyc 9 | __pycache__/ui_options.cpython-310.pyc 10 | __pycache__/ui_options.cpython-311.pyc 11 | __pycache__/ui_untitled.cpython-310.pyc 12 | __pycache__/ui_untitled.cpython-311.pyc 13 | dialog.ui 14 | enter_time_machine.ui 15 | mainwindow.ui 16 | migration.ui 17 | options.py 18 | options.ui 19 | resources.qrc 20 | ui.cflags 21 | ui.cxxflags 22 | ui_dialog.py 23 | ui_mainwindow.py 24 | ui_migration.py 25 | ui_options.py 26 | ui_untitled.py 27 | -------------------------------------------------------------------------------- /src/ui/ui.includes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeovaneJefferson/timemachine/b0138c9734134548d88997d9a4a91d0ee724a85a/src/ui/ui.includes -------------------------------------------------------------------------------- /src/ui/ui_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ################################################################################ 4 | ## Form generated from reading UI file 'dialog.ui' 5 | ## 6 | ## Created by: Qt User Interface Compiler version 6.6.2 7 | ## 8 | ## WARNING! All changes made in this file will be lost when recompiling UI file! 9 | ################################################################################ 10 | 11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, 12 | QMetaObject, QObject, QPoint, QRect, 13 | QSize, QTime, QUrl, Qt) 14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, 15 | QFont, QFontDatabase, QGradient, QIcon, 16 | QImage, QKeySequence, QLinearGradient, QPainter, 17 | QPalette, QPixmap, QRadialGradient, QTransform) 18 | from PySide6.QtWidgets import (QApplication, QDialog, QFrame, QHBoxLayout, 19 | QLabel, QPushButton, QScrollArea, QSizePolicy, 20 | QSpacerItem, QVBoxLayout, QWidget) 21 | 22 | class Ui_Dialog(object): 23 | def setupUi(self, Dialog): 24 | if not Dialog.objectName(): 25 | Dialog.setObjectName(u"Dialog") 26 | Dialog.resize(500, 360) 27 | Dialog.setMinimumSize(QSize(500, 360)) 28 | Dialog.setMaximumSize(QSize(500, 360)) 29 | self.verticalLayout_2 = QVBoxLayout(Dialog) 30 | self.verticalLayout_2.setSpacing(0) 31 | self.verticalLayout_2.setObjectName(u"verticalLayout_2") 32 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) 33 | self.verticalLayout = QVBoxLayout() 34 | self.verticalLayout.setSpacing(9) 35 | self.verticalLayout.setObjectName(u"verticalLayout") 36 | self.verticalLayout.setContentsMargins(9, 9, 9, 9) 37 | self.scrollArea = QScrollArea(Dialog) 38 | self.scrollArea.setObjectName(u"scrollArea") 39 | self.scrollArea.setWidgetResizable(True) 40 | self.scrollAreaWidgetContents = QWidget() 41 | self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") 42 | self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 480, 303)) 43 | self.verticalLayout_4 = QVBoxLayout(self.scrollAreaWidgetContents) 44 | self.verticalLayout_4.setObjectName(u"verticalLayout_4") 45 | self.label = QLabel(self.scrollAreaWidgetContents) 46 | self.label.setObjectName(u"label") 47 | font = QFont() 48 | font.setPointSize(12) 49 | font.setBold(True) 50 | self.label.setFont(font) 51 | 52 | self.verticalLayout_4.addWidget(self.label) 53 | 54 | self.label_2 = QLabel(self.scrollAreaWidgetContents) 55 | self.label_2.setObjectName(u"label_2") 56 | font1 = QFont() 57 | font1.setPointSize(10) 58 | font1.setBold(False) 59 | self.label_2.setFont(font1) 60 | self.label_2.setStyleSheet(u"color: rgb(128, 128, 128);") 61 | 62 | self.verticalLayout_4.addWidget(self.label_2) 63 | 64 | self.line_2 = QFrame(self.scrollAreaWidgetContents) 65 | self.line_2.setObjectName(u"line_2") 66 | self.line_2.setFrameShape(QFrame.HLine) 67 | self.line_2.setFrameShadow(QFrame.Sunken) 68 | 69 | self.verticalLayout_4.addWidget(self.line_2) 70 | 71 | self.available_disk_dialog_layout = QVBoxLayout() 72 | self.available_disk_dialog_layout.setObjectName(u"available_disk_dialog_layout") 73 | 74 | self.verticalLayout_4.addLayout(self.available_disk_dialog_layout) 75 | 76 | self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) 77 | 78 | self.verticalLayout_4.addItem(self.verticalSpacer) 79 | 80 | self.scrollArea.setWidget(self.scrollAreaWidgetContents) 81 | 82 | self.verticalLayout.addWidget(self.scrollArea) 83 | 84 | self.horizontalLayout = QHBoxLayout() 85 | self.horizontalLayout.setObjectName(u"horizontalLayout") 86 | self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) 87 | 88 | self.horizontalLayout.addItem(self.horizontalSpacer) 89 | 90 | self.cancel_button_dialog = QPushButton(Dialog) 91 | self.cancel_button_dialog.setObjectName(u"cancel_button_dialog") 92 | sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) 93 | sizePolicy.setHorizontalStretch(0) 94 | sizePolicy.setVerticalStretch(0) 95 | sizePolicy.setHeightForWidth(self.cancel_button_dialog.sizePolicy().hasHeightForWidth()) 96 | self.cancel_button_dialog.setSizePolicy(sizePolicy) 97 | font2 = QFont() 98 | font2.setKerning(True) 99 | self.cancel_button_dialog.setFont(font2) 100 | 101 | self.horizontalLayout.addWidget(self.cancel_button_dialog, 0, Qt.AlignRight) 102 | 103 | self.use_disk_button_dialog = QPushButton(Dialog) 104 | self.use_disk_button_dialog.setObjectName(u"use_disk_button_dialog") 105 | sizePolicy.setHeightForWidth(self.use_disk_button_dialog.sizePolicy().hasHeightForWidth()) 106 | self.use_disk_button_dialog.setSizePolicy(sizePolicy) 107 | self.use_disk_button_dialog.setStyleSheet(u"background-color: #2196f3;\n" 108 | "color: white;") 109 | 110 | self.horizontalLayout.addWidget(self.use_disk_button_dialog, 0, Qt.AlignRight) 111 | 112 | 113 | self.verticalLayout.addLayout(self.horizontalLayout) 114 | 115 | 116 | self.verticalLayout_2.addLayout(self.verticalLayout) 117 | 118 | 119 | self.retranslateUi(Dialog) 120 | 121 | QMetaObject.connectSlotsByName(Dialog) 122 | # setupUi 123 | 124 | def retranslateUi(self, Dialog): 125 | Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Dialog", None)) 126 | self.label.setText(QCoreApplication.translate("Dialog", u"Choose a device", None)) 127 | self.label_2.setText(QCoreApplication.translate("Dialog", u"Backup your Home with a local device.", None)) 128 | self.cancel_button_dialog.setText(QCoreApplication.translate("Dialog", u"Cancel", None)) 129 | self.use_disk_button_dialog.setText(QCoreApplication.translate("Dialog", u"Use Disk", None)) 130 | # retranslateUi 131 | 132 | -------------------------------------------------------------------------------- /src/ui/ui_enter_time_machine.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ################################################################################ 4 | ## Form generated from reading UI file 'enter_time_machine.ui' 5 | ## 6 | ## Created by: Qt User Interface Compiler version 6.6.1 7 | ## 8 | ## WARNING! All changes made in this file will be lost when recompiling UI file! 9 | ################################################################################ 10 | 11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, 12 | QMetaObject, QObject, QPoint, QRect, 13 | QSize, QTime, QUrl, Qt) 14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, 15 | QFont, QFontDatabase, QGradient, QIcon, 16 | QImage, QKeySequence, QLinearGradient, QPainter, 17 | QPalette, QPixmap, QRadialGradient, QTransform) 18 | from PySide6.QtWidgets import (QAbstractItemView, QAbstractScrollArea, QApplication, QGridLayout, 19 | QHBoxLayout, QHeaderView, QLabel, QMainWindow, 20 | QPushButton, QSizePolicy, QSpacerItem, QStatusBar, 21 | QTextBrowser, QTreeView, QTreeWidget, QTreeWidgetItem, 22 | QVBoxLayout, QWidget) 23 | 24 | class Ui_MainWindow(object): 25 | def setupUi(self, MainWindow): 26 | if not MainWindow.objectName(): 27 | MainWindow.setObjectName(u"MainWindow") 28 | MainWindow.resize(1131, 600) 29 | self.centralwidget = QWidget(MainWindow) 30 | self.centralwidget.setObjectName(u"centralwidget") 31 | self.verticalLayout_2 = QVBoxLayout(self.centralwidget) 32 | self.verticalLayout_2.setObjectName(u"verticalLayout_2") 33 | self.verticalLayout = QVBoxLayout() 34 | self.verticalLayout.setObjectName(u"verticalLayout") 35 | self.dates_layout = QGridLayout() 36 | self.dates_layout.setObjectName(u"dates_layout") 37 | 38 | self.verticalLayout.addLayout(self.dates_layout) 39 | 40 | self.horizontalLayout_5 = QHBoxLayout() 41 | self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") 42 | self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) 43 | 44 | self.horizontalLayout_5.addItem(self.horizontalSpacer_3) 45 | 46 | self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) 47 | 48 | self.horizontalLayout_5.addItem(self.horizontalSpacer_4) 49 | 50 | 51 | self.verticalLayout.addLayout(self.horizontalLayout_5) 52 | 53 | self.horizontalLayout = QHBoxLayout() 54 | self.horizontalLayout.setSpacing(6) 55 | self.horizontalLayout.setObjectName(u"horizontalLayout") 56 | self.widget_3 = QWidget(self.centralwidget) 57 | self.widget_3.setObjectName(u"widget_3") 58 | self.widget_3.setMinimumSize(QSize(180, 0)) 59 | self.widget_3.setMaximumSize(QSize(180, 16777215)) 60 | self.verticalLayout_6 = QVBoxLayout(self.widget_3) 61 | self.verticalLayout_6.setObjectName(u"verticalLayout_6") 62 | self.label = QLabel(self.widget_3) 63 | self.label.setObjectName(u"label") 64 | font = QFont() 65 | font.setBold(True) 66 | self.label.setFont(font) 67 | 68 | self.verticalLayout_6.addWidget(self.label, 0, Qt.AlignLeft|Qt.AlignVCenter) 69 | 70 | self.folders_layout = QVBoxLayout() 71 | self.folders_layout.setObjectName(u"folders_layout") 72 | 73 | self.verticalLayout_6.addLayout(self.folders_layout) 74 | 75 | self.verticalLayout_6.setStretch(1, 1) 76 | 77 | self.horizontalLayout.addWidget(self.widget_3) 78 | 79 | self.widget_2 = QWidget(self.centralwidget) 80 | self.widget_2.setObjectName(u"widget_2") 81 | self.verticalLayout_7 = QVBoxLayout(self.widget_2) 82 | self.verticalLayout_7.setObjectName(u"verticalLayout_7") 83 | self.tree_widget = QTreeWidget(self.widget_2) 84 | __qtreewidgetitem = QTreeWidgetItem() 85 | __qtreewidgetitem.setText(0, u"1"); 86 | self.tree_widget.setHeaderItem(__qtreewidgetitem) 87 | self.tree_widget.setObjectName(u"tree_widget") 88 | self.tree_widget.setMinimumSize(QSize(600, 400)) 89 | self.tree_widget.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) 90 | self.tree_widget.setSelectionMode(QAbstractItemView.SingleSelection) 91 | self.tree_widget.setSelectionBehavior(QAbstractItemView.SelectRows) 92 | self.tree_widget.setIconSize(QSize(16, 16)) 93 | self.tree_widget.setAnimated(True) 94 | self.tree_widget.setWordWrap(True) 95 | self.tree_widget.header().setMinimumSectionSize(150) 96 | 97 | self.verticalLayout_7.addWidget(self.tree_widget) 98 | 99 | 100 | self.horizontalLayout.addWidget(self.widget_2) 101 | 102 | self.widget = QWidget(self.centralwidget) 103 | self.widget.setObjectName(u"widget") 104 | self.widget.setMinimumSize(QSize(220, 0)) 105 | self.widget.setMaximumSize(QSize(180, 16777215)) 106 | self.verticalLayout_4 = QVBoxLayout(self.widget) 107 | self.verticalLayout_4.setObjectName(u"verticalLayout_4") 108 | self.verticalLayout_3 = QVBoxLayout() 109 | self.verticalLayout_3.setSpacing(20) 110 | self.verticalLayout_3.setObjectName(u"verticalLayout_3") 111 | self.verticalLayout_3.setContentsMargins(6, 6, 6, 6) 112 | self.small_preview_text = QTextBrowser(self.widget) 113 | self.small_preview_text.setObjectName(u"small_preview_text") 114 | self.small_preview_text.setMaximumSize(QSize(16777215, 0)) 115 | 116 | self.verticalLayout_3.addWidget(self.small_preview_text) 117 | 118 | self.small_preview_label = QLabel(self.widget) 119 | self.small_preview_label.setObjectName(u"small_preview_label") 120 | self.small_preview_label.setMinimumSize(QSize(190, 140)) 121 | self.small_preview_label.setMaximumSize(QSize(0, 140)) 122 | 123 | self.verticalLayout_3.addWidget(self.small_preview_label, 0, Qt.AlignTop) 124 | 125 | self.horizontalLayout_4 = QHBoxLayout() 126 | self.horizontalLayout_4.setSpacing(6) 127 | self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") 128 | self.btn_cancel = QPushButton(self.widget) 129 | self.btn_cancel.setObjectName(u"btn_cancel") 130 | self.btn_cancel.setMinimumSize(QSize(0, 0)) 131 | self.btn_cancel.setMaximumSize(QSize(16777215, 16777215)) 132 | self.btn_cancel.setStyleSheet(u"") 133 | 134 | self.horizontalLayout_4.addWidget(self.btn_cancel, 0, Qt.AlignTop) 135 | 136 | self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) 137 | 138 | self.horizontalLayout_4.addItem(self.verticalSpacer) 139 | 140 | self.btn_restore = QPushButton(self.widget) 141 | self.btn_restore.setObjectName(u"btn_restore") 142 | self.btn_restore.setMinimumSize(QSize(0, 0)) 143 | self.btn_restore.setMaximumSize(QSize(88, 34)) 144 | self.btn_restore.setStyleSheet(u"") 145 | 146 | self.horizontalLayout_4.addWidget(self.btn_restore, 0, Qt.AlignTop) 147 | 148 | 149 | self.verticalLayout_3.addLayout(self.horizontalLayout_4) 150 | 151 | 152 | self.verticalLayout_4.addLayout(self.verticalLayout_3) 153 | 154 | 155 | self.horizontalLayout.addWidget(self.widget) 156 | 157 | self.horizontalLayout.setStretch(1, 1) 158 | 159 | self.verticalLayout.addLayout(self.horizontalLayout) 160 | 161 | self.label_2 = QLabel(self.centralwidget) 162 | self.label_2.setObjectName(u"label_2") 163 | self.label_2.setFont(font) 164 | 165 | self.verticalLayout.addWidget(self.label_2, 0, Qt.AlignLeft|Qt.AlignVCenter) 166 | 167 | self.tree_widget_updates = QTreeView(self.centralwidget) 168 | self.tree_widget_updates.setObjectName(u"tree_widget_updates") 169 | self.tree_widget_updates.setMinimumSize(QSize(0, 0)) 170 | self.tree_widget_updates.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) 171 | self.tree_widget_updates.setSelectionBehavior(QAbstractItemView.SelectRows) 172 | self.tree_widget_updates.setIconSize(QSize(16, 16)) 173 | self.tree_widget_updates.setAnimated(True) 174 | self.tree_widget_updates.setWordWrap(True) 175 | 176 | self.verticalLayout.addWidget(self.tree_widget_updates) 177 | 178 | self.verticalLayout.setStretch(2, 1) 179 | 180 | self.verticalLayout_2.addLayout(self.verticalLayout) 181 | 182 | MainWindow.setCentralWidget(self.centralwidget) 183 | self.statusbar = QStatusBar(MainWindow) 184 | self.statusbar.setObjectName(u"statusbar") 185 | MainWindow.setStatusBar(self.statusbar) 186 | 187 | self.retranslateUi(MainWindow) 188 | 189 | QMetaObject.connectSlotsByName(MainWindow) 190 | # setupUi 191 | 192 | def retranslateUi(self, MainWindow): 193 | MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) 194 | self.label.setText(QCoreApplication.translate("MainWindow", u"Folders", None)) 195 | self.small_preview_label.setText("") 196 | self.btn_cancel.setText(QCoreApplication.translate("MainWindow", u"Cancel", None)) 197 | self.btn_restore.setText(QCoreApplication.translate("MainWindow", u"Restore", None)) 198 | self.label_2.setText(QCoreApplication.translate("MainWindow", u"Updates", None)) 199 | # retranslateUi 200 | 201 | -------------------------------------------------------------------------------- /src/ui/ui_options.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ################################################################################ 4 | ## Form generated from reading UI file 'options.ui' 5 | ## 6 | ## Created by: Qt User Interface Compiler version 6.6.2 7 | ## 8 | ## WARNING! All changes made in this file will be lost when recompiling UI file! 9 | ################################################################################ 10 | 11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, 12 | QMetaObject, QObject, QPoint, QRect, 13 | QSize, QTime, QUrl, Qt) 14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, 15 | QFont, QFontDatabase, QGradient, QIcon, 16 | QImage, QKeySequence, QLinearGradient, QPainter, 17 | QPalette, QPixmap, QRadialGradient, QTransform) 18 | from PySide6.QtWidgets import (QApplication, QCheckBox, QDialog, QGridLayout, 19 | QHBoxLayout, QLabel, QPushButton, QScrollArea, 20 | QSizePolicy, QSpacerItem, QTabWidget, QVBoxLayout, 21 | QWidget) 22 | 23 | class Ui_Options(object): 24 | def setupUi(self, Options): 25 | if not Options.objectName(): 26 | Options.setObjectName(u"Options") 27 | Options.resize(500, 360) 28 | Options.setMinimumSize(QSize(500, 360)) 29 | Options.setMaximumSize(QSize(500, 360)) 30 | self.verticalLayout = QVBoxLayout(Options) 31 | self.verticalLayout.setObjectName(u"verticalLayout") 32 | self.tabWidget = QTabWidget(Options) 33 | self.tabWidget.setObjectName(u"tabWidget") 34 | self.tab_3 = QWidget() 35 | self.tab_3.setObjectName(u"tab_3") 36 | self.verticalLayout_6 = QVBoxLayout(self.tab_3) 37 | self.verticalLayout_6.setObjectName(u"verticalLayout_6") 38 | self.label_10 = QLabel(self.tab_3) 39 | self.label_10.setObjectName(u"label_10") 40 | font = QFont() 41 | font.setBold(True) 42 | self.label_10.setFont(font) 43 | 44 | self.verticalLayout_6.addWidget(self.label_10) 45 | 46 | self.automatically_backup_checkbox = QCheckBox(self.tab_3) 47 | self.automatically_backup_checkbox.setObjectName(u"automatically_backup_checkbox") 48 | self.automatically_backup_checkbox.setEnabled(True) 49 | 50 | self.verticalLayout_6.addWidget(self.automatically_backup_checkbox) 51 | 52 | self.label_11 = QLabel(self.tab_3) 53 | self.label_11.setObjectName(u"label_11") 54 | self.label_11.setFont(font) 55 | 56 | self.verticalLayout_6.addWidget(self.label_11) 57 | 58 | self.show_in_system_tray_checkbox = QCheckBox(self.tab_3) 59 | self.show_in_system_tray_checkbox.setObjectName(u"show_in_system_tray_checkbox") 60 | self.show_in_system_tray_checkbox.setEnabled(True) 61 | 62 | self.verticalLayout_6.addWidget(self.show_in_system_tray_checkbox) 63 | 64 | self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) 65 | 66 | self.verticalLayout_6.addItem(self.verticalSpacer) 67 | 68 | self.tabWidget.addTab(self.tab_3, "") 69 | self.back_up_tab = QWidget() 70 | self.back_up_tab.setObjectName(u"back_up_tab") 71 | self.gridLayout_3 = QGridLayout(self.back_up_tab) 72 | self.gridLayout_3.setObjectName(u"gridLayout_3") 73 | self.label_4 = QLabel(self.back_up_tab) 74 | self.label_4.setObjectName(u"label_4") 75 | self.label_4.setFont(font) 76 | 77 | self.gridLayout_3.addWidget(self.label_4, 0, 0, 1, 1) 78 | 79 | self.scroll_area_folders = QScrollArea(self.back_up_tab) 80 | self.scroll_area_folders.setObjectName(u"scroll_area_folders") 81 | self.scroll_area_folders.setWidgetResizable(True) 82 | self.scrollAreaWidgetContents_2 = QWidget() 83 | self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2") 84 | self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 458, 223)) 85 | self.gridLayout_4 = QGridLayout(self.scrollAreaWidgetContents_2) 86 | self.gridLayout_4.setObjectName(u"gridLayout_4") 87 | self.grid_folders_layout = QGridLayout() 88 | self.grid_folders_layout.setObjectName(u"grid_folders_layout") 89 | 90 | self.gridLayout_4.addLayout(self.grid_folders_layout, 0, 0, 1, 1) 91 | 92 | self.scroll_area_folders.setWidget(self.scrollAreaWidgetContents_2) 93 | 94 | self.gridLayout_3.addWidget(self.scroll_area_folders, 1, 0, 1, 1) 95 | 96 | self.tabWidget.addTab(self.back_up_tab, "") 97 | self.tab = QWidget() 98 | self.tab.setObjectName(u"tab") 99 | self.gridLayout = QGridLayout(self.tab) 100 | self.gridLayout.setObjectName(u"gridLayout") 101 | self.label_8 = QLabel(self.tab) 102 | self.label_8.setObjectName(u"label_8") 103 | self.label_8.setFont(font) 104 | 105 | self.gridLayout.addWidget(self.label_8, 0, 0, 1, 1) 106 | 107 | self.allow_browser_in_time_machine = QCheckBox(self.tab) 108 | self.allow_browser_in_time_machine.setObjectName(u"allow_browser_in_time_machine") 109 | self.allow_browser_in_time_machine.setEnabled(True) 110 | 111 | self.gridLayout.addWidget(self.allow_browser_in_time_machine, 1, 0, 1, 1) 112 | 113 | self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) 114 | 115 | self.gridLayout.addItem(self.verticalSpacer_2, 2, 0, 1, 1) 116 | 117 | self.tabWidget.addTab(self.tab, "") 118 | self.others_tab = QWidget() 119 | self.others_tab.setObjectName(u"others_tab") 120 | self.verticalLayout_4 = QVBoxLayout(self.others_tab) 121 | self.verticalLayout_4.setObjectName(u"verticalLayout_4") 122 | self.verticalLayout_3 = QVBoxLayout() 123 | self.verticalLayout_3.setObjectName(u"verticalLayout_3") 124 | self.label_5 = QLabel(self.others_tab) 125 | self.label_5.setObjectName(u"label_5") 126 | self.label_5.setFont(font) 127 | 128 | self.verticalLayout_3.addWidget(self.label_5) 129 | 130 | self.allow_flatpak_data_checkBox = QCheckBox(self.others_tab) 131 | self.allow_flatpak_data_checkBox.setObjectName(u"allow_flatpak_data_checkBox") 132 | self.allow_flatpak_data_checkBox.setEnabled(False) 133 | 134 | self.verticalLayout_3.addWidget(self.allow_flatpak_data_checkBox) 135 | 136 | self.label_6 = QLabel(self.others_tab) 137 | self.label_6.setObjectName(u"label_6") 138 | self.label_6.setFont(font) 139 | 140 | self.verticalLayout_3.addWidget(self.label_6) 141 | 142 | self.label_7 = QLabel(self.others_tab) 143 | self.label_7.setObjectName(u"label_7") 144 | self.label_7.setScaledContents(False) 145 | self.label_7.setWordWrap(True) 146 | 147 | self.verticalLayout_3.addWidget(self.label_7) 148 | 149 | self.reset_button = QPushButton(self.others_tab) 150 | self.reset_button.setObjectName(u"reset_button") 151 | 152 | self.verticalLayout_3.addWidget(self.reset_button, 0, Qt.AlignLeft) 153 | 154 | self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) 155 | 156 | self.verticalLayout_3.addItem(self.verticalSpacer_3) 157 | 158 | 159 | self.verticalLayout_4.addLayout(self.verticalLayout_3) 160 | 161 | self.tabWidget.addTab(self.others_tab, "") 162 | 163 | self.verticalLayout.addWidget(self.tabWidget) 164 | 165 | self.horizontalLayout_2 = QHBoxLayout() 166 | self.horizontalLayout_2.setSpacing(9) 167 | self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") 168 | self.horizontalLayout_2.setContentsMargins(9, 9, 9, 9) 169 | self.version_label = QLabel(Options) 170 | self.version_label.setObjectName(u"version_label") 171 | 172 | self.horizontalLayout_2.addWidget(self.version_label, 0, Qt.AlignLeft|Qt.AlignBottom) 173 | 174 | self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) 175 | 176 | self.horizontalLayout_2.addItem(self.horizontalSpacer) 177 | 178 | 179 | self.verticalLayout.addLayout(self.horizontalLayout_2) 180 | 181 | self.verticalLayout.setStretch(0, 1) 182 | 183 | self.retranslateUi(Options) 184 | 185 | self.tabWidget.setCurrentIndex(0) 186 | 187 | 188 | QMetaObject.connectSlotsByName(Options) 189 | # setupUi 190 | 191 | def retranslateUi(self, Options): 192 | Options.setWindowTitle(QCoreApplication.translate("Options", u"Dialog", None)) 193 | self.label_10.setText(QCoreApplication.translate("Options", u"Startup Applications Preferences:", None)) 194 | self.automatically_backup_checkbox.setText(QCoreApplication.translate("Options", u"Back Up Automatically", None)) 195 | self.label_11.setText(QCoreApplication.translate("Options", u"System Tray:", None)) 196 | self.show_in_system_tray_checkbox.setText(QCoreApplication.translate("Options", u"Show Time Machine in System Tray", None)) 197 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("Options", u"Settings", None)) 198 | self.label_4.setText(QCoreApplication.translate("Options", u"Backup folders:", None)) 199 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.back_up_tab), QCoreApplication.translate("Options", u"Backup", None)) 200 | self.label_8.setText(QCoreApplication.translate("Options", u"Experimental Features:", None)) 201 | self.allow_browser_in_time_machine.setText(QCoreApplication.translate("Options", u"Browser In Time Machine (System Tray Option)", None)) 202 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Options", u"Experimental", None)) 203 | self.label_5.setText(QCoreApplication.translate("Options", u"Flatpak Settings:", None)) 204 | self.allow_flatpak_data_checkBox.setText(QCoreApplication.translate("Options", u"Back up flatpaks Data", None)) 205 | self.label_6.setText(QCoreApplication.translate("Options", u"Reset:", None)) 206 | self.label_7.setText(QCoreApplication.translate("Options", u"

If something seems broken, click on Reset, to reset all settings.

", None)) 207 | self.reset_button.setText(QCoreApplication.translate("Options", u"Reset", None)) 208 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.others_tab), QCoreApplication.translate("Options", u"Others", None)) 209 | self.version_label.setText(QCoreApplication.translate("Options", u"Version", None)) 210 | # retranslateUi 211 | 212 | -------------------------------------------------------------------------------- /src/update.py: -------------------------------------------------------------------------------- 1 | from setup import * 2 | 3 | def backup_db_file(update_now): 4 | # Make a copy of DB, and move it to src/ 5 | src = SRC_USER_CONFIG_DB 6 | dst = HOME_USER + "/.local/share/" + APP_NAME_CLOSE + "/src" 7 | shutil.copy2(src, dst) 8 | 9 | if update_now: 10 | shutil.rmtree(SRC_PYCACHE) 11 | 12 | update_git(update_now) 13 | 14 | def update_git(update_now): 15 | # Git pull 16 | print("Updating...") 17 | 18 | sub.run(["git", "stash"]) 19 | sub.run(["git", "pull"]) 20 | 21 | if update_now: 22 | delete_db_file(update_now) 23 | 24 | def delete_db_file(update_now): 25 | # Delete DB 26 | print("Deleting old ini file...") 27 | 28 | os.remove(SRC_USER_CONFIG_DB) 29 | 30 | if update_now: 31 | restore_db_file(update_now) 32 | 33 | def restore_db_file(update_now): 34 | print("Moving the backup DB...") 35 | 36 | # Move the backup DB to the right location 37 | src = HOME_USER + "/" + ".local/share/" + APP_NAME_CLOSE + "/src/config.db" 38 | dst = SRC_USER_CONFIG_DB 39 | # sub.run(["mv", "-f", src, dst]) 40 | shutil.move(src, dst) 41 | 42 | if update_now: 43 | open_app() 44 | 45 | def open_app(): 46 | # Re-open application 47 | sub.Popen(['python3', SRC_MAIN_WINDOW_PY]) 48 | 49 | # Exit 50 | exit() -------------------------------------------------------------------------------- /uninstall.py: -------------------------------------------------------------------------------- 1 | import subprocess as sub 2 | import pathlib 3 | from pathlib import Path 4 | import sqlite3 5 | import shutil 6 | 7 | 8 | # Remember to change setup too! 9 | HOME_USER = str(Path.home()) 10 | GET_CURRENT_LOCATION = pathlib.Path().resolve() 11 | 12 | APP_NAME_CLOSE = "timemachine" 13 | DST_FILE_EXE_DESKTOP = f"{HOME_USER}/.local/share/applications/{APP_NAME_CLOSE}.desktop" 14 | DST_MIGRATION_ASSISTANT_DESKTOP = f"{HOME_USER}/.local/share/applications/migration_assistant.desktop" 15 | DST_BACKUP_CHECK_DESKTOP = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/desktop/backup_check.desktop" 16 | SRC_USER_CONFIG_DB = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/src/ini/config.db" 17 | 18 | 19 | # Disable system tray 20 | 21 | # Connect to the SQLite database 22 | conn = sqlite3.connect(SRC_USER_CONFIG_DB) 23 | cursor = conn.cursor() 24 | 25 | cursor.execute(f''' 26 | INSERT OR REPLACE INTO SYSTEMTRAY (key, value) 27 | VALUES (?, ?) 28 | ''', ('system_tray', 'False')) 29 | 30 | conn.commit() 31 | conn.close() 32 | 33 | try: 34 | command = f"{HOME_USER}/.local/share/{APP_NAME_CLOSE}/" 35 | # Remove dir 36 | # sub.run(["rm", "-rf", command]) 37 | shutil.rmtree(command) 38 | except Exception as error: 39 | print(error) 40 | 41 | try: 42 | command = DST_FILE_EXE_DESKTOP 43 | sub.run(["rm", "-rf", command]) 44 | # Remove dir 45 | shutil.rmtree(command) 46 | except Exception as error: 47 | print(error) 48 | 49 | try: 50 | command = DST_MIGRATION_ASSISTANT_DESKTOP 51 | # sub.run(["rm", "-rf", command]) 52 | # Remove dir 53 | shutil.rmtree(command) 54 | except Exception as error: 55 | print(error) 56 | 57 | try: 58 | command = DST_BACKUP_CHECK_DESKTOP 59 | # sub.run(["rm", "-rf", command]) 60 | # Remove dir 61 | shutil.rmtree(command) 62 | except Exception as error: 63 | print(error) 64 | 65 | 66 | print("App was successfully removed.") 67 | exit() 68 | --------------------------------------------------------------------------------