Skip to content

Commit

Permalink
Various improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
probonopd committed Feb 15, 2025
1 parent e8d886e commit 965dec3
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 163 deletions.
209 changes: 122 additions & 87 deletions install.py
Original file line number Diff line number Diff line change
@@ -1,104 +1,139 @@

#!/usr/bin/env python3
import sys, os, subprocess, venv, time

import sys
import os
import subprocess
import venv
import threading
import time

# Configurations
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
VENV_DIR = os.path.join(BASE_DIR, "venv")
SIRACUSA_SCRIPT = os.path.join(BASE_DIR, "siracusa.py")
REQUIREMENTS_FILE = (
os.path.join(BASE_DIR, "requirements-windows.txt")
if sys.platform == "win32"
else os.path.join(BASE_DIR, "requirements-linux.txt")
)
REQUIREMENTS_FILE = os.path.join(BASE_DIR, "requirements-windows.txt") if sys.platform == "win32" else os.path.join(BASE_DIR, "requirements-linux.txt")

# Function to log messages with timestamps
def log(message):
timestamp = time.strftime("[%H:%M:%S]", time.localtime())
print(f"{timestamp} {message}")

# Function to create a virtual environment if it doesn't exist
def create_virtual_env():
def main():
timestamp = lambda: time.strftime("[%H:%M:%S]", time.localtime())
print(f"{timestamp()} Starting setup process...")

# Ensure pip is installed on systems that require a system-level install
print(f"{timestamp()} Install pip...")
if os.path.exists("/etc/debian_version"):
print(f"{timestamp()} Installing pip for Debian/Ubuntu...")
if os.system("sudo apt update") != 0 or os.system("sudo apt install -y python3-pip") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on Debian/Ubuntu.")
sys.exit(1)
elif os.path.exists("/etc/redhat-release"):
print(f"{timestamp()} Installing pip for Fedora/RedHat...")
if os.system("sudo dnf install -y python3-pip") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on Fedora/RedHat.")
sys.exit(1)
elif os.path.exists("/etc/SuSE-release"):
print(f"{timestamp()} Installing pip for SUSE...")
if os.system("sudo zypper install -y python3-pip") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on SUSE.")
sys.exit(1)
elif os.path.exists("/etc/arch-release"):
print(f"{timestamp()} Installing pip for Arch/Arch-based...")
if os.system("sudo pacman -S --noconfirm python-pip") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on Arch.")
sys.exit(1)
elif os.path.exists("/etc/gentoo-release"):
print(f"{timestamp()} Installing pip for Gentoo...")
if os.system("sudo emerge -av app-admin/python-updater") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on Gentoo.")
sys.exit(1)
elif os.path.exists("/etc/alpine-release"):
print(f"{timestamp()} Installing pip for Alpine...")
if os.system("sudo apk add py3-pip") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on Alpine.")
sys.exit(1)
elif sys.platform == "darwin":
print(f"{timestamp()} Installing pip for MacOS...")
if os.system("brew install python3") != 0:
print(f"{timestamp()} ❌ Error: Failed to install pip on MacOS.")
sys.exit(1)

# Check requirements file
if not os.path.exists(REQUIREMENTS_FILE):
print(f"{timestamp()} Error: The requirements file '{REQUIREMENTS_FILE}' is missing.")
sys.exit(1)

# Create virtual environment if needed
if not os.path.exists(VENV_DIR):
log("Creating virtual environment...")
print(f"{timestamp()} Creating virtual environment...")
venv.create(VENV_DIR, with_pip=True)
log(f"Virtual environment created at {VENV_DIR}.")
print(f"{timestamp()} Virtual environment created at {VENV_DIR}.")
else:
log("Virtual environment already exists.")

# Function to install dependencies
def install_dependencies():
if not os.path.exists(REQUIREMENTS_FILE):
log(f"Error: The requirements file '{REQUIREMENTS_FILE}' is missing.")
return False

create_virtual_env()

# Path to the pip executable inside the virtual environment
pip_path = (
os.path.join(VENV_DIR, "Scripts", "pip.exe")
if sys.platform == "win32"
else os.path.join(VENV_DIR, "bin", "pip")
)

