| 1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. | 
|---|
| 2 | // | 
|---|
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later | 
|---|
| 4 |  | 
|---|
| 5 | #include "binarytoolsdialog.h" | 
|---|
| 6 | #include "binarytoolsconfigview.h" | 
|---|
| 7 | #include "common/util/eventdefinitions.h" | 
|---|
| 8 |  | 
|---|
| 9 | #include <QPushButton> | 
|---|
| 10 | #include <QDialogButtonBox> | 
|---|
| 11 | #include <QProcess> | 
|---|
| 12 | #include <QBoxLayout> | 
|---|
| 13 | #include <QTextBlock> | 
|---|
| 14 |  | 
|---|
| 15 | class BinaryToolsDialogPrivate | 
|---|
| 16 | { | 
|---|
| 17 | friend class BinaryToolsDialog; | 
|---|
| 18 | BinaryToolsConfigView *configView = nullptr; | 
|---|
| 19 | QDialogButtonBox *buttons = nullptr; | 
|---|
| 20 | }; | 
|---|
| 21 |  | 
|---|
| 22 | BinaryToolsDialog::BinaryToolsDialog(QDialog *parent) | 
|---|
| 23 | : QDialog(parent) | 
|---|
| 24 | , d (new BinaryToolsDialogPrivate) | 
|---|
| 25 | { | 
|---|
| 26 | setWindowTitle(tr( "Binary Tools")); | 
|---|
| 27 |  | 
|---|
| 28 | QVBoxLayout *vLayout = new QVBoxLayout(this); | 
|---|
| 29 | vLayout->setContentsMargins(20, 20, 20, 20); | 
|---|
| 30 | vLayout->setSpacing(6); | 
|---|
| 31 |  | 
|---|
| 32 | d->configView = new BinaryToolsConfigView; | 
|---|
| 33 | vLayout->addWidget(d->configView); | 
|---|
| 34 | vLayout->addStretch(); | 
|---|
| 35 |  | 
|---|
| 36 | QHBoxLayout * buttonLayout = new QHBoxLayout(); | 
|---|
| 37 | d->buttons = new QDialogButtonBox(this); | 
|---|
| 38 | d->buttons->setStandardButtons(QDialogButtonBox::Apply | QDialogButtonBox::Save | QDialogButtonBox::Cancel); | 
|---|
| 39 | d->buttons->button(QDialogButtonBox::Apply)->setText(tr( "Use Tool")); | 
|---|
| 40 | d->buttons->button(QDialogButtonBox::Save)->setText(tr( "Save")); | 
|---|
| 41 | d->buttons->button(QDialogButtonBox::Cancel)->setText(tr( "Cancel")); | 
|---|
| 42 | d->buttons->button(QDialogButtonBox::Apply)->setDefault(true); | 
|---|
| 43 | buttonLayout->addWidget(d->buttons); | 
|---|
| 44 | vLayout->addLayout(buttonLayout); | 
|---|
| 45 |  | 
|---|
| 46 | connect(d->configView, &BinaryToolsConfigView::useCombinationCommand, [=](){ | 
|---|
| 47 | QtConcurrent::run([=](){ | 
|---|
| 48 | useClicked(); | 
|---|
| 49 | }); | 
|---|
| 50 | }); | 
|---|
| 51 | connect(d->buttons->button(QDialogButtonBox::Apply), &QPushButton::clicked, [=](){ | 
|---|
| 52 | QtConcurrent::run([=](){ | 
|---|
| 53 | useClicked(); | 
|---|
| 54 | }); | 
|---|
| 55 | }); | 
|---|
| 56 | connect(d->buttons->button(QDialogButtonBox::Save), &QPushButton::clicked, this, &BinaryToolsDialog::saveClicked); | 
|---|
| 57 | connect(d->buttons, &QDialogButtonBox::rejected, this, &BinaryToolsDialog::reject); | 
|---|
| 58 | connect(d->buttons, &QDialogButtonBox::accepted, this, &BinaryToolsDialog::accept); | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | BinaryToolsDialog::~BinaryToolsDialog() | 
|---|
| 62 | { | 
|---|
| 63 | if (d) | 
|---|
| 64 | delete d; | 
|---|
| 65 | } | 
|---|
| 66 |  | 
|---|
| 67 | void BinaryToolsDialog::printOutput(const QString &content, OutputPane::OutputFormat format) | 
|---|
| 68 | { | 
|---|
| 69 | editor.switchContext(tr( "&Application Output")); | 
|---|
| 70 | auto outputPane = OutputPane::instance(); | 
|---|
| 71 | QString outputContent = content; | 
|---|
| 72 | if (format == OutputPane::OutputFormat::NormalMessage) { | 
|---|
| 73 | QTextDocument *doc = outputPane->document(); | 
|---|
| 74 | QTextBlock tb = doc->lastBlock(); | 
|---|
| 75 | QString lastLineText = tb.text(); | 
|---|
| 76 | QString prefix = "\n"; | 
|---|
| 77 | if (lastLineText.isEmpty()) { | 
|---|
| 78 | prefix = ""; | 
|---|
| 79 | } | 
|---|
| 80 | QDateTime curDatetime = QDateTime::currentDateTime(); | 
|---|
| 81 | QString time = curDatetime.toString( "hh:mm:ss"); | 
|---|
| 82 | outputContent = prefix + time + ":"+ content; | 
|---|
| 83 | } | 
|---|
| 84 | outputContent += "\n"; | 
|---|
| 85 | OutputPane::AppendMode mode = OutputPane::AppendMode::Normal; | 
|---|
| 86 | outputPane->appendText(outputContent, format, mode); | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 | void BinaryToolsDialog::saveClicked() | 
|---|
| 90 | { | 
|---|
| 91 | d->configView->saveConfig(); | 
|---|
| 92 | } | 
|---|
| 93 |  | 
|---|
| 94 | void BinaryToolsDialog::useClicked() | 
|---|
| 95 | { | 
|---|
| 96 | d->configView->saveConfig(); | 
|---|
| 97 |  | 
|---|
| 98 | QProcess proc; | 
|---|
| 99 | QString retMsg = tr( "Error: execute command error! The reason is unknown.\n");; | 
|---|
| 100 | connect(&proc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), | 
|---|
| 101 | [&](int exitcode, QProcess::ExitStatus exitStatus) { | 
|---|
| 102 | if (0 == exitcode && exitStatus == QProcess::ExitStatus::NormalExit) { | 
|---|
| 103 | retMsg = tr( "The process \"%1\" exited normally.\n").arg(proc.program()); | 
|---|
| 104 | } else if (exitStatus == QProcess::NormalExit) { | 
|---|
| 105 | retMsg = tr( "The process \"%1\" exited with code %2.\n") | 
|---|
| 106 | .arg(proc.program(), QString::number(exitcode)); | 
|---|
| 107 | } else { | 
|---|
| 108 | retMsg = tr( "The process \"%1\" crashed.\n").arg(proc.program()); | 
|---|
| 109 | } | 
|---|
| 110 | }); | 
|---|
| 111 |  | 
|---|
| 112 | connect(&proc, &QProcess::readyReadStandardError, [&]() { | 
|---|
| 113 | proc.setReadChannel(QProcess::StandardError); | 
|---|
| 114 | while (proc.canReadLine()) { | 
|---|
| 115 | QString line = QString::fromUtf8(proc.readLine()); | 
|---|
| 116 | qInfo() << line; | 
|---|
| 117 | outputMsg(line, OutputPane::OutputFormat::StdErr); | 
|---|
| 118 | } | 
|---|
| 119 | }); | 
|---|
| 120 |  | 
|---|
| 121 | connect(&proc, &QProcess::readyReadStandardOutput, [&]() { | 
|---|
| 122 | proc.setReadChannel(QProcess::StandardOutput); | 
|---|
| 123 | while (proc.canReadLine()) { | 
|---|
| 124 | QString line = QString::fromUtf8(proc.readLine()); | 
|---|
| 125 | qInfo() << line; | 
|---|
| 126 | outputMsg(line, OutputPane::OutputFormat::StdOut); | 
|---|
| 127 | } | 
|---|
| 128 | }); | 
|---|
| 129 |  | 
|---|
| 130 | QList<QString> programList = d->configView->getProgramList(); | 
|---|
| 131 | QList<QStringList> argsList = d->configView->getArgumentsList(); | 
|---|
| 132 | QList<QString> workingDirList = d->configView->getWorkingDirList(); | 
|---|
| 133 | QList<QMap<QString, QVariant>> envList = d->configView->getEnvironmentList(); | 
|---|
| 134 |  | 
|---|
| 135 | for (int i =0; i < programList.size(); i++) { | 
|---|
| 136 | proc.setProgram(programList.at(i)); | 
|---|
| 137 | if (!argsList.at(i).at(0).isEmpty()) { | 
|---|
| 138 | proc.setArguments(argsList.at(i)); | 
|---|
| 139 | } else { | 
|---|
| 140 | proc.setArguments({}); | 
|---|
| 141 | } | 
|---|
| 142 | proc.setWorkingDirectory(workingDirList.at(i)); | 
|---|
| 143 | QProcessEnvironment env; | 
|---|
| 144 | auto iterator = envList.at(i).begin(); | 
|---|
| 145 | while (iterator != envList.at(i).end()) { | 
|---|
| 146 | env.insert(iterator.key(), iterator.value().toString()); | 
|---|
| 147 | ++iterator; | 
|---|
| 148 | } | 
|---|
| 149 | proc.setProcessEnvironment(env); | 
|---|
| 150 | QString startMsg = tr( "Start execute command: \"%1\" \"%2\" in workspace \"%3\".\n") | 
|---|
| 151 | .arg(programList.at(i), argsList.at(i).join( " "), workingDirList.at(i)); | 
|---|
| 152 | outputMsg(startMsg, OutputPane::OutputFormat::NormalMessage); | 
|---|
| 153 | proc.start(); | 
|---|
| 154 | proc.waitForFinished(-1); | 
|---|
| 155 |  | 
|---|
| 156 | outputMsg(retMsg, OutputPane::OutputFormat::NormalMessage); | 
|---|
| 157 | QString endMsg = tr( "Execute command finished.\n"); | 
|---|
| 158 | outputMsg(endMsg, OutputPane::OutputFormat::NormalMessage); | 
|---|
| 159 | } | 
|---|
| 160 | QDialog::reject(); | 
|---|
| 161 | } | 
|---|
| 162 |  | 
|---|
| 163 | void BinaryToolsDialog::outputMsg(const QString &content, OutputPane::OutputFormat format) | 
|---|
| 164 | { | 
|---|
| 165 | QMetaObject::invokeMethod(this, "printOutput", Q_ARG(QString, content), Q_ARG(OutputPane::OutputFormat, format)); | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|