| 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 | |