gui-utilities 1.3.42__tar.gz → 1.4.2__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.
Potentially problematic release.
This version of gui-utilities might be problematic. Click here for more details.
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/PKG-INFO +1 -1
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/gui_utilities.py +159 -26
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities.egg-info/PKG-INFO +1 -1
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/pyproject.toml +1 -1
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/LICENSE +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/README.md +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/icons/focused_hide_text_icon.png +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/icons/focused_show_text_icon.png +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/icons/hide_text_icon.png +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/icons/show_text_icon.png +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities/tlds/tlds_list.txt +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities.egg-info/SOURCES.txt +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities.egg-info/dependency_links.txt +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities.egg-info/requires.txt +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/gui_utilities.egg-info/top_level.txt +0 -0
- {gui_utilities-1.3.42 → gui_utilities-1.4.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from PyQt6.QtCore import Qt, QObject, QEvent, QSize
|
|
2
|
-
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QComboBox, QDialog, QToolButton, QWidgetAction, QCheckBox, QTableWidget, QHeaderView
|
|
3
|
-
from PyQt6.QtGui import QIcon
|
|
2
|
+
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QComboBox, QDialog, QToolButton, QWidgetAction, QCheckBox, QTableWidget, QHeaderView, QApplication, QStyle, QStyledItemDelegate
|
|
3
|
+
from PyQt6.QtGui import QIcon, QTextDocument
|
|
4
4
|
import re
|
|
5
5
|
import requests
|
|
6
6
|
import importlib.resources
|
|
@@ -9,6 +9,16 @@ main_dir = importlib.resources.files("gui_utilities")
|
|
|
9
9
|
icons_dir = main_dir / "icons"
|
|
10
10
|
tlds_path = main_dir / "tlds"
|
|
11
11
|
|
|
12
|
+
def latex_to_html(expression):
|
|
13
|
+
html_expression = expression
|
|
14
|
+
html_expression = re.sub(r"\\frac\{(.*?)\}\{(.*?)\}", r"<span style='font-size:90%;'>\1⁄\2</span>", html_expression)
|
|
15
|
+
html_expression = re.sub(r"_\{([^}]+)\}", r"<sub>\1</sub>", html_expression)
|
|
16
|
+
html_expression = re.sub(r"\^\{([^}]+)\}", r"<sup>\1</sup>", html_expression)
|
|
17
|
+
html_expression = re.sub(r"_([a-zA-Z0-9]+)", r"<sub>\1</sub>", html_expression)
|
|
18
|
+
html_expression = re.sub(r"\^([a-zA-Z0-9]+)", r"<sup>\1</sup>", html_expression)
|
|
19
|
+
html_expression = html_expression.replace(" ", " ")
|
|
20
|
+
return html_expression
|
|
21
|
+
|
|
12
22
|
def create_window(title, background_color = "#1e1e1e", parent = None):
|
|
13
23
|
window = QWidget(parent)
|
|
14
24
|
window.setObjectName("window")
|
|
@@ -201,16 +211,6 @@ def create_label(
|
|
|
201
211
|
word_wrap = False,
|
|
202
212
|
parent = None
|
|
203
213
|
):
|
|
204
|
-
def latex_to_html(expression):
|
|
205
|
-
html_expression = expression
|
|
206
|
-
html_expression = re.sub(r"\\frac\{(.*?)\}\{(.*?)\}", r"<span style='font-size:90%;'>\1⁄\2</span>", html_expression)
|
|
207
|
-
html_expression = re.sub(r"_\{([^}]+)\}", r"<sub>\1</sub>", html_expression)
|
|
208
|
-
html_expression = re.sub(r"\^\{([^}]+)\}", r"<sup>\1</sup>", html_expression)
|
|
209
|
-
html_expression = re.sub(r"_([a-zA-Z0-9]+)", r"<sub>\1</sub>", html_expression)
|
|
210
|
-
html_expression = re.sub(r"\^([a-zA-Z0-9]+)", r"<sup>\1</sup>", html_expression)
|
|
211
|
-
html_expression = html_expression.replace(" ", " ")
|
|
212
|
-
return html_expression
|
|
213
|
-
|
|
214
214
|
if math_expression:
|
|
215
215
|
label = QLabel(latex_to_html(text), parent)
|
|
216
216
|
label.setTextFormat(Qt.TextFormat.RichText)
|
|
@@ -367,6 +367,7 @@ def create_text_box(
|
|
|
367
367
|
focused_show_text_icon_url = str(icons_dir / "focused_show_text_icon.png"),
|
|
368
368
|
focused_hide_text_icon_url = str(icons_dir / "focused_hide_text_icon.png"),
|
|
369
369
|
hide_text = False,
|
|
370
|
+
math_expression = False,
|
|
370
371
|
parent = None
|
|
371
372
|
):
|
|
372
373
|
text_box = QLineEdit(parent)
|
|
@@ -403,7 +404,6 @@ def create_text_box(
|
|
|
403
404
|
}}
|
|
404
405
|
"""
|
|
405
406
|
text_box.setStyleSheet(style_sheet)
|
|
406
|
-
text_box.setPlaceholderText(placeholder_text)
|
|
407
407
|
if hide_text:
|
|
408
408
|
show_text_icon = QIcon(show_text_icon_url)
|
|
409
409
|
hide_text_icon = QIcon(hide_text_icon_url)
|
|
@@ -425,7 +425,7 @@ def create_text_box(
|
|
|
425
425
|
margin-right: 10px;
|
|
426
426
|
}
|
|
427
427
|
""")
|
|
428
|
-
|
|
428
|
+
|
|
429
429
|
def update_icon():
|
|
430
430
|
is_password = text_box.echoMode() == QLineEdit.EchoMode.Password
|
|
431
431
|
if text_box.hasFocus(): icon = focused_hide_text_icon if is_password else focused_show_text_icon
|
|
@@ -440,7 +440,6 @@ def create_text_box(
|
|
|
440
440
|
toggle_text_visibility_button.clicked.connect(toggle_visibility)
|
|
441
441
|
|
|
442
442
|
class _IconFocusWatcher(QObject):
|
|
443
|
-
|
|
444
443
|
def __init__(self, watched, on_focus_change):
|
|
445
444
|
super().__init__(watched)
|
|
446
445
|
self._watched = watched
|
|
@@ -454,7 +453,45 @@ def create_text_box(
|
|
|
454
453
|
icon_focus_watcher = _IconFocusWatcher(text_box, update_icon)
|
|
455
454
|
text_box.installEventFilter(icon_focus_watcher)
|
|
456
455
|
setattr(text_box, "_icon_focus_watcher", icon_focus_watcher)
|
|
457
|
-
|
|
456
|
+
|
|
457
|
+
placeholder_label = create_label(
|
|
458
|
+
text = placeholder_text,
|
|
459
|
+
font_family = font_family,
|
|
460
|
+
font_size = font_size,
|
|
461
|
+
font_color = placeholder_font_color,
|
|
462
|
+
font_weight = font_weight,
|
|
463
|
+
padding = padding,
|
|
464
|
+
padding_left = padding_left,
|
|
465
|
+
padding_top = padding_top,
|
|
466
|
+
padding_right = padding_right,
|
|
467
|
+
padding_bottom = padding_bottom,
|
|
468
|
+
math_expression = math_expression,
|
|
469
|
+
transparent_for_mouse = True,
|
|
470
|
+
parent = text_box
|
|
471
|
+
)
|
|
472
|
+
placeholder_label.move(0, 2)
|
|
473
|
+
|
|
474
|
+
def update_placeholder_visibility():
|
|
475
|
+
has_text = bool(text_box.text().strip())
|
|
476
|
+
has_focus = text_box.hasFocus()
|
|
477
|
+
placeholder_label.setVisible(not has_text and not has_focus)
|
|
478
|
+
if hide_text: update_icon()
|
|
479
|
+
|
|
480
|
+
class _PlaceholderFocusWatcher(QObject):
|
|
481
|
+
def __init__(self, watched, on_focus_change):
|
|
482
|
+
super().__init__(watched)
|
|
483
|
+
self._watched = watched
|
|
484
|
+
self._on_focus_change = on_focus_change
|
|
485
|
+
|
|
486
|
+
def eventFilter(self, watched, event):
|
|
487
|
+
if watched is self._watched and event.type() in (QEvent.Type.FocusIn, QEvent.Type.FocusOut):
|
|
488
|
+
if callable(self._on_focus_change): self._on_focus_change()
|
|
489
|
+
return super().eventFilter(watched, event)
|
|
490
|
+
|
|
491
|
+
placeholder_focus_watcher = _PlaceholderFocusWatcher(text_box, update_placeholder_visibility)
|
|
492
|
+
text_box.installEventFilter(placeholder_focus_watcher)
|
|
493
|
+
setattr(text_box, "_placeholder_focus_watcher", placeholder_focus_watcher)
|
|
494
|
+
update_placeholder_visibility()
|
|
458
495
|
return text_box
|
|
459
496
|
|
|
460
497
|
def create_combo_box(
|
|
@@ -485,21 +522,107 @@ def create_combo_box(
|
|
|
485
522
|
dropdown_selection_background_color = "#0078d7",
|
|
486
523
|
dropdown_border_width = 1,
|
|
487
524
|
dropdown_border_color = "#5c5c5c",
|
|
525
|
+
math_expression = False,
|
|
488
526
|
parent = None
|
|
489
527
|
):
|
|
490
528
|
combo_box = QComboBox(parent)
|
|
491
|
-
combo_box.
|
|
492
|
-
combo_box.addItems(items)
|
|
493
|
-
combo_box.setCurrentIndex(-1)
|
|
494
|
-
|
|
529
|
+
combo_box.setAccessibleName("combo_box")
|
|
495
530
|
padding_left_value = padding_left if padding_left is not None else padding
|
|
496
531
|
padding_top_value = padding_top if padding_top is not None else padding
|
|
497
532
|
padding_right_value = padding_right if padding_right is not None else padding
|
|
498
533
|
padding_bottom_value = padding_bottom if padding_bottom is not None else padding
|
|
534
|
+
if math_expression:
|
|
535
|
+
placeholder_label = create_label(
|
|
536
|
+
text = placeholder_text,
|
|
537
|
+
font_family = font_family,
|
|
538
|
+
font_size = font_size,
|
|
539
|
+
font_color = placeholder_font_color,
|
|
540
|
+
padding = padding,
|
|
541
|
+
padding_left = padding_left,
|
|
542
|
+
padding_top = padding_top,
|
|
543
|
+
padding_right = padding_right,
|
|
544
|
+
padding_bottom = padding_bottom,
|
|
545
|
+
math_expression = True,
|
|
546
|
+
transparent_for_mouse = True,
|
|
547
|
+
parent = combo_box
|
|
548
|
+
)
|
|
549
|
+
placeholder_label.move(0, 2)
|
|
550
|
+
|
|
551
|
+
def update_placeholder_visibility():
|
|
552
|
+
has_selection = combo_box.currentIndex() != -1
|
|
553
|
+
placeholder_label.setVisible(not has_selection)
|
|
554
|
+
|
|
555
|
+
combo_box.currentIndexChanged.connect(update_placeholder_visibility)
|
|
556
|
+
update_placeholder_visibility()
|
|
557
|
+
|
|
558
|
+
class RichTextDelegate(QStyledItemDelegate):
|
|
559
|
+
def __init__(
|
|
560
|
+
self,
|
|
561
|
+
parent = None,
|
|
562
|
+
font_color = "#ffffff",
|
|
563
|
+
selection_font_color = "#ffffff"
|
|
564
|
+
):
|
|
565
|
+
super().__init__(parent)
|
|
566
|
+
self.font_color = font_color
|
|
567
|
+
self.selection_font_color = selection_font_color
|
|
499
568
|
|
|
569
|
+
def paint(self, painter, option, index):
|
|
570
|
+
if option.state & QStyle.StateFlag.State_Selected: text_color = self.selection_font_color
|
|
571
|
+
else: text_color = self.font_color
|
|
572
|
+
document = QTextDocument()
|
|
573
|
+
html = f"<span style = \"color:{text_color};\">{index.data(Qt.ItemDataRole.DisplayRole)}</span>"
|
|
574
|
+
document.setHtml(html)
|
|
575
|
+
option.text = ""
|
|
576
|
+
QApplication.style().drawControl(QStyle.ControlElement.CE_ItemViewItem, option, painter)
|
|
577
|
+
painter.save()
|
|
578
|
+
painter.translate(option.rect.left(), option.rect.top() + (option.rect.height() - document.size().height()) / 2)
|
|
579
|
+
document.drawContents(painter)
|
|
580
|
+
painter.restore()
|
|
581
|
+
|
|
582
|
+
delegate = RichTextDelegate(
|
|
583
|
+
parent = combo_box,
|
|
584
|
+
font_color = dropdown_font_color,
|
|
585
|
+
selection_font_color = font_color
|
|
586
|
+
)
|
|
587
|
+
combo_box.setItemDelegate(delegate)
|
|
588
|
+
combo_box.clear()
|
|
589
|
+
for item in items: combo_box.addItem(latex_to_html(item))
|
|
590
|
+
combo_box.view().setTextElideMode(Qt.TextElideMode.ElideNone)
|
|
591
|
+
else:
|
|
592
|
+
combo_box.setPlaceholderText(placeholder_text)
|
|
593
|
+
combo_box.addItems(items)
|
|
594
|
+
combo_box.setCurrentIndex(-1)
|
|
595
|
+
if math_expression:
|
|
596
|
+
selected_item_label = create_label(
|
|
597
|
+
text = "",
|
|
598
|
+
font_family = font_family,
|
|
599
|
+
font_size = font_size,
|
|
600
|
+
font_color = font_color,
|
|
601
|
+
padding = padding,
|
|
602
|
+
padding_left = padding_left,
|
|
603
|
+
padding_top = padding_top,
|
|
604
|
+
padding_right = padding_right,
|
|
605
|
+
padding_bottom = padding_bottom,
|
|
606
|
+
math_expression = True,
|
|
607
|
+
transparent_for_mouse = True,
|
|
608
|
+
alignment = Qt.AlignmentFlag.AlignCenter,
|
|
609
|
+
parent = combo_box
|
|
610
|
+
)
|
|
611
|
+
selected_item_label.setVisible(False)
|
|
612
|
+
|
|
613
|
+
def update_selected_item_display(index):
|
|
614
|
+
if index != -1:
|
|
615
|
+
html_text = combo_box.itemText(index)
|
|
616
|
+
selected_item_label.setText(html_text)
|
|
617
|
+
selected_item_label.setVisible(True)
|
|
618
|
+
else:
|
|
619
|
+
selected_item_label.setVisible(False)
|
|
620
|
+
|
|
621
|
+
combo_box.currentIndexChanged.connect(update_selected_item_display)
|
|
622
|
+
|
|
500
623
|
def get_stylesheet(font_color):
|
|
501
624
|
return f"""
|
|
502
|
-
QComboBox {{
|
|
625
|
+
QComboBox[accessibleName="combo_box"] {{
|
|
503
626
|
font-family: {font_family};
|
|
504
627
|
font-size: {font_size}px;
|
|
505
628
|
color: {font_color};
|
|
@@ -511,12 +634,12 @@ def create_combo_box(
|
|
|
511
634
|
border: {border_width}px solid {border_color};
|
|
512
635
|
border-radius: {border_radius}px;
|
|
513
636
|
}}
|
|
514
|
-
QComboBox:hover {{
|
|
637
|
+
QComboBox[accessibleName="combo_box"]:hover {{
|
|
515
638
|
background-color: {hover_background_color};
|
|
516
639
|
border: {hover_border_width}px solid {hover_border_color};
|
|
517
640
|
}}
|
|
518
|
-
QComboBox:on {{
|
|
519
|
-
color: {on_font_color};
|
|
641
|
+
QComboBox[accessibleName="combo_box"]:on {{
|
|
642
|
+
color: {"transparent" if math_expression else on_font_color};
|
|
520
643
|
background-color: {on_background_color};
|
|
521
644
|
border: {on_border_width}px solid {on_border_color};
|
|
522
645
|
}}
|
|
@@ -532,8 +655,12 @@ def create_combo_box(
|
|
|
532
655
|
"""
|
|
533
656
|
|
|
534
657
|
def change_color(index):
|
|
535
|
-
if index == -1:
|
|
536
|
-
|
|
658
|
+
if index == -1:
|
|
659
|
+
text_color = "transparent" if math_expression else placeholder_font_color
|
|
660
|
+
combo_box.setStyleSheet(get_stylesheet(text_color))
|
|
661
|
+
else:
|
|
662
|
+
text_color = "transparent" if math_expression else font_color
|
|
663
|
+
combo_box.setStyleSheet(get_stylesheet(text_color))
|
|
537
664
|
|
|
538
665
|
combo_box.currentIndexChanged.connect(change_color)
|
|
539
666
|
change_color(-1)
|
|
@@ -1113,6 +1240,12 @@ def validate_integer(integer, suffix = "El", field = "campo"):
|
|
|
1113
1240
|
if pattern.match(unformatted_integer): return None
|
|
1114
1241
|
return f"No ha ingresado {"un" if suffix == "El" else "una"} {field} {"válido" if suffix == "El" else "válida"}."
|
|
1115
1242
|
|
|
1243
|
+
def validate_float(decimal, suffix = "El", field = "campo"):
|
|
1244
|
+
if not decimal or not decimal.strip(): return f"{suffix} {field} no puede dejarse {"vacío" if suffix == "El" else "vacía"}."
|
|
1245
|
+
pattern = re.compile(r"^-?\d{1,3}(?:\.\d{3})*(?:,\d+)?$|^-?\d+(?:,\d+)?$")
|
|
1246
|
+
if not pattern.match(decimal): return f"No ha ingresado {"un" if suffix == "El" else "una"} {field} {"válido" if suffix == "El" else "válida"}."
|
|
1247
|
+
return None
|
|
1248
|
+
|
|
1116
1249
|
def validate_id(id_str):
|
|
1117
1250
|
if not id_str or not id_str.strip(): return "El D.N.I. no puede dejarse vacio."
|
|
1118
1251
|
pattern = re.compile(r"^(?:\d{8}|(?:\d{1,2}\.\d{3}\.\d{3}))$")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|