From fc85c52b992bf9561344db7307436c53808f0f2d Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 8 Jun 2021 12:43:09 +0200 Subject: [PATCH] QmlDesigner: Allow removing files from generate resource User can remove unwanted files when he/she is generating the .qmlrc resource file using Generate Resource option from the build menu. User can uncheck the files from the file list in the appeared table widget. Also unnecessary git-files and temporary files are filtered out. Task-number: QDS-4430 Change-Id: I45fa0f42bf3a1f7fc7583a9ce29c324c8e7cf9cd Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/generateresource.cpp | 178 ++++++++++++++++++- src/plugins/qmldesigner/generateresource.h | 4 +- 2 files changed, 175 insertions(+), 7 deletions(-) diff --git a/src/plugins/qmldesigner/generateresource.cpp b/src/plugins/qmldesigner/generateresource.cpp index 6925092b539..68f159db1d3 100644 --- a/src/plugins/qmldesigner/generateresource.cpp +++ b/src/plugins/qmldesigner/generateresource.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -47,14 +48,94 @@ #include #include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QmlDesigner { + +QTableWidget* GenerateResource::createFilesTable(const QStringList &fileNames) +{ + auto table = new QTableWidget(0, 1); + table->setSelectionMode(QAbstractItemView::SingleSelection); + + QStringList labels(QCoreApplication::translate("AddImageToResources","File Name")); + table->setHorizontalHeaderLabels(labels); + table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + table->verticalHeader()->hide(); + table->setShowGrid(false); + + for (const QString &filePath : fileNames) { + auto checkboxItem = new QTableWidgetItem(); + checkboxItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + checkboxItem->setCheckState(Qt::Checked); + checkboxItem->setText(filePath); + + int row = table->rowCount(); + table->insertRow(row); + table->setItem(row, 0, checkboxItem); + } + + return table; +} + +QStringList GenerateResource::getFileList(const QStringList &fileNames) +{ + QStringList result; + QDialog *dialog = new QDialog(Core::ICore::dialogParent()); + dialog->setMinimumWidth(480); + + dialog->setModal(true); + dialog->setWindowTitle(QCoreApplication::translate("AddImageToResources","Add Resources")); + QTableWidget *table = createFilesTable(fileNames); + + table->setParent(dialog); + auto mainLayout = new QGridLayout(dialog); + mainLayout->addWidget(table, 0, 0, 1, 4); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel); + + mainLayout->addWidget(buttonBox, 3, 2, 1, 2); + + QObject::connect(buttonBox, &QDialogButtonBox::accepted, dialog, [dialog](){ + dialog->accept(); + dialog->deleteLater(); + }); + + QObject::connect(buttonBox, &QDialogButtonBox::rejected, dialog, [dialog](){ + dialog->reject(); + dialog->deleteLater(); + }); + + QObject::connect(dialog, &QDialog::accepted, [&result, &table](){ + QStringList fileList; + QString file; + + for (int i = 0; i < table->rowCount(); ++i){ + if (table->item(i,0)->checkState()){ + file = table->item(i,0)->text(); + fileList.append(file); + } + } + + result = fileList; + }); + + dialog->exec(); + + return result; +} + void GenerateResource::generateMenuEntry() { Core::ActionContainer *buildMenu = @@ -107,9 +188,94 @@ void GenerateResource::generateMenuEntry() rccProcess.setWorkingDirectory(projectPath); const QStringList arguments1 = {"--project", "--output", temp.fileName()}; - const QStringList arguments2 = {"--binary", "--output", resourceFileName, temp.fileName()}; - for (const auto &arguments : {arguments1, arguments2}) { + for (const auto &arguments : {arguments1}) { + rccProcess.setCommand({rccBinary, arguments}); + rccProcess.start(); + if (!rccProcess.waitForStarted()) { + Core::MessageManager::writeDisrupting( + QCoreApplication::translate("QmlDesigner::GenerateResource", + "Unable to generate resource file: %1") + .arg(resourceFileName)); + return; + } + QByteArray stdOut; + QByteArray stdErr; + if (!rccProcess.readDataFromProcess(30, &stdOut, &stdErr, true)) { + rccProcess.stopProcess(); + Core::MessageManager::writeDisrupting( + QCoreApplication::translate("QmlDesigner::GenerateResource", + "A timeout occurred running \"%1\"") + .arg(rccBinary + " " + arguments.join(" "))); + return; + } + if (!stdOut.trimmed().isEmpty()) { + Core::MessageManager::writeFlashing(QString::fromLocal8Bit(stdOut)); + } + if (!stdErr.trimmed().isEmpty()) + Core::MessageManager::writeFlashing(QString::fromLocal8Bit(stdErr)); + + if (rccProcess.exitStatus() != QProcess::NormalExit) { + Core::MessageManager::writeDisrupting( + QCoreApplication::translate("QmlDesigner::GenerateResource", "\"%1\" crashed.") + .arg(rccBinary + " " + arguments.join(" "))); + return; + } + if (rccProcess.exitCode() != 0) { + Core::MessageManager::writeDisrupting( + QCoreApplication::translate("QmlDesigner::GenerateResource", + "\"%1\" failed (exit code %2).") + .arg(rccBinary + " " + arguments.join(" ")) + .arg(rccProcess.exitCode())); + return; + } + + } + + if (!temp.open()) + return; + + QXmlStreamReader reader(&temp); + QStringList fileList = {}; + QByteArray firstLine = temp.readLine(); + + while (!reader.atEnd()) { + const auto token = reader.readNext(); + + if (token != QXmlStreamReader::StartElement) + continue; + + if (reader.name() == QLatin1String("file")) { + QString fileName = reader.readElementText().trimmed(); + if ((!fileName.startsWith("./.")) && (!fileName.startsWith("./XXXXXXX"))) + fileList.append(fileName); + } + } + + temp.close(); + QStringList modifiedList = getFileList(fileList); + QTemporaryFile tempFile(projectPath + "/XXXXXXX.create.modifiedresource.qrc"); + + if (!tempFile.open()) + return; + + QXmlStreamWriter writer(&tempFile); + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(0); + + tempFile.write(firstLine.trimmed()); + writer.writeStartElement("qresource"); + + for (int i = 0; i < modifiedList.count(); ++i) + writer.writeTextElement("file", modifiedList.at(i).trimmed()); + + writer.writeEndElement(); + tempFile.write("\n\n"); + tempFile.close(); + + const QStringList arguments2 = {"--binary", "--output", resourceFileName, tempFile.fileName()}; + + for (const auto &arguments : {arguments2}) { rccProcess.setCommand({rccBinary, arguments}); rccProcess.start(); if (!rccProcess.waitForStarted()) { diff --git a/src/plugins/qmldesigner/generateresource.h b/src/plugins/qmldesigner/generateresource.h index 4b4dadf9e84..f6030e1c0c4 100644 --- a/src/plugins/qmldesigner/generateresource.h +++ b/src/plugins/qmldesigner/generateresource.h @@ -24,10 +24,12 @@ ****************************************************************************/ #pragma once - +#include namespace QmlDesigner { namespace GenerateResource { void generateMenuEntry(); + QStringList getFileList(const QStringList &); + QTableWidget* createFilesTable(const QStringList &); } } // namespace QmlDesigner