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
50QT_BEGIN_NAMESPACE
51
52static const char *rccRootTag = "RCC";
53static const char *rccTag = "qresource";
54static const char *rccFileTag = "file";
55static const char *rccAliasAttribute = "alias";
56static const char *rccPrefixAttribute = "prefix";
57static const char *rccLangAttribute = "lang";
58static const char *SplitterPosition = "SplitterPosition";
59static const char *Geometry = "Geometry";
60static const char *QrcDialogC = "QrcDialog";
61
62static 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
67static 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
72namespace {
73
74// below 3 data classes should be derived from QSharedData and made implicit shared class
75struct QtResourceFileData {
76 QString path;
77 QString alias;
78 bool operator==(const QtResourceFileData &other) const
79 { return path == other.path && alias == other.alias; }
80};
81
82struct 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
93struct 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
100bool 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
118static 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
143static 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
170QDomElement 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
182QDomElement 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
198QDomDocument 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
212class QtResourceFile {
213public:
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; }
219private:
220 QtResourceFile() = default;
221
222 QString m_path;
223 QString m_alias;
224 QString m_fullPath;
225};
226
227class QtResourcePrefix {
228public:
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; }
234private:
235 QtResourcePrefix() = default;
236
237 QString m_prefix;
238 QString m_language;
239 QList<QtResourceFile *> m_resourceFiles;
240
241};
242// ------------------- QtQrcFile
243class QtQrcFile {
244public:
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
252private:
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
268class QtQrcManager : public QObject
269{
270 Q_OBJECT
271public:
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
298public 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
318signals:
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);
333private:
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
345QtQrcManager::QtQrcManager(QObject *parent)
346 : QObject(parent)
347{
348
349}
350
351QtQrcManager::~QtQrcManager()
352{
353 clear();
354}
355
356QList<QtQrcFile *> QtQrcManager::qrcFiles() const
357{
358 return m_qrcFiles;
359}
360
361QtQrcFile *QtQrcManager::qrcFileOf(const QString &path) const
362{
363 return m_pathToQrc.value(akey: path);
364}
365
366QtQrcFile *QtQrcManager::qrcFileOf(QtResourcePrefix *resourcePrefix) const
367{
368 return m_prefixToQrc.value(akey: resourcePrefix);
369}
370
371QtResourcePrefix *QtQrcManager::resourcePrefixOf(QtResourceFile *resourceFile) const
372{
373 return m_fileToPrefix.value(akey: resourceFile);
374}
375
376QtQrcFile *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
390void 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
424QIcon QtQrcManager::icon(const QString &resourceFullPath) const
425{
426 return m_fullPathToIcon.value(akey: resourceFullPath);
427}
428
429bool QtQrcManager::exists(const QString &resourceFullPath) const
430{
431 return m_fullPathToExists.value(akey: resourceFullPath, adefaultValue: false);
432}
433
434bool QtQrcManager::exists(QtQrcFile *qrcFile) const
435{
436 return m_qrcFileToExists.value(akey: qrcFile, adefaultValue: false);
437}
438
439QtQrcFile *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
449QtQrcFile *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
459QtResourcePrefix *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
470QtResourcePrefix *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
481QtResourceFile *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
492QtResourceFile *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
503void QtQrcManager::clear()
504{
505 const auto oldQrcFiles = qrcFiles();
506 for (QtQrcFile *qf : oldQrcFiles)
507 removeQrcFile(qrcFile: qf);
508}
509
510QtQrcFile *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
532void 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
561void QtQrcManager::setInitialState(QtQrcFile *qrcFile, const QtQrcFileData &initialState)
562{
563 qrcFile->m_initialState = initialState;
564}
565
566void 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
584QtResourcePrefix *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
605void 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
639void 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
653void 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
667void 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
686QtResourceFile *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
717void 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
751void 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
765void 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
792class QtResourceEditorDialogPrivate
793{
794 QtResourceEditorDialog *q_ptr;
795 Q_DECLARE_PUBLIC(QtResourceEditorDialog)
796public:
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
897QMessageBox::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
903QString 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
915void 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
939void 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
960void 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
972QStandardItem *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
1003void 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
1028void 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
1043void 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
1057void 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
1078void 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
1117void 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
1140void 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
1154void 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
1178void 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
1220void 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
1257void QtResourceEditorDialogPrivate::slotListWidgetContextMenuRequested(const QPoint &pos)
1258{
1259 QMenu menu(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
1269void QtResourceEditorDialogPrivate::slotTreeViewContextMenuRequested(const QPoint &pos)
1270{
1271 QMenu menu(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
1287void 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
1312QString 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
1341QString 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
1349void 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
1374void 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
1399void 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
1416void 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
1428void 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
1441QtResourceFile *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
1455QtResourcePrefix *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
1474void 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
1481void 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
1503static 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
1511static 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
1521void 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
1607void 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
1620void 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
1633void 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
1646void 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
1679void 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
1717void 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
1738void 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
1759QString 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
1784QString 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}
1804bool 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}
1812bool 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
1842bool 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
1875QtResourceEditorDialog::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
2005QtResourceEditorDialog::~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
2015QtResourceModel *QtResourceEditorDialog::model() const
2016{
2017 return d_ptr->m_resourceModel;
2018}
2019
2020void 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
2046QString 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
2087void 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
2094void 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
2130QString 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
2142QT_END_NAMESPACE
2143
2144#include "moc_qtresourceeditordialog_p.cpp"
2145#include "qtresourceeditordialog.moc"
2146

source code of qttools/src/designer/src/lib/shared/qtresourceeditordialog.cpp