Skip to content

Commit

Permalink
FIx styling issues
Browse files Browse the repository at this point in the history
  • Loading branch information
probonopd committed Feb 18, 2025
1 parent 06ff3dd commit af88749
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 128 deletions.
20 changes: 5 additions & 15 deletions main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@
including file navigation, status bar updates, etc.
"""

# FIXME: For whatever strange reason we need to do this here or else Windows will say
# QWidget: Must construct a QApplication before a QWidget
import sys
from PyQt6 import QtWidgets
app = QtWidgets.QApplication(sys.argv)

import os
import os, sys

# 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
Expand All @@ -26,6 +20,8 @@

import menus, toolbar, status_bar, getinfo, appimage

from styling import Styling

class CustomFileSystemModel(QFileSystemModel):
"""
Custom file system model that allows us to customize e.g., the icons being used.
Expand Down Expand Up @@ -595,7 +591,8 @@ def empty_trash(self):
QtWidgets.QMessageBox.critical(self, "Error", f"Failed to empty trash: {e}")

if __name__ == "__main__":
# app = QApplication(sys.argv) # See the top of this file
app = QApplication(sys.argv)
s = Styling(app)

# Output not only to the console but also to the GUI
try:
Expand All @@ -607,13 +604,6 @@ def empty_trash(self):
sys.stdout = log_console.Tee(sys.stdout, app.log_console)
sys.stderr = log_console.Tee(sys.stderr, app.log_console)

try:
import styling
except ImportError:
pass
if "styling" in sys.modules:
styling.apply_styling(app)

app.setWindowIcon(app.style().standardIcon(QStyle.StandardPixmap.SP_DirIcon))
window = MillerColumns()
window.show()
Expand Down
4 changes: 2 additions & 2 deletions menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

if sys.platform == "win32":
import win32gui, win32con, win32ui # For managing windows
import window_start_menu
import windows_start_menu

class ColorMenu(QtWidgets.QMenu):
def __init__(self, title, window):
Expand Down Expand Up @@ -89,7 +89,7 @@ def create_menus(window):

# Start Menu
if sys.platform == "win32" and window.is_desktop_window:
start_menu = window_start_menu.StartMenu(window)
start_menu = windows_start_menu.StartMenu(window)
left_menubar.addMenu(start_menu)

# File Menu
Expand Down
23 changes: 6 additions & 17 deletions siracusa.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
# A file manager in Python?
# "These days I prefer programming in Python... it's beautiful, exppressive, and simple" - Andy Hertzfeld, https://youtu.be/kqm7ahl2ZYg?feature=shared&t=3705

# FIXME: For whatever strange reason we need to do this here or else Windows will say
# QWidget: Must construct a QApplication before a QWidget
import sys
from PyQt6 import QtWidgets
app = QtWidgets.QApplication(sys.argv)

