forked from qt-creator/qt-creator
This makes IOutputParser structurally more similar to Utils::OutputFormatter, which makes it simpler to explore possibilities of somehow uniting these two related classes. Task-number: QTCREATORBUG-22665 Change-Id: Ibb12ab6c8c785d863b9a921102a929864d0a5251 Reviewed-by: hjk <hjk@qt.io>
172 lines
6.5 KiB
C++
172 lines
6.5 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2019 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of Qt Creator.
|
|
**
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "parseissuesdialog.h"
|
|
|
|
#include "ioutputparser.h"
|
|
#include "kitinformation.h"
|
|
#include "kitchooser.h"
|
|
#include "kitmanager.h"
|
|
#include "projectexplorerconstants.h"
|
|
#include "taskhub.h"
|
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
|
#include <utils/runextensions.h>
|
|
|
|
#include <QButtonGroup>
|
|
#include <QCheckBox>
|
|
#include <QDialogButtonBox>
|
|
#include <QFile>
|
|
#include <QFileDialog>
|
|
#include <QGroupBox>
|
|
#include <QLabel>
|
|
#include <QMessageBox>
|
|
#include <QPlainTextEdit>
|
|
#include <QPushButton>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <memory>
|
|
|
|
namespace ProjectExplorer {
|
|
namespace Internal {
|
|
|
|
class ParseIssuesDialog::Private
|
|
{
|
|
public:
|
|
QPlainTextEdit compileOutputEdit;
|
|
QCheckBox stderrCheckBox;
|
|
QCheckBox clearTasksCheckBox;
|
|
KitChooser kitChooser;
|
|
};
|
|
|
|
ParseIssuesDialog::ParseIssuesDialog(QWidget *parent) : QDialog(parent), d(new Private)
|
|
{
|
|
setWindowTitle(tr("Parse Build Output"));
|
|
|
|
d->stderrCheckBox.setText(tr("Output went to stderr"));
|
|
d->stderrCheckBox.setChecked(true);
|
|
|
|
d->clearTasksCheckBox.setText(tr("Clear existing tasks"));
|
|
d->clearTasksCheckBox.setChecked(true);
|
|
|
|
const auto loadFileButton = new QPushButton(tr("Load from File..."));
|
|
connect(loadFileButton, &QPushButton::clicked, this, [this] {
|
|
const QString filePath = QFileDialog::getOpenFileName(this, tr("Choose File"));
|
|
if (filePath.isEmpty())
|
|
return;
|
|
QFile file(filePath);
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
QMessageBox::critical(this, tr("Could Not Open File"),
|
|
tr("Could not open file: \"%1\": %2")
|
|
.arg(filePath, file.errorString()));
|
|
return;
|
|
}
|
|
d->compileOutputEdit.setPlainText(QString::fromLocal8Bit(file.readAll()));
|
|
});
|
|
|
|
d->kitChooser.populate();
|
|
if (!d->kitChooser.hasStartupKit()) {
|
|
for (const Kit * const k : KitManager::kits()) {
|
|
if (DeviceTypeKitAspect::deviceTypeId(k) == Constants::DESKTOP_DEVICE_TYPE) {
|
|
d->kitChooser.setCurrentKitId(k->id());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(d->kitChooser.currentKit());
|
|
|
|
const auto layout = new QVBoxLayout(this);
|
|
const auto outputGroupBox = new QGroupBox(tr("Build Output"));
|
|
layout->addWidget(outputGroupBox);
|
|
const auto outputLayout = new QHBoxLayout(outputGroupBox);
|
|
outputLayout->addWidget(&d->compileOutputEdit);
|
|
const auto buttonsWidget = new QWidget;
|
|
const auto outputButtonsLayout = new QVBoxLayout(buttonsWidget);
|
|
outputLayout->addWidget(buttonsWidget);
|
|
outputButtonsLayout->addWidget(loadFileButton);
|
|
outputButtonsLayout->addWidget(&d->stderrCheckBox);
|
|
outputButtonsLayout->addStretch(1);
|
|
|
|
// TODO: Only very few parsers are available from a Kit (basically just the Toolchain one).
|
|
// If we introduced factories for IOutputParsers, we could offer the user
|
|
// to combine arbitrary parsers here.
|
|
const auto parserGroupBox = new QGroupBox(tr("Parsing Options"));
|
|
layout->addWidget(parserGroupBox);
|
|
const auto parserLayout = new QVBoxLayout(parserGroupBox);
|
|
const auto kitChooserWidget = new QWidget;
|
|
const auto kitChooserLayout = new QHBoxLayout(kitChooserWidget);
|
|
kitChooserLayout->setContentsMargins(0, 0, 0, 0);
|
|
kitChooserLayout->addWidget(new QLabel(tr("Use parsers from kit:")));
|
|
kitChooserLayout->addWidget(&d->kitChooser);
|
|
parserLayout->addWidget(kitChooserWidget);
|
|
parserLayout->addWidget(&d->clearTasksCheckBox);
|
|
|
|
layout->addWidget(buttonBox);
|
|
}
|
|
|
|
ParseIssuesDialog::~ParseIssuesDialog()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
static void parse(QFutureInterface<void> &future, const QString &output,
|
|
const std::unique_ptr<IOutputParser> &parser, bool isStderr)
|
|
{
|
|
const QStringList lines = output.split('\n');
|
|
future.setProgressRange(0, lines.count());
|
|
const auto parserFunc = isStderr ? &IOutputParser::handleStderr : &IOutputParser::handleStdout;
|
|
for (const QString &line : lines) {
|
|
(parser.get()->*parserFunc)(line + '\n');
|
|
future.setProgressValue(future.progressValue() + 1);
|
|
if (future.isCanceled())
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ParseIssuesDialog::accept()
|
|
{
|
|
std::unique_ptr<IOutputParser> parser(d->kitChooser.currentKit()->createOutputParser());
|
|
if (!parser) {
|
|
QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
|
|
"not provide an output parser."));
|
|
return;
|
|
}
|
|
if (d->clearTasksCheckBox.isChecked())
|
|
TaskHub::clearTasks();
|
|
connect(parser.get(), &IOutputParser::addTask, [](const Task &t) { TaskHub::addTask(t); });
|
|
const QFuture<void> f = Utils::runAsync(&parse, d->compileOutputEdit.toPlainText(),
|
|
std::move(parser), d->stderrCheckBox.isChecked());
|
|
Core::ProgressManager::addTask(f, tr("Parsing build output"),
|
|
"ProgressExplorer.ParseExternalBuildOutput");
|
|
QDialog::accept();
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namespace ProjectExplorer
|