pyloid 0.21.0.dev1__py3-none-any.whl → 0.22.0.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pyloid/pyloid.py CHANGED
@@ -26,9 +26,11 @@ import logging
26
26
  from .browser_window import BrowserWindow
27
27
  from .tray import TrayEvent
28
28
  from PySide6.QtCore import QCoreApplication
29
- from PySide6.QtCore import QRunnable, QThreadPool, Signal, QObject
30
- import time
31
- from .thread_pool import PyloidThreadPool
29
+ from PySide6.QtCore import Signal, QObject, Slot
30
+ import uuid
31
+ from PySide6.QtCore import QEventLoop
32
+ import socket
33
+ from typing import Any
32
34
 
33
35
  # for linux debug
34
36
  os.environ["QTWEBENGINE_DICTIONARIES_PATH"] = "/"
@@ -73,11 +75,14 @@ class _WindowController(QObject):
73
75
  )
74
76
 
75
77
 
76
- class Pyloid(QApplication):
78
+
79
+ # Only Work in Main Thread
80
+ class _Pyloid(QApplication):
77
81
  def __init__(
78
82
  self,
79
83
  app_name,
80
84
  single_instance=True,
85
+ data=None,
81
86
  ):
82
87
  """
83
88
  Initializes the Pyloid application.
@@ -88,6 +93,8 @@ class Pyloid(QApplication):
88
93
  The name of the application
89
94
  single_instance : bool, optional
90
95
  Whether to run the application as a single instance (default is True)
96
+ data : dict, optional
97
+ Data to be transmitted to the frontend web engine via IPC
91
98
 
92
99
  Examples
93
100
  --------
@@ -101,8 +108,10 @@ class Pyloid(QApplication):
101
108
  ```
102
109
  """
103
110
  super().__init__(sys.argv)
111
+
112
+ self.data = data
104
113
 
105
- self.windows = []
114
+ self.windows_dict = {} # 윈도우 ID를 키로 사용하는 딕셔너리
106
115
  self.server = None
107
116
 
108
117
  self.app_name = app_name
@@ -199,8 +208,8 @@ class Pyloid(QApplication):
199
208
  self.icon = QIcon(icon_path)
200
209
 
201
210
  # Immediately update the icon for all open windows.
202
- for window in self.windows:
203
- window._window.setWindowIcon(self.icon)
211
+ for window in self.windows_dict.values():
212
+ window.set_icon(self.icon)
204
213
 
205
214
  def create_window(
206
215
  self,
@@ -261,7 +270,8 @@ class Pyloid(QApplication):
261
270
  dev_tools,
262
271
  js_apis,
263
272
  )
264
- return self.windows[-1]
273
+ latest_window_id = list(self.windows_dict.keys())[-1]
274
+ return self.windows_dict[latest_window_id]
265
275
 
266
276
  def _create_window_signal_function(
267
277
  self,
@@ -289,7 +299,7 @@ class Pyloid(QApplication):
289
299
  dev_tools,
290
300
  js_apis,
291
301
  )
292
- self.windows.append(window)
302
+ self.windows_dict[window._window.id] = window
293
303
  return window
294
304
 
295
305
  def run(self):
@@ -333,7 +343,7 @@ class Pyloid(QApplication):
333
343
  ###########################################################################################
334
344
  # App window
335
345
  ###########################################################################################
336
- def get_windows(self) -> List[BrowserWindow]:
346
+ def get_windows(self) -> Dict[str, BrowserWindow]:
337
347
  """
338
348
  Returns a list of all browser windows.
339
349
 
@@ -351,7 +361,7 @@ class Pyloid(QApplication):
351
361
  print(window.get_id())
352
362
  ```
353
363
  """
354
- return self.windows
364
+ return self.windows_dict
355
365
 
356
366
  def show_main_window(self):
357
367
  """
@@ -364,8 +374,9 @@ class Pyloid(QApplication):
364
374
  app.show_main_window()
365
375
  ```
366
376
  """
367
- if self.windows:
368
- main_window = self.windows[0]
377
+ if self.windows_dict:
378
+ # 번째 윈도우 가져오기
379
+ main_window = next(iter(self.windows_dict.values()))
369
380
  main_window._window.show()
370
381
 
371
382
  def focus_main_window(self):
@@ -379,8 +390,9 @@ class Pyloid(QApplication):
379
390
  app.focus_main_window()
380
391
  ```
381
392
  """
382
- if self.windows:
383
- main_window = self.windows[0]
393
+ if self.windows_dict:
394
+ # 번째 윈도우 가져오기
395
+ main_window = next(iter(self.windows_dict.values()))
384
396
  main_window._window.activateWindow()
385
397
  main_window._window.raise_()
386
398
  main_window._window.setWindowState(
@@ -399,8 +411,8 @@ class Pyloid(QApplication):
399
411
  app.show_and_focus_main_window()
400
412
  ```
