ZToolTip 2.0.0__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.
- ztooltip/__init__.py +1 -0
- ztooltip/constants.py +3 -0
- ztooltip/drop_shadow.py +59 -0
- ztooltip/enums.py +9 -0
- ztooltip/placement_utils.py +58 -0
- ztooltip/tooltip.py +990 -0
- ztooltip/tooltip_interface.py +27 -0
- ztooltip/tooltip_triangle.py +125 -0
- ztooltip/utils.py +37 -0
- ztooltip-2.0.0.dist-info/METADATA +249 -0
- ztooltip-2.0.0.dist-info/RECORD +14 -0
- ztooltip-2.0.0.dist-info/WHEEL +5 -0
- ztooltip-2.0.0.dist-info/licenses/LICENSE +21 -0
- ztooltip-2.0.0.dist-info/top_level.txt +1 -0
ztooltip/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .tooltip import Tooltip, TooltipPlacement
|
ztooltip/constants.py
ADDED
ztooltip/drop_shadow.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from qtpy.QtWidgets import QWidget
|
|
2
|
+
from qtpy.QtCore import QSize
|
|
3
|
+
from .tooltip_interface import TooltipInterface
|
|
4
|
+
from .constants import *
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DropShadow(QWidget):
|
|
8
|
+
|
|
9
|
+
def __init__(self, tooltip: TooltipInterface):
|
|
10
|
+
"""Create a new DropShadow instance
|
|
11
|
+
|
|
12
|
+
:param tooltip: tooltip the drop shadow belongs to
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
super(DropShadow, self).__init__(tooltip)
|
|
16
|
+
|
|
17
|
+
self.tooltip = tooltip
|
|
18
|
+
|
|
19
|
+
# Drop shadow drawn manually since only one graphics effect can be applied
|
|
20
|
+
self.layers = []
|
|
21
|
+
|
|
22
|
+
for i in range(DROP_SHADOW_SIZE):
|
|
23
|
+
layer = QWidget(self)
|
|
24
|
+
self.__apply_layer_stylesheet(layer, i)
|
|
25
|
+
self.layers.append(layer)
|
|
26
|
+
|
|
27
|
+
def update(self):
|
|
28
|
+
"""Update the stylesheets of the layers"""
|
|
29
|
+
|
|
30
|
+
for i, layer in enumerate(self.layers):
|
|
31
|
+
self.__apply_layer_stylesheet(layer, i)
|
|
32
|
+
|
|
33
|
+
def resize(self, size: QSize):
|
|
34
|
+
"""Resize the drop shadow widget
|
|
35
|
+
|
|
36
|
+
:param size: new size
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
super().resize(size)
|
|
40
|
+
width = size.width()
|
|
41
|
+
height = size.height()
|
|
42
|
+
|
|
43
|
+
# Resize and move drop shadow layers
|
|
44
|
+
for i, layer in enumerate(self.layers):
|
|
45
|
+
layer.resize(width - i * 2, height - i * 2)
|
|
46
|
+
layer.move(i, i)
|
|
47
|
+
|
|
48
|
+
def __apply_layer_stylesheet(self, layer: QWidget, index: int):
|
|
49
|
+
"""Apply stylesheet to a layer widget
|
|
50
|
+
|
|
51
|
+
:param layer: layer to apply the stylesheet to
|
|
52
|
+
:param index: index of the layer
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
layer.setStyleSheet(
|
|
56
|
+
'background: rgba(0, 0, 0, {}); '
|
|
57
|
+
'border-radius: 8px;'
|
|
58
|
+
.format((index + 1) * 0.001 * self.tooltip.getDropShadowStrength())
|
|
59
|
+
)
|
ztooltip/enums.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from qtpy.QtWidgets import QWidget
|
|
2
|
+
from qtpy.QtCore import QPoint
|
|
3
|
+
from .enums import TooltipPlacement
|
|
4
|
+
from .utils import Utils
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PlacementUtils:
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
def get_optimal_placement(widget: QWidget, triangle_size: int, border_radius: int) -> TooltipPlacement:
|
|
11
|
+
"""Calculate the optimal placement of a tooltip based on the widget,
|
|
12
|
+
triangle size, and border radius.
|
|
13
|
+
|
|
14
|
+
:param widget: widget of the tooltip
|
|
15
|
+
:param triangle_size: size of the tooltip triangle
|
|
16
|
+
:param border_radius: border radius of the tooltip
|
|
17
|
+
:return: optimal placement
|
|
18
|
+
"""
|
|
19
|
+
top_level_parent = Utils.get_top_level_parent(widget)
|
|
20
|
+
top_level_parent_geometry = top_level_parent.geometry()
|
|
21
|
+
widget_pos = widget.mapToGlobal(QPoint(0, 0))
|
|
22
|
+
widget_center_x = widget_pos.x() + widget.width() // 2
|
|
23
|
+
|
|
24
|
+
min_space_required = 2 * triangle_size + border_radius
|
|
25
|
+
|
|
26
|
+
# Available space left and right from widget center
|
|
27
|
+
left_space_from_center = widget_center_x - top_level_parent.pos().x()
|
|
28
|
+
right_space_from_center = top_level_parent_geometry.right() - widget_center_x
|
|
29
|
+
|
|
30
|
+
# Available space top and bottom
|
|
31
|
+
top_space = widget_pos.y() - top_level_parent.pos().y()
|
|
32
|
+
bottom_space = top_level_parent_geometry.bottom() - widget_pos.y() - widget.height()
|
|
33
|
+
|
|
34
|
+
# Available space left and right
|
|
35
|
+
left_space = widget_pos.x() - top_level_parent.pos().x()
|
|
36
|
+
right_space = top_level_parent_geometry.right() - widget_pos.x() - widget.width()
|
|
37
|
+
|
|
38
|
+
# Check if top/bottom placement is possible
|
|
39
|
+
can_place_top_bottom = (left_space_from_center > min_space_required and
|
|
40
|
+
right_space_from_center > min_space_required)
|
|
41
|
+
|
|
42
|
+
# Check if left/right placement is possible
|
|
43
|
+
can_place_left_right = (top_space > min_space_required and
|
|
44
|
+
bottom_space > min_space_required)
|
|
45
|
+
|
|
46
|
+
if can_place_top_bottom:
|
|
47
|
+
return TooltipPlacement.TOP if top_space >= bottom_space else TooltipPlacement.BOTTOM
|
|
48
|
+
elif can_place_left_right:
|
|
49
|
+
return TooltipPlacement.RIGHT if right_space >= left_space else TooltipPlacement.LEFT
|
|
50
|
+
else:
|
|
51
|
+
# Fallback: choose placement with most available space
|
|
52
|
+
spaces = [
|
|
53
|
+
(TooltipPlacement.LEFT, left_space),
|
|
54
|
+
(TooltipPlacement.RIGHT, right_space),
|
|
55
|
+
(TooltipPlacement.TOP, top_space),
|
|
56
|
+
(TooltipPlacement.BOTTOM, bottom_space)
|
|
57
|
+
]
|
|
58
|
+
return max(spaces, key=lambda x: x[1])[0]
|