labelimgplusplus 2.3.3__tar.gz → 2.4.1__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.
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/HISTORY.rst +45 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/PKG-INFO +3 -3
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/README.rst +2 -2
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelImgPlusPlus.py +11 -10
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/PKG-INFO +3 -3
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/SOURCES.txt +1 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/resources.py +43 -43
- labelimgplusplus-2.4.1/libs/utils/dpi.py +50 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/styles.py +85 -83
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/batchVerifyDialog.py +3 -1
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/canvas.py +6 -2
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/galleryWidget.py +3 -2
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/keypointPanel.py +4 -3
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/shortcutsDialog.py +2 -1
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/splitDialog.py +3 -1
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/toolBar.py +6 -29
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/pyproject.toml +1 -1
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/CONTRIBUTING.rst +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/LICENSE +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/MANIFEST.in +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/data/predefined_classes.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/dependency_links.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/entry_points.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/requires.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/top_level.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/commands.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/keypoint_config.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/settings.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/shape.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/core/shortcut_config.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/data/predefined_classes.txt +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/annotation_loader.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/annotation_probe.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/coco_io.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/create_ml_io.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/format_metadata.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/labelFile.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/pascal_voc_io.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/yolo_io.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/formats/yolo_seg_io.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/tools/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/tools/dataset_splitter.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/tools/label_checker.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/constants.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/hashableQListWidgetItem.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/stringBundle.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/ustr.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/utils/utils.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/__init__.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/colorDialog.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/combobox.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/default_label_combobox.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/gallery_status_controller.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/labelCheckerDialog.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/labelDialog.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/lightWidget.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/statsWidget.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/stats_controller.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/view_scaling.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/libs/widgets/zoomWidget.py +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/resources.qrc +0 -0
- {labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
History
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
2.4.1 (2026-06-09)
|
|
5
|
+
------------------
|
|
6
|
+
|
|
7
|
+
Documentation and discoverability release. Adds an animated demo to the README
|
|
8
|
+
and improves how the project is found and presented. No functional changes —
|
|
9
|
+
the application behaves identically to 2.4.0.
|
|
10
|
+
|
|
11
|
+
Documentation
|
|
12
|
+
~~~~~~~~~~~~~
|
|
13
|
+
|
|
14
|
+
* Add an animated demo GIF to the README showcasing the core workflow —
|
|
15
|
+
gallery mode, bounding boxes, dark theme, polygons, face keypoints, and save
|
|
16
|
+
* Refresh project metadata for discoverability (description, topics, homepage)
|
|
17
|
+
|
|
18
|
+
2.4.0 (2026-06-09)
|
|
19
|
+
------------------
|
|
20
|
+
|
|
21
|
+
HiDPI scaling release. The interface now scales consistently on high-density
|
|
22
|
+
and fractionally-scaled displays: chrome, dialogs, stylesheets, and the canvas
|
|
23
|
+
grab tolerance all grow by the same factor that already drove icon sizing.
|
|
24
|
+
Backward compatible — every change is a no-op at the standard 96 DPI baseline,
|
|
25
|
+
so non-HiDPI displays are unchanged.
|
|
26
|
+
|
|
27
|
+
New features
|
|
28
|
+
~~~~~~~~~~~~
|
|
29
|
+
|
|
30
|
+
* Scale the full UI for HiDPI displays from a single DPI factor (#66) —
|
|
31
|
+
dialog and dock minimum sizes, status-bar labels, keypoint-panel
|
|
32
|
+
indicators, gallery preset controls, the collapsible toolbar, every
|
|
33
|
+
stylesheet padding/margin/border/font-size value, and the canvas
|
|
34
|
+
hit-test radius
|
|
35
|
+
|
|
36
|
+
Bug fixes
|
|
37
|
+
~~~~~~~~~
|
|
38
|
+
|
|
39
|
+
* Fix a ``ModuleNotFoundError`` crash when selecting the "Auto" toolbar icon
|
|
40
|
+
size — the handler imported from a stale ``libs.toolBar`` path (#93)
|
|
41
|
+
|
|
42
|
+
Internal
|
|
43
|
+
~~~~~~~~
|
|
44
|
+
|
|
45
|
+
* Add ``libs/utils/dpi.py`` as the single source of truth for screen scaling
|
|
46
|
+
(``get_dpi_scale_factor`` + ``scale_px``); chrome and stylesheets now scale
|
|
47
|
+
through it instead of recomputing DPI per site
|
|
48
|
+
|
|
4
49
|
2.3.3 (2026-06-09)
|
|
5
50
|
------------------
|
|
6
51
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: labelimgplusplus
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: labelImg++ is an enhanced graphical image annotation tool with Gallery Mode for browsing and labeling images
|
|
5
5
|
Author-email: Abhik Sarkar <abhiksark@gmail.com>
|
|
6
6
|
License: Copyright (c) <2015-Present> Tzutalin
|
|
@@ -64,8 +64,8 @@ labelImg++
|
|
|
64
64
|
|
|
65
65
|
**Version 2.0.0** - First stable release! Install with ``pip install labelImgPlusPlus``
|
|
66
66
|
|
|
67
|
-
.. image:: resources/demo/
|
|
68
|
-
:alt: labelImg++
|
|
67
|
+
.. image:: https://raw.githubusercontent.com/abhiksark/labelImg-plus-plus/c7fbd5fc08a561206b210706143a50023c82a782/resources/demo/demo.gif
|
|
68
|
+
:alt: labelImg++ demo - gallery, bounding boxes, dark theme, polygons, keypoints and save
|
|
69
69
|
:align: center
|
|
70
70
|
|
|
71
71
|
Features
|
|
@@ -28,8 +28,8 @@ labelImg++
|
|
|
28
28
|
|
|
29
29
|
**Version 2.0.0** - First stable release! Install with ``pip install labelImgPlusPlus``
|
|
30
30
|
|
|
31
|
-
.. image:: resources/demo/
|
|
32
|
-
:alt: labelImg++
|
|
31
|
+
.. image:: https://raw.githubusercontent.com/abhiksark/labelImg-plus-plus/c7fbd5fc08a561206b210706143a50023c82a782/resources/demo/demo.gif
|
|
32
|
+
:alt: labelImg++ demo - gallery, bounding boxes, dark theme, polygons, keypoints and save
|
|
33
33
|
:align: center
|
|
34
34
|
|
|
35
35
|
Features
|
|
@@ -95,6 +95,7 @@ from libs.utils.utils import (
|
|
|
95
95
|
new_icon, themed_icon, new_action, add_actions, format_shortcut, Struct,
|
|
96
96
|
generate_color_by_text, have_qstring, natural_sort
|
|
97
97
|
)
|
|
98
|
+
from libs.utils.dpi import scale_px
|
|
98
99
|
from libs.utils.stringBundle import StringBundle
|
|
99
100
|
from libs.utils.styles import get_combined_style, Theme, get_stylesheet, get_canvas_background
|
|
100
101
|
from libs.utils.ustr import ustr
|
|
@@ -507,10 +508,10 @@ class MainWindow(QMainWindow, WindowMixin):
|
|
|
507
508
|
self.file_dock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
|
|
508
509
|
|
|
509
510
|
# Set minimum sizes for better resize UX
|
|
510
|
-
self.dock.setMinimumHeight(100)
|
|
511
|
-
self.file_dock.setMinimumHeight(100)
|
|
512
|
-
self.dock.setMinimumWidth(200)
|
|
513
|
-
self.file_dock.setMinimumWidth(200)
|
|
511
|
+
self.dock.setMinimumHeight(scale_px(100))
|
|
512
|
+
self.file_dock.setMinimumHeight(scale_px(100))
|
|
513
|
+
self.dock.setMinimumWidth(scale_px(200))
|
|
514
|
+
self.file_dock.setMinimumWidth(scale_px(200))
|
|
514
515
|
|
|
515
516
|
# Features toggled by advanced mode (closable/floatable for labels dock)
|
|
516
517
|
self.dock_features = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
|
|
@@ -1069,17 +1070,17 @@ class MainWindow(QMainWindow, WindowMixin):
|
|
|
1069
1070
|
# Status bar permanent widgets (left to right)
|
|
1070
1071
|
# Image counter
|
|
1071
1072
|
self.label_image_count = QLabel('Image: 0 / 0')
|
|
1072
|
-
self.label_image_count.setMinimumWidth(100)
|
|
1073
|
+
self.label_image_count.setMinimumWidth(scale_px(100))
|
|
1073
1074
|
self.statusBar().addPermanentWidget(self.label_image_count)
|
|
1074
1075
|
|
|
1075
1076
|
# Annotation count
|
|
1076
1077
|
self.label_box_count = QLabel('Boxes: 0')
|
|
1077
|
-
self.label_box_count.setMinimumWidth(70)
|
|
1078
|
+
self.label_box_count.setMinimumWidth(scale_px(70))
|
|
1078
1079
|
self.statusBar().addPermanentWidget(self.label_box_count)
|
|
1079
1080
|
|
|
1080
1081
|
# Zoom level
|
|
1081
1082
|
self.label_zoom = QLabel('Zoom: 100%')
|
|
1082
|
-
self.label_zoom.setMinimumWidth(80)
|
|
1083
|
+
self.label_zoom.setMinimumWidth(scale_px(80))
|
|
1083
1084
|
self.statusBar().addPermanentWidget(self.label_zoom)
|
|
1084
1085
|
|
|
1085
1086
|
# Save status indicator
|
|
@@ -1220,8 +1221,8 @@ class MainWindow(QMainWindow, WindowMixin):
|
|
|
1220
1221
|
# Stats panel (side)
|
|
1221
1222
|
self.gallery_stats = StatsWidget()
|
|
1222
1223
|
self.gallery_stats.refresh_btn.clicked.connect(self._refresh_all_statistics)
|
|
1223
|
-
self.gallery_stats.setMaximumWidth(300)
|
|
1224
|
-
self.gallery_stats.setMinimumWidth(250)
|
|
1224
|
+
self.gallery_stats.setMaximumWidth(scale_px(300))
|
|
1225
|
+
self.gallery_stats.setMinimumWidth(scale_px(250))
|
|
1225
1226
|
layout.addWidget(self.gallery_stats, stretch=1)
|
|
1226
1227
|
|
|
1227
1228
|
self.gallery_window.setCentralWidget(central_widget)
|
|
@@ -3256,7 +3257,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|
|
3256
3257
|
|
|
3257
3258
|
if size == 0:
|
|
3258
3259
|
# Auto mode - recalculate from DPI
|
|
3259
|
-
from libs.toolBar import calculate_icon_size
|
|
3260
|
+
from libs.widgets.toolBar import calculate_icon_size
|
|
3260
3261
|
size = calculate_icon_size()
|
|
3261
3262
|
|
|
3262
3263
|
# Update toolbar icon size
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: labelimgplusplus
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: labelImg++ is an enhanced graphical image annotation tool with Gallery Mode for browsing and labeling images
|
|
5
5
|
Author-email: Abhik Sarkar <abhiksark@gmail.com>
|
|
6
6
|
License: Copyright (c) <2015-Present> Tzutalin
|
|
@@ -64,8 +64,8 @@ labelImg++
|
|
|
64
64
|
|
|
65
65
|
**Version 2.0.0** - First stable release! Install with ``pip install labelImgPlusPlus``
|
|
66
66
|
|
|
67
|
-
.. image:: resources/demo/
|
|
68
|
-
:alt: labelImg++
|
|
67
|
+
.. image:: https://raw.githubusercontent.com/abhiksark/labelImg-plus-plus/c7fbd5fc08a561206b210706143a50023c82a782/resources/demo/demo.gif
|
|
68
|
+
:alt: labelImg++ demo - gallery, bounding boxes, dark theme, polygons, keypoints and save
|
|
69
69
|
:align: center
|
|
70
70
|
|
|
71
71
|
Features
|
|
@@ -4195,91 +4195,91 @@ qt_resource_struct_v2 = b"\
|
|
|
4195
4195
|
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x2b\x00\x00\x00\x01\
|
|
4196
4196
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
|
4197
4197
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
|
4198
|
-
\x00\x00\x01\x9e\
|
|
4198
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4b\
|
|
4199
4199
|
\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x97\
|
|
4200
|
-
\x00\x00\x01\x9e\
|
|
4200
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4201
4201
|
\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x7b\xd5\
|
|
4202
|
-
\x00\x00\x01\x9e\
|
|
4202
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4203
4203
|
\x00\x00\x00\x24\x00\x00\x00\x00\x00\x01\x00\x00\x7e\x0a\
|
|
4204
|
-
\x00\x00\x01\x9e\
|
|
4204
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4205
4205
|
\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x7f\x3f\
|
|
4206
|
-
\x00\x00\x01\x9e\
|
|
4206
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4207
4207
|
\x00\x00\x00\x40\x00\x00\x00\x00\x00\x01\x00\x00\x80\x1c\
|
|
4208
|
-
\x00\x00\x01\x9e\
|
|
4208
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4209
4209
|
\x00\x00\x00\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x81\x2d\
|
|
4210
|
-
\x00\x00\x01\x9e\
|
|
4210
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4211
4211
|
\x00\x00\x00\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x82\x50\
|
|
4212
|
-
\x00\x00\x01\x9e\
|
|
4212
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4213
4213
|
\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x83\x84\
|
|
4214
|
-
\x00\x00\x01\x9e\
|
|
4214
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4215
4215
|
\x00\x00\x00\x78\x00\x00\x00\x00\x00\x01\x00\x00\x85\x23\
|
|
4216
|
-
\x00\x00\x01\x9e\
|
|
4216
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4217
4217
|
\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x86\x00\
|
|
4218
|
-
\x00\x00\x01\x9e\
|
|
4218
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4219
4219
|
\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x87\x11\
|
|
4220
|
-
\x00\x00\x01\x9e\
|
|
4220
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4221
4221
|
\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x01\x00\x00\x87\xef\
|
|
4222
|
-
\x00\x00\x01\x9e\
|
|
4222
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4223
4223
|
\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x88\xfe\
|
|
4224
|
-
\x00\x00\x01\x9e\
|
|
4224
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4225
4225
|
\x00\x00\x00\xbe\x00\x00\x00\x00\x00\x01\x00\x00\x8a\x36\
|
|
4226
|
-
\x00\x00\x01\x9e\
|
|
4226
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4227
4227
|
\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x8b\x86\
|
|
4228
|
-
\x00\x00\x01\x9e\
|
|
4228
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4229
4229
|
\x00\x00\x00\xda\x00\x00\x00\x00\x00\x01\x00\x00\x8c\x8f\
|
|
4230
|
-
\x00\x00\x01\x9e\
|
|
4230
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4231
4231
|
\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x8d\x95\
|
|
4232
|
-
\x00\x00\x01\x9e\
|
|
4232
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4233
4233
|
\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x8e\x99\
|
|
4234
|
-
\x00\x00\x01\x9e\
|
|
4234
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4235
4235
|
\x00\x00\x01\x08\x00\x00\x00\x00\x00\x01\x00\x00\x8f\x84\
|
|
4236
|
-
\x00\x00\x01\x9e\
|
|
4236
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4237
4237
|
\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x90\xd6\
|
|
4238
|
-
\x00\x00\x01\x9e\
|
|
4238
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4f\
|
|
4239
4239
|
\x00\x00\x01\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x9b\x2a\
|
|
4240
|
-
\x00\x00\x01\x9e\
|
|
4240
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4f\
|
|
4241
4241
|
\x00\x00\x01\x5c\x00\x00\x00\x00\x00\x01\x00\x00\xa4\x77\
|
|
4242
|
-
\x00\x00\x01\x9e\
|
|
4242
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4f\
|
|
4243
4243
|
\x00\x00\x01\x7c\x00\x00\x00\x00\x00\x01\x00\x00\xb0\xcb\
|
|
4244
|
-
\x00\x00\x01\x9e\
|
|
4244
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4245
4245
|
\x00\x00\x01\x96\x00\x00\x00\x00\x00\x01\x00\x00\xb3\xe1\
|
|
4246
|
-
\x00\x00\x01\x9e\
|
|
4246
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4247
4247
|
\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00\xb5\x2d\
|
|
4248
|
-
\x00\x00\x01\x9e\
|
|
4248
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4249
4249
|
\x00\x00\x01\xc6\x00\x00\x00\x00\x00\x01\x00\x00\xb6\x59\
|
|
4250
|
-
\x00\x00\x01\x9e\
|
|
4250
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4251
4251
|
\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x01\x00\x00\xb7\x56\
|
|
4252
|
-
\x00\x00\x01\x9e\
|
|
4252
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4253
4253
|
\x00\x00\x01\xf2\x00\x00\x00\x00\x00\x01\x00\x00\xb8\xd9\
|
|
4254
|
-
\x00\x00\x01\x9e\
|
|
4254
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4255
4255
|
\x00\x00\x02\x04\x00\x00\x00\x00\x00\x01\x00\x00\xba\xe5\
|
|
4256
|
-
\x00\x00\x01\x9e\
|
|
4256
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4257
4257
|
\x00\x00\x02\x24\x00\x00\x00\x00\x00\x01\x00\x00\xbd\x1a\
|
|
4258
|
-
\x00\x00\x01\x9e\
|
|
4258
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4259
4259
|
\x00\x00\x02\x36\x00\x00\x00\x00\x00\x01\x00\x00\xbe\x78\
|
|
4260
|
-
\x00\x00\x01\x9e\
|
|
4260
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4261
4261
|
\x00\x00\x02\x4e\x00\x00\x00\x00\x00\x01\x00\x00\xbf\x9b\
|
|
4262
|
-
\x00\x00\x01\x9e\
|
|
4262
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4b\
|
|
4263
4263
|
\x00\x00\x02\x60\x00\x00\x00\x00\x00\x01\x00\x00\xc0\xad\
|
|
4264
|
-
\x00\x00\x01\x9e\
|
|
4264
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4265
4265
|
\x00\x00\x02\x7c\x00\x00\x00\x00\x00\x01\x00\x00\xc3\x54\
|
|
4266
|
-
\x00\x00\x01\x9e\
|
|
4266
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4267
4267
|
\x00\x00\x02\x90\x00\x00\x00\x00\x00\x01\x00\x00\xc4\x8e\
|
|
4268
|
-
\x00\x00\x01\x9e\
|
|
4268
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4269
4269
|
\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00\xc6\xc3\
|
|
4270
|
-
\x00\x00\x01\x9e\
|
|
4270
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4f\
|
|
4271
4271
|
\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x01\x00\x00\xd9\x78\
|
|
4272
|
-
\x00\x00\x01\x9e\
|
|
4272
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4273
4273
|
\x00\x00\x02\xe4\x00\x00\x00\x00\x00\x01\x00\x00\xe9\xb8\
|
|
4274
|
-
\x00\x00\x01\x9e\
|
|
4274
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4275
4275
|
\x00\x00\x03\x02\x00\x00\x00\x00\x00\x01\x00\x00\xea\x96\
|
|
4276
|
-
\x00\x00\x01\x9e\
|
|
4276
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4277
4277
|
\x00\x00\x03\x20\x00\x00\x00\x00\x00\x01\x00\x00\xeb\x8b\
|
|
4278
|
-
\x00\x00\x01\x9e\
|
|
4278
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4279
4279
|
\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\xec\xdd\
|
|
4280
|
-
\x00\x00\x01\x9e\
|
|
4280
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4281
4281
|
\x00\x00\x03\x4c\x00\x00\x00\x00\x00\x01\x00\x00\xf0\xa0\
|
|
4282
|
-
\x00\x00\x01\x9e\
|
|
4282
|
+
\x00\x00\x01\x9e\xac\xad\xcd\x4c\
|
|
4283
4283
|
"
|
|
4284
4284
|
|
|
4285
4285
|
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# libs/utils/dpi.py
|
|
2
|
+
"""Central DPI scaling utilities for HiDPI displays.
|
|
3
|
+
|
|
4
|
+
A single source of truth for the screen scale factor so chrome, dialogs,
|
|
5
|
+
stylesheets, and icons all scale by the same amount. Widget modules and the
|
|
6
|
+
theme system import from here rather than computing DPI themselves.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from PyQt5.QtWidgets import QApplication
|
|
11
|
+
except ImportError:
|
|
12
|
+
from PyQt4.QtGui import QApplication
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_dpi_scale_factor():
|
|
16
|
+
"""Return the DPI scale factor for the primary screen.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
float: Scale factor (1.0 for standard 96 DPI, higher for HiDPI
|
|
20
|
+
displays). Falls back to 1.0 when no application or screen is
|
|
21
|
+
available (e.g. headless tests, Qt4).
|
|
22
|
+
"""
|
|
23
|
+
app = QApplication.instance()
|
|
24
|
+
if app is None:
|
|
25
|
+
return 1.0
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
screen = app.primaryScreen()
|
|
29
|
+
if screen:
|
|
30
|
+
# Logical DPI accounts for the user's display scaling setting.
|
|
31
|
+
logical_dpi = screen.logicalDotsPerInch()
|
|
32
|
+
# 96 DPI is the standard baseline on most systems.
|
|
33
|
+
return logical_dpi / 96.0
|
|
34
|
+
except AttributeError:
|
|
35
|
+
# Qt4 has no primaryScreen(); treat as unscaled.
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
return 1.0
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def scale_px(n):
|
|
42
|
+
"""Scale a base pixel value by the current DPI factor.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
n: Pixel value defined at the 96 DPI baseline.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
int: ``n`` scaled by the DPI factor, rounded to the nearest integer.
|
|
49
|
+
"""
|
|
50
|
+
return int(round(n * get_dpi_scale_factor()))
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
from enum import Enum
|
|
5
5
|
|
|
6
|
+
from libs.utils.dpi import scale_px
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
class Theme(Enum):
|
|
8
10
|
"""Available application themes."""
|
|
@@ -108,24 +110,24 @@ def get_toolbar_style(theme: Theme) -> str:
|
|
|
108
110
|
QToolBar {{
|
|
109
111
|
background: {c['surface']};
|
|
110
112
|
border: none;
|
|
111
|
-
border-right:
|
|
112
|
-
spacing:
|
|
113
|
-
padding:
|
|
113
|
+
border-right: {scale_px(1)}px solid {c['border']};
|
|
114
|
+
spacing: {scale_px(2)}px;
|
|
115
|
+
padding: {scale_px(4)}px;
|
|
114
116
|
}}
|
|
115
117
|
|
|
116
118
|
QToolBar::separator {{
|
|
117
119
|
background: {c['border']};
|
|
118
|
-
width:
|
|
119
|
-
height:
|
|
120
|
-
margin:
|
|
120
|
+
width: {scale_px(1)}px;
|
|
121
|
+
height: {scale_px(20)}px;
|
|
122
|
+
margin: {scale_px(6)}px {scale_px(4)}px;
|
|
121
123
|
}}
|
|
122
124
|
|
|
123
125
|
QToolButton {{
|
|
124
126
|
background: transparent;
|
|
125
127
|
border: none;
|
|
126
|
-
border-radius:
|
|
127
|
-
padding:
|
|
128
|
-
margin:
|
|
128
|
+
border-radius: {scale_px(4)}px;
|
|
129
|
+
padding: {scale_px(4)}px;
|
|
130
|
+
margin: {scale_px(1)}px;
|
|
129
131
|
color: {c['text']};
|
|
130
132
|
}}
|
|
131
133
|
|
|
@@ -167,18 +169,18 @@ QDockWidget {{
|
|
|
167
169
|
|
|
168
170
|
QDockWidget::title {{
|
|
169
171
|
background: {c['surface']};
|
|
170
|
-
padding:
|
|
171
|
-
border-bottom:
|
|
172
|
+
padding: {scale_px(6)}px;
|
|
173
|
+
border-bottom: {scale_px(1)}px solid {c['border']};
|
|
172
174
|
}}
|
|
173
175
|
|
|
174
176
|
QListWidget {{
|
|
175
177
|
background: {c['background']};
|
|
176
|
-
border:
|
|
178
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
177
179
|
color: {c['text']};
|
|
178
180
|
}}
|
|
179
181
|
|
|
180
182
|
QListWidget::item {{
|
|
181
|
-
padding:
|
|
183
|
+
padding: {scale_px(4)}px;
|
|
182
184
|
}}
|
|
183
185
|
|
|
184
186
|
QListWidget::item:selected {{
|
|
@@ -192,15 +194,15 @@ QListWidget::item:hover {{
|
|
|
192
194
|
|
|
193
195
|
QScrollBar:vertical {{
|
|
194
196
|
background: {c['surface']};
|
|
195
|
-
width:
|
|
197
|
+
width: {scale_px(12)}px;
|
|
196
198
|
border: none;
|
|
197
199
|
}}
|
|
198
200
|
|
|
199
201
|
QScrollBar::handle:vertical {{
|
|
200
202
|
background: {c['border']};
|
|
201
|
-
border-radius:
|
|
202
|
-
min-height:
|
|
203
|
-
margin:
|
|
203
|
+
border-radius: {scale_px(4)}px;
|
|
204
|
+
min-height: {scale_px(20)}px;
|
|
205
|
+
margin: {scale_px(2)}px;
|
|
204
206
|
}}
|
|
205
207
|
|
|
206
208
|
QScrollBar::handle:vertical:hover {{
|
|
@@ -208,20 +210,20 @@ QScrollBar::handle:vertical:hover {{
|
|
|
208
210
|
}}
|
|
209
211
|
|
|
210
212
|
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
|
|
211
|
-
height:
|
|
213
|
+
height: {scale_px(0)}px;
|
|
212
214
|
}}
|
|
213
215
|
|
|
214
216
|
QScrollBar:horizontal {{
|
|
215
217
|
background: {c['surface']};
|
|
216
|
-
height:
|
|
218
|
+
height: {scale_px(12)}px;
|
|
217
219
|
border: none;
|
|
218
220
|
}}
|
|
219
221
|
|
|
220
222
|
QScrollBar::handle:horizontal {{
|
|
221
223
|
background: {c['border']};
|
|
222
|
-
border-radius:
|
|
223
|
-
min-width:
|
|
224
|
-
margin:
|
|
224
|
+
border-radius: {scale_px(4)}px;
|
|
225
|
+
min-width: {scale_px(20)}px;
|
|
226
|
+
margin: {scale_px(2)}px;
|
|
225
227
|
}}
|
|
226
228
|
|
|
227
229
|
QScrollBar::handle:horizontal:hover {{
|
|
@@ -229,19 +231,19 @@ QScrollBar::handle:horizontal:hover {{
|
|
|
229
231
|
}}
|
|
230
232
|
|
|
231
233
|
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{
|
|
232
|
-
width:
|
|
234
|
+
width: {scale_px(0)}px;
|
|
233
235
|
}}
|
|
234
236
|
|
|
235
237
|
QMenu {{
|
|
236
238
|
background: {c['surface']};
|
|
237
|
-
border:
|
|
239
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
238
240
|
color: {c['text']};
|
|
239
|
-
padding:
|
|
241
|
+
padding: {scale_px(4)}px;
|
|
240
242
|
}}
|
|
241
243
|
|
|
242
244
|
QMenu::item {{
|
|
243
|
-
padding:
|
|
244
|
-
border-radius:
|
|
245
|
+
padding: {scale_px(6)}px {scale_px(20)}px;
|
|
246
|
+
border-radius: {scale_px(4)}px;
|
|
245
247
|
}}
|
|
246
248
|
|
|
247
249
|
QMenu::item:selected {{
|
|
@@ -250,19 +252,19 @@ QMenu::item:selected {{
|
|
|
250
252
|
}}
|
|
251
253
|
|
|
252
254
|
QMenu::separator {{
|
|
253
|
-
height:
|
|
255
|
+
height: {scale_px(1)}px;
|
|
254
256
|
background: {c['border']};
|
|
255
|
-
margin:
|
|
257
|
+
margin: {scale_px(4)}px {scale_px(8)}px;
|
|
256
258
|
}}
|
|
257
259
|
|
|
258
260
|
QMenuBar {{
|
|
259
261
|
background: {c['surface']};
|
|
260
262
|
color: {c['text']};
|
|
261
|
-
border-bottom:
|
|
263
|
+
border-bottom: {scale_px(1)}px solid {c['border']};
|
|
262
264
|
}}
|
|
263
265
|
|
|
264
266
|
QMenuBar::item {{
|
|
265
|
-
padding:
|
|
267
|
+
padding: {scale_px(6)}px {scale_px(10)}px;
|
|
266
268
|
}}
|
|
267
269
|
|
|
268
270
|
QMenuBar::item:selected {{
|
|
@@ -271,9 +273,9 @@ QMenuBar::item:selected {{
|
|
|
271
273
|
|
|
272
274
|
QComboBox {{
|
|
273
275
|
background: {c['surface']};
|
|
274
|
-
border:
|
|
275
|
-
border-radius:
|
|
276
|
-
padding:
|
|
276
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
277
|
+
border-radius: {scale_px(4)}px;
|
|
278
|
+
padding: {scale_px(4)}px {scale_px(8)}px;
|
|
277
279
|
color: {c['text']};
|
|
278
280
|
}}
|
|
279
281
|
|
|
@@ -283,12 +285,12 @@ QComboBox:hover {{
|
|
|
283
285
|
|
|
284
286
|
QComboBox::drop-down {{
|
|
285
287
|
border: none;
|
|
286
|
-
padding-right:
|
|
288
|
+
padding-right: {scale_px(8)}px;
|
|
287
289
|
}}
|
|
288
290
|
|
|
289
291
|
QComboBox QAbstractItemView {{
|
|
290
292
|
background: {c['surface']};
|
|
291
|
-
border:
|
|
293
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
292
294
|
color: {c['text']};
|
|
293
295
|
selection-background-color: {c['accent_light']};
|
|
294
296
|
selection-color: {c['accent_text']};
|
|
@@ -296,9 +298,9 @@ QComboBox QAbstractItemView {{
|
|
|
296
298
|
|
|
297
299
|
QLineEdit {{
|
|
298
300
|
background: {c['background']};
|
|
299
|
-
border:
|
|
300
|
-
border-radius:
|
|
301
|
-
padding:
|
|
301
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
302
|
+
border-radius: {scale_px(4)}px;
|
|
303
|
+
padding: {scale_px(4)}px {scale_px(8)}px;
|
|
302
304
|
color: {c['text']};
|
|
303
305
|
}}
|
|
304
306
|
|
|
@@ -308,9 +310,9 @@ QLineEdit:focus {{
|
|
|
308
310
|
|
|
309
311
|
QPushButton {{
|
|
310
312
|
background: {c['surface']};
|
|
311
|
-
border:
|
|
312
|
-
border-radius:
|
|
313
|
-
padding:
|
|
313
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
314
|
+
border-radius: {scale_px(4)}px;
|
|
315
|
+
padding: {scale_px(6)}px {scale_px(16)}px;
|
|
314
316
|
color: {c['text']};
|
|
315
317
|
}}
|
|
316
318
|
|
|
@@ -331,10 +333,10 @@ QCheckBox {{
|
|
|
331
333
|
}}
|
|
332
334
|
|
|
333
335
|
QCheckBox::indicator {{
|
|
334
|
-
width:
|
|
335
|
-
height:
|
|
336
|
-
border:
|
|
337
|
-
border-radius:
|
|
336
|
+
width: {scale_px(16)}px;
|
|
337
|
+
height: {scale_px(16)}px;
|
|
338
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
339
|
+
border-radius: {scale_px(3)}px;
|
|
338
340
|
background: {c['background']};
|
|
339
341
|
}}
|
|
340
342
|
|
|
@@ -349,27 +351,27 @@ QLabel {{
|
|
|
349
351
|
|
|
350
352
|
QGroupBox {{
|
|
351
353
|
color: {c['text']};
|
|
352
|
-
border:
|
|
353
|
-
border-radius:
|
|
354
|
-
margin-top:
|
|
355
|
-
padding-top:
|
|
354
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
355
|
+
border-radius: {scale_px(4)}px;
|
|
356
|
+
margin-top: {scale_px(8)}px;
|
|
357
|
+
padding-top: {scale_px(8)}px;
|
|
356
358
|
}}
|
|
357
359
|
|
|
358
360
|
QGroupBox::title {{
|
|
359
361
|
subcontrol-origin: margin;
|
|
360
|
-
left:
|
|
361
|
-
padding: 0
|
|
362
|
+
left: {scale_px(10)}px;
|
|
363
|
+
padding: 0 {scale_px(5)}px;
|
|
362
364
|
}}
|
|
363
365
|
|
|
364
366
|
QTabWidget::pane {{
|
|
365
|
-
border:
|
|
367
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
366
368
|
background: {c['background']};
|
|
367
369
|
}}
|
|
368
370
|
|
|
369
371
|
QTabBar::tab {{
|
|
370
372
|
background: {c['surface']};
|
|
371
|
-
border:
|
|
372
|
-
padding:
|
|
373
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
374
|
+
padding: {scale_px(8)}px {scale_px(16)}px;
|
|
373
375
|
color: {c['text']};
|
|
374
376
|
}}
|
|
375
377
|
|
|
@@ -383,8 +385,8 @@ QTabBar::tab:hover:!selected {{
|
|
|
383
385
|
}}
|
|
384
386
|
|
|
385
387
|
QProgressBar {{
|
|
386
|
-
border:
|
|
387
|
-
border-radius:
|
|
388
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
389
|
+
border-radius: {scale_px(4)}px;
|
|
388
390
|
background: {c['surface']};
|
|
389
391
|
text-align: center;
|
|
390
392
|
color: {c['text']};
|
|
@@ -392,12 +394,12 @@ QProgressBar {{
|
|
|
392
394
|
|
|
393
395
|
QProgressBar::chunk {{
|
|
394
396
|
background: {c['accent']};
|
|
395
|
-
border-radius:
|
|
397
|
+
border-radius: {scale_px(3)}px;
|
|
396
398
|
}}
|
|
397
399
|
|
|
398
400
|
QTableWidget {{
|
|
399
401
|
background: {c['background']};
|
|
400
|
-
border:
|
|
402
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
401
403
|
color: {c['text']};
|
|
402
404
|
gridline-color: {c['border']};
|
|
403
405
|
}}
|
|
@@ -410,9 +412,9 @@ QTableWidget::item:selected {{
|
|
|
410
412
|
QHeaderView::section {{
|
|
411
413
|
background: {c['surface']};
|
|
412
414
|
border: none;
|
|
413
|
-
border-right:
|
|
414
|
-
border-bottom:
|
|
415
|
-
padding:
|
|
415
|
+
border-right: {scale_px(1)}px solid {c['border']};
|
|
416
|
+
border-bottom: {scale_px(1)}px solid {c['border']};
|
|
417
|
+
padding: {scale_px(6)}px;
|
|
416
418
|
color: {c['text']};
|
|
417
419
|
}}
|
|
418
420
|
|
|
@@ -428,17 +430,17 @@ QMessageBox {{
|
|
|
428
430
|
|
|
429
431
|
QSpinBox, QDoubleSpinBox {{
|
|
430
432
|
background: {c['background']};
|
|
431
|
-
border:
|
|
432
|
-
border-radius:
|
|
433
|
-
padding:
|
|
433
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
434
|
+
border-radius: {scale_px(4)}px;
|
|
435
|
+
padding: {scale_px(4)}px;
|
|
434
436
|
color: {c['text']};
|
|
435
437
|
}}
|
|
436
438
|
|
|
437
439
|
QToolTip {{
|
|
438
440
|
background: {c['surface']};
|
|
439
|
-
border:
|
|
441
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
440
442
|
color: {c['text']};
|
|
441
|
-
padding:
|
|
443
|
+
padding: {scale_px(4)}px;
|
|
442
444
|
}}
|
|
443
445
|
"""
|
|
444
446
|
|
|
@@ -449,7 +451,7 @@ def get_status_bar_style(theme: Theme) -> str:
|
|
|
449
451
|
return f"""
|
|
450
452
|
QStatusBar {{
|
|
451
453
|
background: {c['surface']};
|
|
452
|
-
border-top:
|
|
454
|
+
border-top: {scale_px(1)}px solid {c['border']};
|
|
453
455
|
color: {c['text']};
|
|
454
456
|
}}
|
|
455
457
|
|
|
@@ -469,23 +471,23 @@ def get_slider_style(theme: Theme) -> str:
|
|
|
469
471
|
c = _get_colors(theme)
|
|
470
472
|
return f"""
|
|
471
473
|
QSlider::groove:horizontal {{
|
|
472
|
-
height:
|
|
474
|
+
height: {scale_px(6)}px;
|
|
473
475
|
background: {c['border']};
|
|
474
|
-
border-radius:
|
|
476
|
+
border-radius: {scale_px(3)}px;
|
|
475
477
|
}}
|
|
476
478
|
QSlider::handle:horizontal {{
|
|
477
479
|
background: {c['accent']};
|
|
478
|
-
width:
|
|
479
|
-
height:
|
|
480
|
-
margin: -
|
|
481
|
-
border-radius:
|
|
480
|
+
width: {scale_px(16)}px;
|
|
481
|
+
height: {scale_px(16)}px;
|
|
482
|
+
margin: -{scale_px(5)}px 0;
|
|
483
|
+
border-radius: {scale_px(8)}px;
|
|
482
484
|
}}
|
|
483
485
|
QSlider::handle:horizontal:hover {{
|
|
484
486
|
background: {c['accent_text']};
|
|
485
487
|
}}
|
|
486
488
|
QSlider::sub-page:horizontal {{
|
|
487
489
|
background: {c['accent']};
|
|
488
|
-
border-radius:
|
|
490
|
+
border-radius: {scale_px(3)}px;
|
|
489
491
|
}}
|
|
490
492
|
"""
|
|
491
493
|
|
|
@@ -494,13 +496,13 @@ def get_gallery_controls_style(theme: Theme) -> str:
|
|
|
494
496
|
"""Generate gallery slider frame and button styles."""
|
|
495
497
|
c = _get_colors(theme)
|
|
496
498
|
return {
|
|
497
|
-
'frame': f"QFrame {{ background-color: {c['surface']}; border-bottom:
|
|
499
|
+
'frame': f"QFrame {{ background-color: {c['surface']}; border-bottom: {scale_px(1)}px solid {c['border']}; }}",
|
|
498
500
|
'button': f"""QPushButton {{
|
|
499
501
|
background-color: {c['background']};
|
|
500
|
-
border:
|
|
501
|
-
border-radius:
|
|
502
|
+
border: {scale_px(1)}px solid {c['border']};
|
|
503
|
+
border-radius: {scale_px(4)}px;
|
|
502
504
|
font-weight: bold;
|
|
503
|
-
font-size:
|
|
505
|
+
font-size: {scale_px(11)}px;
|
|
504
506
|
color: {c['text']};
|
|
505
507
|
}}
|
|
506
508
|
QPushButton:hover {{
|
|
@@ -520,11 +522,11 @@ def get_expand_button_style(theme: Theme) -> str:
|
|
|
520
522
|
QToolButton {{
|
|
521
523
|
border: none;
|
|
522
524
|
background: transparent;
|
|
523
|
-
padding:
|
|
525
|
+
padding: {scale_px(4)}px;
|
|
524
526
|
}}
|
|
525
527
|
QToolButton:hover {{
|
|
526
528
|
background: {c['hover']};
|
|
527
|
-
border-radius:
|
|
529
|
+
border-radius: {scale_px(4)}px;
|
|
528
530
|
}}
|
|
529
531
|
"""
|
|
530
532
|
|
|
@@ -534,7 +536,7 @@ def get_label_dialog_style(theme: Theme) -> str:
|
|
|
534
536
|
c = _get_colors(theme)
|
|
535
537
|
return {
|
|
536
538
|
'filter_label': f"color: {c['text_secondary']};",
|
|
537
|
-
'count_label': f"color: {c['text_secondary']}; font-size:
|
|
539
|
+
'count_label': f"color: {c['text_secondary']}; font-size: {scale_px(11)}px;",
|
|
538
540
|
}
|
|
539
541
|
|
|
540
542
|
|
|
@@ -549,7 +551,7 @@ QListWidget {{
|
|
|
549
551
|
}}
|
|
550
552
|
QListWidget::item {{
|
|
551
553
|
color: {c['text']};
|
|
552
|
-
padding:
|
|
554
|
+
padding: {scale_px(4)}px;
|
|
553
555
|
}}
|
|
554
556
|
QListWidget::item:selected {{
|
|
555
557
|
background: {c['accent_light']};
|
|
@@ -7,6 +7,8 @@ from PyQt5.QtWidgets import (
|
|
|
7
7
|
)
|
|
8
8
|
from PyQt5.QtCore import Qt
|
|
9
9
|
|
|
10
|
+
from libs.utils.dpi import scale_px
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
class BatchVerifyDialog(QDialog):
|
|
12
14
|
"""Dialog for batch verifying or unverifying annotated images.
|
|
@@ -28,7 +30,7 @@ class BatchVerifyDialog(QDialog):
|
|
|
28
30
|
"""
|
|
29
31
|
super().__init__(parent)
|
|
30
32
|
self.setWindowTitle('Batch Verify')
|
|
31
|
-
self.setMinimumWidth(350)
|
|
33
|
+
self.setMinimumWidth(scale_px(350))
|
|
32
34
|
|
|
33
35
|
layout = QVBoxLayout()
|
|
34
36
|
layout.addWidget(QLabel(f'Images: {image_count}'))
|
|
@@ -14,6 +14,7 @@ except ImportError:
|
|
|
14
14
|
import math
|
|
15
15
|
|
|
16
16
|
from libs.core.shape import Shape, ShapeType
|
|
17
|
+
from libs.utils.dpi import scale_px
|
|
17
18
|
from libs.utils.utils import distance
|
|
18
19
|
from libs.utils.styles import Theme
|
|
19
20
|
|
|
@@ -77,11 +78,14 @@ class Canvas(QWidget):
|
|
|
77
78
|
|
|
78
79
|
CREATE, EDIT, CREATE_POLYGON, KEYPOINT_MODE = list(range(4))
|
|
79
80
|
|
|
80
|
-
epsilon = 24.0
|
|
81
|
-
|
|
82
81
|
def __init__(self, *args, **kwargs):
|
|
83
82
|
super(Canvas, self).__init__(*args, **kwargs)
|
|
84
83
|
# Initialise local state.
|
|
84
|
+
# Hit-test tolerance as a screen-pixel radius; scaled for HiDPI so
|
|
85
|
+
# grabbing vertices feels the same on high-density displays. Set per
|
|
86
|
+
# instance (not a class attribute) so the DPI factor is read after the
|
|
87
|
+
# QApplication exists.
|
|
88
|
+
self.epsilon = float(scale_px(24))
|
|
85
89
|
self.mode = self.EDIT
|
|
86
90
|
self.shapes = []
|
|
87
91
|
self.current = None
|
|
@@ -21,6 +21,7 @@ try:
|
|
|
21
21
|
except ImportError:
|
|
22
22
|
ElementTree = None
|
|
23
23
|
|
|
24
|
+
from libs.utils.dpi import scale_px
|
|
24
25
|
from libs.utils.styles import Theme, get_slider_style, get_gallery_controls_style, get_gallery_list_style
|
|
25
26
|
|
|
26
27
|
|
|
@@ -374,7 +375,7 @@ class GalleryWidget(QWidget):
|
|
|
374
375
|
}
|
|
375
376
|
for label, size in self.size_presets.items():
|
|
376
377
|
btn = QPushButton(label)
|
|
377
|
-
btn.setFixedSize(32, 26)
|
|
378
|
+
btn.setFixedSize(scale_px(32), scale_px(26))
|
|
378
379
|
btn.setAutoFillBackground(True) # Required for stylesheet bg
|
|
379
380
|
btn.clicked.connect(lambda checked, s=size: self._set_preset_size(s))
|
|
380
381
|
slider_layout.addWidget(btn)
|
|
@@ -392,7 +393,7 @@ class GalleryWidget(QWidget):
|
|
|
392
393
|
|
|
393
394
|
# Size value display
|
|
394
395
|
self.size_value_label = QLabel(f"{self._icon_size}px")
|
|
395
|
-
self.size_value_label.setMinimumWidth(50)
|
|
396
|
+
self.size_value_label.setMinimumWidth(scale_px(50))
|
|
396
397
|
slider_layout.addWidget(self.size_value_label)
|
|
397
398
|
|
|
398
399
|
layout.addWidget(self._slider_frame)
|
|
@@ -6,6 +6,7 @@ from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
|
6
6
|
from PyQt5.QtCore import pyqtSignal, Qt
|
|
7
7
|
|
|
8
8
|
from libs.core.keypoint_config import get_keypoint_color, get_template
|
|
9
|
+
from libs.utils.dpi import scale_px
|
|
9
10
|
from libs.utils.styles import Theme, get_theme_colors
|
|
10
11
|
|
|
11
12
|
|
|
@@ -54,7 +55,7 @@ class KeypointPanel(QWidget):
|
|
|
54
55
|
row.setSpacing(4)
|
|
55
56
|
|
|
56
57
|
status_label = QLabel('\u25cb')
|
|
57
|
-
status_label.setFixedWidth(16)
|
|
58
|
+
status_label.setFixedWidth(scale_px(16))
|
|
58
59
|
status_label.setAlignment(Qt.AlignCenter)
|
|
59
60
|
|
|
60
61
|
name_btn = QPushButton(name.replace('_', ' ').title())
|
|
@@ -64,10 +65,10 @@ class KeypointPanel(QWidget):
|
|
|
64
65
|
lambda checked, idx=i: self.keypointClicked.emit(idx))
|
|
65
66
|
|
|
66
67
|
color_indicator = QLabel()
|
|
67
|
-
color_indicator.setFixedSize(8, 8)
|
|
68
|
+
color_indicator.setFixedSize(scale_px(8), scale_px(8))
|
|
68
69
|
color_hex = get_keypoint_color(i, template_name)
|
|
69
70
|
color_indicator.setStyleSheet(
|
|
70
|
-
'background: %s; border-radius:
|
|
71
|
+
'background: %s; border-radius: %dpx;' % (color_hex, scale_px(4)))
|
|
71
72
|
|
|
72
73
|
row.addWidget(color_indicator)
|
|
73
74
|
row.addWidget(status_label)
|
|
@@ -7,6 +7,7 @@ from PyQt5.QtWidgets import (
|
|
|
7
7
|
)
|
|
8
8
|
from PyQt5.QtCore import Qt
|
|
9
9
|
|
|
10
|
+
from libs.utils.dpi import scale_px
|
|
10
11
|
from libs.utils.styles import Theme, get_theme_colors, hex_to_qcolor
|
|
11
12
|
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ class ShortcutsDialog(QDialog):
|
|
|
14
15
|
def __init__(self, shortcut_config, action_map, parent=None):
|
|
15
16
|
super().__init__(parent)
|
|
16
17
|
self.setWindowTitle('Keyboard Shortcuts')
|
|
17
|
-
self.setMinimumSize(550, 500)
|
|
18
|
+
self.setMinimumSize(scale_px(550), scale_px(500))
|
|
18
19
|
self.config = shortcut_config
|
|
19
20
|
self.action_map = action_map # {action_name: QAction}
|
|
20
21
|
self._pending = dict(shortcut_config.get_all())
|
|
@@ -9,6 +9,8 @@ from PyQt5.QtWidgets import (
|
|
|
9
9
|
QProgressBar, QPushButton, QRadioButton, QSpinBox, QVBoxLayout,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
+
from libs.utils.dpi import scale_px
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
class SplitDialog(QDialog):
|
|
14
16
|
"""Dialog for configuring dataset train/val/test split parameters."""
|
|
@@ -16,7 +18,7 @@ class SplitDialog(QDialog):
|
|
|
16
18
|
def __init__(self, parent=None, image_count=0, default_dir=''):
|
|
17
19
|
super().__init__(parent)
|
|
18
20
|
self.setWindowTitle('Split Dataset')
|
|
19
|
-
self.setMinimumWidth(450)
|
|
21
|
+
self.setMinimumWidth(scale_px(450))
|
|
20
22
|
self._image_count = image_count
|
|
21
23
|
|
|
22
24
|
layout = QVBoxLayout()
|
|
@@ -5,16 +5,18 @@ try:
|
|
|
5
5
|
from PyQt5.QtCore import Qt, pyqtSignal, QSize
|
|
6
6
|
from PyQt5.QtWidgets import (
|
|
7
7
|
QToolBar, QToolButton, QWidgetAction, QWidget,
|
|
8
|
-
QMenu, QSizePolicy
|
|
8
|
+
QMenu, QSizePolicy
|
|
9
9
|
)
|
|
10
10
|
except ImportError:
|
|
11
11
|
from PyQt4.QtGui import (
|
|
12
12
|
QToolBar, QToolButton, QWidgetAction, QWidget,
|
|
13
|
-
QMenu, QSizePolicy
|
|
13
|
+
QMenu, QSizePolicy
|
|
14
14
|
)
|
|
15
15
|
from PyQt4.QtCore import Qt, pyqtSignal, QSize
|
|
16
16
|
|
|
17
17
|
from libs.utils.styles import Theme, get_expand_button_style
|
|
18
|
+
# get_dpi_scale_factor re-exported for back-compat; it now lives in libs.utils.dpi.
|
|
19
|
+
from libs.utils.dpi import get_dpi_scale_factor, scale_px
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
# Base icon size for toolbar buttons (Feather icons are 24x24)
|
|
@@ -24,31 +26,6 @@ MIN_ICON_SIZE = 16
|
|
|
24
26
|
MAX_ICON_SIZE = 48
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
def get_dpi_scale_factor():
|
|
28
|
-
"""Get the DPI scale factor for the primary screen.
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
float: Scale factor (1.0 for standard 96 DPI, higher for HiDPI displays)
|
|
32
|
-
"""
|
|
33
|
-
app = QApplication.instance()
|
|
34
|
-
if app is None:
|
|
35
|
-
return 1.0
|
|
36
|
-
|
|
37
|
-
# Try to get the primary screen
|
|
38
|
-
try:
|
|
39
|
-
screen = app.primaryScreen()
|
|
40
|
-
if screen:
|
|
41
|
-
# Get logical DPI (accounts for user scaling settings)
|
|
42
|
-
logical_dpi = screen.logicalDotsPerInch()
|
|
43
|
-
# Standard DPI is 96 on most systems
|
|
44
|
-
return logical_dpi / 96.0
|
|
45
|
-
except AttributeError:
|
|
46
|
-
# Qt4 fallback
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
return 1.0
|
|
50
|
-
|
|
51
|
-
|
|
52
29
|
def calculate_icon_size(base_size=BASE_ICON_SIZE):
|
|
53
30
|
"""Calculate appropriate icon size based on DPI.
|
|
54
31
|
|
|
@@ -84,8 +61,8 @@ class ToolBar(QToolBar):
|
|
|
84
61
|
|
|
85
62
|
# Expand/collapse state
|
|
86
63
|
self._expanded = False
|
|
87
|
-
self._collapsed_width = 85
|
|
88
|
-
self._expanded_width = 140
|
|
64
|
+
self._collapsed_width = scale_px(85)
|
|
65
|
+
self._expanded_width = scale_px(140)
|
|
89
66
|
self._expand_btn = None
|
|
90
67
|
|
|
91
68
|
def addAction(self, action):
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "labelimgplusplus"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.4.1"
|
|
8
8
|
description = "labelImg++ is an enhanced graphical image annotation tool with Gallery Mode for browsing and labeling images"
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
license = {file = "LICENSE"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{labelimgplusplus-2.3.3 → labelimgplusplus-2.4.1}/labelimgplusplus.egg-info/entry_points.txt
RENAMED
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|