1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Designer of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "qtresourceeditordialog_p.h" |
30 | #include "ui_qtresourceeditordialog.h" |
31 | #include "qtresourcemodel_p.h" |
32 | #include "iconloader_p.h" |
33 | |
34 | #include <abstractdialoggui_p.h> |
35 | |
36 | #include <QtDesigner/abstractsettings.h> |
37 | #include <QtDesigner/abstractformeditor.h> |
38 | |
39 | #include <QtCore/qfileinfo.h> |
40 | #include <QtCore/qdir.h> |
41 | #include <QtCore/qcoreapplication.h> |
42 | #include <QtXml/qdom.h> |
43 | #include <QtWidgets/qmenu.h> |
44 | #include <QtWidgets/qheaderview.h> |
45 | #include <QtWidgets/qinputdialog.h> |
46 | #include <QtWidgets/qmessagebox.h> |
47 | #include <QtWidgets/qpushbutton.h> |
48 | #include <QtGui/qstandarditemmodel.h> |
49 | |
50 | QT_BEGIN_NAMESPACE |
51 | |
52 | static const char *rccRootTag = "RCC" ; |
53 | static const char *rccTag = "qresource" ; |
54 | static const char *rccFileTag = "file" ; |
55 | static const char *rccAliasAttribute = "alias" ; |
56 | static const char *rccPrefixAttribute = "prefix" ; |
57 | static const char *rccLangAttribute = "lang" ; |
58 | static const char *SplitterPosition = "SplitterPosition" ; |
59 | static const char *Geometry = "Geometry" ; |
60 | static const char *QrcDialogC = "QrcDialog" ; |
61 | |
62 | static QString msgOverwrite(const QString &fname) |
63 | { |
64 | return QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "%1 already exists.\nDo you want to replace it?" ).arg(a: fname); |
65 | } |
66 | |
67 | static QString msgTagMismatch(const QString &got, const QString &expected) |
68 | { |
69 | return QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "The file does not appear to be a resource file; element '%1' was found where '%2' was expected." ).arg(a1: got, a2: expected); |
70 | } |
71 | |
72 | namespace { |
73 | |
74 | // below 3 data classes should be derived from QSharedData and made implicit shared class |
75 | struct QtResourceFileData { |
76 | QString path; |
77 | QString alias; |
78 | bool operator==(const QtResourceFileData &other) const |
79 | { return path == other.path && alias == other.alias; } |
80 | }; |
81 | |
82 | struct QtResourcePrefixData { |
83 | QString prefix; |
84 | QString language; |
85 | QList<QtResourceFileData> resourceFileList; |
86 | bool operator==(const QtResourcePrefixData &other) const |
87 | { |
88 | return prefix == other.prefix && language == other.language |
89 | && resourceFileList == other.resourceFileList; |
90 | } |
91 | }; |
92 | |
93 | struct QtQrcFileData { |
94 | QString qrcPath; |
95 | QList<QtResourcePrefixData> resourceList; |
96 | bool operator==(const QtQrcFileData &other) const |
97 | { return qrcPath == other.qrcPath && resourceList == other.resourceList; } |
98 | }; |
99 | |
100 | bool loadResourceFileData(const QDomElement &fileElem, QtResourceFileData *fileData, QString *errorMessage) |
101 | { |
102 | if (!fileData) |
103 | return false; |
104 | |
105 | if (fileElem.tagName() != QLatin1String(rccFileTag)) { |
106 | *errorMessage = msgTagMismatch(got: fileElem.tagName(), expected: QLatin1String(rccFileTag)); |
107 | return false; |
108 | } |
109 | |
110 | QtResourceFileData &data = *fileData; |
111 | |
112 | data.path = fileElem.text(); |
113 | data.alias = fileElem.attribute(name: QLatin1String(rccAliasAttribute)); |
114 | |
115 | return true; |
116 | } |
117 | |
118 | static bool loadResourcePrefixData(const QDomElement &prefixElem, QtResourcePrefixData *prefixData, QString *errorMessage) |
119 | { |
120 | if (!prefixData) |
121 | return false; |
122 | |
123 | if (prefixElem.tagName() != QLatin1String(rccTag)) { |
124 | *errorMessage = msgTagMismatch(got: prefixElem.tagName(), expected: QLatin1String(rccTag)); |
125 | return false; |
126 | } |
127 | |
128 | QtResourcePrefixData &data = *prefixData; |
129 | |
130 | data.prefix = prefixElem.attribute(name: QLatin1String(rccPrefixAttribute)); |
131 | data.language = prefixElem.attribute(name: QLatin1String(rccLangAttribute)); |
132 | QDomElement fileElem = prefixElem.firstChildElement(); |
133 | while (!fileElem.isNull()) { |
134 | QtResourceFileData fileData; |
135 | if (!loadResourceFileData(fileElem, fileData: &fileData, errorMessage)) |
136 | return false; |
137 | data.resourceFileList.append(t: fileData); |
138 | fileElem = fileElem.nextSiblingElement(); |
139 | } |
140 | return true; |
141 | } |
142 | |
143 | static bool loadQrcFileData(const QDomDocument &doc, const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage) |
144 | { |
145 | if (!qrcFileData) |
146 | return false; |
147 | |
148 | QtQrcFileData &data = *qrcFileData; |
149 | |
150 | QDomElement docElem = doc.documentElement(); |
151 | if (docElem.tagName() != QLatin1String(rccRootTag)) { |
152 | *errorMessage = msgTagMismatch(got: docElem.tagName(), expected: QLatin1String(rccRootTag)); |
153 | return false; |
154 | } |
155 | |
156 | QDomElement prefixElem = docElem.firstChildElement(); |
157 | while (!prefixElem.isNull()) { |
158 | QtResourcePrefixData prefixData; |
159 | if (!loadResourcePrefixData(prefixElem, prefixData: &prefixData, errorMessage)) |
160 | return false; |
161 | data.resourceList.append(t: prefixData); |
162 | prefixElem = prefixElem.nextSiblingElement(); |
163 | } |
164 | |
165 | data.qrcPath = path; |
166 | |
167 | return true; |
168 | } |
169 | |
170 | QDomElement saveResourceFileData(QDomDocument &doc, const QtResourceFileData &fileData) |
171 | { |
172 | QDomElement fileElem = doc.createElement(tagName: QLatin1String(rccFileTag)); |
173 | if (!fileData.alias.isEmpty()) |
174 | fileElem.setAttribute(name: QLatin1String(rccAliasAttribute), value: fileData.alias); |
175 | |
176 | QDomText textElem = doc.createTextNode(data: fileData.path); |
177 | fileElem.appendChild(newChild: textElem); |
178 | |
179 | return fileElem; |
180 | } |
181 | |
182 | QDomElement saveResourcePrefixData(QDomDocument &doc, const QtResourcePrefixData &prefixData) |
183 | { |
184 | QDomElement prefixElem = doc.createElement(tagName: QLatin1String(rccTag)); |
185 | if (!prefixData.prefix.isEmpty()) |
186 | prefixElem.setAttribute(name: QLatin1String(rccPrefixAttribute), value: prefixData.prefix); |
187 | if (!prefixData.language.isEmpty()) |
188 | prefixElem.setAttribute(name: QLatin1String(rccLangAttribute), value: prefixData.language); |
189 | |
190 | for (const QtResourceFileData &rfd : prefixData.resourceFileList) { |
191 | QDomElement fileElem = saveResourceFileData(doc, fileData: rfd); |
192 | prefixElem.appendChild(newChild: fileElem); |
193 | } |
194 | |
195 | return prefixElem; |
196 | } |
197 | |
198 | QDomDocument saveQrcFileData(const QtQrcFileData &qrcFileData) |
199 | { |
200 | QDomDocument doc; |
201 | QDomElement docElem = doc.createElement(tagName: QLatin1String(rccRootTag)); |
202 | for (const QtResourcePrefixData &prefixData : qrcFileData.resourceList) { |
203 | QDomElement prefixElem = saveResourcePrefixData(doc, prefixData); |
204 | |
205 | docElem.appendChild(newChild: prefixElem); |
206 | } |
207 | doc.appendChild(newChild: docElem); |
208 | |
209 | return doc; |
210 | } |
211 | // --------------- QtResourceFile |
212 | class QtResourceFile { |
213 | public: |
214 | friend class QtQrcManager; |
215 | |
216 | QString path() const { return m_path; } |
217 | QString alias() const { return m_alias; } |
218 | QString fullPath() const { return m_fullPath; } |
219 | private: |
220 | QtResourceFile() = default; |
221 | |
222 | QString m_path; |
223 | QString m_alias; |
224 | QString m_fullPath; |
225 | }; |
226 | |
227 | class QtResourcePrefix { |
228 | public: |
229 | friend class QtQrcManager; |
230 | |
231 | QString prefix() const { return m_prefix; } |
232 | QString language() const { return m_language; } |
233 | QList<QtResourceFile *> resourceFiles() const { return m_resourceFiles; } |
234 | private: |
235 | QtResourcePrefix() = default; |
236 | |
237 | QString m_prefix; |
238 | QString m_language; |
239 | QList<QtResourceFile *> m_resourceFiles; |
240 | |
241 | }; |
242 | // ------------------- QtQrcFile |
243 | class QtQrcFile { |
244 | public: |
245 | friend class QtQrcManager; |
246 | |
247 | QString path() const { return m_path; } |
248 | QString fileName() const { return m_fileName; } |
249 | QList<QtResourcePrefix *> resourcePrefixList() const { return m_resourcePrefixes; } |
250 | QtQrcFileData initialState() const { return m_initialState; } |
251 | |
252 | private: |
253 | QtQrcFile() = default; |
254 | |
255 | void setPath(const QString &path) { |
256 | m_path = path; |
257 | QFileInfo fi(path); |
258 | m_fileName = fi.fileName(); |
259 | } |
260 | |
261 | QString m_path; |
262 | QString m_fileName; |
263 | QList<QtResourcePrefix *> m_resourcePrefixes; |
264 | QtQrcFileData m_initialState; |
265 | }; |
266 | |
267 | // ------------------ QtQrcManager |
268 | class QtQrcManager : public QObject |
269 | { |
270 | Q_OBJECT |
271 | public: |
272 | QtQrcManager(QObject *parent = nullptr); |
273 | ~QtQrcManager() override; |
274 | |
275 | QList<QtQrcFile *> qrcFiles() const; |
276 | |
277 | // helpers |
278 | QtQrcFile *qrcFileOf(const QString &path) const; |
279 | QtQrcFile *qrcFileOf(QtResourcePrefix *resourcePrefix) const; |
280 | QtResourcePrefix *resourcePrefixOf(QtResourceFile *resourceFile) const; |
281 | |
282 | QtQrcFile *importQrcFile(const QtQrcFileData &qrcFileData, QtQrcFile *beforeQrcFile = nullptr); |
283 | void exportQrcFile(QtQrcFile *qrcFile, QtQrcFileData *qrcFileData) const; |
284 | |
285 | QIcon icon(const QString &resourceFullPath) const; |
286 | bool exists(const QString &resourceFullPath) const; |
287 | bool exists(QtQrcFile *qrcFile) const; |
288 | |
289 | QtQrcFile *prevQrcFile(QtQrcFile *qrcFile) const; |
290 | QtQrcFile *nextQrcFile(QtQrcFile *qrcFile) const; |
291 | QtResourcePrefix *prevResourcePrefix(QtResourcePrefix *resourcePrefix) const; |
292 | QtResourcePrefix *nextResourcePrefix(QtResourcePrefix *resourcePrefix) const; |
293 | QtResourceFile *prevResourceFile(QtResourceFile *resourceFile) const; |
294 | QtResourceFile *nextResourceFile(QtResourceFile *resourceFile) const; |
295 | |
296 | void clear(); |
297 | |
298 | public slots: |
299 | |
300 | QtQrcFile *insertQrcFile(const QString &path, QtQrcFile *beforeQrcFile = nullptr, bool newFile = false); |
301 | void moveQrcFile(QtQrcFile *qrcFile, QtQrcFile *beforeQrcFile); |
302 | void setInitialState(QtQrcFile *qrcFile, const QtQrcFileData &initialState); |
303 | void removeQrcFile(QtQrcFile *qrcFile); |
304 | |
305 | QtResourcePrefix *insertResourcePrefix(QtQrcFile *qrcFile, const QString &prefix, |
306 | const QString &language, QtResourcePrefix *beforeResourcePrefix = nullptr); |
307 | void moveResourcePrefix(QtResourcePrefix *resourcePrefix, QtResourcePrefix *beforeResourcePrefix); // the same qrc file??? |
308 | void changeResourcePrefix(QtResourcePrefix *resourcePrefix, const QString &newPrefix); |
309 | void changeResourceLanguage(QtResourcePrefix *resourcePrefix, const QString &newLanguage); |
310 | void removeResourcePrefix(QtResourcePrefix *resourcePrefix); |
311 | |
312 | QtResourceFile *insertResourceFile(QtResourcePrefix *resourcePrefix, const QString &path, |
313 | const QString &alias, QtResourceFile *beforeResourceFile = nullptr); |
314 | void moveResourceFile(QtResourceFile *resourceFile, QtResourceFile *beforeResourceFile); // the same prefix??? |
315 | void changeResourceAlias(QtResourceFile *resourceFile, const QString &newAlias); |
316 | void removeResourceFile(QtResourceFile *resourceFile); |
317 | |
318 | signals: |
319 | void qrcFileInserted(QtQrcFile *qrcFile); |
320 | void qrcFileMoved(QtQrcFile *qrcFile, QtQrcFile *oldBeforeQrcFile); |
321 | void qrcFileRemoved(QtQrcFile *qrcFile); |
322 | |
323 | void resourcePrefixInserted(QtResourcePrefix *resourcePrefix); |
324 | void resourcePrefixMoved(QtResourcePrefix *resourcePrefix, QtResourcePrefix *oldBeforeResourcePrefix); |
325 | void resourcePrefixChanged(QtResourcePrefix *resourcePrefix, const QString &oldPrefix); |
326 | void resourceLanguageChanged(QtResourcePrefix *resourcePrefix, const QString &oldLanguage); |
327 | void resourcePrefixRemoved(QtResourcePrefix *resourcePrefix); |
328 | |
329 | void resourceFileInserted(QtResourceFile *resourceFile); |
330 | void resourceFileMoved(QtResourceFile *resourceFile, QtResourceFile *oldBeforeResourceFile); |
331 | void resourceAliasChanged(QtResourceFile *resourceFile, const QString &oldAlias); |
332 | void resourceFileRemoved(QtResourceFile *resourceFile); |
333 | private: |
334 | |
335 | QList<QtQrcFile *> m_qrcFiles; |
336 | QMap<QString, QtQrcFile *> m_pathToQrc; |
337 | QMap<QtQrcFile *, bool> m_qrcFileToExists; |
338 | QMap<QtResourcePrefix *, QtQrcFile *> m_prefixToQrc; |
339 | QMap<QtResourceFile *, QtResourcePrefix *> m_fileToPrefix; |
340 | QMap<QString, QList<QtResourceFile *> > m_fullPathToResourceFiles; |
341 | QMap<QString, QIcon> m_fullPathToIcon; |
342 | QMap<QString, bool> m_fullPathToExists; |
343 | }; |
344 | |
345 | QtQrcManager::QtQrcManager(QObject *parent) |
346 | : QObject(parent) |
347 | { |
348 | |
349 | } |
350 | |
351 | QtQrcManager::~QtQrcManager() |
352 | { |
353 | clear(); |
354 | } |
355 | |
356 | QList<QtQrcFile *> QtQrcManager::qrcFiles() const |
357 | { |
358 | return m_qrcFiles; |
359 | } |
360 | |
361 | QtQrcFile *QtQrcManager::qrcFileOf(const QString &path) const |
362 | { |
363 | return m_pathToQrc.value(akey: path); |
364 | } |
365 | |
366 | QtQrcFile *QtQrcManager::qrcFileOf(QtResourcePrefix *resourcePrefix) const |
367 | { |
368 | return m_prefixToQrc.value(akey: resourcePrefix); |
369 | } |
370 | |
371 | QtResourcePrefix *QtQrcManager::resourcePrefixOf(QtResourceFile *resourceFile) const |
372 | { |
373 | return m_fileToPrefix.value(akey: resourceFile); |
374 | } |
375 | |
376 | QtQrcFile *QtQrcManager::importQrcFile(const QtQrcFileData &qrcFileData, QtQrcFile *beforeQrcFile) |
377 | { |
378 | QtQrcFile *qrcFile = insertQrcFile(path: qrcFileData.qrcPath, beforeQrcFile); |
379 | if (!qrcFile) |
380 | return nullptr; |
381 | for (const QtResourcePrefixData &prefixData : qrcFileData.resourceList) { |
382 | QtResourcePrefix *resourcePrefix = insertResourcePrefix(qrcFile, prefix: prefixData.prefix, language: prefixData.language, beforeResourcePrefix: nullptr); |
383 | for (const QtResourceFileData &fileData : prefixData.resourceFileList) |
384 | insertResourceFile(resourcePrefix, path: fileData.path, alias: fileData.alias, beforeResourceFile: nullptr); |
385 | } |
386 | setInitialState(qrcFile, initialState: qrcFileData); |
387 | return qrcFile; |
388 | } |
389 | |
390 | void QtQrcManager::exportQrcFile(QtQrcFile *qrcFile, QtQrcFileData *qrcFileData) const |
391 | { |
392 | if (!qrcFileData) |
393 | return; |
394 | |
395 | if (!qrcFile) |
396 | return; |
397 | |
398 | QtQrcFileData &data = *qrcFileData; |
399 | |
400 | QList<QtResourcePrefixData> resourceList; |
401 | |
402 | const auto resourcePrefixes = qrcFile->resourcePrefixList(); |
403 | for (const QtResourcePrefix *prefix : resourcePrefixes) { |
404 | QList<QtResourceFileData> resourceFileList; |
405 | const auto resourceFiles = prefix->resourceFiles(); |
406 | for (QtResourceFile *file : resourceFiles) { |
407 | QtResourceFileData fileData; |
408 | fileData.path = file->path(); |
409 | fileData.alias = file->alias(); |
410 | resourceFileList << fileData; |
411 | } |
412 | QtResourcePrefixData prefixData; |
413 | prefixData.prefix = prefix->prefix(); |
414 | prefixData.language = prefix->language(); |
415 | prefixData.resourceFileList = resourceFileList; |
416 | |
417 | resourceList << prefixData; |
418 | } |
419 | data = QtQrcFileData(); |
420 | data.qrcPath = qrcFile->path(); |
421 | data.resourceList = resourceList; |
422 | } |
423 | |
424 | QIcon QtQrcManager::icon(const QString &resourceFullPath) const |
425 | { |
426 | return m_fullPathToIcon.value(akey: resourceFullPath); |
427 | } |
428 | |
429 | bool QtQrcManager::exists(const QString &resourceFullPath) const |
430 | { |
431 | return m_fullPathToExists.value(akey: resourceFullPath, adefaultValue: false); |
432 | } |
433 | |
434 | bool QtQrcManager::exists(QtQrcFile *qrcFile) const |
435 | { |
436 | return m_qrcFileToExists.value(akey: qrcFile, adefaultValue: false); |
437 | } |
438 | |
439 | QtQrcFile *QtQrcManager::prevQrcFile(QtQrcFile *qrcFile) const |
440 | { |
441 | if (!qrcFile) |
442 | return nullptr; |
443 | const int idx = m_qrcFiles.indexOf(t: qrcFile); |
444 | if (idx <= 0) |
445 | return nullptr; |
446 | return m_qrcFiles.at(i: idx - 1); |
447 | } |
448 | |
449 | QtQrcFile *QtQrcManager::nextQrcFile(QtQrcFile *qrcFile) const |
450 | { |
451 | if (!qrcFile) |
452 | return nullptr; |
453 | const int idx = m_qrcFiles.indexOf(t: qrcFile); |
454 | if (idx < 0 || idx == m_qrcFiles.size() - 1) |
455 | return nullptr; |
456 | return m_qrcFiles.at(i: idx + 1); |
457 | } |
458 | |
459 | QtResourcePrefix *QtQrcManager::prevResourcePrefix(QtResourcePrefix *resourcePrefix) const |
460 | { |
461 | if (!resourcePrefix) |
462 | return nullptr; |
463 | const auto prefixes = qrcFileOf(resourcePrefix)->resourcePrefixList(); |
464 | const int idx = prefixes.indexOf(t: resourcePrefix); |
465 | if (idx <= 0) |
466 | return nullptr; |
467 | return prefixes.at(i: idx - 1); |
468 | } |
469 | |
470 | QtResourcePrefix *QtQrcManager::nextResourcePrefix(QtResourcePrefix *resourcePrefix) const |
471 | { |
472 | if (!resourcePrefix) |
473 | return nullptr; |
474 | const auto prefixes = qrcFileOf(resourcePrefix)->resourcePrefixList(); |
475 | const int idx = prefixes.indexOf(t: resourcePrefix); |
476 | if (idx < 0 || idx == prefixes.size() - 1) |
477 | return nullptr; |
478 | return prefixes.at(i: idx + 1); |
479 | } |
480 | |
481 | QtResourceFile *QtQrcManager::prevResourceFile(QtResourceFile *resourceFile) const |
482 | { |
483 | if (!resourceFile) |
484 | return nullptr; |
485 | const auto files = resourcePrefixOf(resourceFile)->resourceFiles(); |
486 | const int idx = files.indexOf(t: resourceFile); |
487 | if (idx <= 0) |
488 | return nullptr; |
489 | return files.at(i: idx - 1); |
490 | } |
491 | |
492 | QtResourceFile *QtQrcManager::nextResourceFile(QtResourceFile *resourceFile) const |
493 | { |
494 | if (!resourceFile) |
495 | return nullptr; |
496 | const auto files = resourcePrefixOf(resourceFile)->resourceFiles(); |
497 | const int idx = files.indexOf(t: resourceFile); |
498 | if (idx < 0 || idx == files.size() - 1) |
499 | return nullptr; |
500 | return files.at(i: idx + 1); |
501 | } |
502 | |
503 | void QtQrcManager::clear() |
504 | { |
505 | const auto oldQrcFiles = qrcFiles(); |
506 | for (QtQrcFile *qf : oldQrcFiles) |
507 | removeQrcFile(qrcFile: qf); |
508 | } |
509 | |
510 | QtQrcFile *QtQrcManager::insertQrcFile(const QString &path, QtQrcFile *beforeQrcFile, bool newFile) |
511 | { |
512 | if (m_pathToQrc.contains(akey: path)) |
513 | return nullptr; |
514 | |
515 | int idx = m_qrcFiles.indexOf(t: beforeQrcFile); |
516 | if (idx < 0) |
517 | idx = m_qrcFiles.size(); |
518 | |
519 | QtQrcFile *qrcFile = new QtQrcFile(); |
520 | qrcFile->setPath(path); |
521 | |
522 | m_qrcFiles.insert(i: idx, t: qrcFile); |
523 | m_pathToQrc[path] = qrcFile; |
524 | |
525 | const QFileInfo fi(path); |
526 | m_qrcFileToExists[qrcFile] = fi.exists() || newFile; |
527 | |
528 | emit qrcFileInserted(qrcFile); |
529 | return qrcFile; |
530 | } |
531 | |
532 | void QtQrcManager::moveQrcFile(QtQrcFile *qrcFile, QtQrcFile *beforeQrcFile) |
533 | { |
534 | if (qrcFile == beforeQrcFile) |
535 | return; |
536 | |
537 | const int idx = m_qrcFiles.indexOf(t: qrcFile); |
538 | if (idx < 0) |
539 | return; |
540 | |
541 | int beforeIdx = m_qrcFiles.indexOf(t: beforeQrcFile); |
542 | if (beforeIdx < 0) |
543 | beforeIdx = m_qrcFiles.size(); |
544 | |
545 | if (idx == beforeIdx - 1) // the same position, nothing changes |
546 | return; |
547 | |
548 | QtQrcFile *oldBefore = nullptr; |
549 | if (idx < m_qrcFiles.size() - 1) |
550 | oldBefore = m_qrcFiles.at(i: idx + 1); |
551 | |
552 | m_qrcFiles.removeAt(i: idx); |
553 | if (idx < beforeIdx) |
554 | beforeIdx -= 1; |
555 | |
556 | m_qrcFiles.insert(i: beforeIdx, t: qrcFile); |
557 | |
558 | emit qrcFileMoved(qrcFile, oldBeforeQrcFile: oldBefore); |
559 | } |
560 | |
561 | void QtQrcManager::setInitialState(QtQrcFile *qrcFile, const QtQrcFileData &initialState) |
562 | { |
563 | qrcFile->m_initialState = initialState; |
564 | } |
565 | |
566 | void QtQrcManager::removeQrcFile(QtQrcFile *qrcFile) |
567 | { |
568 | const int idx = m_qrcFiles.indexOf(t: qrcFile); |
569 | if (idx < 0) |
570 | return; |
571 | |
572 | const auto resourcePrefixes = qrcFile->resourcePrefixList(); |
573 | for (QtResourcePrefix *rp : resourcePrefixes) |
574 | removeResourcePrefix(resourcePrefix: rp); |
575 | |
576 | emit qrcFileRemoved(qrcFile); |
577 | |
578 | m_qrcFiles.removeAt(i: idx); |
579 | m_pathToQrc.remove(akey: qrcFile->path()); |
580 | m_qrcFileToExists.remove(akey: qrcFile); |
581 | delete qrcFile; |
582 | } |
583 | |
584 | QtResourcePrefix *QtQrcManager::insertResourcePrefix(QtQrcFile *qrcFile, const QString &prefix, |
585 | const QString &language, QtResourcePrefix *beforeResourcePrefix) |
586 | { |
587 | if (!qrcFile) |
588 | return nullptr; |
589 | |
590 | int idx = qrcFile->m_resourcePrefixes.indexOf(t: beforeResourcePrefix); |
591 | if (idx < 0) |
592 | idx = qrcFile->m_resourcePrefixes.size(); |
593 | |
594 | QtResourcePrefix *resourcePrefix = new QtResourcePrefix(); |
595 | resourcePrefix->m_prefix = prefix; |
596 | resourcePrefix->m_language = language; |
597 | |
598 | qrcFile->m_resourcePrefixes.insert(i: idx, t: resourcePrefix); |
599 | m_prefixToQrc[resourcePrefix] = qrcFile; |
600 | |
601 | emit resourcePrefixInserted(resourcePrefix); |
602 | return resourcePrefix; |
603 | } |
604 | |
605 | void QtQrcManager::moveResourcePrefix(QtResourcePrefix *resourcePrefix, QtResourcePrefix *beforeResourcePrefix) |
606 | { |
607 | if (resourcePrefix == beforeResourcePrefix) |
608 | return; |
609 | |
610 | QtQrcFile *qrcFile = qrcFileOf(resourcePrefix); |
611 | if (!qrcFile) |
612 | return; |
613 | |
614 | if (beforeResourcePrefix && qrcFileOf(resourcePrefix: beforeResourcePrefix) != qrcFile) |
615 | return; |
616 | |
617 | const int idx = qrcFile->m_resourcePrefixes.indexOf(t: resourcePrefix); |
618 | |
619 | int beforeIdx = qrcFile->m_resourcePrefixes.indexOf(t: beforeResourcePrefix); |
620 | if (beforeIdx < 0) |
621 | beforeIdx = qrcFile->m_resourcePrefixes.size(); |
622 | |
623 | if (idx == beforeIdx - 1) // the same position, nothing changes |
624 | return; |
625 | |
626 | QtResourcePrefix *oldBefore = nullptr; |
627 | if (idx < qrcFile->m_resourcePrefixes.size() - 1) |
628 | oldBefore = qrcFile->m_resourcePrefixes.at(i: idx + 1); |
629 | |
630 | qrcFile->m_resourcePrefixes.removeAt(i: idx); |
631 | if (idx < beforeIdx) |
632 | beforeIdx -= 1; |
633 | |
634 | qrcFile->m_resourcePrefixes.insert(i: beforeIdx, t: resourcePrefix); |
635 | |
636 | emit resourcePrefixMoved(resourcePrefix, oldBeforeResourcePrefix: oldBefore); |
637 | } |
638 | |
639 | void QtQrcManager::changeResourcePrefix(QtResourcePrefix *resourcePrefix, const QString &newPrefix) |
640 | { |
641 | if (!resourcePrefix) |
642 | return; |
643 | |
644 | const QString oldPrefix = resourcePrefix->m_prefix; |
645 | if (oldPrefix == newPrefix) |
646 | return; |
647 | |
648 | resourcePrefix->m_prefix = newPrefix; |
649 | |
650 | emit resourcePrefixChanged(resourcePrefix, oldPrefix); |
651 | } |
652 | |
653 | void QtQrcManager::changeResourceLanguage(QtResourcePrefix *resourcePrefix, const QString &newLanguage) |
654 | { |
655 | if (!resourcePrefix) |
656 | return; |
657 | |
658 | const QString oldLanguage = resourcePrefix->m_language; |
659 | if (oldLanguage == newLanguage) |
660 | return; |
661 | |
662 | resourcePrefix->m_language = newLanguage; |
663 | |
664 | emit resourceLanguageChanged(resourcePrefix, oldLanguage); |
665 | } |
666 | |
667 | void QtQrcManager::removeResourcePrefix(QtResourcePrefix *resourcePrefix) |
668 | { |
669 | QtQrcFile *qrcFile = qrcFileOf(resourcePrefix); |
670 | if (!qrcFile) |
671 | return; |
672 | |
673 | const int idx = qrcFile->m_resourcePrefixes.indexOf(t: resourcePrefix); |
674 | |
675 | const auto resourceFiles = resourcePrefix->resourceFiles(); |
676 | for (QtResourceFile *rf : resourceFiles) |
677 | removeResourceFile(resourceFile: rf); |
678 | |
679 | emit resourcePrefixRemoved(resourcePrefix); |
680 | |
681 | qrcFile->m_resourcePrefixes.removeAt(i: idx); |
682 | m_prefixToQrc.remove(akey: resourcePrefix); |
683 | delete resourcePrefix; |
684 | } |
685 | |
686 | QtResourceFile *QtQrcManager::insertResourceFile(QtResourcePrefix *resourcePrefix, const QString &path, |
687 | const QString &alias, QtResourceFile *beforeResourceFile) |
688 | { |
689 | if (!resourcePrefix) |
690 | return nullptr; |
691 | |
692 | int idx = resourcePrefix->m_resourceFiles.indexOf(t: beforeResourceFile); |
693 | if (idx < 0) |
694 | idx = resourcePrefix->m_resourceFiles.size(); |
695 | |
696 | QtResourceFile *resourceFile = new QtResourceFile(); |
697 | resourceFile->m_path = path; |
698 | resourceFile->m_alias = alias; |
699 | const QFileInfo fi(qrcFileOf(resourcePrefix)->path()); |
700 | const QDir dir(fi.absolutePath()); |
701 | const QString fullPath = dir.absoluteFilePath(fileName: path); |
702 | resourceFile->m_fullPath = fullPath; |
703 | |
704 | resourcePrefix->m_resourceFiles.insert(i: idx, t: resourceFile); |
705 | m_fileToPrefix[resourceFile] = resourcePrefix; |
706 | m_fullPathToResourceFiles[fullPath].append(t: resourceFile); |
707 | if (!m_fullPathToIcon.contains(akey: fullPath)) { |
708 | m_fullPathToIcon[fullPath] = QIcon(fullPath); |
709 | const QFileInfo fullInfo(fullPath); |
710 | m_fullPathToExists[fullPath] = fullInfo.exists(); |
711 | } |
712 | |
713 | emit resourceFileInserted(resourceFile); |
714 | return resourceFile; |
715 | } |
716 | |
717 | void QtQrcManager::moveResourceFile(QtResourceFile *resourceFile, QtResourceFile *beforeResourceFile) |
718 | { |
719 | if (resourceFile == beforeResourceFile) |
720 | return; |
721 | |
722 | QtResourcePrefix *resourcePrefix = resourcePrefixOf(resourceFile); |
723 | if (!resourcePrefix) |
724 | return; |
725 | |
726 | if (beforeResourceFile && resourcePrefixOf(resourceFile: beforeResourceFile) != resourcePrefix) |
727 | return; |
728 | |
729 | const int idx = resourcePrefix->m_resourceFiles.indexOf(t: resourceFile); |
730 | |
731 | int beforeIdx = resourcePrefix->m_resourceFiles.indexOf(t: beforeResourceFile); |
732 | if (beforeIdx < 0) |
733 | beforeIdx = resourcePrefix->m_resourceFiles.size(); |
734 | |
735 | if (idx == beforeIdx - 1) // the same position, nothing changes |
736 | return; |
737 | |
738 | QtResourceFile *oldBefore = nullptr; |
739 | if (idx < resourcePrefix->m_resourceFiles.size() - 1) |
740 | oldBefore = resourcePrefix->m_resourceFiles.at(i: idx + 1); |
741 | |
742 | resourcePrefix->m_resourceFiles.removeAt(i: idx); |
743 | if (idx < beforeIdx) |
744 | beforeIdx -= 1; |
745 | |
746 | resourcePrefix->m_resourceFiles.insert(i: beforeIdx, t: resourceFile); |
747 | |
748 | emit resourceFileMoved(resourceFile, oldBeforeResourceFile: oldBefore); |
749 | } |
750 | |
751 | void QtQrcManager::changeResourceAlias(QtResourceFile *resourceFile, const QString &newAlias) |
752 | { |
753 | if (!resourceFile) |
754 | return; |
755 | |
756 | const QString oldAlias = resourceFile->m_alias; |
757 | if (oldAlias == newAlias) |
758 | return; |
759 | |
760 | resourceFile->m_alias = newAlias; |
761 | |
762 | emit resourceAliasChanged(resourceFile, oldAlias); |
763 | } |
764 | |
765 | void QtQrcManager::removeResourceFile(QtResourceFile *resourceFile) |
766 | { |
767 | QtResourcePrefix *resourcePrefix = resourcePrefixOf(resourceFile); |
768 | if (!resourcePrefix) |
769 | return; |
770 | |
771 | const int idx = resourcePrefix->m_resourceFiles.indexOf(t: resourceFile); |
772 | |
773 | emit resourceFileRemoved(resourceFile); |
774 | |
775 | resourcePrefix->m_resourceFiles.removeAt(i: idx); |
776 | m_fileToPrefix.remove(akey: resourceFile); |
777 | const QString fullPath = resourceFile->fullPath(); |
778 | m_fullPathToResourceFiles[fullPath].removeAll(t: resourceFile); // optimize me |
779 | if (m_fullPathToResourceFiles[fullPath].isEmpty()) { |
780 | m_fullPathToResourceFiles.remove(akey: fullPath); |
781 | m_fullPathToIcon.remove(akey: fullPath); |
782 | m_fullPathToExists.remove(akey: fullPath); |
783 | } |
784 | delete resourceFile; |
785 | } |
786 | |
787 | |
788 | |
789 | } |
790 | |
791 | // ----------------- QtResourceEditorDialogPrivate |
792 | class QtResourceEditorDialogPrivate |
793 | { |
794 | QtResourceEditorDialog *q_ptr; |
795 | Q_DECLARE_PUBLIC(QtResourceEditorDialog) |
796 | public: |
797 | QtResourceEditorDialogPrivate() = default; |
798 | |
799 | void slotQrcFileInserted(QtQrcFile *qrcFile); |
800 | void slotQrcFileMoved(QtQrcFile *qrcFile); |
801 | void slotQrcFileRemoved(QtQrcFile *qrcFile); |
802 | |
803 | QStandardItem *insertResourcePrefix(QtResourcePrefix *resourcePrefix); |
804 | |
805 | void slotResourcePrefixInserted(QtResourcePrefix *resourcePrefix) { insertResourcePrefix(resourcePrefix); } |
806 | void slotResourcePrefixMoved(QtResourcePrefix *resourcePrefix); |
807 | void slotResourcePrefixChanged(QtResourcePrefix *resourcePrefix); |
808 | void slotResourceLanguageChanged(QtResourcePrefix *resourcePrefix); |
809 | void slotResourcePrefixRemoved(QtResourcePrefix *resourcePrefix); |
810 | void slotResourceFileInserted(QtResourceFile *resourceFile); |
811 | void slotResourceFileMoved(QtResourceFile *resourceFile); |
812 | void slotResourceAliasChanged(QtResourceFile *resourceFile); |
813 | void slotResourceFileRemoved(QtResourceFile *resourceFile); |
814 | |
815 | void slotCurrentQrcFileChanged(QListWidgetItem *item); |
816 | void slotCurrentTreeViewItemChanged(const QModelIndex &index); |
817 | void slotListWidgetContextMenuRequested(const QPoint &pos); |
818 | void slotTreeViewContextMenuRequested(const QPoint &pos); |
819 | void slotTreeViewItemChanged(QStandardItem *item); |
820 | |
821 | void slotNewQrcFile(); |
822 | void slotImportQrcFile(); |
823 | void slotRemoveQrcFile(); |
824 | void slotMoveUpQrcFile(); |
825 | void slotMoveDownQrcFile(); |
826 | |
827 | void slotNewPrefix(); |
828 | void slotAddFiles(); |
829 | void slotChangePrefix(); |
830 | void slotChangeLanguage(); |
831 | void slotChangeAlias(); |
832 | void slotClonePrefix(); |
833 | void slotRemove(); |
834 | void slotMoveUp(); |
835 | void slotMoveDown(); |
836 | |
837 | bool loadQrcFile(const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage); |
838 | bool loadQrcFile(const QString &path, QtQrcFileData *qrcFileData); |
839 | bool saveQrcFile(const QtQrcFileData &qrcFileData); |
840 | |
841 | QString qrcFileText(QtQrcFile *qrcFile) const; |
842 | |
843 | QMessageBox::StandardButton warning(const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, |
844 | QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) const; |
845 | |
846 | QString browseForNewLocation(const QString &resourceFile, const QDir &rootDir) const; |
847 | QString copyResourceFile(const QString &resourceFile, const QString &destPath) const; |
848 | QtResourceFile *getCurrentResourceFile() const; |
849 | QtResourcePrefix *getCurrentResourcePrefix() const; |
850 | void selectTreeRow(QStandardItem *item); |
851 | QString getSaveFileNameWithExtension(QWidget *parent, |
852 | const QString &title, QString dir, const QString &filter, const QString &extension) const; |
853 | QString qrcStartDirectory() const; |
854 | |
855 | Ui::QtResourceEditorDialog m_ui; |
856 | QDesignerFormEditorInterface *m_core = nullptr; |
857 | QtResourceModel *m_resourceModel = nullptr; |
858 | QDesignerDialogGuiInterface *m_dlgGui = nullptr; |
859 | QtQrcManager *m_qrcManager = nullptr; |
860 | QList<QtQrcFileData> m_initialState; |
861 | |
862 | QMap<QtQrcFile *, QListWidgetItem *> m_qrcFileToItem; |
863 | QMap<QListWidgetItem *, QtQrcFile *> m_itemToQrcFile; |
864 | QMap<QtResourcePrefix *, QStandardItem *> m_resourcePrefixToPrefixItem; |
865 | QMap<QtResourcePrefix *, QStandardItem *> m_resourcePrefixToLanguageItem; |
866 | QMap<QStandardItem *, QtResourcePrefix *> m_prefixItemToResourcePrefix; |
867 | QMap<QStandardItem *, QtResourcePrefix *> m_languageItemToResourcePrefix; |
868 | QMap<QtResourceFile *, QStandardItem *> m_resourceFileToPathItem; |
869 | QMap<QtResourceFile *, QStandardItem *> m_resourceFileToAliasItem; |
870 | QMap<QStandardItem *, QtResourceFile *> m_pathItemToResourceFile; |
871 | QMap<QStandardItem *, QtResourceFile *> m_aliasItemToResourceFile; |
872 | |
873 | bool m_ignoreCurrentChanged = false; |
874 | bool m_firstQrcFileDialog = true; |
875 | QtQrcFile *m_currentQrcFile = nullptr; |
876 | |
877 | QAction *m_newQrcFileAction = nullptr; |
878 | QAction *m_importQrcFileAction = nullptr; |
879 | QAction *m_removeQrcFileAction = nullptr; |
880 | QAction *m_moveUpQrcFileAction = nullptr; |
881 | QAction *m_moveDownQrcFileAction = nullptr; |
882 | |
883 | QAction *m_newPrefixAction = nullptr; |
884 | QAction *m_addResourceFileAction = nullptr; |
885 | QAction *m_changePrefixAction = nullptr; |
886 | QAction *m_changeLanguageAction = nullptr; |
887 | QAction *m_changeAliasAction = nullptr; |
888 | QAction *m_clonePrefixAction = nullptr; |
889 | QAction *m_moveUpAction = nullptr; |
890 | QAction *m_moveDownAction = nullptr; |
891 | QAction *m_removeAction = nullptr; |
892 | |
893 | QStandardItemModel *m_treeModel = nullptr; |
894 | QItemSelectionModel *m_treeSelection = nullptr; |
895 | }; |
896 | |
897 | QMessageBox::StandardButton QtResourceEditorDialogPrivate::warning(const QString &title, const QString &text, QMessageBox::StandardButtons buttons, |
898 | QMessageBox::StandardButton defaultButton) const |
899 | { |
900 | return m_dlgGui->message(parent: q_ptr, context: QDesignerDialogGuiInterface::ResourceEditorMessage, icon: QMessageBox::Warning, title, text, buttons, defaultButton); |
901 | } |
902 | |
903 | QString QtResourceEditorDialogPrivate::qrcFileText(QtQrcFile *qrcFile) const |
904 | { |
905 | const QString path = qrcFile->path(); |
906 | const QString fileName = qrcFile->fileName(); |
907 | const QFileInfo fi(path); |
908 | if (fi.exists() && !fi.isWritable()) |
909 | return QApplication::translate(context: "QtResourceEditorDialog" , key: "%1 [read-only]" ).arg(a: fileName); |
910 | if (!m_qrcManager->exists(qrcFile)) |
911 | return QApplication::translate(context: "QtResourceEditorDialog" , key: "%1 [missing]" ).arg(a: fileName); |
912 | return fileName; |
913 | } |
914 | |
915 | void QtResourceEditorDialogPrivate::slotQrcFileInserted(QtQrcFile *qrcFile) |
916 | { |
917 | QListWidgetItem *currentItem = m_ui.qrcFileList->currentItem(); |
918 | int idx = m_ui.qrcFileList->count(); |
919 | QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile); |
920 | QListWidgetItem *nextItem = m_qrcFileToItem.value(akey: nextQrcFile); |
921 | if (nextItem) { |
922 | const int row = m_ui.qrcFileList->row(item: nextItem); |
923 | if (row >= 0) |
924 | idx = row; |
925 | } |
926 | const QString path = qrcFile->path(); |
927 | QListWidgetItem *item = new QListWidgetItem(qrcFileText(qrcFile)); |
928 | item->setToolTip(path); |
929 | m_ignoreCurrentChanged = true; |
930 | m_ui.qrcFileList->insertItem(row: idx, item); |
931 | m_ui.qrcFileList->setCurrentItem(currentItem); |
932 | m_ignoreCurrentChanged = false; |
933 | m_qrcFileToItem[qrcFile] = item; |
934 | m_itemToQrcFile[item] = qrcFile; |
935 | if (!m_qrcManager->exists(qrcFile)) |
936 | item->setForeground(QBrush(Qt::red)); |
937 | } |
938 | |
939 | void QtResourceEditorDialogPrivate::slotQrcFileMoved(QtQrcFile *qrcFile) |
940 | { |
941 | QListWidgetItem *currentItem = m_ui.qrcFileList->currentItem(); |
942 | QListWidgetItem *item = m_qrcFileToItem.value(akey: qrcFile); |
943 | m_ignoreCurrentChanged = true; |
944 | m_ui.qrcFileList->takeItem(row: m_ui.qrcFileList->row(item)); |
945 | |
946 | int idx = m_ui.qrcFileList->count(); |
947 | QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile); |
948 | QListWidgetItem *nextItem = m_qrcFileToItem.value(akey: nextQrcFile); |
949 | if (nextItem) { |
950 | int row = m_ui.qrcFileList->row(item: nextItem); |
951 | if (row >= 0) |
952 | idx = row; |
953 | } |
954 | m_ui.qrcFileList->insertItem(row: idx, item); |
955 | if (currentItem == item) |
956 | m_ui.qrcFileList->setCurrentItem(item); |
957 | m_ignoreCurrentChanged = false; |
958 | } |
959 | |
960 | void QtResourceEditorDialogPrivate::slotQrcFileRemoved(QtQrcFile *qrcFile) |
961 | { |
962 | QListWidgetItem *item = m_qrcFileToItem.value(akey: qrcFile); |
963 | if (item == m_ui.qrcFileList->currentItem()) |
964 | m_ui.qrcFileList->setCurrentItem(nullptr); // this should trigger list view signal currentItemChanged(0), and slot should set m_currentQrcFile to 0 |
965 | m_ignoreCurrentChanged = true; |
966 | delete item; |
967 | m_ignoreCurrentChanged = false; |
968 | m_itemToQrcFile.remove(akey: item); |
969 | m_qrcFileToItem.remove(akey: qrcFile); |
970 | } |
971 | |
972 | QStandardItem *QtResourceEditorDialogPrivate::insertResourcePrefix(QtResourcePrefix *resourcePrefix) |
973 | { |
974 | if (m_qrcManager->qrcFileOf(resourcePrefix) != m_currentQrcFile) |
975 | return nullptr; |
976 | |
977 | QtResourcePrefix *prevResourcePrefix = m_qrcManager->prevResourcePrefix(resourcePrefix); |
978 | QStandardItem *prevItem = m_resourcePrefixToPrefixItem.value(akey: prevResourcePrefix); |
979 | |
980 | int row = 0; |
981 | if (prevItem) |
982 | row = m_treeModel->indexFromItem(item: prevItem).row() + 1; |
983 | |
984 | QStandardItem *prefixItem = new QStandardItem(); |
985 | QStandardItem *languageItem = new QStandardItem(); |
986 | QList<QStandardItem *> items; |
987 | items << prefixItem; |
988 | items << languageItem; |
989 | m_treeModel->insertRow(row, items); |
990 | const QModelIndex newIndex = m_treeModel->indexFromItem(item: prefixItem); |
991 | m_ui.resourceTreeView->setExpanded(index: newIndex, expand: true); |
992 | prefixItem->setFlags(prefixItem->flags() | Qt::ItemIsEditable); |
993 | languageItem->setFlags(languageItem->flags() | Qt::ItemIsEditable); |
994 | m_resourcePrefixToPrefixItem[resourcePrefix] = prefixItem; |
995 | m_resourcePrefixToLanguageItem[resourcePrefix] = languageItem; |
996 | m_prefixItemToResourcePrefix[prefixItem] = resourcePrefix; |
997 | m_languageItemToResourcePrefix[languageItem] = resourcePrefix; |
998 | slotResourcePrefixChanged(resourcePrefix); |
999 | slotResourceLanguageChanged(resourcePrefix); |
1000 | return prefixItem; |
1001 | } |
1002 | |
1003 | void QtResourceEditorDialogPrivate::slotResourcePrefixMoved(QtResourcePrefix *resourcePrefix) |
1004 | { |
1005 | QStandardItem *prefixItem = m_resourcePrefixToPrefixItem.value(akey: resourcePrefix); |
1006 | if (!prefixItem) |
1007 | return; |
1008 | |
1009 | QStandardItem *languageItem = m_resourcePrefixToLanguageItem.value(akey: resourcePrefix); |
1010 | if (!languageItem) |
1011 | return; |
1012 | |
1013 | const QModelIndex index = m_treeModel->indexFromItem(item: prefixItem); |
1014 | const bool expanded = m_ui.resourceTreeView->isExpanded(index); |
1015 | m_ignoreCurrentChanged = true; |
1016 | const auto items = m_treeModel->takeRow(row: index.row()); |
1017 | |
1018 | int row = m_treeModel->rowCount(); |
1019 | QtResourcePrefix *nextResourcePrefix = m_qrcManager->nextResourcePrefix(resourcePrefix); |
1020 | QStandardItem *nextItem = m_resourcePrefixToPrefixItem.value(akey: nextResourcePrefix); |
1021 | if (nextItem) |
1022 | row = m_treeModel->indexFromItem(item: nextItem).row(); |
1023 | m_treeModel->insertRow(row, items); |
1024 | m_ignoreCurrentChanged = false; |
1025 | m_ui.resourceTreeView->setExpanded(index: m_treeModel->indexFromItem(item: items.at(i: 0)), expand: expanded); |
1026 | } |
1027 | |
1028 | void QtResourceEditorDialogPrivate::slotResourcePrefixChanged(QtResourcePrefix *resourcePrefix) |
1029 | { |
1030 | QStandardItem *item = m_resourcePrefixToPrefixItem.value(akey: resourcePrefix); |
1031 | if (!item) |
1032 | return; |
1033 | |
1034 | m_ignoreCurrentChanged = true; |
1035 | QString prefix = resourcePrefix->prefix(); |
1036 | if (prefix.isEmpty()) |
1037 | prefix = QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "<no prefix>" ); |
1038 | item->setText(prefix); |
1039 | item->setToolTip(prefix); |
1040 | m_ignoreCurrentChanged = false; |
1041 | } |
1042 | |
1043 | void QtResourceEditorDialogPrivate::slotResourceLanguageChanged(QtResourcePrefix *resourcePrefix) |
1044 | { |
1045 | QStandardItem *item = m_resourcePrefixToLanguageItem.value(akey: resourcePrefix); |
1046 | if (!item) |
1047 | return; |
1048 | |
1049 | m_ignoreCurrentChanged = true; |
1050 | const QString language = resourcePrefix->language(); |
1051 | item->setText(language); |
1052 | item->setToolTip(language); |
1053 | |
1054 | m_ignoreCurrentChanged = false; |
1055 | } |
1056 | |
1057 | void QtResourceEditorDialogPrivate::slotResourcePrefixRemoved(QtResourcePrefix *resourcePrefix) |
1058 | { |
1059 | QStandardItem *prefixItem = m_resourcePrefixToPrefixItem.value(akey: resourcePrefix); |
1060 | if (!prefixItem) |
1061 | return; |
1062 | |
1063 | QStandardItem *languageItem = m_resourcePrefixToLanguageItem.value(akey: resourcePrefix); |
1064 | if (!languageItem) |
1065 | return; |
1066 | |
1067 | m_ignoreCurrentChanged = true; |
1068 | m_treeModel->takeRow(row: m_treeModel->indexFromItem(item: prefixItem).row()); |
1069 | delete prefixItem; |
1070 | delete languageItem; |
1071 | m_ignoreCurrentChanged = false; |
1072 | m_prefixItemToResourcePrefix.remove(akey: prefixItem); |
1073 | m_languageItemToResourcePrefix.remove(akey: languageItem); |
1074 | m_resourcePrefixToPrefixItem.remove(akey: resourcePrefix); |
1075 | m_resourcePrefixToLanguageItem.remove(akey: resourcePrefix); |
1076 | } |
1077 | |
1078 | void QtResourceEditorDialogPrivate::slotResourceFileInserted(QtResourceFile *resourceFile) |
1079 | { |
1080 | QtResourcePrefix *resourcePrefix = m_qrcManager->resourcePrefixOf(resourceFile); |
1081 | if (m_qrcManager->qrcFileOf(resourcePrefix) != m_currentQrcFile) |
1082 | return; |
1083 | |
1084 | QtResourceFile *prevResourceFile = m_qrcManager->prevResourceFile(resourceFile); |
1085 | QStandardItem *prevItem = m_resourceFileToPathItem.value(akey: prevResourceFile); |
1086 | |
1087 | QStandardItem *pathItem = new QStandardItem(resourceFile->path()); |
1088 | QStandardItem *aliasItem = new QStandardItem(); |
1089 | QStandardItem *parentItem = m_resourcePrefixToPrefixItem.value(akey: resourcePrefix); |
1090 | QList<QStandardItem *> items; |
1091 | items << pathItem; |
1092 | items << aliasItem; |
1093 | |
1094 | int row = 0; |
1095 | if (prevItem) |
1096 | row = m_treeModel->indexFromItem(item: prevItem).row() + 1; |
1097 | |
1098 | parentItem->insertRow(row, items); |
1099 | |
1100 | pathItem->setFlags(pathItem->flags() & ~Qt::ItemIsEditable); |
1101 | aliasItem->setFlags(aliasItem->flags() | Qt::ItemIsEditable); |
1102 | m_resourceFileToPathItem[resourceFile] = pathItem; |
1103 | m_resourceFileToAliasItem[resourceFile] = aliasItem; |
1104 | m_pathItemToResourceFile[pathItem] = resourceFile; |
1105 | m_aliasItemToResourceFile[aliasItem] = resourceFile; |
1106 | pathItem->setToolTip(resourceFile->path()); |
1107 | pathItem->setIcon(m_qrcManager->icon(resourceFullPath: resourceFile->fullPath())); |
1108 | if (!m_qrcManager->exists(resourceFullPath: resourceFile->fullPath())) { |
1109 | pathItem->setText(QApplication::translate(context: "QtResourceEditorDialog" , key: "%1 [missing]" ).arg(a: resourceFile->path())); |
1110 | QBrush redBrush(Qt::red); |
1111 | pathItem->setForeground(redBrush); |
1112 | aliasItem->setForeground(redBrush); |
1113 | } |
1114 | slotResourceAliasChanged(resourceFile); |
1115 | } |
1116 | |
1117 | void QtResourceEditorDialogPrivate::slotResourceFileMoved(QtResourceFile *resourceFile) |
1118 | { |
1119 | QStandardItem *pathItem = m_resourceFileToPathItem.value(akey: resourceFile); |
1120 | if (!pathItem) |
1121 | return; |
1122 | |
1123 | QStandardItem *aliasItem = m_resourceFileToAliasItem.value(akey: resourceFile); |
1124 | if (!aliasItem) |
1125 | return; |
1126 | |
1127 | QStandardItem *parentItem = pathItem->parent(); |
1128 | m_ignoreCurrentChanged = true; |
1129 | const auto items = parentItem->takeRow(row: m_treeModel->indexFromItem(item: pathItem).row()); |
1130 | |
1131 | int row = parentItem->rowCount(); |
1132 | QtResourceFile *nextResourceFile = m_qrcManager->nextResourceFile(resourceFile); |
1133 | QStandardItem *nextItem = m_resourceFileToPathItem.value(akey: nextResourceFile); |
1134 | if (nextItem) |
1135 | row = m_treeModel->indexFromItem(item: nextItem).row(); |
1136 | parentItem->insertRow(row, items); |
1137 | m_ignoreCurrentChanged = false; |
1138 | } |
1139 | |
1140 | void QtResourceEditorDialogPrivate::slotResourceAliasChanged(QtResourceFile *resourceFile) |
1141 | { |
1142 | QStandardItem *item = m_resourceFileToAliasItem.value(akey: resourceFile); |
1143 | if (!item) |
1144 | return; |
1145 | |
1146 | m_ignoreCurrentChanged = true; |
1147 | const QString alias = resourceFile->alias(); |
1148 | item->setText(alias); |
1149 | item->setToolTip(alias); |
1150 | |
1151 | m_ignoreCurrentChanged = false; |
1152 | } |
1153 | |
1154 | void QtResourceEditorDialogPrivate::slotResourceFileRemoved(QtResourceFile *resourceFile) |
1155 | { |
1156 | QStandardItem *pathItem = m_resourceFileToPathItem.value(akey: resourceFile); |
1157 | if (!pathItem) |
1158 | return; |
1159 | |
1160 | QStandardItem *aliasItem = m_resourceFileToAliasItem.value(akey: resourceFile); |
1161 | if (!aliasItem) |
1162 | return; |
1163 | |
1164 | QStandardItem *parentItem = pathItem->parent(); |
1165 | |
1166 | m_ignoreCurrentChanged = true; |
1167 | parentItem->takeRow(row: m_treeModel->indexFromItem(item: pathItem).row()); |
1168 | delete pathItem; |
1169 | delete aliasItem; |
1170 | m_ignoreCurrentChanged = false; |
1171 | m_pathItemToResourceFile.remove(akey: pathItem); |
1172 | m_aliasItemToResourceFile.remove(akey: aliasItem); |
1173 | m_resourceFileToPathItem.remove(akey: resourceFile); |
1174 | m_resourceFileToAliasItem.remove(akey: resourceFile); |
1175 | } |
1176 | |
1177 | |
1178 | void QtResourceEditorDialogPrivate::slotCurrentQrcFileChanged(QListWidgetItem *item) |
1179 | { |
1180 | if (m_ignoreCurrentChanged) |
1181 | return; |
1182 | |
1183 | QtQrcFile *newCurrentQrcFile = m_itemToQrcFile.value(akey: item); |
1184 | |
1185 | if (newCurrentQrcFile == m_currentQrcFile) |
1186 | return; |
1187 | |
1188 | if (m_currentQrcFile) { |
1189 | QMap<QtResourcePrefix *, QStandardItem *> currentPrefixList = m_resourcePrefixToPrefixItem; |
1190 | for (auto it = currentPrefixList.cbegin(), end = currentPrefixList.cend(); it != end; ++it) { |
1191 | QtResourcePrefix *resourcePrefix = it.key(); |
1192 | const auto currentResourceFiles = resourcePrefix->resourceFiles(); |
1193 | for (QtResourceFile *rf : currentResourceFiles) |
1194 | slotResourceFileRemoved(resourceFile: rf); |
1195 | slotResourcePrefixRemoved(resourcePrefix); |
1196 | } |
1197 | } |
1198 | |
1199 | m_currentQrcFile = newCurrentQrcFile; |
1200 | slotCurrentTreeViewItemChanged(index: QModelIndex()); |
1201 | QStandardItem *firstPrefix = nullptr; // select first prefix |
1202 | if (m_currentQrcFile) { |
1203 | const auto newPrefixList = m_currentQrcFile->resourcePrefixList(); |
1204 | for (QtResourcePrefix *resourcePrefix : newPrefixList) { |
1205 | if (QStandardItem *newPrefixItem = insertResourcePrefix(resourcePrefix)) |
1206 | if (!firstPrefix) |
1207 | firstPrefix = newPrefixItem; |
1208 | const auto newResourceFiles = resourcePrefix->resourceFiles(); |
1209 | for (QtResourceFile *rf : newResourceFiles) |
1210 | slotResourceFileInserted(resourceFile: rf); |
1211 | } |
1212 | } |
1213 | m_ui.resourceTreeView->setCurrentIndex(firstPrefix ? m_treeModel->indexFromItem(item: firstPrefix) : QModelIndex()); |
1214 | |
1215 | m_removeQrcFileAction->setEnabled(m_currentQrcFile); |
1216 | m_moveUpQrcFileAction->setEnabled(m_currentQrcFile && m_qrcManager->prevQrcFile(qrcFile: m_currentQrcFile)); |
1217 | m_moveDownQrcFileAction->setEnabled(m_currentQrcFile && m_qrcManager->nextQrcFile(qrcFile: m_currentQrcFile)); |
1218 | } |
1219 | |
1220 | void QtResourceEditorDialogPrivate::slotCurrentTreeViewItemChanged(const QModelIndex &index) |
1221 | { |
1222 | QStandardItem *item = m_treeModel->itemFromIndex(index); |
1223 | QtResourceFile *resourceFile = m_pathItemToResourceFile.value(akey: item); |
1224 | if (!resourceFile) |
1225 | resourceFile = m_aliasItemToResourceFile.value(akey: item); |
1226 | QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(akey: item); |
1227 | if (!resourcePrefix) |
1228 | resourcePrefix = m_languageItemToResourcePrefix.value(akey: item); |
1229 | |
1230 | bool moveUpEnabled = false; |
1231 | bool moveDownEnabled = false; |
1232 | bool currentItem = resourceFile || resourcePrefix; |
1233 | |
1234 | if (resourceFile) { |
1235 | if (m_qrcManager->prevResourceFile(resourceFile)) |
1236 | moveUpEnabled = true; |
1237 | if (m_qrcManager->nextResourceFile(resourceFile)) |
1238 | moveDownEnabled = true; |
1239 | } else if (resourcePrefix) { |
1240 | if (m_qrcManager->prevResourcePrefix(resourcePrefix)) |
1241 | moveUpEnabled = true; |
1242 | if (m_qrcManager->nextResourcePrefix(resourcePrefix)) |
1243 | moveDownEnabled = true; |
1244 | } |
1245 | |
1246 | m_newPrefixAction->setEnabled(m_currentQrcFile); |
1247 | m_addResourceFileAction->setEnabled(currentItem); |
1248 | m_changePrefixAction->setEnabled(currentItem); |
1249 | m_changeLanguageAction->setEnabled(currentItem); |
1250 | m_changeAliasAction->setEnabled(resourceFile); |
1251 | m_removeAction->setEnabled(currentItem); |
1252 | m_moveUpAction->setEnabled(moveUpEnabled); |
1253 | m_moveDownAction->setEnabled(moveDownEnabled); |
1254 | m_clonePrefixAction->setEnabled(currentItem); |
1255 | } |
1256 | |
1257 | void QtResourceEditorDialogPrivate::(const QPoint &pos) |
1258 | { |
1259 | QMenu (q_ptr); |
1260 | menu.addAction(action: m_newQrcFileAction); |
1261 | menu.addAction(action: m_importQrcFileAction); |
1262 | menu.addAction(action: m_removeQrcFileAction); |
1263 | menu.addSeparator(); |
1264 | menu.addAction(action: m_moveUpQrcFileAction); |
1265 | menu.addAction(action: m_moveDownQrcFileAction); |
1266 | menu.exec(pos: m_ui.qrcFileList->mapToGlobal(pos)); |
1267 | } |
1268 | |
1269 | void QtResourceEditorDialogPrivate::(const QPoint &pos) |
1270 | { |
1271 | QMenu (q_ptr); |
1272 | menu.addAction(action: m_newPrefixAction); |
1273 | menu.addAction(action: m_addResourceFileAction); |
1274 | menu.addAction(action: m_removeAction); |
1275 | menu.addSeparator(); |
1276 | menu.addAction(action: m_changePrefixAction); |
1277 | menu.addAction(action: m_changeLanguageAction); |
1278 | menu.addAction(action: m_changeAliasAction); |
1279 | menu.addSeparator(); |
1280 | menu.addAction(action: m_clonePrefixAction); |
1281 | menu.addSeparator(); |
1282 | menu.addAction(action: m_moveUpAction); |
1283 | menu.addAction(action: m_moveDownAction); |
1284 | menu.exec(pos: m_ui.resourceTreeView->mapToGlobal(pos)); |
1285 | } |
1286 | |
1287 | void QtResourceEditorDialogPrivate::slotTreeViewItemChanged(QStandardItem *item) |
1288 | { |
1289 | if (m_ignoreCurrentChanged) |
1290 | return; |
1291 | |
1292 | const QString newValue = item->text(); |
1293 | QtResourceFile *resourceFile = m_aliasItemToResourceFile.value(akey: item); |
1294 | if (resourceFile) { |
1295 | m_qrcManager->changeResourceAlias(resourceFile, newAlias: newValue); |
1296 | return; |
1297 | } |
1298 | |
1299 | QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(akey: item); |
1300 | if (resourcePrefix) { |
1301 | m_qrcManager->changeResourcePrefix(resourcePrefix, newPrefix: newValue); |
1302 | return; |
1303 | } |
1304 | |
1305 | resourcePrefix = m_languageItemToResourcePrefix.value(akey: item); |
1306 | if (resourcePrefix) { |
1307 | m_qrcManager->changeResourceLanguage(resourcePrefix, newLanguage: newValue); |
1308 | return; |
1309 | } |
1310 | } |
1311 | |
1312 | QString QtResourceEditorDialogPrivate::getSaveFileNameWithExtension(QWidget *parent, |
1313 | const QString &title, QString dir, const QString &filter, const QString &extension) const |
1314 | { |
1315 | const QChar dot = QLatin1Char('.'); |
1316 | |
1317 | QString saveFile; |
1318 | while (true) { |
1319 | saveFile = m_dlgGui->getSaveFileName(parent, caption: title, dir, filter, selectedFilter: nullptr, options: QFileDialog::DontConfirmOverwrite); |
1320 | if (saveFile.isEmpty()) |
1321 | return saveFile; |
1322 | |
1323 | const QFileInfo fInfo(saveFile); |
1324 | if (fInfo.suffix().isEmpty() && !fInfo.fileName().endsWith(c: dot)) { |
1325 | saveFile += dot; |
1326 | saveFile += extension; |
1327 | } |
1328 | |
1329 | const QFileInfo fi(saveFile); |
1330 | if (!fi.exists()) |
1331 | break; |
1332 | |
1333 | if (warning(title, text: msgOverwrite(fname: fi.fileName()), buttons: QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) |
1334 | break; |
1335 | |
1336 | dir = saveFile; |
1337 | } |
1338 | return saveFile; |
1339 | } |
1340 | |
1341 | QString QtResourceEditorDialogPrivate::qrcStartDirectory() const |
1342 | { |
1343 | if (!m_currentQrcFile) |
1344 | return QString(); |
1345 | const QDir dir = QFileInfo(m_currentQrcFile->path()).dir(); |
1346 | return dir.exists() ? dir.absolutePath() : QString(); |
1347 | } |
1348 | |
1349 | void QtResourceEditorDialogPrivate::slotNewQrcFile() |
1350 | { |
1351 | const QString qrcPath = getSaveFileNameWithExtension(parent: q_ptr, |
1352 | title: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "New Resource File" ), |
1353 | dir: m_firstQrcFileDialog ? qrcStartDirectory() : QString(), |
1354 | filter: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Resource files (*.qrc)" ), |
1355 | QStringLiteral("qrc" )); |
1356 | if (qrcPath.isEmpty()) |
1357 | return; |
1358 | |
1359 | m_firstQrcFileDialog = false; |
1360 | if (QtQrcFile *sameQrcFile = m_qrcManager->qrcFileOf(path: qrcPath)) { |
1361 | // QMessageBox ??? |
1362 | QListWidgetItem *item = m_qrcFileToItem.value(akey: sameQrcFile); |
1363 | m_ui.qrcFileList->setCurrentItem(item); |
1364 | item->setSelected(true); |
1365 | return; |
1366 | } |
1367 | |
1368 | QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile: m_currentQrcFile); |
1369 | |
1370 | QtQrcFile *qrcFile = m_qrcManager->insertQrcFile(path: qrcPath, beforeQrcFile: nextQrcFile, newFile: true); |
1371 | m_ui.qrcFileList->setCurrentItem(m_qrcFileToItem.value(akey: qrcFile)); |
1372 | } |
1373 | |
1374 | void QtResourceEditorDialogPrivate::slotImportQrcFile() |
1375 | { |
1376 | const QString qrcPath = m_dlgGui->getOpenFileName(parent: q_ptr, |
1377 | caption: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Import Resource File" ), |
1378 | dir: m_firstQrcFileDialog ? qrcStartDirectory() : QString(), |
1379 | filter: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Resource files (*.qrc)" )); |
1380 | if (qrcPath.isEmpty()) |
1381 | return; |
1382 | m_firstQrcFileDialog = false; |
1383 | if (QtQrcFile *sameQrcFile = m_qrcManager->qrcFileOf(path: qrcPath)) { |
1384 | // QMessageBox ??? |
1385 | QListWidgetItem *item = m_qrcFileToItem.value(akey: sameQrcFile); |
1386 | m_ui.qrcFileList->setCurrentItem(item); |
1387 | item->setSelected(true); |
1388 | return; |
1389 | } |
1390 | |
1391 | QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile: m_currentQrcFile); |
1392 | |
1393 | QtQrcFileData qrcFileData; |
1394 | loadQrcFile(path: qrcPath, qrcFileData: &qrcFileData); |
1395 | QtQrcFile *qrcFile = m_qrcManager->importQrcFile(qrcFileData, beforeQrcFile: nextQrcFile); |
1396 | m_ui.qrcFileList->setCurrentItem(m_qrcFileToItem.value(akey: qrcFile)); |
1397 | } |
1398 | |
1399 | void QtResourceEditorDialogPrivate::slotRemoveQrcFile() |
1400 | { |
1401 | if (!m_currentQrcFile) |
1402 | return; |
1403 | |
1404 | QtQrcFile *currentQrcFile = m_qrcManager->nextQrcFile(qrcFile: m_currentQrcFile); |
1405 | if (!currentQrcFile) |
1406 | currentQrcFile = m_qrcManager->prevQrcFile(qrcFile: m_currentQrcFile); |
1407 | |
1408 | m_qrcManager->removeQrcFile(qrcFile: m_currentQrcFile); |
1409 | QListWidgetItem *item = m_qrcFileToItem.value(akey: currentQrcFile); |
1410 | if (item) { |
1411 | m_ui.qrcFileList->setCurrentItem(item); |
1412 | item->setSelected(true); |
1413 | } |
1414 | } |
1415 | |
1416 | void QtResourceEditorDialogPrivate::slotMoveUpQrcFile() |
1417 | { |
1418 | if (!m_currentQrcFile) |
1419 | return; |
1420 | |
1421 | QtQrcFile *prevQrcFile = m_qrcManager->prevQrcFile(qrcFile: m_currentQrcFile); |
1422 | if (!prevQrcFile) |
1423 | return; |
1424 | |
1425 | m_qrcManager->moveQrcFile(qrcFile: m_currentQrcFile, beforeQrcFile: prevQrcFile); |
1426 | } |
1427 | |
1428 | void QtResourceEditorDialogPrivate::slotMoveDownQrcFile() |
1429 | { |
1430 | if (!m_currentQrcFile) |
1431 | return; |
1432 | |
1433 | QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile: m_currentQrcFile); |
1434 | if (!nextQrcFile) |
1435 | return; |
1436 | nextQrcFile = m_qrcManager->nextQrcFile(qrcFile: nextQrcFile); |
1437 | |
1438 | m_qrcManager->moveQrcFile(qrcFile: m_currentQrcFile, beforeQrcFile: nextQrcFile); |
1439 | } |
1440 | |
1441 | QtResourceFile *QtResourceEditorDialogPrivate::getCurrentResourceFile() const |
1442 | { |
1443 | QStandardItem *currentItem = m_treeModel->itemFromIndex(index: m_treeSelection->currentIndex()); |
1444 | |
1445 | |
1446 | QtResourceFile *currentResourceFile = nullptr; |
1447 | if (currentItem) { |
1448 | currentResourceFile = m_pathItemToResourceFile.value(akey: currentItem); |
1449 | if (!currentResourceFile) |
1450 | currentResourceFile = m_aliasItemToResourceFile.value(akey: currentItem); |
1451 | } |
1452 | return currentResourceFile; |
1453 | } |
1454 | |
1455 | QtResourcePrefix *QtResourceEditorDialogPrivate::getCurrentResourcePrefix() const |
1456 | { |
1457 | QStandardItem *currentItem = m_treeModel->itemFromIndex(index: m_treeSelection->currentIndex()); |
1458 | |
1459 | QtResourcePrefix *currentResourcePrefix = nullptr; |
1460 | if (currentItem) { |
1461 | currentResourcePrefix = m_prefixItemToResourcePrefix.value(akey: currentItem); |
1462 | if (!currentResourcePrefix) { |
1463 | currentResourcePrefix = m_languageItemToResourcePrefix.value(akey: currentItem); |
1464 | if (!currentResourcePrefix) { |
1465 | QtResourceFile *currentResourceFile = getCurrentResourceFile(); |
1466 | if (currentResourceFile) |
1467 | currentResourcePrefix = m_qrcManager->resourcePrefixOf(resourceFile: currentResourceFile); |
1468 | } |
1469 | } |
1470 | } |
1471 | return currentResourcePrefix; |
1472 | } |
1473 | |
1474 | void QtResourceEditorDialogPrivate::selectTreeRow(QStandardItem *item) |
1475 | { |
1476 | const QModelIndex index = m_treeModel->indexFromItem(item); |
1477 | m_treeSelection->select(index, command: QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); |
1478 | m_treeSelection->setCurrentIndex(index, command: QItemSelectionModel::Select); |
1479 | } |
1480 | |
1481 | void QtResourceEditorDialogPrivate::slotNewPrefix() |
1482 | { |
1483 | if (!m_currentQrcFile) |
1484 | return; |
1485 | |
1486 | QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix(); |
1487 | QtResourcePrefix *nextResourcePrefix = m_qrcManager->nextResourcePrefix(resourcePrefix: currentResourcePrefix); |
1488 | QtResourcePrefix *newResourcePrefix = m_qrcManager->insertResourcePrefix(qrcFile: m_currentQrcFile, |
1489 | prefix: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "newPrefix" ), |
1490 | language: QString(), beforeResourcePrefix: nextResourcePrefix); |
1491 | if (!newResourcePrefix) |
1492 | return; |
1493 | |
1494 | QStandardItem *newItem = m_resourcePrefixToPrefixItem.value(akey: newResourcePrefix); |
1495 | if (!newItem) |
1496 | return; |
1497 | |
1498 | const QModelIndex index = m_treeModel->indexFromItem(item: newItem); |
1499 | selectTreeRow(item: newItem); |
1500 | m_ui.resourceTreeView->edit(index); |
1501 | } |
1502 | |
1503 | static inline QString outOfPathWarning(const QString &fname) |
1504 | { |
1505 | return QApplication::translate(context: "QtResourceEditorDialog" , |
1506 | key: "<p><b>Warning:</b> The file</p>" |
1507 | "<p>%1</p>" |
1508 | "<p>is outside of the current resource file's parent directory.</p>" ).arg(a: fname); |
1509 | } |
1510 | |
1511 | static inline QString outOfPathWarningInfo() |
1512 | { |
1513 | return QApplication::translate(context: "QtResourceEditorDialog" , |
1514 | key: "<p>To resolve the issue, press:</p>" |
1515 | "<table>" |
1516 | "<tr><th align=\"left\">Copy</th><td>to copy the file to the resource file's parent directory.</td></tr>" |
1517 | "<tr><th align=\"left\">Copy As...</th><td>to copy the file into a subdirectory of the resource file's parent directory.</td></tr>" |
1518 | "<tr><th align=\"left\">Keep</th><td>to use its current location.</td></tr></table>" ); |
1519 | } |
1520 | |
1521 | void QtResourceEditorDialogPrivate::slotAddFiles() |
1522 | { |
1523 | if (!m_currentQrcFile) |
1524 | return; |
1525 | |
1526 | QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix(); |
1527 | QtResourceFile *currentResourceFile = getCurrentResourceFile(); |
1528 | if (!currentResourcePrefix) |
1529 | return; |
1530 | |
1531 | QString initialPath = m_currentQrcFile->path(); |
1532 | if (currentResourceFile) { |
1533 | QFileInfo fi(currentResourceFile->fullPath()); |
1534 | initialPath = fi.absolutePath(); |
1535 | } |
1536 | |
1537 | const QStringList resourcePaths = m_dlgGui->getOpenImageFileNames(parent: q_ptr, |
1538 | caption: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Add Files" ), |
1539 | dir: initialPath); |
1540 | if (resourcePaths.isEmpty()) |
1541 | return; |
1542 | |
1543 | QtResourceFile *nextResourceFile = m_qrcManager->nextResourceFile(resourceFile: currentResourceFile); |
1544 | if (!currentResourceFile) { |
1545 | const auto resourceFiles = currentResourcePrefix->resourceFiles(); |
1546 | if (resourceFiles.count() > 0) |
1547 | nextResourceFile = resourceFiles.first(); |
1548 | } |
1549 | |
1550 | const QFileInfo fi(m_currentQrcFile->path()); |
1551 | const QString destDir = fi.absolutePath(); |
1552 | const QDir dir(fi.absolutePath()); |
1553 | for (QString resourcePath : resourcePaths) { |
1554 | QString relativePath = dir.relativeFilePath(fileName: resourcePath); |
1555 | if (relativePath.startsWith(QStringLiteral(".." ))) { |
1556 | QMessageBox msgBox(QMessageBox::Warning, |
1557 | QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Incorrect Path" ), |
1558 | outOfPathWarning(fname: relativePath), QMessageBox::Cancel); |
1559 | msgBox.setInformativeText(outOfPathWarningInfo()); |
1560 | QPushButton *copyButton = msgBox.addButton(text: QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1561 | key: "Copy" ), role: QMessageBox::ActionRole); |
1562 | QPushButton *copyAsButton = msgBox.addButton(text: QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1563 | key: "Copy As..." ), role: QMessageBox::ActionRole); |
1564 | QPushButton *keepButton = msgBox.addButton(text: QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1565 | key: "Keep" ), role: QMessageBox::ActionRole); |
1566 | QPushButton *skipButton = msgBox.addButton(text: QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1567 | key: "Skip" ), role: QMessageBox::ActionRole); |
1568 | msgBox.setEscapeButton(QMessageBox::Cancel); |
1569 | msgBox.setDefaultButton(copyButton); |
1570 | msgBox.exec(); |
1571 | QString destPath; |
1572 | if (msgBox.clickedButton() == keepButton) { |
1573 | // nothing |
1574 | } else if (msgBox.clickedButton() == copyButton) { |
1575 | QFileInfo resInfo(resourcePath); |
1576 | QDir dd(destDir); |
1577 | destPath = dd.absoluteFilePath(fileName: resInfo.fileName()); |
1578 | if (dd.exists(name: resInfo.fileName())) { |
1579 | if (warning(title: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Copy" ), |
1580 | text: msgOverwrite(fname: resInfo.fileName()), |
1581 | buttons: QMessageBox::Yes | QMessageBox::Cancel, defaultButton: QMessageBox::Cancel) != QMessageBox::Yes) |
1582 | continue; |
1583 | } |
1584 | resourcePath = copyResourceFile(resourceFile: resourcePath, destPath); // returns empty string in case copy failed or was canceled |
1585 | } else if (msgBox.clickedButton() == copyAsButton) { |
1586 | destPath = browseForNewLocation(resourceFile: resourcePath, rootDir: dir); // returns empty string in case browsing was canceled |
1587 | if (destPath.isEmpty()) |
1588 | continue; |
1589 | resourcePath = copyResourceFile(resourceFile: resourcePath, destPath); // returns empty string in case copy failed or was canceled |
1590 | } else if (msgBox.clickedButton() == skipButton) { // skipped |
1591 | continue; |
1592 | } else { // canceled |
1593 | return; |
1594 | } |
1595 | if (resourcePath.isEmpty()) |
1596 | continue; |
1597 | } |
1598 | relativePath = dir.relativeFilePath(fileName: resourcePath); |
1599 | QtResourceFile *newResourceFile = m_qrcManager->insertResourceFile(resourcePrefix: currentResourcePrefix, path: relativePath, alias: QString(), beforeResourceFile: nextResourceFile); |
1600 | |
1601 | QStandardItem *newItem = m_resourceFileToPathItem.value(akey: newResourceFile); |
1602 | if (newItem) |
1603 | selectTreeRow(item: newItem); |
1604 | } |
1605 | } |
1606 | |
1607 | void QtResourceEditorDialogPrivate::slotChangePrefix() |
1608 | { |
1609 | QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix(); |
1610 | if (!currentResourcePrefix) |
1611 | return; |
1612 | |
1613 | QStandardItem *item = m_resourcePrefixToPrefixItem.value(akey: currentResourcePrefix); |
1614 | QModelIndex index = m_treeModel->indexFromItem(item); |
1615 | selectTreeRow(item); |
1616 | m_ui.resourceTreeView->scrollTo(index); |
1617 | m_ui.resourceTreeView->edit(index); |
1618 | } |
1619 | |
1620 | void QtResourceEditorDialogPrivate::slotChangeLanguage() |
1621 | { |
1622 | QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix(); |
1623 | if (!currentResourcePrefix) |
1624 | return; |
1625 | |
1626 | QStandardItem *item = m_resourcePrefixToLanguageItem.value(akey: currentResourcePrefix); |
1627 | QModelIndex index = m_treeModel->indexFromItem(item); |
1628 | selectTreeRow(item); |
1629 | m_ui.resourceTreeView->scrollTo(index); |
1630 | m_ui.resourceTreeView->edit(index); |
1631 | } |
1632 | |
1633 | void QtResourceEditorDialogPrivate::slotChangeAlias() |
1634 | { |
1635 | QtResourceFile *currentResourceFile = getCurrentResourceFile(); |
1636 | if (!currentResourceFile) |
1637 | return; |
1638 | |
1639 | QStandardItem *item = m_resourceFileToAliasItem.value(akey: currentResourceFile); |
1640 | QModelIndex index = m_treeModel->indexFromItem(item); |
1641 | selectTreeRow(item); |
1642 | m_ui.resourceTreeView->scrollTo(index); |
1643 | m_ui.resourceTreeView->edit(index); |
1644 | } |
1645 | |
1646 | void QtResourceEditorDialogPrivate::slotClonePrefix() |
1647 | { |
1648 | QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix(); |
1649 | if (!currentResourcePrefix) |
1650 | return; |
1651 | |
1652 | bool ok; |
1653 | QString suffix = QInputDialog::getText(parent: q_ptr, title: QApplication::translate(context: "QtResourceEditorDialog" , key: "Clone Prefix" ), |
1654 | label: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Enter the suffix which you want to add to the names of the cloned files.\n" |
1655 | "This could for example be a language extension like \"_de\"." ), |
1656 | echo: QLineEdit::Normal, text: QString(), ok: &ok); |
1657 | if (!ok) |
1658 | return; |
1659 | |
1660 | QtResourcePrefix *newResourcePrefix = m_qrcManager->insertResourcePrefix(qrcFile: m_currentQrcFile, prefix: currentResourcePrefix->prefix(), |
1661 | language: currentResourcePrefix->language(), beforeResourcePrefix: m_qrcManager->nextResourcePrefix(resourcePrefix: currentResourcePrefix)); |
1662 | if (newResourcePrefix) { |
1663 | const auto files = currentResourcePrefix->resourceFiles(); |
1664 | for (QtResourceFile *resourceFile : files) { |
1665 | QString path = resourceFile->path(); |
1666 | QFileInfo fi(path); |
1667 | QDir dir(fi.dir()); |
1668 | QString oldSuffix = fi.completeSuffix(); |
1669 | if (!oldSuffix.isEmpty()) |
1670 | oldSuffix = QLatin1Char('.') + oldSuffix; |
1671 | const QString newBaseName = fi.baseName() + suffix + oldSuffix; |
1672 | const QString newPath = QDir::cleanPath(path: dir.filePath(fileName: newBaseName)); |
1673 | m_qrcManager->insertResourceFile(resourcePrefix: newResourcePrefix, path: newPath, |
1674 | alias: resourceFile->alias()); |
1675 | } |
1676 | } |
1677 | } |
1678 | |
1679 | void QtResourceEditorDialogPrivate::slotRemove() |
1680 | { |
1681 | QStandardItem *item = m_treeModel->itemFromIndex(index: m_treeSelection->currentIndex()); |
1682 | if (!item) |
1683 | return; |
1684 | |
1685 | QtResourceFile *resourceFile = m_pathItemToResourceFile.value(akey: item); |
1686 | if (!resourceFile) |
1687 | resourceFile = m_aliasItemToResourceFile.value(akey: item); |
1688 | QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(akey: item); |
1689 | if (!resourcePrefix) |
1690 | resourcePrefix = m_languageItemToResourcePrefix.value(akey: item); |
1691 | |
1692 | QStandardItem *newCurrentItem = nullptr; |
1693 | |
1694 | if (resourceFile) { |
1695 | QtResourceFile *nextFile = m_qrcManager->nextResourceFile(resourceFile); |
1696 | if (!nextFile) |
1697 | nextFile = m_qrcManager->prevResourceFile(resourceFile); |
1698 | newCurrentItem = m_resourceFileToPathItem.value(akey: nextFile); |
1699 | if (!newCurrentItem) |
1700 | newCurrentItem = m_resourcePrefixToPrefixItem.value(akey: m_qrcManager->resourcePrefixOf(resourceFile)); |
1701 | } |
1702 | if (!newCurrentItem) { |
1703 | QtResourcePrefix *nextPrefix = m_qrcManager->nextResourcePrefix(resourcePrefix); |
1704 | if (!nextPrefix) |
1705 | nextPrefix = m_qrcManager->prevResourcePrefix(resourcePrefix); |
1706 | newCurrentItem = m_resourcePrefixToPrefixItem.value(akey: nextPrefix); |
1707 | } |
1708 | |
1709 | selectTreeRow(item: newCurrentItem); |
1710 | |
1711 | if (resourcePrefix) |
1712 | m_qrcManager->removeResourcePrefix(resourcePrefix); |
1713 | else if (resourceFile) |
1714 | m_qrcManager->removeResourceFile(resourceFile); |
1715 | } |
1716 | |
1717 | void QtResourceEditorDialogPrivate::slotMoveUp() |
1718 | { |
1719 | if (QtResourceFile *resourceFile = getCurrentResourceFile()) { |
1720 | QtResourceFile *prevFile = m_qrcManager->prevResourceFile(resourceFile); |
1721 | |
1722 | if (!prevFile) |
1723 | return; |
1724 | |
1725 | m_qrcManager->moveResourceFile(resourceFile, beforeResourceFile: prevFile); |
1726 | selectTreeRow(item: m_resourceFileToPathItem.value(akey: resourceFile)); |
1727 | } else if (QtResourcePrefix *resourcePrefix = getCurrentResourcePrefix()) { |
1728 | QtResourcePrefix *prevPrefix = m_qrcManager->prevResourcePrefix(resourcePrefix); |
1729 | |
1730 | if (!prevPrefix) |
1731 | return; |
1732 | |
1733 | m_qrcManager->moveResourcePrefix(resourcePrefix, beforeResourcePrefix: prevPrefix); |
1734 | selectTreeRow(item: m_resourcePrefixToPrefixItem.value(akey: resourcePrefix)); |
1735 | } |
1736 | } |
1737 | |
1738 | void QtResourceEditorDialogPrivate::slotMoveDown() |
1739 | { |
1740 | if (QtResourceFile *resourceFile = getCurrentResourceFile()) { |
1741 | QtResourceFile *nextFile = m_qrcManager->nextResourceFile(resourceFile); |
1742 | |
1743 | if (!nextFile) |
1744 | return; |
1745 | |
1746 | m_qrcManager->moveResourceFile(resourceFile, beforeResourceFile: m_qrcManager->nextResourceFile(resourceFile: nextFile)); |
1747 | selectTreeRow(item: m_resourceFileToPathItem.value(akey: resourceFile)); |
1748 | } else if (QtResourcePrefix *resourcePrefix = getCurrentResourcePrefix()) { |
1749 | QtResourcePrefix *nextPrefix = m_qrcManager->nextResourcePrefix(resourcePrefix); |
1750 | |
1751 | if (!nextPrefix) |
1752 | return; |
1753 | |
1754 | m_qrcManager->moveResourcePrefix(resourcePrefix, beforeResourcePrefix: m_qrcManager->nextResourcePrefix(resourcePrefix: nextPrefix)); |
1755 | selectTreeRow(item: m_resourcePrefixToPrefixItem.value(akey: resourcePrefix)); |
1756 | } |
1757 | } |
1758 | |
1759 | QString QtResourceEditorDialogPrivate::browseForNewLocation(const QString &resourceFile, const QDir &rootDir) const |
1760 | { |
1761 | QFileInfo fi(resourceFile); |
1762 | const QString initialPath = rootDir.absoluteFilePath(fileName: fi.fileName()); |
1763 | while (true) { |
1764 | QString newPath = m_dlgGui->getSaveFileName(parent: q_ptr, |
1765 | caption: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Copy As" ), |
1766 | dir: initialPath); |
1767 | QString relativePath = rootDir.relativeFilePath(fileName: newPath); |
1768 | if (relativePath.startsWith(QStringLiteral(".." ))) { |
1769 | if (warning(title: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Copy As" ), |
1770 | text: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "<p>The selected file:</p>" |
1771 | "<p>%1</p><p>is outside of the current resource file's directory:</p><p>%2</p>" |
1772 | "<p>Please select another path within this directory.<p>" ). |
1773 | arg(args&: relativePath, args: rootDir.absolutePath()), |
1774 | buttons: QMessageBox::Ok | QMessageBox::Cancel, defaultButton: QMessageBox::Ok) != QMessageBox::Ok) |
1775 | return QString(); |
1776 | } else { |
1777 | return newPath; |
1778 | } |
1779 | } |
1780 | |
1781 | return QString(); |
1782 | } |
1783 | |
1784 | QString QtResourceEditorDialogPrivate::copyResourceFile(const QString &resourceFile, const QString &destPath) const |
1785 | { |
1786 | QFileInfo fi(destPath); |
1787 | if (fi.exists()) { |
1788 | while (fi.exists() && !QFile::remove(fileName: destPath)) { |
1789 | if (warning(title: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Copy" ), |
1790 | text: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Could not overwrite %1." ).arg(a: fi.fileName()), |
1791 | buttons: QMessageBox::Retry | QMessageBox::Cancel, defaultButton: QMessageBox::Cancel) != QMessageBox::Retry) |
1792 | return QString(); |
1793 | } |
1794 | } |
1795 | while (!QFile::copy(fileName: resourceFile, newName: destPath)) { |
1796 | if (warning(title: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Copy" ), |
1797 | text: QCoreApplication::translate(context: "QtResourceEditorDialog" , key: "Could not copy\n%1\nto\n%2" ) |
1798 | .arg(a1: resourceFile, a2: destPath), |
1799 | buttons: QMessageBox::Retry | QMessageBox::Cancel, defaultButton: QMessageBox::Cancel) != QMessageBox::Retry) |
1800 | return QString(); |
1801 | } |
1802 | return destPath; |
1803 | } |
1804 | bool QtResourceEditorDialogPrivate::loadQrcFile(const QString &path, QtQrcFileData *qrcFileData) |
1805 | { |
1806 | QString errorMessage; |
1807 | const bool rc = loadQrcFile(path, qrcFileData, errorMessage: &errorMessage); |
1808 | // if (!rc) |
1809 | // warning(QApplication::translate("QtResourceEditorDialog", "Resource File Load Error"), errorMessage); |
1810 | return rc; |
1811 | } |
1812 | bool QtResourceEditorDialogPrivate::loadQrcFile(const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage) |
1813 | { |
1814 | if (!qrcFileData) |
1815 | return false; |
1816 | |
1817 | qrcFileData->qrcPath = path; |
1818 | |
1819 | QFile file(path); |
1820 | if (!file.open(flags: QIODevice::ReadOnly)) { |
1821 | // there is sufficient hint while loading a form and after opening the editor (qrc marked marked with red and with [missing] text) |
1822 | //*errorMessage = QApplication::translate("QtResourceEditorDialog", "Unable to open %1 for reading: %2").arg(path).arg(file.errorString()); |
1823 | return false; |
1824 | } |
1825 | |
1826 | QByteArray dataArray = file.readAll(); |
1827 | file.close(); |
1828 | |
1829 | QDomDocument doc; |
1830 | int errLine, errCol; |
1831 | if (!doc.setContent(text: dataArray, errorMsg: errorMessage, errorLine: &errLine, errorColumn: &errCol)) { |
1832 | *errorMessage = |
1833 | QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1834 | key: "A parse error occurred at line %1, column %2 of %3:\n%4" ) |
1835 | .arg(a: errLine).arg(a: errCol).arg(args: path, args&: *errorMessage); |
1836 | return false; |
1837 | } |
1838 | |
1839 | return loadQrcFileData(doc, path, qrcFileData, errorMessage); |
1840 | } |
1841 | |
1842 | bool QtResourceEditorDialogPrivate::saveQrcFile(const QtQrcFileData &qrcFileData) |
1843 | { |
1844 | QFile file(qrcFileData.qrcPath); |
1845 | while (!file.open(flags: QIODevice::WriteOnly)) { |
1846 | QMessageBox msgBox(QMessageBox::Warning, |
1847 | QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1848 | key: "Save Resource File" ), |
1849 | QCoreApplication::translate(context: "QtResourceEditorDialog" , |
1850 | key: "Could not write %1: %2" ) |
1851 | .arg(args: qrcFileData.qrcPath, |
1852 | args: file.errorString()), |
1853 | QMessageBox::Cancel|QMessageBox::Ignore|QMessageBox::Retry); |
1854 | msgBox.setEscapeButton(QMessageBox::Cancel); |
1855 | msgBox.setDefaultButton(QMessageBox::Ignore); |
1856 | switch (msgBox.exec()) { |
1857 | case QMessageBox::Retry: |
1858 | break; // nothing |
1859 | case QMessageBox::Ignore: |
1860 | return true; |
1861 | default: |
1862 | return false; |
1863 | } |
1864 | } |
1865 | |
1866 | QDomDocument doc = saveQrcFileData(qrcFileData); |
1867 | |
1868 | QByteArray dataArray = doc.toByteArray(2); |
1869 | file.write(data: dataArray); |
1870 | |
1871 | file.close(); |
1872 | return true; |
1873 | } |
1874 | |
1875 | QtResourceEditorDialog::QtResourceEditorDialog(QDesignerFormEditorInterface *core, QDesignerDialogGuiInterface *dlgGui, QWidget *parent) |
1876 | : QDialog(parent), d_ptr(new QtResourceEditorDialogPrivate()) |
1877 | { |
1878 | d_ptr->q_ptr = this; |
1879 | d_ptr->m_ui.setupUi(this); |
1880 | d_ptr->m_qrcManager = new QtQrcManager(this); |
1881 | d_ptr->m_dlgGui = dlgGui; |
1882 | d_ptr->m_core = core; |
1883 | |
1884 | setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); |
1885 | setWindowTitle(tr(s: "Edit Resources" )); |
1886 | |
1887 | connect(sender: d_ptr->m_qrcManager, SIGNAL(qrcFileInserted(QtQrcFile*)), |
1888 | receiver: this, SLOT(slotQrcFileInserted(QtQrcFile*))); |
1889 | connect(sender: d_ptr->m_qrcManager, SIGNAL(qrcFileMoved(QtQrcFile*,QtQrcFile*)), |
1890 | receiver: this, SLOT(slotQrcFileMoved(QtQrcFile*))); |
1891 | connect(sender: d_ptr->m_qrcManager, SIGNAL(qrcFileRemoved(QtQrcFile*)), |
1892 | receiver: this, SLOT(slotQrcFileRemoved(QtQrcFile*))); |
1893 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourcePrefixInserted(QtResourcePrefix*)), |
1894 | receiver: this, SLOT(slotResourcePrefixInserted(QtResourcePrefix*))); |
1895 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourcePrefixMoved(QtResourcePrefix*,QtResourcePrefix*)), |
1896 | receiver: this, SLOT(slotResourcePrefixMoved(QtResourcePrefix*))); |
1897 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourcePrefixChanged(QtResourcePrefix*,QString)), |
1898 | receiver: this, SLOT(slotResourcePrefixChanged(QtResourcePrefix*))); |
1899 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourceLanguageChanged(QtResourcePrefix*,QString)), |
1900 | receiver: this, SLOT(slotResourceLanguageChanged(QtResourcePrefix*))); |
1901 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourcePrefixRemoved(QtResourcePrefix*)), |
1902 | receiver: this, SLOT(slotResourcePrefixRemoved(QtResourcePrefix*))); |
1903 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourceFileInserted(QtResourceFile*)), |
1904 | receiver: this, SLOT(slotResourceFileInserted(QtResourceFile*))); |
1905 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourceFileMoved(QtResourceFile*,QtResourceFile*)), |
1906 | receiver: this, SLOT(slotResourceFileMoved(QtResourceFile*))); |
1907 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourceAliasChanged(QtResourceFile*,QString)), |
1908 | receiver: this, SLOT(slotResourceAliasChanged(QtResourceFile*))); |
1909 | connect(sender: d_ptr->m_qrcManager, SIGNAL(resourceFileRemoved(QtResourceFile*)), |
1910 | receiver: this, SLOT(slotResourceFileRemoved(QtResourceFile*))); |
1911 | |
1912 | QIcon upIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "up.png" )); |
1913 | QIcon downIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "down.png" )); |
1914 | QIcon minusIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "minus-16.png" )); |
1915 | QIcon newIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "filenew-16.png" )); |
1916 | QIcon openIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "fileopen-16.png" )); |
1917 | QIcon removeIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "editdelete-16.png" )); |
1918 | QIcon addPrefixIcon = qdesigner_internal::createIconSet(name: QString::fromUtf8(str: "prefix-add.png" )); |
1919 | |
1920 | d_ptr->m_newQrcFileAction = new QAction(newIcon, tr(s: "New..." ), this); |
1921 | d_ptr->m_newQrcFileAction->setToolTip(tr(s: "New Resource File" )); |
1922 | d_ptr->m_importQrcFileAction = new QAction(openIcon, tr(s: "Open..." ), this); |
1923 | d_ptr->m_importQrcFileAction->setToolTip(tr(s: "Open Resource File" )); |
1924 | d_ptr->m_removeQrcFileAction = new QAction(removeIcon, tr(s: "Remove" ), this); |
1925 | d_ptr->m_moveUpQrcFileAction = new QAction(upIcon, tr(s: "Move Up" ), this); |
1926 | d_ptr->m_moveDownQrcFileAction = new QAction(downIcon, tr(s: "Move Down" ), this); |
1927 | |
1928 | d_ptr->m_newPrefixAction = new QAction(addPrefixIcon, tr(s: "Add Prefix" ), this); |
1929 | d_ptr->m_newPrefixAction->setToolTip(tr(s: "Add Prefix" )); |
1930 | d_ptr->m_addResourceFileAction = new QAction(openIcon, tr(s: "Add Files..." ), this); |
1931 | d_ptr->m_changePrefixAction = new QAction(tr(s: "Change Prefix" ), this); |
1932 | d_ptr->m_changeLanguageAction = new QAction(tr(s: "Change Language" ), this); |
1933 | d_ptr->m_changeAliasAction = new QAction(tr(s: "Change Alias" ), this); |
1934 | d_ptr->m_clonePrefixAction = new QAction(tr(s: "Clone Prefix..." ), this); |
1935 | d_ptr->m_removeAction = new QAction(minusIcon, tr(s: "Remove" ), this); |
1936 | d_ptr->m_moveUpAction = new QAction(upIcon, tr(s: "Move Up" ), this); |
1937 | d_ptr->m_moveDownAction = new QAction(downIcon, tr(s: "Move Down" ), this); |
1938 | |
1939 | d_ptr->m_ui.newQrcButton->setDefaultAction(d_ptr->m_newQrcFileAction); |
1940 | d_ptr->m_ui.importQrcButton->setDefaultAction(d_ptr->m_importQrcFileAction); |
1941 | d_ptr->m_ui.removeQrcButton->setDefaultAction(d_ptr->m_removeQrcFileAction); |
1942 | |
1943 | d_ptr->m_ui.newResourceButton->setDefaultAction(d_ptr->m_newPrefixAction); |
1944 | d_ptr->m_ui.addResourceButton->setDefaultAction(d_ptr->m_addResourceFileAction); |
1945 | d_ptr->m_ui.removeResourceButton->setDefaultAction(d_ptr->m_removeAction); |
1946 | |
1947 | connect(sender: d_ptr->m_newQrcFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotNewQrcFile())); |
1948 | connect(sender: d_ptr->m_importQrcFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotImportQrcFile())); |
1949 | connect(sender: d_ptr->m_removeQrcFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotRemoveQrcFile())); |
1950 | connect(sender: d_ptr->m_moveUpQrcFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotMoveUpQrcFile())); |
1951 | connect(sender: d_ptr->m_moveDownQrcFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotMoveDownQrcFile())); |
1952 | |
1953 | connect(sender: d_ptr->m_newPrefixAction, SIGNAL(triggered()), receiver: this, SLOT(slotNewPrefix())); |
1954 | connect(sender: d_ptr->m_addResourceFileAction, SIGNAL(triggered()), receiver: this, SLOT(slotAddFiles())); |
1955 | connect(sender: d_ptr->m_changePrefixAction, SIGNAL(triggered()), receiver: this, SLOT(slotChangePrefix())); |
1956 | connect(sender: d_ptr->m_changeLanguageAction, SIGNAL(triggered()), receiver: this, SLOT(slotChangeLanguage())); |
1957 | connect(sender: d_ptr->m_changeAliasAction, SIGNAL(triggered()), receiver: this, SLOT(slotChangeAlias())); |
1958 | connect(sender: d_ptr->m_clonePrefixAction, SIGNAL(triggered()), receiver: this, SLOT(slotClonePrefix())); |
1959 | connect(sender: d_ptr->m_removeAction, SIGNAL(triggered()), receiver: this, SLOT(slotRemove())); |
1960 | connect(sender: d_ptr->m_moveUpAction, SIGNAL(triggered()), receiver: this, SLOT(slotMoveUp())); |
1961 | connect(sender: d_ptr->m_moveDownAction, SIGNAL(triggered()), receiver: this, SLOT(slotMoveDown())); |
1962 | |
1963 | d_ptr->m_ui.qrcFileList->setContextMenuPolicy(Qt::CustomContextMenu); |
1964 | connect(sender: d_ptr->m_ui.qrcFileList, SIGNAL(customContextMenuRequested(QPoint)), |
1965 | receiver: this, SLOT(slotListWidgetContextMenuRequested(QPoint))); |
1966 | connect(sender: d_ptr->m_ui.qrcFileList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), |
1967 | receiver: this, SLOT(slotCurrentQrcFileChanged(QListWidgetItem*))); |
1968 | |
1969 | d_ptr->m_treeModel = new QStandardItemModel(this); |
1970 | d_ptr->m_treeModel->setColumnCount(2); |
1971 | d_ptr->m_treeModel->setHorizontalHeaderItem(column: 0, item: new QStandardItem(tr(s: "Prefix / Path" ))); |
1972 | d_ptr->m_treeModel->setHorizontalHeaderItem(column: 1, item: new QStandardItem(tr(s: "Language / Alias" ))); |
1973 | d_ptr->m_ui.resourceTreeView->setModel(d_ptr->m_treeModel); |
1974 | d_ptr->m_ui.resourceTreeView->setContextMenuPolicy(Qt::CustomContextMenu); |
1975 | d_ptr->m_treeSelection = d_ptr->m_ui.resourceTreeView->selectionModel(); |
1976 | connect(sender: d_ptr->m_ui.resourceTreeView->header(), signal: &QHeaderView::sectionDoubleClicked, |
1977 | receiver: d_ptr->m_ui.resourceTreeView, slot: &QTreeView::resizeColumnToContents); |
1978 | d_ptr->m_ui.resourceTreeView->setTextElideMode(Qt::ElideLeft); |
1979 | |
1980 | connect(sender: d_ptr->m_ui.resourceTreeView, SIGNAL(customContextMenuRequested(QPoint)), |
1981 | receiver: this, SLOT(slotTreeViewContextMenuRequested(QPoint))); |
1982 | connect(sender: d_ptr->m_treeModel, SIGNAL(itemChanged(QStandardItem*)), |
1983 | receiver: this, SLOT(slotTreeViewItemChanged(QStandardItem*))); |
1984 | connect(sender: d_ptr->m_treeSelection, SIGNAL(currentChanged(QModelIndex,QModelIndex)), |
1985 | receiver: this, SLOT(slotCurrentTreeViewItemChanged(QModelIndex))); |
1986 | |
1987 | d_ptr->m_ui.resourceTreeView->setColumnWidth(column: 0, width: 200); |
1988 | |
1989 | d_ptr->slotCurrentTreeViewItemChanged(index: QModelIndex()); |
1990 | d_ptr->m_removeQrcFileAction->setEnabled(false); |
1991 | d_ptr->m_moveUpQrcFileAction->setEnabled(false); |
1992 | d_ptr->m_moveDownQrcFileAction->setEnabled(false); |
1993 | |
1994 | QDesignerSettingsInterface *settings = core->settingsManager(); |
1995 | settings->beginGroup(prefix: QLatin1String(QrcDialogC)); |
1996 | |
1997 | d_ptr->m_ui.splitter->restoreState(state: settings->value(key: QLatin1String(SplitterPosition)).toByteArray()); |
1998 | const QVariant geometry = settings->value(key: QLatin1String(Geometry)); |
1999 | if (geometry.type() == QVariant::ByteArray) // Used to be a QRect up until 5.4.0, QTBUG-43374 |
2000 | restoreGeometry(geometry: geometry.toByteArray()); |
2001 | |
2002 | settings->endGroup(); |
2003 | } |
2004 | |
2005 | QtResourceEditorDialog::~QtResourceEditorDialog() |
2006 | { |
2007 | QDesignerSettingsInterface *settings = d_ptr->m_core->settingsManager(); |
2008 | settings->beginGroup(prefix: QLatin1String(QrcDialogC)); |
2009 | |
2010 | settings->setValue(key: QLatin1String(SplitterPosition), value: d_ptr->m_ui.splitter->saveState()); |
2011 | settings->setValue(key: QLatin1String(Geometry), value: saveGeometry()); |
2012 | settings->endGroup(); |
2013 | } |
2014 | |
2015 | QtResourceModel *QtResourceEditorDialog::model() const |
2016 | { |
2017 | return d_ptr->m_resourceModel; |
2018 | } |
2019 | |
2020 | void QtResourceEditorDialog::setResourceModel(QtResourceModel *model) |
2021 | { |
2022 | d_ptr->m_resourceModel = model; |
2023 | |
2024 | QtResourceSet *resourceSet = d_ptr->m_resourceModel->currentResourceSet(); |
2025 | if (!resourceSet) { |
2026 | // disable everything but cancel button |
2027 | return; |
2028 | } |
2029 | |
2030 | d_ptr->m_initialState.clear(); |
2031 | |
2032 | // enable qrcBox |
2033 | |
2034 | const QStringList paths = resourceSet->activeResourceFilePaths(); |
2035 | for (const QString &path : paths) { |
2036 | QtQrcFileData qrcFileData; |
2037 | d_ptr->loadQrcFile(path, qrcFileData: &qrcFileData); |
2038 | d_ptr->m_initialState << qrcFileData; |
2039 | d_ptr->m_qrcManager->importQrcFile(qrcFileData); |
2040 | } |
2041 | if (d_ptr->m_ui.qrcFileList->count() > 0) { |
2042 | d_ptr->m_ui.qrcFileList->item(row: 0)->setSelected(true); |
2043 | } |
2044 | } |
2045 | |
2046 | QString QtResourceEditorDialog::selectedResource() const |
2047 | { |
2048 | //QtResourcePrefix *currentResourcePrefix = d_ptr->m_qrcManager->resourcePrefixOf(currentResourceFile); |
2049 | QtResourcePrefix *currentResourcePrefix = d_ptr->getCurrentResourcePrefix(); |
2050 | if (!currentResourcePrefix) |
2051 | return QString(); |
2052 | |
2053 | const QChar slash(QLatin1Char('/')); |
2054 | QString resource = currentResourcePrefix->prefix(); |
2055 | if (!resource.startsWith(c: slash)) |
2056 | resource.prepend(c: slash); |
2057 | if (!resource.endsWith(c: slash)) |
2058 | resource.append(c: slash); |
2059 | resource.prepend(c: QLatin1Char(':')); |
2060 | |
2061 | QtResourceFile *currentResourceFile = d_ptr->getCurrentResourceFile(); |
2062 | if (!currentResourceFile) |
2063 | return resource; |
2064 | |
2065 | QString resourceEnding = currentResourceFile->path(); |
2066 | if (!currentResourceFile->alias().isEmpty()) |
2067 | resourceEnding = currentResourceFile->alias(); |
2068 | |
2069 | const QString dotSlash(QStringLiteral("./" )); |
2070 | const QString dotDotSlash(QStringLiteral("../" )); |
2071 | while (true) { |
2072 | if (resourceEnding.startsWith(c: slash)) |
2073 | resourceEnding = resourceEnding.mid(position: 1); |
2074 | else if (resourceEnding.startsWith(s: dotSlash)) |
2075 | resourceEnding = resourceEnding.mid(position: dotSlash.count()); |
2076 | else if (resourceEnding.startsWith(s: dotDotSlash)) |
2077 | resourceEnding = resourceEnding.mid(position: dotDotSlash.count()); |
2078 | else |
2079 | break; |
2080 | } |
2081 | |
2082 | resource.append(s: resourceEnding); |
2083 | |
2084 | return resource; |
2085 | } |
2086 | |
2087 | void QtResourceEditorDialog::displayResourceFailures(const QString &logOutput, QDesignerDialogGuiInterface *dlgGui, QWidget *parent) |
2088 | { |
2089 | const QString msg = tr(s: "<html><p><b>Warning:</b> There have been problems while reloading the resources:</p><pre>%1</pre></html>" ).arg(a: logOutput); |
2090 | dlgGui->message(parent, context: QDesignerDialogGuiInterface::ResourceEditorMessage, icon: QMessageBox::Warning, |
2091 | title: tr(s: "Resource Warning" ), text: msg); |
2092 | } |
2093 | |
2094 | void QtResourceEditorDialog::accept() |
2095 | { |
2096 | QStringList newQrcPaths; |
2097 | QList<QtQrcFileData> currentState; |
2098 | |
2099 | const auto qrcFiles = d_ptr->m_qrcManager->qrcFiles(); |
2100 | for (QtQrcFile *qrcFile : qrcFiles) { |
2101 | QtQrcFileData qrcFileData; |
2102 | d_ptr->m_qrcManager->exportQrcFile(qrcFile, qrcFileData: &qrcFileData); |
2103 | currentState << qrcFileData; |
2104 | if (qrcFileData == qrcFile->initialState()) { |
2105 | // nothing |
2106 | } else { |
2107 | d_ptr->m_resourceModel->setWatcherEnabled(path: qrcFileData.qrcPath, enable: false); |
2108 | bool ok = d_ptr->saveQrcFile(qrcFileData); |
2109 | d_ptr->m_resourceModel->setWatcherEnabled(path: qrcFileData.qrcPath, enable: true); |
2110 | if (!ok) |
2111 | return; |
2112 | |
2113 | d_ptr->m_resourceModel->setModified(qrcFileData.qrcPath); |
2114 | } |
2115 | newQrcPaths << qrcFileData.qrcPath; |
2116 | } |
2117 | |
2118 | if (currentState == d_ptr->m_initialState) { |
2119 | // nothing |
2120 | } else { |
2121 | int errorCount; |
2122 | QString errorMessages; |
2123 | d_ptr->m_resourceModel->currentResourceSet()->activateResourceFilePaths(paths: newQrcPaths, errorCount: &errorCount, errorMessages: &errorMessages); |
2124 | if (errorCount) |
2125 | displayResourceFailures(logOutput: errorMessages, dlgGui: d_ptr->m_dlgGui, parent: this); |
2126 | } |
2127 | QDialog::accept(); |
2128 | } |
2129 | |
2130 | QString QtResourceEditorDialog::editResources(QDesignerFormEditorInterface *core, |
2131 | QtResourceModel *model, |
2132 | QDesignerDialogGuiInterface *dlgGui, |
2133 | QWidget *parent) |
2134 | { |
2135 | QtResourceEditorDialog dialog(core, dlgGui, parent); |
2136 | dialog.setResourceModel(model); |
2137 | if (dialog.exec() == QDialog::Accepted) |
2138 | return dialog.selectedResource(); |
2139 | return QString(); |
2140 | } |
2141 | |
2142 | QT_END_NAMESPACE |
2143 | |
2144 | #include "moc_qtresourceeditordialog_p.cpp" |
2145 | #include "qtresourceeditordialog.moc" |
2146 | |