"""
A spatial file manager (“Siracusa style spatial Filer) implemented in PyQt6.
Features:
Expand Down Expand Up @@ -61,15 +55,13 @@

import getinfo, menus, fileops, appimage

from styling import Styling

LAYOUT_FILENAME = "._layout.json"

item_width = grid_width = 100
item_height = grid_height = 60

from styling import setup_icon_theme
setup_icon_theme()
icon_provider = QtWidgets.QFileIconProvider()

# DriveWatcher: Detects newly inserted drives and updates the UI
class DriveWatcher(QtCore.QThread):
newDriveDetected = QtCore.pyqtSignal(str)
Expand Down Expand Up @@ -375,6 +367,7 @@ def paint(self, painter: QtGui.QPainter, option: QtWidgets.QStyleOptionGraphicsI
if self.icon is None:
self.icon = QtGui.QIcon.fromTheme("application-x-executable")
else:
icon_provider = QtWidgets.QFileIconProvider()
self.icon = icon_provider.icon(file_info)
icon_size = QtCore.QSize(32, 32)
self.pixmap = self.icon.pixmap(icon_size)
Expand Down Expand Up @@ -1710,6 +1703,9 @@ def apply_desktop_picture_with_gradient(view, desktop_picture_path, target_width
# Ctrl-C quits
signal.signal(signal.SIGINT, signal.SIG_DFL)

app = QtWidgets.QApplication(sys.argv)
s = Styling(app)

# app = QtWidgets.QApplication(sys.argv) # See top of this file
app.setApplicationName("Spatial")
app.preferences = QtCore.QSettings(app.applicationName())
Expand All @@ -1718,13 +1714,6 @@ def apply_desktop_picture_with_gradient(view, desktop_picture_path, target_width
# Global registry of open windows by folder path.
open_windows = {}

try:
import styling
except ImportError:
pass
if "styling" in sys.modules:
styling.apply_styling(app)

# Reserving space for the menu bar on Windows
if sys.platform == "win32":
appbar = windows_struts.Strut()
Expand Down
204 changes: 113 additions & 91 deletions styling.py
Original file line number Diff line number Diff line change
@@ -1,104 +1,126 @@
import os, sys
from PyQt6 import QtGui, QtCore, QtWidgets

def apply_styling(app):
app.setStyle("Fusion")

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

# Show a dialog if any fonts are missing
if missing_fonts:
missing_fonts_str = ", ".join(missing_fonts)
class Styling:
_instance = None

def __new__(cls, app):
if cls._instance is None:
cls._instance = super(Styling, cls).__new__(cls)
else:
if cls._instance.app != app:
raise Exception("Styling instance already exists with a different QApplication")
cls._instance.init(app)
return cls._instance

def init(self, app):
self.app = app
self.apply_styling()
self.setup_icon_theme()

def resource_path(self, relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)

def apply_styling(self):
app = self.app
app.setStyle("Fusion")

if not sys.platform == "win32":
# Load the custom fonts
font_paths = {
"regular": self.resource_path("fonts/Inter-Regular.ttf"),
"bold": self.resource_path("fonts/Inter-Bold.ttf"),
"italic": self.resource_path("fonts/Inter-Italic.ttf"),
"bold_italic": self.resource_path("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

# 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)

# 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()
palette.setColor(QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(64, 64, 255))
app.setPalette(palette)

# 0px window border in red
app.setStyleSheet("QMainWindow { border: 0px; }")

def setup_icon_theme(self):
# Set icon theme
icon_theme_path = self.resource_path("icons/")
# Check if the icon theme path exists
if not os.path.exists(icon_theme_path):
print(f"Icon theme path does not exist: {icon_theme_path}")

# Check that it contains a folder named elementary-xfce that contains index.theme; if not, show a dialog
if not os.path.exists(os.path.join(icon_theme_path, "elementary-xfce", "index.theme")):
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
msg_box.setText("Missing Fonts")
msg_box.setText("Missing Icon Theme")
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."
"Oops! It looks like the icon theme is missing.\n\n"
"Please download the 'elementary-xfce' icon theme from the following link:\n"
"http://archive.ubuntu.com/ubuntu/pool/universe/x/xubuntu-artwork/xubuntu-artwork_16.04.2.tar.xz\n"
"and extract 'elementary-xfce' to the 'icons' directory located in the same folder as your script."
)
msg_box.setWindowTitle("Font Error")
msg_box.setWindowTitle("Icon Theme 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)

# 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()
palette.setColor(QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(64, 64, 255))
app.setPalette(palette)

# 0px window border in red
app.setStyleSheet("QMainWindow { border: 0px; }")

def setup_icon_theme():
# Set icon theme
icon_theme_path = os.path.join(os.path.dirname(__file__), "icons/")
# Check if the icon theme path exists
if not os.path.exists(icon_theme_path):
print(f"Icon theme path does not exist: {icon_theme_path}")

# Check that it contains a folder named elementary-xfce that contains index.theme; if not, show a dialog
if not os.path.exists(os.path.join(icon_theme_path, "elementary-xfce", "index.theme")):
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
msg_box.setText("Missing Icon Theme")
msg_box.setInformativeText(
"Oops! It looks like the icon theme is missing.\n\n"
"Please download the 'elementary-xfce' icon theme from the following link:\n"
"http://archive.ubuntu.com/ubuntu/pool/universe/x/xubuntu-artwork/xubuntu-artwork_16.04.2.tar.xz\n"
"and extract 'elementary-xfce' to the 'icons' directory located in the same folder as your script."
)
msg_box.setWindowTitle("Icon Theme Error")
msg_box.exec()

# qicon_instance = QtGui.QIcon()
QtGui.QIcon.setThemeSearchPaths([icon_theme_path])
QtGui.QIcon.setThemeName("elementary-xfce")

available_fallback_themes = []
if os.path.exists("/usr/share/icons"):
available_fallback_themes += [d for d in os.listdir("/usr/share/icons") if os.path.isdir(os.path.join("/usr/share/icons", d))]
if os.path.exists("/usr/local/share/icons"):
available_fallback_themes += [d for d in os.listdir("/usr/local/share/icons") if os.path.isdir(os.path.join("/usr/local/share/icons", d))]
print(f"Available fallback themes: {available_fallback_themes}")
QtGui.QIcon.setThemeSearchPaths(QtGui.QIcon.themeSearchPaths() + ["/usr/share/icons", "/usr/local/share/icons"] + [os.path.join("/usr/share/icons", d) for d in available_fallback_themes])
QtGui.QIcon.setFallbackThemeName("hicolor")
# qicon_instance = QtGui.QIcon()
QtGui.QIcon.setThemeSearchPaths([icon_theme_path])
QtGui.QIcon.setThemeName("elementary-xfce")

available_fallback_themes = []
if os.path.exists("/usr/share/icons"):
available_fallback_themes += [d for d in os.listdir("/usr/share/icons") if os.path.isdir(os.path.join("/usr/share/icons", d))]
if os.path.exists("/usr/local/share/icons"):
available_fallback_themes += [d for d in os.listdir("/usr/local/share/icons") if os.path.isdir(os.path.join("/usr/local/share/icons", d))]
print(f"Available fallback themes: {available_fallback_themes}")
QtGui.QIcon.setThemeSearchPaths(QtGui.QIcon.themeSearchPaths() + ["/usr/share/icons", "/usr/local/share/icons"] + [os.path.join("/usr/share/icons", d) for d in available_fallback_themes])
QtGui.QIcon.setFallbackThemeName("hicolor")

if __name__ == "__main__":
setup_icon_theme()
app = QtWidgets.QApplication([])
apply_styling(app)
app = QtWidgets.QApplication(sys.argv)
s = Styling(app)
# Make a window with an icon to test the icon theme
window = QtWidgets.QMainWindow()
window.setWindowIcon(QtGui.QIcon.fromTheme("folder"))
Expand All @@ -113,4 +135,4 @@ def setup_icon_theme():
window.show()

app.lastWindowClosed.connect(app.quit)
app.exec()
app.exec()
5 changes: 2 additions & 3 deletions window_start_menu.py → windows_start_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
from PyQt6 import QtWidgets, QtGui, QtCore
from pylnk3 import Lnk

from styling import setup_icon_theme
setup_icon_theme()
icon_provider = QtWidgets.QFileIconProvider()
from styling import Styling

def resolve_shortcut(lnk_path):
try:
Expand Down Expand Up @@ -178,6 +176,7 @@ def __init__(self):

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
s = Styling(app)
window = StartMenuWindow()
window.show()
sys.exit(app.exec())

0 comments on commit af88749

Please sign in to comment.