401
413
  """
402
- if self.windows:
403
- main_window = self.windows[0]
414
+ if self.windows_dict:
415
+ main_window = next(iter(self.windows_dict.values()))
404
416
  main_window._window.show()
405
417
  main_window._window.activateWindow()
406
418
  main_window._window.raise_()
@@ -420,7 +432,7 @@ class Pyloid(QApplication):
420
432
  app.close_all_windows()
421
433
  ```
422
434
  """
423
- for window in self.windows:
435
+ for window in self.windows_dict.values():
424
436
  window._window.close()
425
437
 
426
438
  def quit(self):
@@ -435,12 +447,12 @@ class Pyloid(QApplication):
435
447
  ```
436
448
  """
437
449
 
438
- # 윈도우 정리
439
- for window in self.windows:
450
+ for window in self.windows_dict.values():
440
451
  window._window.close()
441
452
  window.web_page.deleteLater()
442
453
  window.web_view.deleteLater()
443
454
 
455
+ self.windows_dict.clear()
444
456
  QApplication.quit()
445
457
 
446
458
  ###########################################################################################
@@ -449,7 +461,7 @@ class Pyloid(QApplication):
449
461
  def get_window_by_id(self, window_id: str) -> Optional[BrowserWindow]:
450
462
  """
451
463
  Returns the window with the given ID.
452
-
464
+
453
465
  Parameters
454
466
  ----------
455
467
  window_id : str
@@ -459,22 +471,19 @@ class Pyloid(QApplication):
459
471
  -------
460
472
  Optional[BrowserWindow]
461
473
  The window object with the given ID. Returns None if the window is not found.
462
-
474
+
463
475
  Examples
464
476
  --------
465
477
  ```python
466
478
  app = Pyloid(app_name="Pyloid-App")
467
-
479
+
468
480
  window = app.get_window_by_id("123e4567-e89b-12d3-a456-426614174000")
469
-
481
+
470
482
  if window:
471
483
  print("Window found:", window)