print(f"{timestamp()} Virtual environment already exists.")

# Install dependencies
pip_path = os.path.join(VENV_DIR, "Scripts", "pip.exe") if sys.platform == "win32" else os.path.join(VENV_DIR, "bin", "pip")
if not os.path.exists(pip_path):
log("Error: pip is missing in the virtual environment.")
return False

log(f"Installing dependencies from {REQUIREMENTS_FILE}...")
print(f"{timestamp()} Error: pip is missing in the virtual environment.")
sys.exit(1)

result = subprocess.run(
[pip_path, "install", "-r", REQUIREMENTS_FILE],
capture_output=True,
text=True
)

if result.returncode == 0:
log("✅ Installation completed successfully!")
return True
else:
log(f"❌ Error: Installation failed. Details:\n{result.stderr}")
return False

# Function to run siracusa.py inside the virtual environment
def run_siracusa():
print(f"{timestamp()} Installing dependencies from {REQUIREMENTS_FILE}...")
result = subprocess.run([pip_path, "install", "-r", REQUIREMENTS_FILE], capture_output=True, text=True)
if result.returncode != 0:
print(f"{timestamp()} ❌ Error: Installation failed. Details:\n{result.stderr}")
sys.exit(1)
print(f"{timestamp()} ✅ Installation completed successfully!")

if not os.path.exists("icons/elementary-xfce"):
print(f"{timestamp()} Downloading icons...")
import requests
url = "http://archive.ubuntu.com/ubuntu/pool/universe/x/xubuntu-artwork/xubuntu-artwork_16.04.2.tar.xz"
filename = url.split("/")[-1]
response = requests.get(url)
with open(filename, "wb") as f:
f.write(response.content)
print(f"{timestamp()} Downloaded 'xubuntu-artwork_16.04.2.tar.xz' from {url}")
if not os.path.exists("icons"):
os.makedirs("icons")
# Unpack but only the subdirectory elementary-xfce to icons/
print(f"{timestamp()} Extracting icons...")
import tarfile
with tarfile.open(filename, "r:xz") as tar:
# Extract "trunk/usr/share/icons/elementary-xfce" to "icons/elementary-xfce" (need to strip the first directories)
for member in tar.getmembers():
if member.name.startswith("trunk/usr/share/icons/elementary-xfce"):
member.name = member.name.replace("trunk/usr/share/icons/", "")
tar.extract(member, path="icons/")
print(f"{timestamp()} Extracted 'elementary-xfce' to 'icons/'")
os.remove(filename)

# Fonts
if not sys.platform == "win32":
if not os.path.exists("fonts/Inter-Regular.ttf") or not os.path.exists("fonts/Inter-Bold.ttf") or not os.path.exists("fonts/Inter-Italic.ttf") or not os.path.exists("fonts/Inter-BoldItalic.ttf"):
print(f"{timestamp()} Downloading fonts...")
import requests
urls = [
"https://github.com/rdey/rdey-packages/raw/refs/heads/master/design/fonts/Inter-Regular.ttf",
"https://github.com/rdey/rdey-packages/raw/refs/heads/master/design/fonts/Inter-Bold.ttf",
"https://github.com/rdey/rdey-packages/raw/refs/heads/master/design/fonts/Inter-Italic.ttf",
"https://github.com/rdey/rdey-packages/raw/refs/heads/master/design/fonts/Inter-BoldItalic.ttf"
]
if not os.path.exists("fonts"):
os.makedirs("fonts")
for url in urls:
filename = url.split("/")[-1]
response = requests.get(url)
with open(os.path.join("fonts", filename), "wb") as f:
f.write(response.content)
print(f"{timestamp()} Downloaded '{filename}' from {url}")
print(f"{timestamp()} Downloaded fonts to 'fonts/'")

# Run siracusa.py
if not os.path.exists(SIRACUSA_SCRIPT):
log(f"Error: The script '{SIRACUSA_SCRIPT}' is missing.")
return

