michis-python-sammlung 0.0.5__tar.gz → 0.8__tar.gz

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.
Files changed (148) hide show
  1. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/PKG-INFO +10 -7
  2. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/pyproject.toml +34 -31
  3. michis_python_sammlung-0.8/setup.cfg +4 -0
  4. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/clickable_label.py +209 -209
  5. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/expandable_widget.py +494 -494
  6. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/image_paths.py +129 -129
  7. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/pyqt_util.py +96 -96
  8. michis_python_sammlung-0.8/src/michis_python_sammlung.egg-info/PKG-INFO +16 -0
  9. michis_python_sammlung-0.8/src/michis_python_sammlung.egg-info/SOURCES.txt +14 -0
  10. michis_python_sammlung-0.8/src/michis_python_sammlung.egg-info/dependency_links.txt +1 -0
  11. michis_python_sammlung-0.8/src/michis_python_sammlung.egg-info/requires.txt +1 -0
  12. michis_python_sammlung-0.8/src/michis_python_sammlung.egg-info/top_level.txt +1 -0
  13. michis_python_sammlung-0.0.5/LICENSE +0 -19
  14. michis_python_sammlung-0.0.5/src/michis_python_sammlung/packaging/package_doctor.py +0 -100
  15. michis_python_sammlung-0.0.5/src/michis_python_sammlung/packaging/rebuild.py +0 -55
  16. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/BAR.png +0 -0
  17. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/QUELLEN.txt +0 -8
  18. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/activeNotSending.png +0 -0
  19. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/activeNotSendingHoverImage.png +0 -0
  20. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/align_center_icon.png +0 -0
  21. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/align_center_icon_hover.png +0 -0
  22. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/apply_button.png +0 -0
  23. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/apply_button_hover.png +0 -0
  24. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/arrows_outwards_hover_icon.png +0 -0
  25. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/arrows_outwards_icon.png +0 -0
  26. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/blue_minus.png +0 -0
  27. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/blue_minus_hover.png +0 -0
  28. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/blue_plus.png +0 -0
  29. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/blue_plus_hover.png +0 -0
  30. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/cancel_button.png +0 -0
  31. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/cancel_button_hover.png +0 -0
  32. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/cancel_button_small.png +0 -0
  33. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/check_5610944.png +0 -0
  34. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/circle_icon.png +0 -0
  35. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/circle_icon_hover.png +0 -0
  36. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/cogwheel.png +0 -0
  37. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/cogwheel_hover.png +0 -0
  38. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/color_wheel.png +0 -0
  39. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/color_wheel_hover.png +0 -0
  40. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/connectionPending.png +0 -0
  41. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/crosshair_icon.png +0 -0
  42. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/crosshair_icon_hover.png +0 -0
  43. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/dark_sun.png +0 -0
  44. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/delete-button_5974771.png +0 -0
  45. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/disabled_notSending.png +0 -0
  46. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/disabled_notSending_hover.png +0 -0
  47. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/disabled_sending.png +0 -0
  48. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/disabled_sending_hover.png +0 -0
  49. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/drag_series_device_ui_cursor.png +0 -0
  50. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/enabled_notSending.png +0 -0
  51. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/enabled_notSending_hover.png +0 -0
  52. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/enabled_sending.png +0 -0
  53. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/endabled_sending_hover.png +0 -0
  54. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_colorful.png +0 -0
  55. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_colorful_hover.png +0 -0
  56. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_crossed.png +0 -0
  57. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_crossed_hover.png +0 -0
  58. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_open.png +0 -0
  59. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/eye_open_hover.png +0 -0
  60. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/filled_eye_crossed.png +0 -0
  61. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/filled_eye_crossed_hover.png +0 -0
  62. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/filled_eye_open.png +0 -0
  63. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/filled_eye_open_hover.png +0 -0
  64. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_circular_arrow.png +0 -0
  65. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_circular_arrow_hover.png +0 -0
  66. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_grid.png +0 -0
  67. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_grid_hover.png +0 -0
  68. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_minus.png +0 -0
  69. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_minus_hover.png +0 -0
  70. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_plus.png +0 -0
  71. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_plus_hover.png +0 -0
  72. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/green_plus_mask.png +0 -0
  73. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/grey_grid.png +0 -0
  74. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/grey_grid_hover.png +0 -0
  75. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/house_icon.png +0 -0
  76. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/house_icon_hover.png +0 -0
  77. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/inactiveNotSending.png +0 -0
  78. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/inactiveNotSendingHoverImage.png +0 -0
  79. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/inner_background.png +0 -0
  80. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/inner_background_2.png +0 -0
  81. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/lcd_background.png +0 -0
  82. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/left_sided_thickness_arrow_icon.png +0 -0
  83. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/line_icon.png +0 -0
  84. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/line_icon_hover.png +0 -0
  85. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/load_button.png +0 -0
  86. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/load_button_hover.png +0 -0
  87. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/load_button_test.png +0 -0
  88. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/m_button.png +0 -0
  89. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/m_button_hover.png +0 -0
  90. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/magnifying_glass.png +0 -0
  91. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/magnifying_glass_hover.png +0 -0
  92. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/menu.png +0 -0
  93. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/menu_hover.png +0 -0
  94. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/new_action_hover.png +0 -0
  95. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/new_node_icon.png +0 -0
  96. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/new_node_icon_hover.png +0 -0
  97. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/new_node_icon_plus.png +0 -0
  98. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/new_node_icon_plus_hover.png +0 -0
  99. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/outer_ring.png +0 -0
  100. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/outer_ring_2.png +0 -0
  101. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/outer_ring_3.png +0 -0
  102. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/pause.png +0 -0
  103. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/pause_hover.png +0 -0
  104. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play.png +0 -0
  105. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play_hover.png +0 -0
  106. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play_left.png +0 -0
  107. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play_left_hover.png +0 -0
  108. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play_right.png +0 -0
  109. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/play_right_hover.png +0 -0
  110. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/plug_settings.png +0 -0
  111. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/plug_settings_hover.png +0 -0
  112. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_off.png +0 -0
  113. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_off_hover.png +0 -0
  114. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_off_small.png +0 -0
  115. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_off_small_hover.png +0 -0
  116. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_on.png +0 -0
  117. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_on_hover.png +0 -0
  118. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_on_small.png +0 -0
  119. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/power_on_small_hover.png +0 -0
  120. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/question_mark.png +0 -0
  121. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/question_mark_hover.png +0 -0
  122. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/readme.txt +0 -5
  123. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/red_minus.png +0 -0
  124. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/red_minus_hover.png +0 -0
  125. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/red_plus.png +0 -0
  126. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/red_plus_hover.png +0 -0
  127. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/remove.png +0 -0
  128. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/remove2.png +0 -0
  129. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/right_sided_thickness_arrow_icon.png +0 -0
  130. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/save_button.png +0 -0
  131. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/save_button_hover.png +0 -0
  132. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/settings.png +0 -0
  133. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/settings2.png +0 -0
  134. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/starwars_stop.png +0 -0
  135. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop.png +0 -0
  136. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop_3.png +0 -0
  137. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop_3_hover.png +0 -0
  138. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop_hover.png +0 -0
  139. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop_icon.png +0 -0
  140. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/stop_icon_hover.png +0 -0
  141. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/thickness_icon.png +0 -0
  142. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/thickness_icon_hover.png +0 -0
  143. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/trash_icon.png +0 -0
  144. michis_python_sammlung-0.0.5/src/michis_python_sammlung/pyqt/icons/trash_icon_hover.png +0 -0
  145. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/README.md +0 -0
  146. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/__init__.py +0 -0
  147. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/__init__.py +0 -0
  148. {michis_python_sammlung-0.0.5 → michis_python_sammlung-0.8}/src/michis_python_sammlung/pyqt/icons/__init__.py +0 -0
