diff --git a/log_console.py b/log_console.py index e7acb9e..9a2ca53 100644 --- a/log_console.py +++ b/log_console.py @@ -1,6 +1,6 @@ import sys import io -from PyQt6.QtWidgets import QMainWindow, QPlainTextEdit +from PyQt6.QtWidgets import QMainWindow, QPlainTextEdit, QMessageBox from PyQt6.QtGui import QAction """When running a GUI application, it is useful to have a log console @@ -29,7 +29,7 @@ def __init__(self): lambda: self.log_console.verticalScrollBar().setValue( self.log_console.verticalScrollBar().maximum())) # Should the application ever crash, show the log console - sys.excepthook = self.open_log_console + sys.excepthook = self.show_traceback def write(self, s): # Ignore whitespace @@ -45,11 +45,23 @@ def add_menu_items(self, menu, parent): log_console_action.triggered.connect(self.open_log_console) menu.addAction(log_console_action) + # Accept all parameters of sys.excepthook def open_log_console(self): if self.log_console_window.isVisible(): return self.log_console_window.show() + def show_traceback(self, exc_type, exc_value, tb): + message_box = QMessageBox() + message_box.setIcon(QMessageBox.Icon.Critical) + message_box.setWindowTitle('Error') + message_box.setText(f'{exc_value}') + import traceback + traceback_str = ''.join(traceback.format_exception(exc_type, exc_value, tb)) + message_box.setDetailedText(str(traceback_str)) + message_box.setStandardButtons(QMessageBox.StandardButton.Ok) + message_box.exec() + class Tee(object): def __init__(self, stream1, stream2): self.stream1 = stream1 diff --git a/main_window.py b/main_window.py index a3f4e1e..8ac6b53 100644 --- a/main_window.py +++ b/main_window.py @@ -14,8 +14,9 @@ from PyQt6.QtGui import QFileSystemModel, QAction, QPixmap, QDrag, QCursor from PyQt6.QtWebEngineWidgets import QWebEngineView # pip install PyQt6-WebEngine import mimetypes -from windows_integration import show_context_menu, show_properties -import windows_file_operations +if sys.platform == 'win32': + from windows_integration import show_context_menu, show_properties + import windows_file_operations import menus import toolbar import status_bar diff --git a/spatial.py b/spatial.py index 930be93..82f35eb 100644 --- a/spatial.py +++ b/spatial.py @@ -11,13 +11,13 @@ import shutil from PyQt6.QtCore import Qt, QPoint, QSize, QDir, QRect, QMimeData, QUrl, QFileSystemWatcher, QFileInfo, QTimer -from PyQt6.QtGui import QFontMetrics, QPainter, QPen, QAction, QDrag, QColor, QPainter, QPen, QBrush, QPixmap, QKeySequence, QFont +from PyQt6.QtGui import QFontMetrics, QPainter, QPen, QAction, QDrag, QColor, QPainter, QPen, QBrush, QPixmap, QKeySequence, QFont, QIcon from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QScrollArea, QLabel, QSizePolicy, QMainWindow from PyQt6.QtWidgets import QStatusBar, QComboBox, QFileIconProvider, QMenuBar, QGridLayout, QMessageBox, QMenu, QDialog if sys.platform == "win32": from win32com.client import Dispatch - import winreg + import windows_context_menu class SpatialFiler(QMainWindow): @@ -749,7 +749,12 @@ def align_items_circle(self): item.move(int(new_x), int(new_y)) def show_about(self): - QMessageBox.about(self, "About", "Spatial File Manager\n\nA simple file manager that uses a spatial interface.") + dialog = QMessageBox(self) + dialog.setIconPixmap(app.icon.pixmap(app.icon_size, app.icon_size)) + dialog.setWindowTitle("About") + dialog.setText("Spatial File Manager\n\nA simple file manager that uses a spatial interface.") + dialog.exec() + def robust_filename(path): # Use this instead of os.path.basename to avoid issues on Windows @@ -862,28 +867,33 @@ def text_label_deactivate(self): self.text_label.setStyleSheet("background-color: rgba(255, 255, 255, 0.66); color: black;") def show_context_menu(self, pos): - context_menu = QMenu(self) - self.open_action = QAction("Open", self) - self.open_action.triggered.connect(self.open) - context_menu.addAction(self.open_action) - context_menu.addSeparator() - self.get_info_action = QAction("Get Info", self) - self.get_info_action.triggered.connect(self.get_info) - context_menu.addAction(self.get_info_action) - context_menu.addSeparator() - self.cut_action = QAction("Cut", self) - self.cut_action.setDisabled(True) - context_menu.addAction(self.cut_action) - self.copy_action = QAction("Copy", self) - self.copy_action.setDisabled(True) - context_menu.addAction(self.copy_action) - self.paste_action = QAction("Paste", self) - self.paste_action.setDisabled(True) - context_menu.addAction(self.paste_action) - self.trash_action = QAction("Move to Trash", self) - self.trash_action.setDisabled(True) - context_menu.addAction(self.trash_action) - context_menu.exec(self.mapToGlobal(pos)) + # On Windows, use windows_context_menu.py + if sys.platform == "win32": + import windows_context_menu + windows_context_menu.show_context_menu(self.path) + else: + context_menu = QMenu(self) + self.open_action = QAction("Open", self) + self.open_action.triggered.connect(self.open) + context_menu.addAction(self.open_action) + context_menu.addSeparator() + self.get_info_action = QAction("Get Info", self) + self.get_info_action.triggered.connect(self.get_info) + context_menu.addAction(self.get_info_action) + context_menu.addSeparator() + self.cut_action = QAction("Cut", self) + self.cut_action.setDisabled(True) + context_menu.addAction(self.cut_action) + self.copy_action = QAction("Copy", self) + self.copy_action.setDisabled(True) + context_menu.addAction(self.copy_action) + self.paste_action = QAction("Paste", self) + self.paste_action.setDisabled(True) + context_menu.addAction(self.paste_action) + self.trash_action = QAction("Move to Trash", self) + self.trash_action.setDisabled(True) + context_menu.addAction(self.trash_action) + context_menu.exec(self.mapToGlobal(pos)) def get_info(self): dialog = QDialog(self) @@ -976,6 +986,7 @@ def get_desktop_directory(): app.desktop_settings_file = ".DS_Spatial" app.trash_name = "Trash" app.icon_size = 32 + app.icon = QFileIconProvider().icon(QFileIconProvider.IconType.Folder) # Output not only to the console but also to the GUI try: @@ -987,8 +998,6 @@ def get_desktop_directory(): sys.stdout = log_console.Tee(sys.stdout, app.log_console) sys.stderr = log_console.Tee(sys.stderr, app.log_console) - - for screen in QApplication.screens(): # TODO: Possibly only create the desktop window on the primary screen and just show a background image on the other screens desktop = SpatialFiler(get_desktop_directory(), is_desktop_window = True)