python_executable = (
os.path.join(VENV_DIR, "Scripts", "python.exe")
if sys.platform == "win32"
else os.path.join(VENV_DIR, "bin", "python")
)

if not os.path.exists(python_executable):
log("Error: Python executable not found in virtual environment.")
return

log(f"Running '{SIRACUSA_SCRIPT}' inside virtual environment...")
result = subprocess.run([python_executable, SIRACUSA_SCRIPT], text=True)

if result.returncode == 0:
log("✅ 'siracusa.py' executed successfully!")
else:
log(f"❌ Error: 'siracusa.py' exited with code {result.returncode}")

# Function to execute installation and run the script
def main():
log("Starting setup process...")
print(f"{timestamp()} Error: The script '{SIRACUSA_SCRIPT}' is missing.")
sys.exit(1)

install_thread = threading.Thread(target=install_dependencies, daemon=True)
install_thread.start()
install_thread.join() # Wait for installation to complete
python_executable = os.path.join(VENV_DIR, "Scripts", "python.exe") if sys.platform == "win32" else os.path.join(VENV_DIR, "bin", "python")
if not os.path.exists(python_executable):
print(f"{timestamp()} Error: Python executable not found in virtual environment.")
sys.exit(1)

run_siracusa() # Run siracusa.py after dependencies are installed
print(f"{timestamp()} Running '{SIRACUSA_SCRIPT}' inside virtual environment...")
result = subprocess.run([python_executable, SIRACUSA_SCRIPT], text=True)
if result.returncode != 0:
print(f"{timestamp()} ❌ Error: 'siracusa.py' exited with code {result.returncode}")
sys.exit(1)
print(f"{timestamp()} ✅ 'siracusa.py' executed successfully!")

if __name__ == "__main__":
main()
5 changes: 1 addition & 4 deletions main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
import sys, os
import appimage

# FIXME: Import Qt like this: from PyQt6 import QtWidgets, QtGui, QtCore, QtWebEngineWidgets
# FIXME: Import Qt like this: from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QListView, QWidget, QAbstractItemView, QMessageBox, QLabel, QTextEdit, QStackedWidget, QInputDialog, QMenu, QStyle
from PyQt6.QtCore import QSettings, QByteArray, Qt, QDir, QModelIndex, QUrl, QMimeData
from PyQt6.QtGui import QFileSystemModel, QAction, QPixmap, QDrag, QCursor, QIcon
from PyQt6.QtWebEngineWidgets import QWebEngineView # pip install PyQt6-WebEngine
import mimetypes
if sys.platform == 'win32':
from windows_integration import show_context_menu
Expand Down Expand Up @@ -183,7 +182,6 @@ def create_preview_panel(self):
self.text_preview.setReadOnly(True)
self.image_preview = QLabel()
self.image_preview.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.pdf_preview = QWebEngineView()

self.preview_panel.setFixedWidth(200)

Expand All @@ -194,7 +192,6 @@ def create_preview_panel(self):

self.preview_panel.addWidget(self.text_preview)
self.preview_panel.addWidget(self.image_preview)
self.preview_panel.addWidget(self.pdf_preview)

