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 <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Thomas Hartmann
2021-06-08 12:43:09 +02:00
parent 1456dbb2fa
commit fc85c52b99
2 changed files with 175 additions and 7 deletions

View File

@@ -30,6 +30,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/icore.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
@@ -47,14 +48,94 @@
#include <utils/qtcprocess.h>
#include <QAction>
#include <QTemporaryFile>
#include <QMap>
#include <QProcess>
#include <QByteArray>
#include <QObject>
#include <QCheckBox>
#include <QDebug>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QGridLayout>
#include <QHeaderView>
#include <QMap>
#include <QObject>
#include <QProcess>
#include <QTemporaryFile>
#include <QXmlStreamReader>
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</RCC>\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()) {