commit 1bf3a11208f5cb21ae128cc9aeeb957cc20cc34a Author: N0\A Date: Tue Oct 21 14:18:26 2025 +0200 first commit diff --git a/core/__pycache__/file_search.cpython-313.pyc b/core/__pycache__/file_search.cpython-313.pyc new file mode 100644 index 0000000..788e353 Binary files /dev/null and b/core/__pycache__/file_search.cpython-313.pyc differ diff --git a/core/file_search.py b/core/file_search.py new file mode 100644 index 0000000..e53c393 --- /dev/null +++ b/core/file_search.py @@ -0,0 +1,8 @@ +import shutil, subprocess, os + +def find(pattern: str, root: str='/'): + path = os.path.expanduser(root) + if shutil.which('fd') is None: + raise RuntimeError("fd not installed") + out = subprocess.check_output(['fd', pattern, path], text=True, errors='ignore') + return out.splitlines() \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..9f5e065 --- /dev/null +++ b/main.py @@ -0,0 +1,2 @@ +from ui import gui +gui.main() \ No newline at end of file diff --git a/ui/2ktan.png b/ui/2ktan.png new file mode 100644 index 0000000..bfd28a2 Binary files /dev/null and b/ui/2ktan.png differ diff --git a/ui/__pycache__/gui.cpython-313.pyc b/ui/__pycache__/gui.cpython-313.pyc new file mode 100644 index 0000000..674c390 Binary files /dev/null and b/ui/__pycache__/gui.cpython-313.pyc differ diff --git a/ui/__pycache__/ui.cpython-313.pyc b/ui/__pycache__/ui.cpython-313.pyc new file mode 100644 index 0000000..e76decb Binary files /dev/null and b/ui/__pycache__/ui.cpython-313.pyc differ diff --git a/ui/demo/gui.py b/ui/demo/gui.py new file mode 100644 index 0000000..75a3fb1 --- /dev/null +++ b/ui/demo/gui.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +""" +desktop_pet_x11.py +X11-only: shows a frameless, always-on-top pet using pet.png. +Transparent pixels are click-through via a per-pixel mask (setMask). +""" +import sys +from pathlib import Path +from PySide6 import QtCore, QtGui, QtWidgets + +ASSET = Path(__file__).with_name("pet.png") + + +class PetWindow(QtWidgets.QWidget): + def __init__(self): + super().__init__() + + # Ensure X11 (xcb) — exit if not + platform = QtGui.QGuiApplication.platformName().lower() + if not platform.startswith("xcb"): + raise SystemExit( + f"desktop_pet_x11.py requires X11 (platformName={platform}). Exiting." + ) + + # Window flags: frameless, always-on-top, tool window (no taskbar entry) + flags = ( + QtCore.Qt.FramelessWindowHint + | QtCore.Qt.WindowStaysOnTopHint + | QtCore.Qt.Tool + ) + self.setWindowFlags(flags) + # Let the window be transparent where the PNG is transparent + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) + + # Load pixmap + pix = QtGui.QPixmap(str(ASSET)) + if pix.isNull(): + raise SystemExit(f"Could not load image: {ASSET}") + + # Show pixmap in a label + self.label = QtWidgets.QLabel(self) + self.label.setPixmap(pix) + self.label.resize(pix.size()) + self.resize(pix.size()) + + # Apply per-pixel mask from alpha channel so transparent areas are outside the window shape. + img = pix.toImage() + if img.hasAlphaChannel(): + # createAlphaMask returns a QImage where alpha pixels are white/black (suitable for QBitmap) + mask_img = img.createAlphaMask() + mask = QtGui.QBitmap.fromImage(mask_img) + self.setMask(mask) + else: + # No alpha channel: warn but continue (window will be rectangular and not click-through) + print("Warning: pet.png has no alpha channel; per-pixel click-through unavailable.") + + # System tray + self.tray = QtWidgets.QSystemTrayIcon(self) + # Prefer a small icon; QIcon will scale automatically + self.tray.setIcon(QtGui.QIcon(str(ASSET))) + menu = QtWidgets.QMenu() + menu.addAction("Hide/Show", self.toggle_visible) + menu.addSeparator() + menu.addAction("Quit", QtWidgets.QApplication.quit) + self.tray.setContextMenu(menu) + self.tray.show() + + # Dragging support + self._drag_pos = None + + # Drag only when clicking opaque pixels + def mousePressEvent(self, event: QtGui.QMouseEvent): + if event.button() == QtCore.Qt.LeftButton: + # global pos - top-left -> offset + self._drag_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft() + event.accept() + elif event.button() == QtCore.Qt.RightButton: + # show tray menu at pointer + self.tray.contextMenu().popup(event.globalPosition().toPoint()) + + def mouseMoveEvent(self, event: QtGui.QMouseEvent): + if self._drag_pos and (event.buttons() & QtCore.Qt.LeftButton): + self.move(event.globalPosition().toPoint() - self._drag_pos) + + def mouseReleaseEvent(self, event: QtGui.QMouseEvent): + self._drag_pos = None + + def toggle_visible(self): + self.setVisible(not self.isVisible()) + + +def main(): + app = QtWidgets.QApplication(sys.argv) + app.setApplicationName("DesktopPetX11") + + pet = PetWindow() + pet.move(200, 200) + pet.show() + + print("Desktop pet started (X11). Transparent pixels are click-through.") + sys.exit(app.exec()) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ui/gui.py b/ui/gui.py new file mode 100644 index 0000000..08054e0 --- /dev/null +++ b/ui/gui.py @@ -0,0 +1,67 @@ +import sys +from pathlib import Path +from PySide6 import QtCore, QtGui, QtWidgets + +ASSET = Path(__file__).with_name("2ktan.png") + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self): + super().__init__() + + flags = ( + QtCore.Qt.FramelessWindowHint + | QtCore.Qt.WindowStaysOnTopHint + | QtCore.Qt.Tool + ) + + self.setWindowFlags(flags) + self.setAttribute(QtCore.Qt.WA_TranslucentBackground) + pix = QtGui.QPixmap(str(ASSET)) + + self.label = QtWidgets.QLabel(self) + self.label.setPixmap(pix) + self.label.resize(pix.size()) + self.resize(pix.size()) + + img = pix.toImage() + mask_img = img.createAlphaMask() + mask = QtGui.QBitmap.fromImage(mask_img) + self.setMask(mask) + + self.tray = QtWidgets.QSystemTrayIcon(self) + self.tray.setIcon(QtGui.QIcon(str(ASSET))) + menu = QtWidgets.QMenu() + menu.addAction("Hide/Show", self.toggle_visible) + menu.addSeparator() + menu.addAction("Quit", QtWidgets.QApplication.quit) + self.tray.setContextMenu(menu) + self.tray.show() + + self._drag_pos = None + + def mousePressEvent(self, event: QtGui.QMouseEvent): + if event.button() == QtCore.Qt.LeftButton: + self._drag_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft() + event.accept() + elif event.button() == QtCore.Qt.RightButton: + self.tray.contextMenu().popup(event.globalPosition().toPoint()) + + def mouseMoveEvent(self, event: QtGui.QMouseEvent): + if self._drag_pos and (event.buttons() & QtCore.Qt.LeftButton): + self.move(event.globalPosition().toPoint() - self._drag_pos) + + def mouseReleaseEvent(self, event: QtGui.QMouseEvent): + self._drag_pos = None + + def toggle_visible(self): + self.setVisible(not self.isVisible()) + +def main(): + app = QtWidgets.QApplication(sys.argv) + app.setApplicationName("CLARA") + + pet = MainWindow() + pet.move(200, 200) + pet.show() + + sys.exit(app.exec()) \ No newline at end of file diff --git a/ui/pet.png b/ui/pet.png new file mode 100644 index 0000000..629268e Binary files /dev/null and b/ui/pet.png differ diff --git a/ui/ui.py b/ui/ui.py new file mode 100644 index 0000000..3868bfe --- /dev/null +++ b/ui/ui.py @@ -0,0 +1,20 @@ +import core.file_search as fs + +def main(): + filename = input("Enter the filename: ") + files = fs.find(filename, "~") + for file in files: + print(file) + if len(files) == 0: + print("I didn't find anything, would you like to try searching the whole disk?") + answer = input("(y/n): ") + if answer.lower() == 'y': + files = fs.find(filename) + if len(files) == 0: + print("No files found on the whole disk.") + else: + for file in files: + print(file) + +if __name__ == "__main__": + main() \ No newline at end of file