@@ -1,13 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: michis_python_sammlung
3
- Version: 0.0.5
4
- Summary: Collection of mostly QT related stuff
3
+ Version: 0.8
4
+ Summary: Personal collection of mostly QT related stuff
5
+ Author: Michael Mischko
6
+ License-Expression: MIT
5
7
  Project-URL: Homepage, https://github.com/mischkomichael/Michis_python_sammlung
8
+ Project-URL: Repository, https://github.com/mischkomichael/Michis_python_sammlung
6
9
  Project-URL: Issues, https://github.com/mischkomichael/Michis_python_sammlung/issues
7
- Author-email: Michael Mischko <mischkom@web.de>
8
- License-Expression: MIT
9
- License-File: LICENSE
10
- Classifier: Operating System :: OS Independent
10
+ Keywords: pyqt6,widgets,gui
11
11
  Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Operating System :: OS Independent
12
14
  Requires-Python: >=3.10
13
- Requires-Dist: pyqt6>=6.6
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: PyQt6<7,>=6.11
@@ -1,32 +1,35 @@
1
- [build-system]
2
- requires = ["hatchling"]
3
- build-backend = "hatchling.build"
4
-
5
- [tool.hatch.build]
6
- include = [
7
- "src/michis_python_sammlung/**"
8
- ]
9
-
10
- [project]
11
- name = "michis_python_sammlung"
12
- version = "0.0.5"
13
- authors = [
14
- { name="Michael Mischko", email="mischkom@web.de" },
15
- ]
16
- description = "Collection of mostly QT related stuff"
17
- readme = "README.md"
18
- requires-python = ">=3.10"
19
- classifiers = [
20
- "Programming Language :: Python :: 3",
21
- "Operating System :: OS Independent",
22
- ]
23
- license = "MIT"
24
- license-files = ["LICEN[CS]E*"]
25
-
26
- dependencies = [
27
- "PyQt6>=6.6"
28
- ]
29
-
30
- [project.urls]
31
- Homepage = "https://github.com/mischkomichael/Michis_python_sammlung"
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "michis_python_sammlung"
7
+ version = "0.8"
8
+ description = "Personal collection of mostly QT related stuff"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [
12
+ { name = "Michael Mischko" }
13
+ ]
14
+ requires-python = ">=3.10"
15
+
16
+ dependencies = [
17
+ "PyQt6>=6.11,<7",
18
+ ]
19
+
20
+ keywords = [
21
+ "pyqt6",
22
+ "widgets",
23
+ "gui",
24
+ ]
25
+
26
+ classifiers = [
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.10",
29
+ "Operating System :: OS Independent",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/mischkomichael/Michis_python_sammlung"
34
+ Repository = "https://github.com/mischkomichael/Michis_python_sammlung"
32
35
  Issues = "https://github.com/mischkomichael/Michis_python_sammlung/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -1,210 +1,210 @@
1
- from __future__ import annotations
2
-
3
- from PyQt6.QtCore import Qt, QSize, pyqtSignal, Qt, QPoint, QTimer, QRect
4
- from PyQt6.QtWidgets import QLabel, QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLayout, QSizePolicy, QStackedLayout
5
- from PyQt6.QtGui import QPixmap, QResizeEvent, QColorConstants, QPainter, QRegion, QCursor, QMouseEvent, QColor, QBitmap, QTransform
6
-
7
- from numbers import Number
8
- from typing import Callable
9
-
10
- from PyQt6.QtGui import QImage
11
- from ..pyqt.image_paths import Image_paths
12
-
13
- def create_alpha_mask(image: QImage | QPixmap) -> QBitmap:
14
- # Ensure the image has an alpha channel
15
- if isinstance(image, QPixmap):
16
- image = image.toImage()
17
- image_with_alpha = image.convertToFormat(QImage.Format.Format_ARGB32)
18
- mask_image = image_with_alpha.createAlphaMask()
19
- return QBitmap.fromImage(mask_image)
20
-
21
- class Clickable_label(QLabel):
22
-
23
- sg_clicked = pyqtSignal(QMouseEvent)
24
-
25
- def __init__(
26
- self,
27
- pixmap: str | QPixmap,
28
- pixmap_hover: str | QPixmap,
29
- on_click_action: Callable = lambda: ...,
30
- cursor: QPixmap | Qt.CursorShape = Qt.CursorShape.ArrowCursor,
31
- scaled: float = None,
32
- heuristic_mask: bool = True,
33
- parent: QWidget = None
34
- ):
35
- super().__init__(parent)
36
- self.setAlignment(Qt.AlignmentFlag.AlignCenter)
37
- self._scaled = scaled
38
- self.configure_pixmaps(pixmap, pixmap_hover, scaled=scaled)
39
- self._hovering = False
40
- #somehow, the sizes are too small for the mask to not clip from the top and bottom ...
41
- self.setMinimumSize(self._pixmap_hover.size())
42
- cursor = QCursor(cursor) if isinstance(cursor, QPixmap) else cursor
43
- self.setCursor(cursor)
44
- self._on_click_action: Callable = on_click_action
45
- self._heuristic_mask = heuristic_mask
46
- self._mask_initialized = True
47
- # ### lazy mask evaluation to make sure Clickable_labels can be instantiated even without properly initialized paintDevice
48
- #self.set_mask(heuristic_mask=heuristic_mask)
49
- self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
50
- self.setAutoFillBackground(False)
51
-
52
- def sizeHint(self):
53
- return self._pixmap_hover.size()
54
-
55
- def showEvent(self, a0):
56
- if not self._mask_initialized:
57
- QTimer.singleShot(0, lambda: self._lazy_mask_init(self._heuristic_mask))
58
- return super().showEvent(a0)
59
-
60
- def _lazy_mask_init(self, heuristic_mask: bool) -> None:
61
- self.set_mask(heuristic_mask=heuristic_mask)
62
- self._mask_initialized
63
-
64
- def replace_widget(
65
- self,
66
- widget_to_replace: QWidget,
67
- delete_old: bool = True
68
- ) -> Clickable_label | tuple[Clickable_label]:
69
- """
70
- Replace an existing QWidget with self. Return self if delete_old is True or a tuple (self, replaced_widget) if not.
71
- """
72
- layouts_to_search: list[QLayout] = widget_to_replace.parent().findChildren(QVBoxLayout) + widget_to_replace.parent().findChildren(QHBoxLayout)
73
- found_layout: None | QHBoxLayout | QVBoxLayout = None
74
- for layout in layouts_to_search:
75
- for index in range(layout.count()):
76
- if widget_to_replace is layout.itemAt(index).widget():
77
- found_layout = layout
78
- break
79
- if found_layout is None:
80
- raise Exception("clickable_label.replace_widget_in_layout: widget has no layout !")
81
- else:
82
- found_layout.replaceWidget(widget_to_replace, self)
83
- if delete_old:
84
- widget_to_replace.deleteLater()
85
- return self
86
- else:
87
- return (self, widget_to_replace)
88
-
89
- def resizeEvent(self, a0: QResizeEvent):
90
- super().resizeEvent(a0)
91
- self.set_mask(a0.size(), self._heuristic_mask)
92
-
93
- def enterEvent(self, event):
94
- self._hovering = True
95
- self.setPixmap(self._pixmap_hover)
96
- super().enterEvent(event)
97
-
98
- def leaveEvent(self, a0):
99
- self._hovering = False
100
- self.setPixmap(self._pixmap)
101
- super().leaveEvent(a0)
102
-
103
- def mouseReleaseEvent(self, ev):
104
- self._on_click_action()
105
- self.sg_clicked.emit(ev)
106
- return super().mouseReleaseEvent(ev)
107
-
108
- def set_mask(self, new_size: QSize | None = None, heuristic_mask: bool=True) -> None:
109
- new_size = new_size if new_size is not None else self._pixmap_hover.size()
110
- empty_mask = QPixmap(new_size)
111
- empty_mask.fill(QColorConstants.Transparent)
112
- painter = QPainter(empty_mask)
113
- center_anker_x = (new_size.width()-self._pixmap_hover.size().width())//2
114
- center_anker_y = (new_size.height()-self._pixmap_hover.size().height())//2
115
- painter.drawPixmap(center_anker_x, center_anker_y, self._pixmap_hover)
116
- painter.end()
117
- if not heuristic_mask:
118
- self._mask = create_alpha_mask(empty_mask)
119
- else:
120
- self._mask = empty_mask.createHeuristicMask(clipTight=False)
121
- self.setMask(self._mask)
122
- # self.setMask(empty_mask.createMaskFromColor(QColorConstants.Transparent, Qt.MaskMode.MaskInColor))
123
-
124
- def replace_on_click_action(self, new_action: Callable) -> None:
125
- if not isinstance(new_action, Callable):
126
- raise ValueError(f"utility.custom_widgets.clickable_label.Cliclable_label.replace_on_click_action:\
127
- Action must be of type 'Callable', is {type(new_action)} instead.")
128
- self._on_click_action = new_action
129
-
130
- def configure_pixmaps(self,
131
- pixmap: str | QPixmap,
132
- pixmap_hover: str | QPixmap,
133
- scaled: float = None
134
- ) -> None:
135
- self._pixmap = QPixmap(pixmap) if isinstance(pixmap,str) else pixmap
136
- self._pixmap_hover = QPixmap(pixmap_hover) if isinstance(pixmap_hover,str) else pixmap_hover
137
- if self._pixmap.isNull() or self._pixmap_hover.isNull():
138
- raise ValueError(f"Failed instantiating pixmap from path: {pixmap} / {pixmap_hover}")
139
- if isinstance(scaled, Number):
140
- self._scaled = scaled
141
- self._pixmap = self._pixmap.scaled(self._pixmap.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
142
- self._pixmap_hover = self._pixmap_hover.scaled(self._pixmap_hover.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
143
- elif scaled is None:
144
- self.setScaledContents(False)
145
- self.setPixmap(self._pixmap)
146
-
147
- def scale_pixmap(self, scaled: Number) -> None:
148
- self._scaled = scaled
149
- self._pixmap = self._pixmap.scaled(self.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
150
- self._pixmap_hover = self._pixmap_hover.scaled(self.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
151
-
152
- def reset(self) -> None:
153
- self.setPixmap(self._pixmap)
154
- self._hovering = False
155
-
156
- class Togglable_clickable_label(QWidget):
157
-
158
- def __init__(
159
- self,
160
- untoggled_label: Clickable_label,
161
- toggled_label: Clickable_label,
162
- toggle_on_click: bool = True,
163
- parent=None,
164
- allow_expansion=True
165
- ):
166
- super().__init__(parent=parent)
167
- if not (isinstance(untoggled_label, Clickable_label) or isinstance(toggled_label, Clickable_label)):
168
- raise ValueError(f"label_1 and label_2 need to be of type Clickable_label not {type(untoggled_label), type(toggled_label)}")
169
- self.untoggled_label = untoggled_label
170
- self.toggled_label = toggled_label
171
- size_1 = self.untoggled_label._pixmap_hover
172
- size_2 = self.toggled_label._pixmap_hover
173
- if allow_expansion:
174
- self.setMinimumSize(QSize(size_1.width() if size_1.width() > size_2.width() else size_2.width(),
175
- size_1.height() if size_1.height() > size_2.height() else size_2.height()))
176
- else:
177
- self.setFixedSize(QSize(size_1.width() if size_1.width() > size_2.width() else size_2.width(),
178
- size_1.height() if size_1.height() > size_2.height() else size_2.height()))
179
- self._layout = QVBoxLayout(self)
180
- self._layout.setContentsMargins(0,0,0,0)
181
- self._layout.addWidget(untoggled_label)
182
- self._layout.addWidget(toggled_label)
183
- self.toggled = False
184
- self.toggle(toggle=self.toggled)
185
- if toggle_on_click:
186
- print("TOGGLING")
187
- self.untoggled_label.sg_clicked.connect(self.toggle)
188
- self.toggled_label.sg_clicked.connect(self.toggle)
189
-
190
- def toggle(self, mouse_event: QMouseEvent=None, toggle=None) -> None:
191
- self.toggled = not self.toggled if toggle is None else toggle
192
- if self.toggled:
193
- self.untoggled_label.setVisible(False)
194
- self.toggled_label.setVisible(True)
195
- else:
196
- self.toggled_label.setVisible(False)
197
- self.untoggled_label.setVisible(True)
198
-
199
- def replace_on_click_actions(self, action_1: Callable, action_2: Callable) -> None:
200
- self.untoggled_label.replace_on_click_action(action_1)
201
- self.toggled_label.replace_on_click_action(action_2)
202
-
203
- def main():
204
- import sys
205
- app = QApplication(sys.argv)
206
- label = Clickable_label(Image_paths.cogwheel, Image_paths.cogwheel_hover, heuristic_mask=False)
207
- label.show()
208
- sys.exit(app.exec())
209
- if __name__ == "__main__":
1
+ from __future__ import annotations
2
+
3
+ from PyQt6.QtCore import Qt, QSize, pyqtSignal, Qt, QPoint, QTimer, QRect
4
+ from PyQt6.QtWidgets import QLabel, QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLayout, QSizePolicy, QStackedLayout
5
+ from PyQt6.QtGui import QPixmap, QResizeEvent, QColorConstants, QPainter, QRegion, QCursor, QMouseEvent, QColor, QBitmap, QTransform
6
+
7
+ from numbers import Number
8
+ from typing import Callable
9
+
10
+ from PyQt6.QtGui import QImage
11
+ from ..pyqt.image_paths import Image_paths
12
+
13
+ def create_alpha_mask(image: QImage | QPixmap) -> QBitmap:
14
+ # Ensure the image has an alpha channel
15
+ if isinstance(image, QPixmap):
16
+ image = image.toImage()
17
+ image_with_alpha = image.convertToFormat(QImage.Format.Format_ARGB32)
18
+ mask_image = image_with_alpha.createAlphaMask()
19
+ return QBitmap.fromImage(mask_image)
20
+
21
+ class Clickable_label(QLabel):
22
+
23
+ sg_clicked = pyqtSignal(QMouseEvent)
24
+
25
+ def __init__(
26
+ self,
27
+ pixmap: str | QPixmap,
28
+ pixmap_hover: str | QPixmap,
29
+ on_click_action: Callable = lambda: ...,
30
+ cursor: QPixmap | Qt.CursorShape = Qt.CursorShape.ArrowCursor,
31
+ scaled: float = None,
32
+ heuristic_mask: bool = True,
33
+ parent: QWidget = None
34
+ ):
35
+ super().__init__(parent)
36
+ self.setAlignment(Qt.AlignmentFlag.AlignCenter)
37
+ self._scaled = scaled
38
+ self.configure_pixmaps(pixmap, pixmap_hover, scaled=scaled)
39
+ self._hovering = False
40
+ #somehow, the sizes are too small for the mask to not clip from the top and bottom ...
41
+ self.setMinimumSize(self._pixmap_hover.size())
42
+ cursor = QCursor(cursor) if isinstance(cursor, QPixmap) else cursor
43
+ self.setCursor(cursor)
44
+ self._on_click_action: Callable = on_click_action
45
+ self._heuristic_mask = heuristic_mask
46
+ self._mask_initialized = True
47
+ # ### lazy mask evaluation to make sure Clickable_labels can be instantiated even without properly initialized paintDevice
48
+ #self.set_mask(heuristic_mask=heuristic_mask)
49
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
50
+ self.setAutoFillBackground(False)
51
+
52
+ def sizeHint(self):
53
+ return self._pixmap_hover.size()
54
+
55
+ def showEvent(self, a0):
56
+ if not self._mask_initialized:
57
+ QTimer.singleShot(0, lambda: self._lazy_mask_init(self._heuristic_mask))
58
+ return super().showEvent(a0)
59
+
60
+ def _lazy_mask_init(self, heuristic_mask: bool) -> None:
61
+ self.set_mask(heuristic_mask=heuristic_mask)
62
+ self._mask_initialized
63
+
64
+ def replace_widget(
65
+ self,
66
+ widget_to_replace: QWidget,
67
+ delete_old: bool = True
68
+ ) -> Clickable_label | tuple[Clickable_label]:
69
+ """
70
+ Replace an existing QWidget with self. Return self if delete_old is True or a tuple (self, replaced_widget) if not.
71
+ """
72
+ layouts_to_search: list[QLayout] = widget_to_replace.parent().findChildren(QVBoxLayout) + widget_to_replace.parent().findChildren(QHBoxLayout)
73
+ found_layout: None | QHBoxLayout | QVBoxLayout = None
74
+ for layout in layouts_to_search:
75
+ for index in range(layout.count()):
76
+ if widget_to_replace is layout.itemAt(index).widget():
77
+ found_layout = layout
78
+ break
79
+ if found_layout is None:
80
+ raise Exception("clickable_label.replace_widget_in_layout: widget has no layout !")
81
+ else:
82
+ found_layout.replaceWidget(widget_to_replace, self)
83
+ if delete_old:
84
+ widget_to_replace.deleteLater()
85
+ return self
86
+ else:
87
+ return (self, widget_to_replace)
88
+
89
+ def resizeEvent(self, a0: QResizeEvent):
90
+ super().resizeEvent(a0)
91
+ self.set_mask(a0.size(), self._heuristic_mask)
92
+
93
+ def enterEvent(self, event):
94
+ self._hovering = True
95
+ self.setPixmap(self._pixmap_hover)
96
+ super().enterEvent(event)
97
+
98
+ def leaveEvent(self, a0):
99
+ self._hovering = False
100
+ self.setPixmap(self._pixmap)
101
+ super().leaveEvent(a0)
102
+
103
+ def mouseReleaseEvent(self, ev):
104
+ self._on_click_action()
105
+ self.sg_clicked.emit(ev)
106
+ return super().mouseReleaseEvent(ev)
107
+
108
+ def set_mask(self, new_size: QSize | None = None, heuristic_mask: bool=True) -> None:
109
+ new_size = new_size if new_size is not None else self._pixmap_hover.size()
110
+ empty_mask = QPixmap(new_size)
111
+ empty_mask.fill(QColorConstants.Transparent)
112
+ painter = QPainter(empty_mask)
113
+ center_anker_x = (new_size.width()-self._pixmap_hover.size().width())//2
114
+ center_anker_y = (new_size.height()-self._pixmap_hover.size().height())//2
115
+ painter.drawPixmap(center_anker_x, center_anker_y, self._pixmap_hover)
116
+ painter.end()
117
+ if not heuristic_mask:
118
+ self._mask = create_alpha_mask(empty_mask)
119
+ else:
120
+ self._mask = empty_mask.createHeuristicMask(clipTight=False)
121
+ self.setMask(self._mask)
122
+ # self.setMask(empty_mask.createMaskFromColor(QColorConstants.Transparent, Qt.MaskMode.MaskInColor))
123
+
124
+ def replace_on_click_action(self, new_action: Callable) -> None:
125
+ if not isinstance(new_action, Callable):
126
+ raise ValueError(f"utility.custom_widgets.clickable_label.Cliclable_label.replace_on_click_action:\
127
+ Action must be of type 'Callable', is {type(new_action)} instead.")
128
+ self._on_click_action = new_action
129
+
130
+ def configure_pixmaps(self,
131
+ pixmap: str | QPixmap,
132
+ pixmap_hover: str | QPixmap,
133
+ scaled: float = None
134
+ ) -> None:
135
+ self._pixmap = QPixmap(pixmap) if isinstance(pixmap,str) else pixmap
136
+ self._pixmap_hover = QPixmap(pixmap_hover) if isinstance(pixmap_hover,str) else pixmap_hover
137
+ if self._pixmap.isNull() or self._pixmap_hover.isNull():
138
+ raise ValueError(f"Failed instantiating pixmap from path: {pixmap} / {pixmap_hover}")
139
+ if isinstance(scaled, Number):
140
+ self._scaled = scaled
141
+ self._pixmap = self._pixmap.scaled(self._pixmap.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
142
+ self._pixmap_hover = self._pixmap_hover.scaled(self._pixmap_hover.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
143
+ elif scaled is None:
144
+ self.setScaledContents(False)
145
+ self.setPixmap(self._pixmap)
146
+
147
+ def scale_pixmap(self, scaled: Number) -> None:
148
+ self._scaled = scaled
149
+ self._pixmap = self._pixmap.scaled(self.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
150
+ self._pixmap_hover = self._pixmap_hover.scaled(self.size()*self._scaled,transformMode=Qt.TransformationMode.SmoothTransformation)
151
+
152
+ def reset(self) -> None:
153
+ self.setPixmap(self._pixmap)
154
+ self._hovering = False
155
+
156
+ class Togglable_clickable_label(QWidget):
157
+
158
+ def __init__(
159
+ self,
160
+ untoggled_label: Clickable_label,
161
+ toggled_label: Clickable_label,
162
+ toggle_on_click: bool = True,
163
+ parent=None,
164
+ allow_expansion=True
165
+ ):
166
+ super().__init__(parent=parent)
167
+ if not (isinstance(untoggled_label, Clickable_label) or isinstance(toggled_label, Clickable_label)):
168
+ raise ValueError(f"label_1 and label_2 need to be of type Clickable_label not {type(untoggled_label), type(toggled_label)}")
169
+ self.untoggled_label = untoggled_label
170
+ self.toggled_label = toggled_label
171
+ size_1 = self.untoggled_label._pixmap_hover
172
+ size_2 = self.toggled_label._pixmap_hover
173
+ if allow_expansion:
174
+ self.setMinimumSize(QSize(size_1.width() if size_1.width() > size_2.width() else size_2.width(),
175
+ size_1.height() if size_1.height() > size_2.height() else size_2.height()))
176
+ else:
177
+ self.setFixedSize(QSize(size_1.width() if size_1.width() > size_2.width() else size_2.width(),
178
+ size_1.height() if size_1.height() > size_2.height() else size_2.height()))
179
+ self._layout = QVBoxLayout(self)
180
+ self._layout.setContentsMargins(0,0,0,0)
181
+ self._layout.addWidget(untoggled_label)
182
+ self._layout.addWidget(toggled_label)
183
+ self.toggled = False
184
+ self.toggle(toggle=self.toggled)
185
+ if toggle_on_click:
186
+ print("TOGGLING")
187
+ self.untoggled_label.sg_clicked.connect(self.toggle)
188
+ self.toggled_label.sg_clicked.connect(self.toggle)
189
+
190
+ def toggle(self, mouse_event: QMouseEvent=None, toggle=None) -> None:
191
+ self.toggled = not self.toggled if toggle is None else toggle
192
+ if self.toggled:
193
+ self.untoggled_label.setVisible(False)
194
+ self.toggled_label.setVisible(True)
195
+ else:
196
+ self.toggled_label.setVisible(False)
197
+ self.untoggled_label.setVisible(True)
198
+
199
+ def replace_on_click_actions(self, action_1: Callable, action_2: Callable) -> None:
200
+ self.untoggled_label.replace_on_click_action(action_1)
201
+ self.toggled_label.replace_on_click_action(action_2)
202
+
203
+ def main():
204
+ import sys
205
+ app = QApplication(sys.argv)
206
+ label = Clickable_label(Image_paths.cogwheel, Image_paths.cogwheel_hover, heuristic_mask=False)
207
+ label.show()
208
+ sys.exit(app.exec())
209
+ if __name__ == "__main__":
210
210
  main()