Skip to content

Commit

Permalink
Find desktop directory more robust; add log console
Browse files Browse the repository at this point in the history
  • Loading branch information
probonopd committed Jul 28, 2024
1 parent a12cae0 commit a013782
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 10 deletions.
68 changes: 68 additions & 0 deletions log_console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import sys
import io
from PyQt6.QtWidgets import QMainWindow, QPlainTextEdit
from PyQt6.QtGui import QAction

"""When running a GUI application, it is useful to have a log console
since the standard output and standard error streams are not visible.
This module provides a log console that can be opened from the application's
menu bar. It is a simple text window that displays the output of sys.stdout
and sys.stderr. The log console is not shown by default, but can be opened
from the application's menu bar.
"""

class ConsoleOutputStream(io.TextIOBase):
def __init__(self):
self.log_console = QPlainTextEdit()
self.log_console.setReadOnly(True)
self.log_console_window = QMainWindow()
self.log_console_window.setCentralWidget(self.log_console)
self.log_console_window.setGeometry(0, 300, 600, 300)
screen_geometry = self.log_console_window.screen().geometry()
screen_height = screen_geometry.height()
window_geometry = self.log_console_window.geometry()
window_height = window_geometry.height()
self.log_console_window.setGeometry(0, screen_height - window_height, 600, 300)
self.log_console_window.setWindowTitle('Log Console')
# Autoscroll to the bottom
self.log_console.verticalScrollBar().rangeChanged.connect(
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

def write(self, s):
# Ignore whitespace
if s.isspace():
return
# Remove newline characters; does not seem to work
s = s.rstrip()
self.log_console.appendHtml(s)

def add_menu_items(self, menu, parent):
menu.addSeparator()
log_console_action = QAction('Open Log Console', parent)
log_console_action.triggered.connect(self.open_log_console)
menu.addAction(log_console_action)

def open_log_console(self):
if self.log_console_window.isVisible():
return
self.log_console_window.show()

class Tee(object):
def __init__(self, stream1, stream2):
self.stream1 = stream1
self.stream2 = stream2

def write(self, data):
self.stream1.write(data)
self.stream2.write(data)

def flush(self):
self.stream1.flush()
self.stream2.flush()

"""app.log_console = log_console.ConsoleOutputStream()
sys.stdout = log_console.Tee(sys.stdout, app.log_console)
sys.stderr = log_console.Tee(sys.stderr, app.log_console)"""
52 changes: 42 additions & 10 deletions spatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ def __init__(self, path=None, is_desktop_window=False):
self.timer.start(5000)
self.update_status_bar()


# Watch for changes in the directory
self.file_watcher = QFileSystemWatcher()
self.file_watcher.directoryChanged.connect(self.directory_changed)
Expand Down Expand Up @@ -254,8 +253,6 @@ def init_menu_bar(self):
up_and_close_current_action.setShortcut("Shift+Ctrl+Up")
up_and_close_current_action.triggered.connect(self.open_parent_and_close_current)
if not os.path.exists(parent) or os.path.normpath(self.path) == os.path.normpath(QDir.rootPath()):
# or (os.path.normpath(os.path.dirname(self.path)) == os.path.normpath(QDir.homePath()) and os.path.basename(self.path) == "Desktop") \
# or (os.path.normpath(os.path.dirname(os.path.dirname(self.path))) == os.path.normpath(QDir.homePath()) and os.path.basename(os.path.dirname(self.path)) == "Desktop"):
up_action.setDisabled(True)
up_and_close_current_action.setDisabled(True)
if self.is_desktop_window == True:
Expand All @@ -272,7 +269,7 @@ def init_menu_bar(self):
go_menu.addAction(start_menu_action)
# View Menu
view_menu = self.menu_bar.addMenu("View")
if os.path.normpath(os.path.dirname(self.path)) == os.path.normpath(QDir.homePath()) and os.path.basename(self.path) == "Desktop":
if os.path.normpath(self.path) == get_desktop_directory():
align_items_desktop_action = QAction("Align Items", self)
align_items_desktop_action.triggered.connect(self.align_items_desktop)
view_menu.addAction(align_items_desktop_action)
Expand All @@ -293,9 +290,13 @@ def init_menu_bar(self):

# Help Menu
help_menu = self.menu_bar.addMenu("Help")

about_action = QAction("About", self)
about_action.triggered.connect(self.show_about)
help_menu.addAction(about_action)
help_menu.addSeparator
if "log_console" in sys.modules:
app.log_console.add_menu_items(help_menu, self)

def open_parent(self):
# TODO: Detect whether the Shift key is pressed; if yes; if yes, close the current window if it is not the fullscreen desktop window
Expand Down Expand Up @@ -329,7 +330,7 @@ def adjust_window_size(self):
self.resize(max_x, max_y)

def populate_items(self):
if os.path.normpath(os.path.dirname(self.path)) == os.path.normpath(QDir.homePath()) and os.path.basename(self.path) == "Desktop":
if os.path.normpath(self.path) == get_desktop_directory():

# Add every disk in the system
print("Adding disks")
Expand Down Expand Up @@ -359,7 +360,7 @@ def populate_items(self):
if entry == app.desktop_settings_file:
continue
# ~/Desktop is a special case; we don't want to show it
if self.path == QDir.homePath() and entry == "Desktop":
if self.path == os.path.basename(get_desktop_directory()) and entry == "Desktop":
continue
entry_path = os.path.join(self.path, entry)
is_directory = os.path.isdir(entry_path)
Expand Down Expand Up @@ -608,6 +609,8 @@ def dropEvent(self, event):
event.ignore()

def align_items(self):
if not self.items:
return
num_columns = self.width() // self.item_width_for_positioning
current_column = 0
current_row = 0
Expand Down Expand Up @@ -641,6 +644,8 @@ def align_items(self):
self.update_container_size()

def align_items_staggered(self):
if not self.items:
return
num_columns = self.width() // self.item_width_for_positioning
line_height = int(self.line_height - 0.5 * app.icon_size)
current_column = 0
Expand Down Expand Up @@ -686,6 +691,8 @@ def align_items_staggered(self):
self.update_container_size()

def align_items_desktop(self):
if not self.items:
return
num_rows = (self.height() // self.line_height ) - 1
current_column = 0
current_row = 0
Expand Down Expand Up @@ -719,6 +726,8 @@ def align_items_desktop(self):
current_column += 1

def align_items_circle(self):
if not self.items:
return
radius = self.width() // 2 - self.horizontal_spacing - self.item_width_for_positioning // 2

# Calculate the center of the circle
Expand Down Expand Up @@ -767,7 +776,8 @@ def __init__(self, path, is_directory, position, parent=None):
self.position = position

icon_provider = QFileIconProvider()
if self.path == os.path.normpath(os.path.join(QDir.homePath(), "Desktop", app.trash_name)):
# Trash
if self.path == os.path.normpath(get_desktop_directory() + "/" + app.trash_name):
icon = icon_provider.icon(QFileIconProvider.IconType.Trashcan).pixmap(app.icon_size, app.icon_size)
else:
icon = icon_provider.icon(QFileInfo(self.path)).pixmap(app.icon_size, app.icon_size)
Expand Down Expand Up @@ -947,6 +957,17 @@ def open(self, event):
else:
os.system(f"xdg-open \"{self.path}\"")

def get_desktop_directory():
"""Get the desktop directory of the user."""
if sys.platform == "win32":
from win32com.client import Dispatch
shell = Dispatch("WScript.Shell")
desktop = os.path.normpath(shell.SpecialFolders("Desktop"))
else:
desktop = QDir.homePath() + "/Desktop"
return os.path.normpath(desktop)


if __name__ == "__main__":
app = QApplication(sys.argv)
if sys.platform == "win32":
Expand All @@ -955,10 +976,22 @@ def open(self, event):
app.desktop_settings_file = ".DS_Spatial"
app.trash_name = "Trash"
app.icon_size = 32


# Output not only to the console but also to the GUI
try:
import log_console
except ImportError:
pass
if "log_console" in sys.modules:
app.log_console = log_console.ConsoleOutputStream()
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(os.path.normpath(QDir.homePath() + "/Desktop"), is_desktop_window = True)
desktop = SpatialFiler(get_desktop_directory(), is_desktop_window = True)
desktop.move(screen.geometry().x(), screen.geometry().y())
desktop.resize(screen.geometry().width(), screen.geometry().height())
desktop.setWindowFlags(Qt.WindowType.FramelessWindowHint)
Expand All @@ -978,7 +1011,6 @@ def open(self, event):
windows_wallpaper_path = os.path.normpath(shell.RegRead("HKEY_CURRENT_USER\\Control Panel\\Desktop\\Wallpaper")).replace("\\", "/")
print("Windows wallpaper path:", windows_wallpaper_path)
if windows_wallpaper_path != "." and os.path.exists(windows_wallpaper_path):
# Set the background image of the window
p = desktop.container.palette()
p.setBrush(desktop.container.backgroundRole(), QBrush(QPixmap(windows_wallpaper_path).scaled(desktop.width(), desktop.height(), Qt.AspectRatioMode.KeepAspectRatioByExpanding)))
desktop.container.setPalette(p)
Expand Down

0 comments on commit a013782

Please sign in to comment.