472
484
  ```
473
485
  """
474
- for window in self.windows:
475
- if window.id == window_id:
476
- return window
477
- return None
486
+ return self.windows_dict.get(window_id)
478
487
 
479
488
  def hide_window_by_id(self, window_id: str):
480
489
  """
@@ -520,12 +529,7 @@ class Pyloid(QApplication):
520
529
  """
521
530
  window = self.get_window_by_id(window_id)
522
531
  if window:
523
- window._window.show()
524
- window._window.activateWindow()
525
- window._window.raise_()
526
- window._window.setWindowState(
527
- window._window.windowState() & ~Qt.WindowMinimized | Qt.WindowActive
528
- )
532
+ window.show()
529
533
 
530
534
  def close_window_by_id(self, window_id: str):
531
535
  """
@@ -1397,8 +1401,867 @@ class Pyloid(QApplication):
1397
1401
  """
1398
1402
 
1399
1403
  # 모든 윈도우에 변경사항 적용
1400
- for window in self.windows:
1404
+ for window in self.windows_dict.values():
1401
1405
  window.web_view.page().runJavaScript(js_code)
1402
1406
  window.web_view.page().setBackgroundColor(
1403
1407
  Qt.GlobalColor.black if self.theme == "dark" else Qt.GlobalColor.white
1404
1408
  )
1409
+
1410
+
1411
+ class Pyloid(QObject):
1412
+ command_signal = Signal(str, str, object)
1413
+ result_signal = Signal(str, object)
1414
+
1415
+ def __init__(self, app_name: str, single_instance: bool = True, data: Optional[Dict[str, Any]] = None):
1416
+ """
1417
+ Initialize the Pyloid application.
1418
+
1419
+ This application is designed to work in a multi-threaded environment.
1420
+ All Qt GUI related operations are executed in the main thread's event queue regardless of the calling thread,
1421
+ ensuring thread safety for GUI operations.
1422
+
1423
+ Parameters
1424
+ ----------
1425
+ app_name : str, required
1426
+ The name of the application.
1427
+ single_instance : bool, optional
1428
+ Determines whether to run as a single instance. (Default is True)
1429
+ data : dict, optional
1430
+ Data to be transmitted to the frontend web engine via IPC
1431
+
1432
+ Notes
1433
+ -----
1434
+ The generated or passed `id` is transmitted to the frontend via IPC,
1435
+ and is used as an API key to connect to the integrated backend FastAPI server.
1436
+ """
1437
+ super().__init__()
1438
+
1439
+ self.data = data
1440
+
1441
+ self.app = _Pyloid(app_name, single_instance, self.data)
1442
+
1443
+ self.command_signal.connect(self._handle_command)
1444
+
1445
+ @Slot(str, str, object)
1446
+ def _handle_command(self, command_id, command_type, params):
1447
+ result = None
1448
+
1449
+ if command_type == "set_icon":
1450
+ result = self.app.set_icon(params["icon_path"])
1451
+
1452
+ elif command_type == "create_window":
1453
+ window = self.app.create_window(
1454
+ title=params.get("title", ""),
1455
+ width=params.get("width", 800),
1456
+ height=params.get("height", 600),
1457
+ x=params.get("x", 200),
1458
+ y=params.get("y", 200),
1459
+ frame=params.get("frame", True),
1460
+ context_menu=params.get("context_menu", False),
1461
+ dev_tools=params.get("dev_tools", False)
1462
+ )
1463
+ result = window
1464
+
1465
+ elif command_type == "run":
1466
+ result = self.app.run()
1467
+
1468
+ elif command_type == "get_windows":
1469
+ result = self.app.get_windows()
1470
+
1471
+ elif command_type == "show_main_window":
1472
+ result = self.app.show_main_window()
1473
+
1474
+ elif command_type == "focus_main_window":
1475
+ result = self.app.focus_main_window()
1476
+
1477
+ elif command_type == "show_and_focus_main_window":
1478
+ result = self.app.show_and_focus_main_window()
1479
+
1480
+ elif command_type == "close_all_windows":
1481
+ result = self.app.close_all_windows()
1482
+
1483
+ elif command_type == "quit":
1484
+ result = self.app.quit()
1485
+
1486
+ elif command_type == "get_window_by_id":
1487
+ result = self.app.get_window_by_id(params["window_id"])
1488
+
1489
+ elif command_type == "set_tray_icon":
1490
+ result = self.app.set_tray_icon(params["tray_icon_path"])
1491
+
1492
+ elif command_type == "set_tray_menu_items":
1493
+ result = self.app.set_tray_menu_items(params["tray_menu_items"])
1494
+
1495
+ elif command_type == "set_tray_actions":
1496
+ result = self.app.set_tray_actions(params["actions"])
1497
+
1498
+ elif command_type == "show_notification":
1499
+ result = self.app.show_notification(params["title"], params["message"])
1500
+
1501
+ elif command_type == "set_tray_icon_animation":
1502
+ result = self.app.set_tray_icon_animation(params["icon_frames"], params.get("interval", 200))
1503
+
1504
+ elif command_type == "set_tray_tooltip":
1505
+ result = self.app.set_tray_tooltip(params["message"])
1506
+
1507
+ elif command_type == "set_notification_callback":
1508
+ result = self.app.set_notification_callback(params["callback"])
1509
+
1510
+ elif command_type == "get_all_monitors":
1511
+ result = self.app.get_all_monitors()
1512
+
1513
+ elif command_type == "get_primary_monitor":
1514
+ result = self.app.get_primary_monitor()
1515
+
1516
+ elif command_type == "set_clipboard_text":
1517
+ result = self.app.set_clipboard_text(params["text"])
1518
+
1519
+ elif command_type == "get_clipboard_text":
1520
+ result = self.app.get_clipboard_text()
1521
+
1522
+ elif command_type == "set_clipboard_image":
1523
+ result = self.app.set_clipboard_image(params["image"])
1524
+
1525
+ elif command_type == "get_clipboard_image":
1526
+ result = self.app.get_clipboard_image()
1527
+
1528
+ elif command_type == "set_auto_start":
1529
+ result = self.app.set_auto_start(params["enable"])
1530
+
1531
+ elif command_type == "is_auto_start":
1532
+ result = self.app.is_auto_start()
1533
+
1534
+ elif command_type == "watch_file":
1535
+ result = self.app.watch_file(params["file_path"])
1536
+
1537
+ elif command_type == "watch_directory":
1538
+ result = self.app.watch_directory(params["dir_path"])
1539
+
1540
+ elif command_type == "stop_watching":
1541
+ result = self.app.stop_watching(params["path"])
1542
+
1543
+ elif command_type == "get_watched_paths":
1544
+ result = self.app.get_watched_paths()
1545
+
1546
+ elif command_type == "get_watched_files":
1547
+ result = self.app.get_watched_files()
1548
+
1549
+ elif command_type == "get_watched_directories":
1550
+ result = self.app.get_watched_directories()
1551
+
1552
+ elif command_type == "remove_all_watched_paths":
1553
+ result = self.app.remove_all_watched_paths()
1554
+
1555
+ elif command_type == "set_file_change_callback":
1556
+ result = self.app.set_file_change_callback(params["callback"])
1557
+
1558
+ elif command_type == "set_directory_change_callback":
1559
+ result = self.app.set_directory_change_callback(params["callback"])
1560
+
1561
+ elif command_type == "open_file_dialog":
1562
+ result = self.app.open_file_dialog(params.get("dir"), params.get("filter"))
1563
+
1564
+ elif command_type == "save_file_dialog":
1565
+ result = self.app.save_file_dialog(params.get("dir"), params.get("filter"))
1566
+
1567
+ elif command_type == "select_directory_dialog":
1568
+ result = self.app.select_directory_dialog(params.get("dir"))
1569
+
1570
+ else:
1571
+ return None
1572
+
1573
+ self.result_signal.emit(command_id, result)
1574
+
1575
+ def execute_command(self, command_type: str, params: object, timeout: Optional[int] = None):
1576
+ command_id = str(uuid.uuid4())
1577
+
1578
+ result_data = [None]
1579
+ loop = QEventLoop()
1580
+
1581
+ if timeout:
1582
+ timer = QTimer()
1583
+ timer.setSingleShot(True)
1584
+ timer.timeout.connect(loop.quit)
1585
+ timer.start(timeout)
1586
+
1587
+ def on_result(received_id, result):
1588
+ if received_id == command_id:
1589
+ result_data[0] = result
1590
+ loop.quit()
1591
+
1592
+
1593
+ self.result_signal.connect(on_result, Qt.QueuedConnection)
1594
+
1595
+ self.command_signal.emit(command_id, command_type, params)
1596
+
1597
+ loop.exec()
1598
+
1599
+ self.result_signal.disconnect(on_result)
1600
+
1601
+ return result_data[0]
1602
+
1603
+ # -------------------------------------------------------------------
1604
+ # Execute_command 래퍼 (wrapper) 함수들
1605
+ # -------------------------------------------------------------------
1606
+
1607
+ def set_icon(self, icon_path: str) -> bool:
1608
+ """
1609
+ Dynamically sets the application's icon.
1610
+
1611
+ Parameters
1612
+ ----------
1613
+ icon_path : str
1614
+ Path to the new icon file
1615
+
1616
+ Examples
1617
+ --------
1618
+ >>> app = Pyloid(app_name="Pyloid-App")
1619
+ >>> app.set_icon("icons/icon.png")
1620
+ """
1621
+ return self.execute_command("set_icon", {"icon_path": icon_path})
1622
+
1623
+ def create_window(
1624
+ self,
1625
+ title: str,
1626
+ width: int = 800,
1627
+ height: int = 600,
1628
+ x: int = 200,
1629
+ y: int = 200,
1630
+ frame: bool = True,
1631
+ context_menu: bool = False,
1632
+ dev_tools: bool = False,
1633
+ ) -> BrowserWindow:
1634
+ """
1635
+ Creates a new browser window.
1636
+
1637
+ Parameters
1638
+ ----------
1639
+ title : str, required
1640
+ Title of the window
1641
+ width : int, optional
1642
+ Width of the window (default is 800)
1643
+ height : int, optional
1644
+ Height of the window (default is 600)
1645
+ x : int, optional
1646
+ X coordinate of the window (default is 200)
1647
+ y : int, optional
1648
+ Y coordinate of the window (default is 200)
1649
+ frame : bool, optional
1650
+ Whether the window has a frame (default is True)
1651
+ context_menu : bool, optional
1652
+ Whether to use the context menu (default is False)
1653
+ dev_tools : bool, optional
1654
+ Whether to use developer tools (default is False)
1655
+
1656
+ Returns
1657
+ -------
1658
+ BrowserWindow
1659
+ The created browser window object
1660
+
1661
+ Examples
1662
+ --------
1663
+ >>> app = Pyloid(app_name="Pyloid-App")
1664
+ >>> window_id = app.create_window(title="New Window", width=1024, height=768)
1665
+ """
1666
+ params = {
1667
+ "title": title,
1668
+ "width": width,
1669
+ "height": height,
1670
+ "x": x,
1671
+ "y": y,
1672
+ "frame": frame,
1673
+ "context_menu": context_menu,
1674
+ "dev_tools": dev_tools,
1675
+ }
1676
+ return self.execute_command("create_window", params)
1677
+
1678
+ def run(self) -> None:
1679
+ """
1680
+ Runs the application event loop.
1681
+
1682
+ Examples
1683
+ --------
1684
+ >>> app = Pyloid(app_name="Pyloid-App")
1685
+ >>> app.run()
1686
+ """
1687
+ return self.app.run()
1688
+
1689
+ def get_windows(self) -> Dict[str, BrowserWindow]:
1690
+ """
1691
+ Returns a list of all browser windows.
1692
+
1693
+ Returns
1694
+ -------
1695
+ Dict[str, BrowserWindow]
1696
+ Dictionary of all browser windows
1697
+
1698
+ Examples
1699
+ --------
1700
+ >>> app = Pyloid(app_name="Pyloid-App")
1701
+ >>> windows = app.get_windows()
1702
+ """
1703
+ return self.execute_command("get_windows", {})
1704
+
1705
+ def show_main_window(self) -> None:
1706
+ """
1707
+ Shows and focuses the first window.
1708
+
1709
+ Examples
1710
+ --------
1711
+ >>> app = Pyloid(app_name="Pyloid-App")
1712
+ >>> app.show_main_window()
1713
+ """
1714
+ return self.execute_command("show_main_window", {})
1715
+
1716
+ def focus_main_window(self) -> None:
1717
+ """
1718
+ Focuses the first window.
1719
+
1720
+ Examples
1721
+ --------
1722
+ >>> app = Pyloid(app_name="Pyloid-App")
1723
+ >>> app.focus_main_window()
1724
+ """
1725
+ return self.execute_command("focus_main_window", {})
1726
+
1727
+ def show_and_focus_main_window(self) -> None:
1728
+ """
1729
+ Shows and focuses the first window.
1730
+
1731
+ Examples
1732
+ --------
1733
+ >>> app = Pyloid(app_name="Pyloid-App")
1734
+ >>> app.show_and_focus_main_window()
1735
+ """
1736
+ return self.execute_command("show_and_focus_main_window", {})
1737
+
1738
+ def close_all_windows(self) -> None:
1739
+ """
1740
+ Closes all windows.
1741
+
1742
+ Examples
1743
+ --------
1744
+ >>> app = Pyloid(app_name="Pyloid-App")
1745
+ >>> app.close_all_windows()
1746
+ """
1747
+ return self.execute_command("close_all_windows", {})
1748
+
1749
+ def quit(self) -> None:
1750
+ """
1751
+ Quits the application.
1752
+
1753
+ Examples
1754
+ --------
1755
+ >>> app = Pyloid(app_name="Pyloid-App")
1756
+ >>> app.quit()
1757
+ """
1758
+ return self.execute_command("quit", {})
1759
+
1760
+ def get_window_by_id(self, window_id: str) -> Optional[BrowserWindow]:
1761
+ """
1762
+ Returns the window with the given ID.
1763
+
1764
+ Parameters
1765
+ ----------
1766
+ window_id : str
1767
+ The ID of the window to find
1768
+
1769
+ Returns
1770
+ -------
1771
+ Optional[BrowserWindow]
1772
+ The window object with the given ID. Returns None if the window is not found.
1773
+
1774
+ Examples
1775
+ --------
1776
+ >>> app = Pyloid(app_name="Pyloid-App")
1777
+ >>> window = app.get_window_by_id("some-window-id")
1778
+ """
1779
+ return self.execute_command("get_window_by_id", {"window_id": window_id})
1780
+
1781
+ def set_tray_icon(self, tray_icon_path: str) -> bool:
1782
+ """
1783
+ Dynamically sets the tray icon.
1784
+
1785
+ Parameters
1786
+ ----------
1787
+ tray_icon_path : str
1788
+ The path of the new tray icon file
1789
+
1790
+ Examples
1791
+ --------
1792
+ >>> app = Pyloid(app_name="Pyloid-App")
1793
+ >>> app.set_tray_icon("icons/icon.png")
1794
+ """
1795
+ return self.execute_command("set_tray_icon", {"tray_icon_path": tray_icon_path})
1796
+
1797
+ def set_tray_menu_items(self, tray_menu_items: List[Dict[str, Union[str, Callable]]]) -> bool:
1798
+ """
1799
+ Dynamically sets the tray menu items.
1800
+
1801
+ Parameters
1802
+ ----------
1803
+ tray_menu_items : List[Dict[str, Union[str, Callable]]]
1804
+ The list of new tray menu items
1805
+
1806
+ Examples
1807
+ --------
1808
+ >>> app = Pyloid(app_name="Pyloid-App")
1809
+ >>> menu_items = [{"label": "Open", "callback": lambda: print("Open clicked")},
1810
+ >>> {"label": "Exit", "callback": app.quit}]
1811
+ >>> app.set_tray_menu_items(menu_items)
1812
+ """
1813
+ return self.execute_command("set_tray_menu_items", {"tray_menu_items": tray_menu_items})
1814
+
1815
+ def set_tray_actions(self, actions: Dict[TrayEvent, Callable]) -> bool:
1816
+ """
1817
+ Dynamically sets the actions for tray icon activation.
1818
+
1819
+ Parameters
1820
+ ----------
1821
+ actions : Dict[TrayEvent, Callable]
1822
+ Dictionary with TrayEvent enum values as keys and corresponding callback functions as values
1823
+
1824
+ Examples
1825
+ --------
1826
+ >>> app = Pyloid(app_name="Pyloid-App")
1827
+ >>> app.set_tray_actions({TrayEvent.DoubleClick: lambda: print("Double-clicked")})
1828
+ """
1829
+ return self.execute_command("set_tray_actions", {"actions": actions})
1830
+
1831
+ def show_notification(self, title: str, message: str) -> bool:
1832
+ """
1833
+ Displays a notification in the system tray.
1834
+
1835
+ Parameters
1836
+ ----------
1837
+ title : str
1838
+ Notification title
1839
+ message : str
1840
+ Notification message
1841
+
1842
+ Examples
1843
+ --------
1844
+ >>> app = Pyloid(app_name="Pyloid-App")
1845
+ >>> app.show_notification("Update Available", "A new update is available for download.")
1846
+ """
1847
+ return self.execute_command("show_notification", {"title": title, "message": message})
1848
+
1849
+ def set_tray_icon_animation(self, icon_frames: List[str], interval: int = 200) -> bool:
1850
+ """
1851
+ Dynamically sets and starts the animation for the tray icon.
1852
+
1853
+ Parameters
1854
+ ----------
1855
+ icon_frames : list of str
1856
+ List of animation frame image paths
1857
+ interval : int, optional
1858
+ Frame interval in milliseconds, default is 200
1859
+
1860
+ Examples
1861
+ --------
1862
+ >>> app = Pyloid(app_name="Pyloid-App")
1863
+ >>> app.set_tray_icon_animation(["frame1.png", "frame2.png", "frame3.png"], 100)
1864
+ """
1865
+ return self.execute_command("set_tray_icon_animation", {"icon_frames": icon_frames, "interval": interval})
1866
+
1867
+ def set_tray_tooltip(self, message: str) -> bool:
1868
+ """
1869
+ Dynamically sets the tooltip for the tray icon.
1870
+
1871
+ Parameters
1872
+ ----------
1873
+ message : str
1874
+ New tooltip message
1875
+
1876
+ Examples
1877
+ --------
1878
+ >>> app = Pyloid(app_name="Pyloid-App")
1879
+ >>> app.set_tray_tooltip("Pyloid is running")
1880
+ """
1881
+ return self.execute_command("set_tray_tooltip", {"message": message})
1882
+
1883
+ def set_notification_callback(self, callback: Callable[[str], None]) -> bool:
1884
+ """
1885
+ Sets the callback function to be called when a notification is clicked.
1886
+
1887
+ Parameters
1888
+ ----------
1889
+ callback : function
1890
+ Callback function to be called when a notification is clicked
1891
+
1892
+ Examples
1893
+ --------
1894
+ >>> app = Pyloid(app_name="Pyloid-App")
1895
+ >>> def on_notification_click():
1896
+ >>> print("Notification clicked")
1897
+ >>> app.set_notification_callback(on_notification_click)
1898
+ """
1899
+ return self.execute_command("set_notification_callback", {"callback": callback})
1900
+
1901
+ def get_all_monitors(self) -> List[Monitor]:
1902
+ """
1903
+ Returns information about all connected monitors.
1904
+
1905
+ Returns
1906
+ -------
1907
+ List[Monitor]
1908
+ List containing monitor information
1909
+
1910
+ Examples
1911
+ --------
1912
+ >>> app = Pyloid(app_name="Pyloid-App")
1913
+ >>> monitors = app.get_all_monitors()
1914
+ >>> for monitor in monitors:
1915
+ >>> print(monitor.info())
1916
+ """
1917
+ return self.execute_command("get_all_monitors", {})
1918
+
1919
+ def get_primary_monitor(self) -> Monitor:
1920
+ """
1921
+ Returns information about the primary monitor.
1922
+
1923
+ Returns
1924
+ -------
1925
+ Monitor
1926
+ Primary monitor information
1927
+
1928
+ Examples
1929
+ --------
1930
+ >>> app = Pyloid(app_name="Pyloid-App")
1931
+ >>> primary_monitor = app.get_primary_monitor()
1932
+ >>> print(primary_monitor.info())
1933
+ """
1934
+ return self.execute_command("get_primary_monitor", {})
1935
+
1936
+ def set_clipboard_text(self, text: str) -> None:
1937
+ """
1938
+ Copies text to the clipboard.
1939
+
1940
+ Parameters
1941
+ ----------
1942
+ text : str
1943
+ Text to copy to the clipboard
1944
+
1945
+ Examples
1946
+ --------
1947
+ >>> app = Pyloid(app_name="Pyloid-App")
1948
+ >>> app.set_clipboard_text("Hello, World!")
1949
+ """
1950
+ return self.execute_command("set_clipboard_text", {"text": text})
1951
+
1952
+ def get_clipboard_text(self) -> str:
1953
+ """
1954
+ Retrieves text from the clipboard.
1955
+
1956
+ Returns
1957
+ -------
1958
+ str
1959
+ Text stored in the clipboard
1960
+
1961
+ Examples
1962
+ --------
1963
+ >>> app = Pyloid(app_name="Pyloid-App")
1964
+ >>> text = app.get_clipboard_text()
1965
+ >>> print(text)
1966
+ """
1967
+ return self.execute_command("get_clipboard_text", {})
1968
+
1969
+ def set_clipboard_image(self, image: Union[str, bytes, os.PathLike]) -> None:
1970
+ """
1971
+ Copies an image to the clipboard.
1972
+
1973
+ Parameters
1974
+ ----------
1975
+ image : Union[str, bytes, os.PathLike]
1976
+ Path to the image file to copy to the clipboard
1977
+
1978
+ Examples
1979
+ --------
1980
+ >>> app = Pyloid(app_name="Pyloid-App")
1981
+ >>> app.set_clipboard_image("/path/to/image.png")
1982
+ """
1983
+ return self.execute_command("set_clipboard_image", {"image": image})
1984
+
1985
+ def get_clipboard_image(self) -> QImage:
1986
+ """
1987
+ Retrieves an image from the clipboard.
1988
+
1989
+ Returns
1990
+ -------
1991
+ QImage
1992
+ QImage object stored in the clipboard (None if no image)
1993
+
1994
+ Examples
1995
+ --------
1996
+ >>> app = Pyloid(app_name="Pyloid-App")
1997
+ >>> image = app.get_clipboard_image()
1998
+ >>> if image is not None:
1999
+ >>> image.save("/path/to/save/image.png")
2000
+ """
2001
+ return self.execute_command("get_clipboard_image", {})
2002
+
2003
+ def set_auto_start(self, enable: bool) -> Union[bool, None]:
2004
+ """
2005
+ Sets the application to start automatically at system startup.
2006
+
2007
+ Parameters
2008
+ ----------
2009
+ enable : bool
2010
+ True to enable auto start, False to disable
2011
+
2012
+ Returns
2013
+ -------
2014
+ bool or None
2015
+ True if auto start is successfully set, False if disabled, None if not supported in non-production environment
2016
+
2017
+ Examples
2018
+ --------
2019
+ >>> app = Pyloid(app_name="Pyloid-App")
2020
+ >>> app.set_auto_start(True)
2021
+ """
2022
+ return self.execute_command("set_auto_start", {"enable": enable})
2023
+
2024
+ def is_auto_start(self) -> bool:
2025
+ """
2026
+ Checks if the application is set to start automatically at system startup.
2027
+
2028
+ Returns
2029
+ -------
2030
+ bool
2031
+ True if auto start is enabled, False otherwise
2032
+
2033
+ Examples
2034
+ --------
2035
+ >>> app = Pyloid(app_name="Pyloid-App")
2036
+ >>> auto_start_enabled = app.is_auto_start()
2037
+ >>> print(auto_start_enabled)
2038
+ """
2039
+ return self.execute_command("is_auto_start", {})
2040
+
2041
+ def watch_file(self, file_path: str) -> bool:
2042
+ """
2043
+ Adds a file to the watch list.
2044
+
2045
+ Parameters
2046
+ ----------
2047
+ file_path : str
2048
+ Path to the file to watch
2049
+
2050
+ Returns
2051
+ -------
2052
+ bool
2053
+ True if the file is successfully added to the watch list, False otherwise
2054
+
2055
+ Examples
2056
+ --------
2057
+ >>> app = Pyloid(app_name="Pyloid-App")
2058
+ >>> app.watch_file("/path/to/file.txt")
2059
+ """
2060
+ return self.execute_command("watch_file", {"file_path": file_path})
2061
+
2062
+ def watch_directory(self, dir_path: str) -> bool:
2063
+ """
2064
+ Adds a directory to the watch list.
2065
+
2066
+ Parameters
2067
+ ----------
2068
+ dir_path : str
2069
+ Path to the directory to watch
2070
+
2071
+ Returns
2072
+ -------
2073
+ bool
2074
+ True if the directory is successfully added to the watch list, False otherwise
2075
+
2076
+ Examples
2077
+ --------
2078
+ >>> app = Pyloid(app_name="Pyloid-App")
2079
+ >>> app.watch_directory("/path/to/directory")
2080
+ """
2081
+ return self.execute_command("watch_directory", {"dir_path": dir_path})
2082
+
2083
+ def stop_watching(self, path: str) -> bool:
2084
+ """
2085
+ Removes a file or directory from the watch list.
2086
+
2087
+ Parameters
2088
+ ----------
2089
+ path : str
2090
+ Path to the file or directory to stop watching
2091
+
2092
+ Returns
2093
+ -------
2094
+ bool
2095
+ True if the path is successfully removed from the watch list, False otherwise
2096
+
2097
+ Examples
2098
+ --------
2099
+ >>> app = Pyloid(app_name="Pyloid-App")
2100
+ >>> app.stop_watching("/path/to/file_or_directory")
2101
+ """
2102
+ return self.execute_command("stop_watching", {"path": path})
2103
+
2104
+ def get_watched_paths(self) -> List[str]:
2105
+ """
2106
+ Returns all currently watched paths.
2107
+
2108
+ Returns
2109
+ -------
2110
+ List[str]
2111
+ List of all watched paths
2112
+
2113
+ Examples
2114
+ --------
2115
+ >>> app = Pyloid(app_name="Pyloid-App")
2116
+ >>> app.get_watched_paths()
2117
+ ['/path/to/file1.txt', '/path/to/directory']
2118
+ """
2119
+ return self.execute_command("get_watched_paths", {})
2120
+
2121
+ def get_watched_files(self) -> List[str]:
2122
+ """
2123
+ Returns all currently watched files.
2124
+
2125
+ Returns
2126
+ -------
2127
+ List[str]
2128
+ List of all watched files
2129
+
2130
+ Examples
2131
+ --------
2132
+ >>> app = Pyloid(app_name="Pyloid-App")
2133
+ >>> app.get_watched_files()
2134
+ ['/path/to/file1.txt', '/path/to/file2.txt']
2135
+ """
2136
+ return self.execute_command("get_watched_files", {})
2137
+
2138
+ def get_watched_directories(self) -> List[str]:
2139
+ """
2140
+ Returns all currently watched directories.
2141
+
2142
+ Returns
2143
+ -------
2144
+ List[str]
2145
+ List of all watched directories
2146
+
2147
+ Examples
2148
+ --------
2149
+ >>> app = Pyloid(app_name="Pyloid-App")
2150
+ >>> app.get_watched_directories()
2151
+ ['/path/to/directory1', '/path/to/directory2']
2152
+ """
2153
+ return self.execute_command("get_watched_directories", {})
2154
+
2155
+ def remove_all_watched_paths(self) -> None:
2156
+ """
2157
+ Removes all paths from the watch list.
2158
+
2159
+ Examples
2160
+ --------
2161
+ >>> app = Pyloid(app_name="Pyloid-App")
2162
+ >>> app.remove_all_watched_paths()
2163
+ """
2164
+ return self.execute_command("remove_all_watched_paths", {})
2165
+
2166
+ def set_file_change_callback(self, callback: Callable[[str], None]) -> None:
2167
+ """
2168
+ Sets the callback function to be called when a file is changed.
2169
+
2170
+ Parameters
2171
+ ----------
2172
+ callback : Callable[[str], None]
2173
+ Function to be called when a file is changed
2174
+
2175
+ Examples
2176
+ --------
2177
+ >>> def on_file_change(file_path):
2178
+ >>> print(f"File changed: {file_path}")
2179
+ >>> app = Pyloid(app_name="Pyloid-App")
2180
+ >>> app.set_file_change_callback(on_file_change)
2181
+ """
2182
+ return self.execute_command("set_file_change_callback", {"callback": callback})
2183
+
2184
+ def set_directory_change_callback(self, callback: Callable[[str], None]) -> None:
2185
+ """
2186
+ Sets the callback function to be called when a directory is changed.
2187
+
2188
+ Parameters
2189
+ ----------
2190
+ callback : Callable[[str], None]
2191
+ Function to be called when a directory is changed
2192
+
2193
+ Examples
2194
+ --------
2195
+ >>> def on_directory_change(dir_path):
2196
+ >>> print(f"Directory changed: {dir_path}")
2197
+ >>> app = Pyloid(app_name="Pyloid-App")
2198
+ >>> app.set_directory_change_callback(on_directory_change)
2199
+ """
2200
+ return self.execute_command("set_directory_change_callback", {"callback": callback})
2201
+
2202
+ def open_file_dialog(self, dir: Optional[str] = None, filter: Optional[str] = None) -> Optional[str]:
2203
+ """
2204
+ Opens a file dialog to select a file to open.
2205
+
2206
+ Parameters
2207
+ ----------
2208
+ dir : str, optional
2209
+ The initial directory that the dialog will open in.
2210
+ filter : str, optional
2211
+ A string that specifies the file types that can be selected.
2212
+
2213
+ Returns
2214
+ -------
2215
+ Optional[str]
2216
+ The path of the selected file or None if no file is selected.
2217
+
2218
+ Examples
2219
+ --------
2220
+ >>> app = Pyloid(app_name="Pyloid-App")
2221
+ >>> file_path = app.open_file_dialog(dir="/home/user", filter="Text Files (*.txt)")
2222
+ """
2223
+ return self.execute_command("open_file_dialog", {"dir": dir, "filter": filter})
2224
+
2225
+ def save_file_dialog(self, dir: Optional[str] = None, filter: Optional[str] = None) -> Optional[str]:
2226
+ """
2227
+ Opens a file dialog to select a file to save.
2228
+
2229
+ Parameters
2230
+ ----------
2231
+ dir : str, optional
2232
+ The initial directory that the dialog will open in.
2233
+ filter : str, optional
2234
+ A string that specifies the file types that can be saved.
2235
+
2236
+ Returns
2237
+ -------
2238
+ Optional[str]
2239
+ The path of the selected file or None if no file is selected.
2240
+
2241
+ Examples
2242
+ --------
2243
+ >>> app = Pyloid(app_name="Pyloid-App")
2244
+ >>> file_path = app.save_file_dialog(dir="/home/user", filter="Text Files (*.txt)")
2245
+ """
2246
+ return self.execute_command("save_file_dialog", {"dir": dir, "filter": filter})
2247
+
2248
+ def select_directory_dialog(self, dir: Optional[str] = None) -> Optional[str]:
2249
+ """
2250
+ Opens a dialog to select a directory.
2251
+
2252
+ Parameters
2253
+ ----------
2254
+ dir : str, optional
2255
+ The initial directory that the dialog will open in.
2256
+
2257
+ Returns
2258
+ -------
2259
+ Optional[str]
2260
+ The path of the selected directory or None if no directory is selected.
2261
+
2262
+ Examples
2263
+ --------
2264
+ >>> app = Pyloid(app_name="Pyloid-App")
2265
+ >>> directory_path = app.select_directory_dialog(dir="/home/user")
2266
+ """
2267
+ return self.execute_command("select_directory_dialog", {"dir": dir})