Merge pull request #301 from maikwoehl/feature/packagable
Create resources to make it packable as python package
@@ -4,7 +4,7 @@ script:
|
||||
- mkdir -p AppDir/usr
|
||||
- mkdir -p AppDir/usr/share/icons/hicolor/48x48
|
||||
- cp src AppDir/usr -r
|
||||
- cp src/resources/images/OneDriveGUI.png AppDir/usr/share/icons/hicolor/48x48
|
||||
- cp src/onedrive_gui/resources/images/OneDriveGUI.png AppDir/usr/share/icons/hicolor/48x48
|
||||
- python3 -m pip install --ignore-installed --prefix=/usr --no-cache-dir --root=AppDir -r ./requirements.txt
|
||||
- rm -rf AppDir/usr/local/lib/python3.10/dist-packages/PySide6/Qt/qml/
|
||||
- rm -rf AppDir/usr/local/lib/python3.10/dist-packages/PySide6/examples/
|
||||
@@ -13,7 +13,9 @@ script:
|
||||
- rm -f AppDir/usr/local/lib/python3.10/dist-packages/PySide6/{assistant,designer,linguist,lrelease,lupdate}
|
||||
- rm -f AppDir/usr/local/lib/python3.10/dist-packages/PySide6/{Qt3D*,QtBluetooth*,QtCharts*,QtConcurrent*,QtDataVisualization*,QtDBus*,QtDesigner*,QtHelp*,QtMultimedia*,QtNetwork*,QtOpenGL*,QtPositioning*,QtPrintSupport*,QtQml*,QtQuick*,QtRemoteObjects*,QtScxml*,QtSensors*,QtSerialPort*,QtSql*,QtStateMachine*,QtSvg*,QtTest*,QtWeb*,QtXml*}
|
||||
- shopt -s extglob
|
||||
- rm -rf AppDir/usr/local/lib/python3.10/dist-packages/PySide6/Qt/lib/!(libQt6OpenGL*|libQt6XcbQpa*|libQt6Wayland*|libQt6Egl*|libicudata*|libicuuc*|libicui18n*|libQt6DBus*|libQt6Network*|libQt6Qml*|libQt6Core*|libQt6Gui*|libQt6Widgets*|libQt6Svg*|libQt6UiTools*)
|
||||
- rm -rf AppDir/usr/local/lib/python3.12/dist-packages/PySide6/Qt/lib/!(libQt6OpenGL*|libQt6XcbQpa*|libQt6Wayland*|libQt6Egl*|libicudata*|libicuuc*|libicui18n*|libQt6DBus*|libQt6Network*|libQt6Qml*|libQt6Core*|libQt6Gui*|libQt6Widgets*|libQt6Svg*|libQt6UiTools*)
|
||||
- python3 -m build
|
||||
- find dist -type f -name *.whl -exec python3 -m pip install --ignore-installed --prefix=/usr --no-cache-dir --root=AppDir {} \;
|
||||
|
||||
|
||||
AppDir:
|
||||
@@ -25,7 +27,7 @@ AppDir:
|
||||
icon: OneDriveGUI
|
||||
version: 1.3.2
|
||||
exec: usr/bin/python3.10
|
||||
exec_args: "$APPDIR/usr/src/OneDriveGUI.py $@"
|
||||
exec_args: "-m onedrive_gui $@"
|
||||
|
||||
apt:
|
||||
arch: amd64
|
||||
|
||||
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
||||
global-include *.png *.ui default_config *.autosave
|
||||
19
README.md
@@ -50,6 +50,21 @@ A GUI for [Linux OneDrive Client](https://github.com/abraunegg/onedrive) with mu
|
||||
## AUR
|
||||
- An AUR package [onedrivegui-git](https://aur.archlinux.org/packages/onedrivegui-git) is available (maintainer: Integral).
|
||||
|
||||
## Python Package
|
||||
|
||||
Use setuptools and build to build the package:
|
||||
|
||||
```
|
||||
python3 -m pip install setuptools build
|
||||
python3 -m build
|
||||
```
|
||||
|
||||
That produces a wheel package in the directory `dist/` than can be installed:
|
||||
|
||||
```
|
||||
python3 -m pip install dist/onedrive_gui-1.3.2-py3-none-any.whl
|
||||
```
|
||||
|
||||
## Running from Source
|
||||
|
||||
1) Ensure Python3 and [pip](https://pip.pypa.io/en/stable/installation/) are installed on your system.
|
||||
@@ -66,13 +81,13 @@ A GUI for [Linux OneDrive Client](https://github.com/abraunegg/onedrive) with mu
|
||||
1) Start OneDrive GUI:
|
||||
```sh
|
||||
cd src/
|
||||
python3 OneDriveGUI.py
|
||||
python3 -m onedrive_gui
|
||||
```
|
||||
|
||||
Optionally, you can detach the GUI from the terminal by using the command below:
|
||||
```sh
|
||||
cd src/
|
||||
nohup python3 OneDriveGUI.py > /dev/null 2>&1 &
|
||||
nohup python3 -m onedrive_gui > /dev/null 2>&1 &
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Step 1: Function to extract version from OneDriveGUI.py without importing
|
||||
get_version() {
|
||||
FILE_PATH="src/options.py"
|
||||
FILE_PATH="src/onedrive_gui/options.py"
|
||||
VERSION=$(grep -Po '^version\s*=\s*"\K[^\"]+' "$FILE_PATH")
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
@@ -28,7 +28,22 @@ update_yaml() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Step 3: Build the AppImage using appimage-builder
|
||||
# Step 3: Update the indented version line in pyproject.toml
|
||||
update_pyproject() {
|
||||
PYPROJECT_TOML_FILE="pyproject.toml"
|
||||
|
||||
if [ -f "$PYPROJECT_TOML_FILE" ]; then
|
||||
echo "Updating version in $PYPROJECT_TOML_FILE..."
|
||||
# Use sed to match the indented version line and update it
|
||||
sed -i "s/^\(version =\).*/\1 \"$VERSION\"/" "$PYPROJECT_TOML_FILE"
|
||||
echo "Version updated to $VERSION in the indented version line of $PYPROJECT_TOML_FILE"
|
||||
else
|
||||
echo "$PYPROJECT_TOML_FILE not found."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Step 4: Build the AppImage using appimage-builder
|
||||
build_appimage() {
|
||||
if ! command -v appimage-builder &> /dev/null; then
|
||||
echo "appimage-builder could not be found. Please install it first."
|
||||
@@ -49,4 +64,5 @@ build_appimage() {
|
||||
# Main script execution
|
||||
get_version
|
||||
update_yaml
|
||||
update_pyproject
|
||||
build_appimage
|
||||
|
||||
@@ -34,7 +34,15 @@ docker run \
|
||||
set -e
|
||||
echo "Installing dependencies..."
|
||||
apt update
|
||||
apt install -y wget python3 python3-pip fuse gtk-update-icon-cache
|
||||
apt install -y \
|
||||
fuse \
|
||||
gtk-update-icon-cache \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
wget
|
||||
|
||||
pip install build setuptools
|
||||
|
||||
echo "Installing appimage-builder..."
|
||||
wget -q -O /tmp/appimage-builder.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
|
||||
|
||||
14
pyproject.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[project]
|
||||
name = "onedrive-gui"
|
||||
version = "1.3.2"
|
||||
description = "A simple GUI for Linux OneDrive Client, with multi-account support."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license-files = ["LICENSE"]
|
||||
|
||||
[project.scripts]
|
||||
onedrive-gui = "onedrive_gui.OneDriveGUI:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools >= 61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
@@ -10,10 +10,10 @@ from PySide6.QtGui import QIcon
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
|
||||
from logger import logger
|
||||
from .logger import logger
|
||||
|
||||
|
||||
from global_config import DIR_PATH
|
||||
from .global_config import DIR_PATH
|
||||
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
@@ -22,15 +22,20 @@ app.setDesktopFileName("OneDriveGUI")
|
||||
app.setWindowIcon(QIcon(DIR_PATH + "/resources/images/icons8-cloud-80.png"))
|
||||
|
||||
|
||||
from options import gui_settings, global_config, version
|
||||
from global_config import save_global_config
|
||||
from main_window import MainWindow
|
||||
from .options import gui_settings, global_config, version
|
||||
from .global_config import save_global_config
|
||||
from .main_window import MainWindow
|
||||
|
||||
workers = {}
|
||||
|
||||
def main_window_start_state():
|
||||
# Determine if OneDriveGUI should start maximized, minimized to tray or minimized to taskbar/dock.
|
||||
# This should help ensure the GUI does not just disappear on Gnome without system tray extension.
|
||||
def main():
|
||||
logging.info(f"Starting OneDriveGUI v{version}")
|
||||
|
||||
if len(global_config) > 0:
|
||||
save_global_config(global_config)
|
||||
|
||||
main_window = MainWindow()
|
||||
|
||||
if gui_settings.get("start_minimized") == "True" or len(global_config) == 0:
|
||||
try:
|
||||
if main_window.tray.isSystemTrayAvailable():
|
||||
@@ -45,16 +50,5 @@ def main_window_start_state():
|
||||
logging.info("[GUI] Starting OneDriveGUI maximized")
|
||||
|
||||
|
||||
workers = {}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.info(f"Starting OneDriveGUI v{version}")
|
||||
|
||||
if len(global_config) > 0:
|
||||
save_global_config(global_config)
|
||||
|
||||
main_window = MainWindow()
|
||||
main_window_start_state()
|
||||
|
||||
app.exec()
|
||||
|
||||
3
src/onedrive_gui/__main__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .OneDriveGUI import main
|
||||
|
||||
main()
|
||||
@@ -3,19 +3,19 @@ from PySide6.QtWidgets import QWidget, QFileDialog
|
||||
|
||||
|
||||
# Imports for GUI settings window
|
||||
from ui.ui_gui_settings_window import Ui_gui_settings_window
|
||||
from .ui.ui_gui_settings_window import Ui_gui_settings_window
|
||||
|
||||
|
||||
import re
|
||||
import os
|
||||
|
||||
from settings.gui_settings import gui_settings
|
||||
from .settings.gui_settings import gui_settings
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
# from logger import logger
|
||||
from global_config import DIR_PATH, PROFILES_FILE
|
||||
from .global_config import DIR_PATH, PROFILES_FILE
|
||||
|
||||
|
||||
class GuiSettingsWindow(QWidget, Ui_gui_settings_window):
|
||||
@@ -119,7 +119,7 @@ class GuiSettingsWindow(QWidget, Ui_gui_settings_window):
|
||||
|
||||
def sync_autostart_on_startup(self):
|
||||
"""Sync autostart file with saved setting on app startup."""
|
||||
from utils.autostart import enable_autostart, disable_autostart, is_autostart_enabled
|
||||
from .utils.autostart import enable_autostart, disable_autostart, is_autostart_enabled
|
||||
|
||||
# Get the saved setting
|
||||
autostart_should_be_enabled = self.get_check_box_state("autostart_enabled")
|
||||
@@ -150,7 +150,7 @@ class GuiSettingsWindow(QWidget, Ui_gui_settings_window):
|
||||
|
||||
def save_settings(self):
|
||||
"""Save all settings and sync autostart file with checkbox state."""
|
||||
from utils.autostart import enable_autostart, disable_autostart
|
||||
from .utils.autostart import enable_autostart, disable_autostart
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
# Save all settings first
|
||||
@@ -3,7 +3,7 @@ import sys
|
||||
import re
|
||||
import logging
|
||||
import logging.handlers as handlers
|
||||
from settings.gui_settings import gui_settings
|
||||
from .settings.gui_settings import gui_settings
|
||||
|
||||
|
||||
def config_debug_level():
|
||||
@@ -15,12 +15,12 @@ from PySide6.QtWidgets import (
|
||||
|
||||
|
||||
# Imports for main window.
|
||||
from ui.ui_mainwindow import Ui_MainWindow
|
||||
from ui.ui_process_status_page import Ui_status_page
|
||||
from .ui.ui_mainwindow import Ui_MainWindow
|
||||
from .ui.ui_process_status_page import Ui_status_page
|
||||
|
||||
|
||||
# Import for login windows.
|
||||
from ui.ui_external_login import Ui_ExternalLoginWindow
|
||||
from .ui.ui_external_login import Ui_ExternalLoginWindow
|
||||
|
||||
|
||||
import re
|
||||
@@ -31,27 +31,27 @@ import requests
|
||||
import subprocess
|
||||
|
||||
|
||||
from wizard import setup_wizard
|
||||
from profile_settings_window import profile_settings_window
|
||||
from .wizard import setup_wizard
|
||||
from .profile_settings_window import profile_settings_window
|
||||
|
||||
from options import (
|
||||
from .options import (
|
||||
global_config,
|
||||
client_bin_path,
|
||||
gui_settings,
|
||||
version,
|
||||
)
|
||||
|
||||
from utils.utils import humanize_file_size, shorten_path, format_relative_time
|
||||
from workers import WorkerThread, MaintenanceWorker, TaskList, workers
|
||||
from gui_settings_window import gui_settings_window
|
||||
from .utils.utils import humanize_file_size, shorten_path, format_relative_time
|
||||
from .workers import WorkerThread, MaintenanceWorker, TaskList, workers
|
||||
from .gui_settings_window import gui_settings_window
|
||||
|
||||
import logging
|
||||
|
||||
# from logger import logger
|
||||
from global_config import DIR_PATH, PROFILES_FILE, save_global_config
|
||||
from .global_config import DIR_PATH, PROFILES_FILE, save_global_config
|
||||
|
||||
try:
|
||||
from ui.ui_login import Ui_LoginWindow
|
||||
from .ui.ui_login import Ui_LoginWindow
|
||||
except ImportError:
|
||||
logging.warning("Failed to import ui_login. This is expected if you are running AppImage version.")
|
||||
|
||||
@@ -66,12 +66,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
def __init__(self):
|
||||
# Expose this instance as main_window.main_window_instance so other modules
|
||||
# (e.g. profile_settings_window) can reach it without a circular import.
|
||||
import main_window
|
||||
from . import main_window
|
||||
|
||||
main_window.main_window_instance = self
|
||||
|
||||
# Access setup_wizard from wizard module to avoid circular imports
|
||||
import wizard
|
||||
from . import wizard
|
||||
|
||||
wizard.setup_wizard.show_main_window_signal.connect(self.show)
|
||||
wizard.setup_wizard.add_profile_signal.connect(self.add_profile)
|
||||
@@ -1,8 +1,8 @@
|
||||
import copy
|
||||
from utils.utils import get_installed_client_version, config_client_bin_path
|
||||
from global_config import create_global_config
|
||||
from .utils.utils import get_installed_client_version, config_client_bin_path
|
||||
from .global_config import create_global_config
|
||||
|
||||
from settings.gui_settings import gui_settings
|
||||
from .settings.gui_settings import gui_settings
|
||||
|
||||
client_bin_path = gui_settings.get("frameless_window")
|
||||
|
||||
@@ -12,8 +12,8 @@ from PySide6.QtWidgets import (
|
||||
)
|
||||
|
||||
# Imports for Profiles windows.
|
||||
from ui.ui_profile_settings_window import Ui_profile_settings_window
|
||||
from ui.ui_profile_settings_page import Ui_profile_settings
|
||||
from .ui.ui_profile_settings_window import Ui_profile_settings_window
|
||||
from .ui.ui_profile_settings_page import Ui_profile_settings
|
||||
|
||||
import re
|
||||
import os
|
||||
@@ -22,20 +22,20 @@ import subprocess
|
||||
from configparser import ConfigParser
|
||||
|
||||
# Import setup_wizard after importing wizard, keeping it at the bottom to avoid circular imports
|
||||
import wizard
|
||||
from global_config import save_global_config
|
||||
from . import wizard
|
||||
from .global_config import save_global_config
|
||||
|
||||
# Import main_window (lazy import to avoid circular references)
|
||||
import main_window
|
||||
from options import client_bin_path, global_config
|
||||
from options import temp_global_config
|
||||
from . import main_window
|
||||
from .options import client_bin_path, global_config
|
||||
from .options import temp_global_config
|
||||
|
||||
from workers import workers
|
||||
from .workers import workers
|
||||
|
||||
import logging
|
||||
|
||||
# from logger import logger
|
||||
from global_config import DIR_PATH, PROFILES_FILE
|
||||
from .global_config import DIR_PATH, PROFILES_FILE
|
||||
|
||||
|
||||
class ProfileSettingsWindow(QWidget, Ui_profile_settings_window):
|
||||
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 511 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 169 B After Width: | Height: | Size: 169 B |
|
Before Width: | Height: | Size: 291 B After Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 629 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
1
src/onedrive_gui/settings/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# do not delete
|
||||
1
src/onedrive_gui/utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# do not delete
|
||||
@@ -6,7 +6,7 @@ from datetime import datetime
|
||||
import logging
|
||||
# from logger import logger
|
||||
|
||||
from settings.gui_settings import gui_settings
|
||||
from ..settings.gui_settings import gui_settings
|
||||
|
||||
|
||||
def humanize_file_size(num, suffix="B"):
|
||||
@@ -22,8 +22,8 @@ import requests
|
||||
import subprocess
|
||||
from configparser import ConfigParser
|
||||
|
||||
from global_config import save_global_config, read_config
|
||||
from options import (
|
||||
from .global_config import save_global_config, read_config
|
||||
from .options import (
|
||||
global_config,
|
||||
temp_global_config,
|
||||
client_bin_path,
|
||||
@@ -31,9 +31,9 @@ from options import (
|
||||
version,
|
||||
)
|
||||
|
||||
from workers import MaintenanceWorker
|
||||
from .workers import MaintenanceWorker
|
||||
import logging
|
||||
from global_config import DIR_PATH, PROFILES_FILE
|
||||
from .global_config import DIR_PATH, PROFILES_FILE
|
||||
|
||||
|
||||
class SetupWizard(QWizard):
|
||||
@@ -5,7 +5,7 @@ from PySide6.QtGui import QFontMetrics, QIcon
|
||||
|
||||
|
||||
# Imports for main window.
|
||||
from ui.ui_list_item_widget import Ui_list_item_widget
|
||||
from .ui.ui_list_item_widget import Ui_list_item_widget
|
||||
|
||||
|
||||
import re
|
||||
@@ -13,8 +13,8 @@ import time
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
from global_config import save_global_config
|
||||
from options import (
|
||||
from .global_config import save_global_config
|
||||
from .options import (
|
||||
# main_window,
|
||||
global_config,
|
||||
temp_global_config,
|
||||
@@ -24,13 +24,13 @@ from options import (
|
||||
version,
|
||||
)
|
||||
|
||||
from utils.utils import humanize_file_size, shorten_path
|
||||
from .utils.utils import humanize_file_size, shorten_path
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
# from logger import logger
|
||||
from global_config import DIR_PATH, PROFILES_FILE
|
||||
from .global_config import DIR_PATH, PROFILES_FILE
|
||||
|
||||
|
||||
class WorkerThread(QThread):
|
||||