20 |
20 |
21 class ImageMarkupDialog(QDialog, Ui_ImageMarkupDialog): |
21 class ImageMarkupDialog(QDialog, Ui_ImageMarkupDialog): |
22 """ |
22 """ |
23 Class implementing a dialog to enter data for an image markup. |
23 Class implementing a dialog to enter data for an image markup. |
24 """ |
24 """ |
|
25 |
25 HtmlMode = 0 |
26 HtmlMode = 0 |
26 MarkDownMode = 1 |
27 MarkDownMode = 1 |
27 RestMode = 2 |
28 RestMode = 2 |
28 |
29 |
29 def __init__(self, mode, parent=None): |
30 def __init__(self, mode, parent=None): |
30 """ |
31 """ |
31 Constructor |
32 Constructor |
32 |
33 |
33 @param mode mode of the dialog |
34 @param mode mode of the dialog |
34 @type int |
35 @type int |
35 @param parent reference to the parent widget |
36 @param parent reference to the parent widget |
36 @type QWidget |
37 @type QWidget |
37 """ |
38 """ |
38 super().__init__(parent) |
39 super().__init__(parent) |
39 self.setupUi(self) |
40 self.setupUi(self) |
40 |
41 |
41 if mode == ImageMarkupDialog.MarkDownMode: |
42 if mode == ImageMarkupDialog.MarkDownMode: |
42 self.sizeCheckBox.setEnabled(False) |
43 self.sizeCheckBox.setEnabled(False) |
43 self.aspectRatioCheckBox.setEnabled(False) |
44 self.aspectRatioCheckBox.setEnabled(False) |
44 self.widthSpinBox.setEnabled(False) |
45 self.widthSpinBox.setEnabled(False) |
45 self.heightSpinBox.setEnabled(False) |
46 self.heightSpinBox.setEnabled(False) |
46 elif mode == ImageMarkupDialog.RestMode: |
47 elif mode == ImageMarkupDialog.RestMode: |
47 self.titleEdit.setEnabled(False) |
48 self.titleEdit.setEnabled(False) |
48 |
49 |
49 self.__mode = mode |
50 self.__mode = mode |
50 self.__originalImageSize = QSize() |
51 self.__originalImageSize = QSize() |
51 |
52 |
52 filters = { |
53 filters = { |
53 'bmp': self.tr("Windows Bitmap File (*.bmp)"), |
54 "bmp": self.tr("Windows Bitmap File (*.bmp)"), |
54 'cur': self.tr("Windows Cursor File (*.cur)"), |
55 "cur": self.tr("Windows Cursor File (*.cur)"), |
55 'dds': self.tr("DirectDraw-Surface File (*.dds)"), |
56 "dds": self.tr("DirectDraw-Surface File (*.dds)"), |
56 'gif': self.tr("Graphic Interchange Format File (*.gif)"), |
57 "gif": self.tr("Graphic Interchange Format File (*.gif)"), |
57 'icns': self.tr("Apple Icon File (*.icns)"), |
58 "icns": self.tr("Apple Icon File (*.icns)"), |
58 'ico': self.tr("Windows Icon File (*.ico)"), |
59 "ico": self.tr("Windows Icon File (*.ico)"), |
59 'jp2': self.tr("JPEG2000 File (*.jp2)"), |
60 "jp2": self.tr("JPEG2000 File (*.jp2)"), |
60 'jpg': self.tr("JPEG File (*.jpg)"), |
61 "jpg": self.tr("JPEG File (*.jpg)"), |
61 'jpeg': self.tr("JPEG File (*.jpeg)"), |
62 "jpeg": self.tr("JPEG File (*.jpeg)"), |
62 'mng': self.tr("Multiple-Image Network Graphics File (*.mng)"), |
63 "mng": self.tr("Multiple-Image Network Graphics File (*.mng)"), |
63 'pbm': self.tr("Portable Bitmap File (*.pbm)"), |
64 "pbm": self.tr("Portable Bitmap File (*.pbm)"), |
64 'pcx': self.tr("Paintbrush Bitmap File (*.pcx)"), |
65 "pcx": self.tr("Paintbrush Bitmap File (*.pcx)"), |
65 'pgm': self.tr("Portable Graymap File (*.pgm)"), |
66 "pgm": self.tr("Portable Graymap File (*.pgm)"), |
66 'png': self.tr("Portable Network Graphics File (*.png)"), |
67 "png": self.tr("Portable Network Graphics File (*.png)"), |
67 'ppm': self.tr("Portable Pixmap File (*.ppm)"), |
68 "ppm": self.tr("Portable Pixmap File (*.ppm)"), |
68 'sgi': self.tr("Silicon Graphics Image File (*.sgi)"), |
69 "sgi": self.tr("Silicon Graphics Image File (*.sgi)"), |
69 'svg': self.tr("Scalable Vector Graphics File (*.svg)"), |
70 "svg": self.tr("Scalable Vector Graphics File (*.svg)"), |
70 'svgz': self.tr("Compressed Scalable Vector Graphics File" |
71 "svgz": self.tr("Compressed Scalable Vector Graphics File" " (*.svgz)"), |
71 " (*.svgz)"), |
72 "tga": self.tr("Targa Graphic File (*.tga)"), |
72 'tga': self.tr("Targa Graphic File (*.tga)"), |
73 "tif": self.tr("TIFF File (*.tif)"), |
73 'tif': self.tr("TIFF File (*.tif)"), |
74 "tiff": self.tr("TIFF File (*.tiff)"), |
74 'tiff': self.tr("TIFF File (*.tiff)"), |
75 "wbmp": self.tr("WAP Bitmap File (*.wbmp)"), |
75 'wbmp': self.tr("WAP Bitmap File (*.wbmp)"), |
76 "webp": self.tr("WebP Image File (*.webp)"), |
76 'webp': self.tr("WebP Image File (*.webp)"), |
77 "xbm": self.tr("X11 Bitmap File (*.xbm)"), |
77 'xbm': self.tr("X11 Bitmap File (*.xbm)"), |
78 "xpm": self.tr("X11 Pixmap File (*.xpm)"), |
78 'xpm': self.tr("X11 Pixmap File (*.xpm)"), |
|
79 } |
79 } |
80 |
80 |
81 inputFormats = [] |
81 inputFormats = [] |
82 readFormats = QImageReader.supportedImageFormats() |
82 readFormats = QImageReader.supportedImageFormats() |
83 for readFormat in readFormats: |
83 for readFormat in readFormats: |
84 with contextlib.suppress(KeyError): |
84 with contextlib.suppress(KeyError): |
85 inputFormats.append(filters[bytes(readFormat).decode()]) |
85 inputFormats.append(filters[bytes(readFormat).decode()]) |
86 inputFormats.sort() |
86 inputFormats.sort() |
87 inputFormats.append(self.tr("All Files (*)")) |
87 inputFormats.append(self.tr("All Files (*)")) |
88 if filters["png"] in inputFormats: |
88 if filters["png"] in inputFormats: |
89 inputFormats.remove(filters["png"]) |
89 inputFormats.remove(filters["png"]) |
90 inputFormats.insert(0, filters["png"]) |
90 inputFormats.insert(0, filters["png"]) |
91 self.imagePicker.setFilters(';;'.join(inputFormats)) |
91 self.imagePicker.setFilters(";;".join(inputFormats)) |
92 self.imagePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
92 self.imagePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
93 |
93 |
94 self.sizeCheckBox.setChecked(True) |
94 self.sizeCheckBox.setChecked(True) |
95 self.aspectRatioCheckBox.setChecked(True) |
95 self.aspectRatioCheckBox.setChecked(True) |
96 |
96 |
97 msh = self.minimumSizeHint() |
97 msh = self.minimumSizeHint() |
98 self.resize(max(self.width(), msh.width()), msh.height()) |
98 self.resize(max(self.width(), msh.width()), msh.height()) |
99 |
99 |
100 self.__updateOkButton() |
100 self.__updateOkButton() |
101 |
101 |
102 def __updateOkButton(self): |
102 def __updateOkButton(self): |
103 """ |
103 """ |
104 Private slot to set the state of the OK button. |
104 Private slot to set the state of the OK button. |
105 """ |
105 """ |
106 enable = bool(self.imagePicker.text()) |
106 enable = bool(self.imagePicker.text()) |
107 if self.__mode == ImageMarkupDialog.MarkDownMode: |
107 if self.__mode == ImageMarkupDialog.MarkDownMode: |
108 enable = enable and bool(self.altTextEdit.text()) |
108 enable = enable and bool(self.altTextEdit.text()) |
109 |
109 |
110 self.buttonBox.button( |
110 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
111 QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
111 |
112 |
|
113 @pyqtSlot(str) |
112 @pyqtSlot(str) |
114 def on_imagePicker_textChanged(self, address): |
113 def on_imagePicker_textChanged(self, address): |
115 """ |
114 """ |
116 Private slot handling changes of the image path. |
115 Private slot handling changes of the image path. |
117 |
116 |
118 @param address image address (URL or local path) |
117 @param address image address (URL or local path) |
119 @type str |
118 @type str |
120 """ |
119 """ |
121 if address and "://" not in address: |
120 if address and "://" not in address: |
122 image = QImage(address) |
121 image = QImage(address) |
129 else: |
128 else: |
130 self.widthSpinBox.setValue(image.width()) |
129 self.widthSpinBox.setValue(image.width()) |
131 self.heightSpinBox.setValue(image.height()) |
130 self.heightSpinBox.setValue(image.height()) |
132 self.__originalImageSize = image.size() |
131 self.__originalImageSize = image.size() |
133 self.__aspectRatio = ( |
132 self.__aspectRatio = ( |
134 float(self.__originalImageSize.height()) / |
133 float(self.__originalImageSize.height()) |
135 self.__originalImageSize.width() |
134 / self.__originalImageSize.width() |
136 ) |
135 ) |
137 else: |
136 else: |
138 self.widthSpinBox.setValue(0) |
137 self.widthSpinBox.setValue(0) |
139 self.heightSpinBox.setValue(0) |
138 self.heightSpinBox.setValue(0) |
140 self.__originalImageSize = QSize() |
139 self.__originalImageSize = QSize() |
141 self.__aspectRatio = 1 |
140 self.__aspectRatio = 1 |
142 |
141 |
143 self.__updateOkButton() |
142 self.__updateOkButton() |
144 |
143 |
145 @pyqtSlot(str) |
144 @pyqtSlot(str) |
146 def on_altTextEdit_textChanged(self, txt): |
145 def on_altTextEdit_textChanged(self, txt): |
147 """ |
146 """ |
148 Private slot handling changes of the alternative text. |
147 Private slot handling changes of the alternative text. |
149 |
148 |
150 @param txt alternative text |
149 @param txt alternative text |
151 @type str |
150 @type str |
152 """ |
151 """ |
153 self.__updateOkButton() |
152 self.__updateOkButton() |
154 |
153 |
155 @pyqtSlot(bool) |
154 @pyqtSlot(bool) |
156 def on_sizeCheckBox_toggled(self, checked): |
155 def on_sizeCheckBox_toggled(self, checked): |
157 """ |
156 """ |
158 Private slot to reset the width and height spin boxes. |
157 Private slot to reset the width and height spin boxes. |
159 |
158 |
160 @param checked flag indicating the state of the check box |
159 @param checked flag indicating the state of the check box |
161 @type bool |
160 @type bool |
162 """ |
161 """ |
163 if checked: |
162 if checked: |
164 self.widthSpinBox.setValue(self.__originalImageSize.width()) |
163 self.widthSpinBox.setValue(self.__originalImageSize.width()) |
165 self.heightSpinBox.setValue(self.__originalImageSize.height()) |
164 self.heightSpinBox.setValue(self.__originalImageSize.height()) |
166 |
165 |
167 @pyqtSlot(bool) |
166 @pyqtSlot(bool) |
168 def on_aspectRatioCheckBox_toggled(self, checked): |
167 def on_aspectRatioCheckBox_toggled(self, checked): |
169 """ |
168 """ |
170 Private slot to adjust the height to match the original aspect ratio. |
169 Private slot to adjust the height to match the original aspect ratio. |
171 |
170 |
172 @param checked flag indicating the state of the check box |
171 @param checked flag indicating the state of the check box |
173 @type bool |
172 @type bool |
174 """ |
173 """ |
175 if checked and self.__originalImageSize.isValid(): |
174 if checked and self.__originalImageSize.isValid(): |
176 height = self.widthSpinBox.value() * self.__aspectRatio |
175 height = self.widthSpinBox.value() * self.__aspectRatio |
177 self.heightSpinBox.setValue(height) |
176 self.heightSpinBox.setValue(height) |
178 |
177 |
179 @pyqtSlot(int) |
178 @pyqtSlot(int) |
180 def on_widthSpinBox_valueChanged(self, width): |
179 def on_widthSpinBox_valueChanged(self, width): |
181 """ |
180 """ |
182 Private slot to adjust the height spin box. |
181 Private slot to adjust the height spin box. |
183 |
182 |
184 @param width width for the image |
183 @param width width for the image |
185 @type int |
184 @type int |
186 """ |
185 """ |
187 if ( |
186 if self.aspectRatioCheckBox.isChecked() and self.widthSpinBox.hasFocus(): |
188 self.aspectRatioCheckBox.isChecked() and |
|
189 self.widthSpinBox.hasFocus() |
|
190 ): |
|
191 height = width * self.__aspectRatio |
187 height = width * self.__aspectRatio |
192 self.heightSpinBox.setValue(height) |
188 self.heightSpinBox.setValue(height) |
193 |
189 |
194 @pyqtSlot(int) |
190 @pyqtSlot(int) |
195 def on_heightSpinBox_valueChanged(self, height): |
191 def on_heightSpinBox_valueChanged(self, height): |
196 """ |
192 """ |
197 Private slot to adjust the width spin box. |
193 Private slot to adjust the width spin box. |
198 |
194 |
199 @param height height for the image |
195 @param height height for the image |
200 @type int |
196 @type int |
201 """ |
197 """ |
202 if ( |
198 if self.aspectRatioCheckBox.isChecked() and self.heightSpinBox.hasFocus(): |
203 self.aspectRatioCheckBox.isChecked() and |
|
204 self.heightSpinBox.hasFocus() |
|
205 ): |
|
206 width = height / self.__aspectRatio |
199 width = height / self.__aspectRatio |
207 self.widthSpinBox.setValue(width) |
200 self.widthSpinBox.setValue(width) |
208 |
201 |
209 def getData(self): |
202 def getData(self): |
210 """ |
203 """ |
211 Public method to get the entered data. |
204 Public method to get the entered data. |
212 |
205 |
213 @return tuple containing the image address, alternative text, |
206 @return tuple containing the image address, alternative text, |
214 title text, flag to keep the original size, width and height |
207 title text, flag to keep the original size, width and height |
215 @rtype tuple of (str, str, str, bool, int, int) |
208 @rtype tuple of (str, str, str, bool, int, int) |
216 """ |
209 """ |
217 return ( |
210 return ( |