1
1
# standard lib
2
2
import os
3
- import pathlib
4
3
import re
5
4
from functools import partial
5
+ from pathlib import Path
6
+ from typing import Literal , Union
6
7
7
8
from qgis .core import QgsApplication
8
9
from qgis .PyQt import uic
9
10
from qgis .PyQt .QtCore import QFile , QModelIndex , QRegExp , Qt , QTextStream , pyqtSignal
10
- from qgis .PyQt .QtGui import QPixmap
11
+ from qgis .PyQt .QtGui import QContextMenuEvent , QPixmap
11
12
from qgis .PyQt .QtSvg import QGraphicsSvgItem
12
13
from qgis .PyQt .QtWidgets import (
13
14
QAction ,
17
18
QGraphicsView ,
18
19
QLabel ,
19
20
QLineEdit ,
21
+ QMenu ,
20
22
QTextBrowser ,
21
23
QToolButton ,
22
24
QWidget ,
27
29
28
30
# plugin
29
31
from pyqgis_resource_browser .__about__ import __title__
30
-
31
- from ..core .resource_table_model import ResourceTableFilterModel , ResourceTableModel
32
- from ..core .resource_table_view import ResourceTableView
33
- from ..toolbelt import PlgOptionsManager
32
+ from pyqgis_resource_browser .core .resource_table_model import (
33
+ ResourceTableFilterModel ,
34
+ ResourceTableModel ,
35
+ )
36
+ from pyqgis_resource_browser .core .resource_table_view import ResourceTableView
37
+ from pyqgis_resource_browser .toolbelt import PlgLogger , PlgOptionsManager
34
38
35
39
36
40
class ResourceGraphicsView (QGraphicsView ):
37
41
resized = pyqtSignal ()
42
+ uri : str = ""
38
43
39
44
def __init__ (self , * args , ** kwds ):
40
45
super ().__init__ (* args , ** kwds )
46
+ self .log = PlgLogger ().log
41
47
self .item = None
42
48
43
- def setItem (self , item ):
49
+ def setItem (self , item : Union [QGraphicsSvgItem , QGraphicsPixmapItem ]):
50
+ """Set view item.
51
+
52
+ :param item: _description_
53
+ :type item: Union[QGraphicsSvgItem, QGraphicsPixmapItem]
54
+ """
44
55
self .scene ().clear ()
45
56
self .scene ().addItem (item )
46
57
self .item = item
@@ -50,6 +61,113 @@ def resizeEvent(self, QResizeEvent):
50
61
if self .item :
51
62
self .fitInView (self .item , Qt .KeepAspectRatio )
52
63
64
+ def contextMenuEvent (self , event : QContextMenuEvent ):
65
+ """Custom menu displayed on righ-click event on widget view.
66
+
67
+ :param event: event that triggers the context-menu, typically right-click
68
+ :type event: QContextMenuEvent
69
+ """
70
+ menu = QMenu (parent = self )
71
+
72
+ # Copy image name
73
+ action_copy_name = QAction (
74
+ icon = QgsApplication .getThemeIcon ("mIconLabelQuadrantOffset.svg" ),
75
+ text = self .tr ("Copy name" ),
76
+ parent = self ,
77
+ )
78
+ action_copy_name .triggered .connect (partial (self .copy_to_clipboard , "name" ))
79
+
80
+ # Copy image path
81
+ action_copy_path = QAction (
82
+ icon = QgsApplication .getThemeIcon ("mIconFileLink.svg" ),
83
+ text = self .tr ("Copy path" ),
84
+ parent = self ,
85
+ )
86
+ action_copy_path .triggered .connect (partial (self .copy_to_clipboard , "path" ))
87
+
88
+ # Copy as getThemeIcon syntax
89
+ action_copy_theme_icon = QAction (
90
+ icon = QgsApplication .getThemeIcon ("mActionEditInsertImage.svg" ),
91
+ text = self .tr ("Copy as getThemeIcon syntax" ),
92
+ parent = self ,
93
+ )
94
+ action_copy_theme_icon .triggered .connect (
95
+ partial (self .copy_to_clipboard , "getThemeIcon" )
96
+ )
97
+
98
+ # Copy as QIcon syntax
99
+ action_copy_qicon = QAction (
100
+ icon = QgsApplication .getThemeIcon ("mActionEditCopy.svg" ),
101
+ text = self .tr ("Copy as QIcon syntax" ),
102
+ parent = self ,
103
+ )
104
+ action_copy_qicon .triggered .connect (partial (self .copy_to_clipboard , "qicon" ))
105
+
106
+ # Copy as QPixmap syntax
107
+ action_copy_qpixmap = QAction (
108
+ icon = QgsApplication .getThemeIcon ("mIconColorPicker.svg" ),
109
+ text = self .tr ("Copy as QPixmap syntax" ),
110
+ parent = self ,
111
+ )
112
+ action_copy_qpixmap .triggered .connect (
113
+ partial (self .copy_to_clipboard , "qpixmap" )
114
+ )
115
+
116
+ # add actions to context menu
117
+ menu .addAction (action_copy_name )
118
+ menu .addAction (action_copy_path )
119
+ menu .addSeparator ()
120
+ menu .addAction (action_copy_theme_icon )
121
+ menu .addAction (action_copy_qicon )
122
+ menu .addAction (action_copy_qpixmap )
123
+
124
+ # open the menu at the event global position
125
+ menu .exec_ (event .globalPos ())
126
+
127
+ def copy_to_clipboard (
128
+ self ,
129
+ expected_format : Literal ["getThemeIcon" , "name" , "path" , "qicon" , "qpixmap" ],
130
+ ) -> str :
131
+ """Copy item uri to system clipboard in an expected format.
132
+
133
+ :param expected_format: expected format
134
+ :type expected_format: Literal["name", "path", "qicon", "qpixmap"]
135
+
136
+ :return: formatted uri in the expected format
137
+ :rtype: str
138
+ """
139
+ self .log (
140
+ message = f"DEBUG - Copy to clipboard { self .uri } in { expected_format } format." ,
141
+ log_level = 4 ,
142
+ )
143
+ if expected_format .lower () == "name" :
144
+ QApplication .clipboard ().setText (Path (self .uri ).name )
145
+ self .log (message = f"Text copied: { Path (self .uri ).name } " , log_level = 4 )
146
+ return Path (self .uri ).name
147
+ if expected_format .lower () == "path" :
148
+ QApplication .clipboard ().setText (self .uri )
149
+ self .log (message = f"Text copied: { self .uri } " , log_level = 4 )
150
+ return self .uri
151
+ if expected_format .lower () == "getthemeicon" :
152
+ QApplication .clipboard ().setText (
153
+ f"QgsApplication.getThemeIcon('{ Path (self .uri ).name } ')"
154
+ )
155
+ self .log (
156
+ message = f"Text copied: QgsApplication.getThemeIcon('{ Path (self .uri ).name } ')" ,
157
+ log_level = 4 ,
158
+ )
159
+ return f"QgsApplication.getThemeIcon('{ self .uri } ')"
160
+ if expected_format .lower () == "qpixmap" :
161
+ QApplication .clipboard ().setText (f"QPixmap('{ self .uri } ')" )
162
+ self .log (message = f"Text copied: QPixmap('{ self .uri } ')" , log_level = 4 )
163
+ return f"QPixmap('{ self .uri } ')"
164
+ if expected_format .lower () == "qicon" :
165
+ QApplication .clipboard ().setText (f"QIcon('{ self .uri } ')" )
166
+ self .log (message = f"Text copied: QIcon('{ self .uri } ')" , log_level = 4 )
167
+ return f"QIcon('{ self .uri } ')"
168
+
169
+ self .log (message = f"Undefined format: { expected_format } " , push = True , log_level = 1 )
170
+
53
171
54
172
class ResourceBrowser (QWidget ):
55
173
"""
@@ -59,7 +177,7 @@ class ResourceBrowser(QWidget):
59
177
def __init__ (self , * args , ** kwds ):
60
178
super ().__init__ (* args , ** kwds )
61
179
62
- pathUi = pathlib . Path (__file__ ).parent / "resource_browser.ui"
180
+ pathUi = Path (__file__ ).parent / "resource_browser.ui"
63
181
with open (pathUi .as_posix ()) as uifile :
64
182
uic .loadUi (uifile , baseinstance = self )
65
183
@@ -183,6 +301,7 @@ def updatePreview(self, uri: str):
183
301
if item :
184
302
hasImage = True
185
303
self .graphicsView .setItem (item )
304
+ self .graphicsView .uri = uri
186
305
187
306
if re .search (r"\.(svg|html|xml|txt|js|css)$" , uri , re .I ) is not None :
188
307
file = QFile (uri )
0 commit comments