def quit_application(self):
app = QApplication.instance()
Expand Down
4 changes: 3 additions & 1 deletion siracusa.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ def __init__(self, file_path: str, pos, width = item_width, height = item_height

self.drag_start_position = None

if os.path.ismount(file_path):

storage_info = QtCore.QStorageInfo(file_path)
if storage_info.isValid() and storage_info.isReady() and os.path.ismount(file_path):
storage_info = QtCore.QStorageInfo(file_path)
self.volume_name = storage_info.displayName() or file_path # Store volume name separately
if sys.platform == "win32":
Expand Down
87 changes: 44 additions & 43 deletions styling.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,54 @@
def apply_styling(app):
app.setStyle("Fusion")

# Load the custom fonts
font_paths = {
"regular": os.path.join(os.path.dirname(__file__), "fonts", "Inter_18pt-Regular.ttf"),
"bold": os.path.join(os.path.dirname(__file__), "fonts", "Inter_18pt-Bold.ttf"),
"italic": os.path.join(os.path.dirname(__file__), "fonts", "Inter_18pt-Italic.ttf"),
"bold_italic": os.path.join(os.path.dirname(__file__), "fonts", "Inter_18pt-BoldItalic.ttf"),
}
if not sys.platform == "win32":
# Load the custom fonts
font_paths = {
"regular": os.path.join(os.path.dirname(__file__), "fonts", "Inter-Regular.ttf"),
"bold": os.path.join(os.path.dirname(__file__), "fonts", "Inter-Bold.ttf"),
"italic": os.path.join(os.path.dirname(__file__), "fonts", "Inter-Italic.ttf"),
"bold_italic": os.path.join(os.path.dirname(__file__), "fonts", "Inter-BoldItalic.ttf"),
}

# Load each font and set it in the application
fonts = {}
missing_fonts = []
for style, path in font_paths.items():
font_id = QtGui.QFontDatabase.addApplicationFont(path)
if font_id == -1:
missing_fonts.append(style)
else:
font_families = QtGui.QFontDatabase.applicationFontFamilies(font_id)
if font_families:
fonts[style] = font_families[0] # Store the family name
# Load each font and set it in the application
fonts = {}
missing_fonts = []
for style, path in font_paths.items():
font_id = QtGui.QFontDatabase.addApplicationFont(path)
if font_id == -1:
missing_fonts.append(style)
else:
font_families = QtGui.QFontDatabase.applicationFontFamilies(font_id)
if font_families:
fonts[style] = font_families[0] # Store the family name

# Show a dialog if any fonts are missing
if missing_fonts:
missing_fonts_str = ", ".join(missing_fonts)
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
msg_box.setText("Missing Fonts")
msg_box.setInformativeText(
f"Oops! It looks like the following fonts are missing: {missing_fonts_str}.\n\n"
"Please download the 'Inter' font family from the following link:\n"
"https://fonts.google.com/specimen/Inter\n\n"
"After downloading, place the font files in the 'fonts' directory located in the same folder as your script."
)
msg_box.setWindowTitle("Font Error")
msg_box.exec()
# Show a dialog if any fonts are missing
if missing_fonts:
missing_fonts_str = ", ".join(missing_fonts)
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
msg_box.setText("Missing Fonts")
msg_box.setInformativeText(
f"Oops! It looks like the following fonts are missing: {missing_fonts_str}.\n\n"
"Please download the 'Inter' font family from the following link:\n"
"https://fonts.google.com/specimen/Inter\n\n"
"After downloading, place the font files in the 'fonts' directory located in the same folder as your script."
)
msg_box.setWindowTitle("Font Error")
msg_box.exec()

# Set the default font
if "regular" in fonts:
default_font = QtGui.QFont(fonts["regular"], 9) # Use the regular font
app.setFont(default_font)
# Set the default font
if "regular" in fonts:
default_font = QtGui.QFont(fonts["regular"], 9) # Use the regular font
app.setFont(default_font)

# Create font instances for bold, italic, and bold-italic
if "bold" in fonts:
bold_font = QtGui.QFont(fonts["bold"], 9, QtGui.QFont.Weight.Bold)
if "italic" in fonts:
italic_font = QtGui.QFont(fonts["italic"], 9, QtGui.QFont.Weight.Normal, True)
if "bold_italic" in fonts:
bold_italic_font = QtGui.QFont(fonts["bold_italic"], 9, QtGui.QFont.Weight.Bold, True)
# Create font instances for bold, italic, and bold-italic
if "bold" in fonts:
bold_font = QtGui.QFont(fonts["bold"], 9, QtGui.QFont.Weight.Bold)
if "italic" in fonts:
italic_font = QtGui.QFont(fonts["italic"], 9, QtGui.QFont.Weight.Normal, True)
if "bold_italic" in fonts:
bold_italic_font = QtGui.QFont(fonts["bold_italic"], 9, QtGui.QFont.Weight.Bold, True)

# Set highlight color for selected items to blue
palette = app.palette()
Expand Down
Loading

0 comments on commit 965dec3

Please sign in to comment.