Axivion: Prepare ui for displaying issues
UI preparation which may change when adding the functionality of retrieving respective information from the dashboard. Change-Id: I9ec8069d780f925b00ba63982af6b410ddec9a5a Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
@@ -2,5 +2,17 @@
|
|||||||
<qresource prefix="/axivion">
|
<qresource prefix="/axivion">
|
||||||
<file>images/axivion.png</file>
|
<file>images/axivion.png</file>
|
||||||
<file>images/axivion@2x.png</file>
|
<file>images/axivion@2x.png</file>
|
||||||
|
<file>images/button-av.png</file>
|
||||||
|
<file>images/button-av@2x.png</file>
|
||||||
|
<file>images/button-cl.png</file>
|
||||||
|
<file>images/button-cl@2x.png</file>
|
||||||
|
<file>images/button-cy.png</file>
|
||||||
|
<file>images/button-cy@2x.png</file>
|
||||||
|
<file>images/button-de.png</file>
|
||||||
|
<file>images/button-de@2x.png</file>
|
||||||
|
<file>images/button-mv.png</file>
|
||||||
|
<file>images/button-mv@2x.png</file>
|
||||||
|
<file>images/button-sv.png</file>
|
||||||
|
<file>images/button-sv@2x.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -10,9 +10,12 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
@@ -168,6 +171,116 @@ void DashboardWidget::updateUi()
|
|||||||
addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row);
|
addValuesWidgets(Tr::tr("Total:"), allTotal, allAdded, allRemoved, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IssuesWidget : public QScrollArea
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit IssuesWidget(QWidget *parent = nullptr);
|
||||||
|
void updateUi();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateTableView();
|
||||||
|
|
||||||
|
QString m_currentPrefix;
|
||||||
|
std::optional<Dto::TableInfoDto> m_currentTableInfo;
|
||||||
|
QHBoxLayout *m_typesLayout = nullptr;
|
||||||
|
QHBoxLayout *m_filtersLayout = nullptr;
|
||||||
|
QPushButton *m_addedFilter = nullptr;
|
||||||
|
QPushButton *m_removedFilter = nullptr;
|
||||||
|
QComboBox *m_ownerFilter = nullptr;
|
||||||
|
QComboBox *m_versionStart = nullptr;
|
||||||
|
QComboBox *m_versionEnd = nullptr;
|
||||||
|
QLineEdit *m_pathGlobFilter = nullptr; // FancyLineEdit instead?
|
||||||
|
};
|
||||||
|
|
||||||
|
IssuesWidget::IssuesWidget(QWidget *parent)
|
||||||
|
: QScrollArea(parent)
|
||||||
|
{
|
||||||
|
QWidget *widget = new QWidget(this);
|
||||||
|
QVBoxLayout *layout = new QVBoxLayout(widget);
|
||||||
|
// row with issue types (-> depending on choice, tables below change)
|
||||||
|
// and a selectable range (start version, end version)
|
||||||
|
// row with added/removed and some filters (assignee, path glob, (named filter))
|
||||||
|
// table, columns depend on chosen issue type
|
||||||
|
QHBoxLayout *top = new QHBoxLayout;
|
||||||
|
layout->addLayout(top);
|
||||||
|
m_typesLayout = new QHBoxLayout;
|
||||||
|
top->addLayout(m_typesLayout);
|
||||||
|
top->addStretch(1);
|
||||||
|
m_versionStart = new QComboBox(this);
|
||||||
|
m_versionStart->setMinimumContentsLength(25);
|
||||||
|
top->addWidget(m_versionStart);
|
||||||
|
m_versionEnd = new QComboBox(this);
|
||||||
|
m_versionEnd->setMinimumContentsLength(25);
|
||||||
|
top->addWidget(m_versionEnd);
|
||||||
|
top->addStretch(1);
|
||||||
|
m_filtersLayout = new QHBoxLayout;
|
||||||
|
m_addedFilter = new QPushButton(this);
|
||||||
|
m_addedFilter->setIcon(trendIcon(1, 0));
|
||||||
|
m_addedFilter->setText("0");
|
||||||
|
m_filtersLayout->addWidget(m_addedFilter);
|
||||||
|
m_removedFilter = new QPushButton(this);
|
||||||
|
m_removedFilter->setIcon(trendIcon(0, 1));
|
||||||
|
m_removedFilter->setText("0");
|
||||||
|
m_filtersLayout->addWidget(m_removedFilter);
|
||||||
|
m_filtersLayout->addSpacing(1);
|
||||||
|
m_ownerFilter = new QComboBox(this);
|
||||||
|
m_ownerFilter->setToolTip(Tr::tr("Owner"));
|
||||||
|
m_ownerFilter->setMinimumContentsLength(25);
|
||||||
|
m_filtersLayout->addWidget(m_ownerFilter);
|
||||||
|
m_pathGlobFilter = new QLineEdit(this);
|
||||||
|
m_pathGlobFilter->setPlaceholderText(Tr::tr("Path globbing"));
|
||||||
|
m_filtersLayout->addWidget(m_pathGlobFilter);
|
||||||
|
layout->addLayout(m_filtersLayout);
|
||||||
|
// TODO the issues table
|
||||||
|
layout->addStretch(1);
|
||||||
|
setWidget(widget);
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
setWidgetResizable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IssuesWidget::updateUi()
|
||||||
|
{
|
||||||
|
m_filtersLayout->setEnabled(false);
|
||||||
|
// TODO extract parts of it and do them only when necessary
|
||||||
|
QLayoutItem *child;
|
||||||
|
while ((child = m_typesLayout->takeAt(0)) != nullptr) {
|
||||||
|
delete child->widget();
|
||||||
|
delete child;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Dto::ProjectInfoDto> projectInfo = Internal::projectInfo();
|
||||||
|
if (!projectInfo)
|
||||||
|
return;
|
||||||
|
const Dto::ProjectInfoDto &info = *projectInfo;
|
||||||
|
if (info.versions.empty()) // add some warning/information?
|
||||||
|
return;
|
||||||
|
|
||||||
|
// for now just a start..
|
||||||
|
const Dto::AnalysisVersionDto &last = info.versions.back();
|
||||||
|
|
||||||
|
const std::vector<Dto::IssueKindInfoDto> &issueKinds = info.issueKinds;
|
||||||
|
for (const Dto::IssueKindInfoDto &kind : issueKinds) {
|
||||||
|
auto button = new QToolButton(this);
|
||||||
|
button->setIcon(iconForIssue(kind.prefix));
|
||||||
|
button->setToolTip(kind.nicePluralName);
|
||||||
|
connect(button, &QToolButton::clicked, this, [this, prefix = kind.prefix]{
|
||||||
|
m_currentPrefix = prefix;
|
||||||
|
updateTableView();
|
||||||
|
});
|
||||||
|
m_typesLayout->addWidget(button);
|
||||||
|
}
|
||||||
|
// TODO versions range...
|
||||||
|
|
||||||
|
// TODO fill owners
|
||||||
|
m_filtersLayout->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IssuesWidget::updateTableView()
|
||||||
|
{
|
||||||
|
// fetch table dto and apply
|
||||||
|
// on done fetch first data for the selected issues
|
||||||
|
}
|
||||||
|
|
||||||
AxivionOutputPane::AxivionOutputPane(QObject *parent)
|
AxivionOutputPane::AxivionOutputPane(QObject *parent)
|
||||||
: Core::IOutputPane(parent)
|
: Core::IOutputPane(parent)
|
||||||
{
|
{
|
||||||
@@ -178,6 +291,8 @@ AxivionOutputPane::AxivionOutputPane(QObject *parent)
|
|||||||
m_outputWidget = new QStackedWidget;
|
m_outputWidget = new QStackedWidget;
|
||||||
DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget);
|
DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget);
|
||||||
m_outputWidget->addWidget(dashboardWidget);
|
m_outputWidget->addWidget(dashboardWidget);
|
||||||
|
IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget);
|
||||||
|
m_outputWidget->addWidget(issuesWidget);
|
||||||
QTextBrowser *browser = new QTextBrowser(m_outputWidget);
|
QTextBrowser *browser = new QTextBrowser(m_outputWidget);
|
||||||
m_outputWidget->addWidget(browser);
|
m_outputWidget->addWidget(browser);
|
||||||
}
|
}
|
||||||
@@ -208,6 +323,16 @@ QList<QWidget *> AxivionOutputPane::toolBarWidgets() const
|
|||||||
m_outputWidget->setCurrentIndex(0);
|
m_outputWidget->setCurrentIndex(0);
|
||||||
});
|
});
|
||||||
buttons.append(showDashboard);
|
buttons.append(showDashboard);
|
||||||
|
auto showIssues = new QToolButton(m_outputWidget);
|
||||||
|
showIssues->setIcon(Utils::Icons::ZOOM_TOOLBAR.icon());
|
||||||
|
showIssues->setToolTip(Tr::tr("Search for issues"));
|
||||||
|
connect(showIssues, &QToolButton::clicked, this, [this]{
|
||||||
|
QTC_ASSERT(m_outputWidget, return);
|
||||||
|
m_outputWidget->setCurrentIndex(1);
|
||||||
|
if (auto issues = static_cast<IssuesWidget *>(m_outputWidget->widget(1)))
|
||||||
|
issues->updateUi();
|
||||||
|
});
|
||||||
|
buttons.append(showIssues);
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,10 +389,10 @@ void AxivionOutputPane::updateDashboard()
|
|||||||
|
|
||||||
void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml)
|
void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml)
|
||||||
{
|
{
|
||||||
if (auto browser = static_cast<QTextBrowser *>(m_outputWidget->widget(1))) {
|
if (auto browser = static_cast<QTextBrowser *>(m_outputWidget->widget(2))) {
|
||||||
browser->setText(ruleHtml);
|
browser->setText(ruleHtml);
|
||||||
if (!ruleHtml.isEmpty()) {
|
if (!ruleHtml.isEmpty()) {
|
||||||
m_outputWidget->setCurrentIndex(1);
|
m_outputWidget->setCurrentIndex(2);
|
||||||
popup(Core::IOutputPane::NoModeSwitch);
|
popup(Core::IOutputPane::NoModeSwitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,20 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace Axivion::Internal {
|
namespace Axivion::Internal {
|
||||||
|
|
||||||
|
QIcon iconForIssue(const QString &prefix)
|
||||||
|
{
|
||||||
|
static QHash<QString, QIcon> prefixToIcon;
|
||||||
|
auto it = prefixToIcon.find(prefix);
|
||||||
|
|
||||||
|
if (it == prefixToIcon.end()) {
|
||||||
|
Icon icon({{FilePath::fromString(":/axivion/images/button-" + prefix.toLower() + ".png"),
|
||||||
|
Theme::PaletteButtonText}},
|
||||||
|
Icon::Tint);
|
||||||
|
it = prefixToIcon.insert(prefix, icon.icon());
|
||||||
|
}
|
||||||
|
return it.value();
|
||||||
|
}
|
||||||
|
|
||||||
class AxivionPluginPrivate : public QObject
|
class AxivionPluginPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -94,6 +108,7 @@ AxivionTextMark::AxivionTextMark(const FilePath &filePath, const ShortIssue &iss
|
|||||||
const QString markText = issue.entity.isEmpty() ? issue.message
|
const QString markText = issue.entity.isEmpty() ? issue.message
|
||||||
: issue.entity + ": " + issue.message;
|
: issue.entity + ": " + issue.message;
|
||||||
setToolTip(issue.errorNumber + " " + markText);
|
setToolTip(issue.errorNumber + " " + markText);
|
||||||
|
setIcon(iconForIssue("SV")); // FIXME adapt to the issue
|
||||||
setPriority(TextEditor::TextMark::NormalPriority);
|
setPriority(TextEditor::TextMark::NormalPriority);
|
||||||
setLineAnnotation(markText);
|
setLineAnnotation(markText);
|
||||||
setActionsProvider([this]{
|
setActionsProvider([this]{
|
||||||
|
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QIcon;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace ProjectExplorer { class Project; }
|
namespace ProjectExplorer { class Project; }
|
||||||
|
|
||||||
namespace Axivion::Internal {
|
namespace Axivion::Internal {
|
||||||
@@ -15,5 +19,7 @@ void fetchProjectInfo(const QString &projectName);
|
|||||||
std::optional<Dto::ProjectInfoDto> projectInfo();
|
std::optional<Dto::ProjectInfoDto> projectInfo();
|
||||||
bool handleCertificateIssue();
|
bool handleCertificateIssue();
|
||||||
|
|
||||||
|
QIcon iconForIssue(const QString &prefix);
|
||||||
|
|
||||||
} // Axivion::Internal
|
} // Axivion::Internal
|
||||||
|
|
||||||
|
BIN
src/plugins/axivion/images/button-av.png
Normal file
After Width: | Height: | Size: 163 B |
BIN
src/plugins/axivion/images/button-av@2x.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
src/plugins/axivion/images/button-cl.png
Normal file
After Width: | Height: | Size: 159 B |
BIN
src/plugins/axivion/images/button-cl@2x.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
src/plugins/axivion/images/button-cy.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
src/plugins/axivion/images/button-cy@2x.png
Normal file
After Width: | Height: | Size: 328 B |
BIN
src/plugins/axivion/images/button-de.png
Normal file
After Width: | Height: | Size: 221 B |
BIN
src/plugins/axivion/images/button-de@2x.png
Normal file
After Width: | Height: | Size: 454 B |
BIN
src/plugins/axivion/images/button-mv.png
Normal file
After Width: | Height: | Size: 173 B |
BIN
src/plugins/axivion/images/button-mv@2x.png
Normal file
After Width: | Height: | Size: 283 B |
BIN
src/plugins/axivion/images/button-sv.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
src/plugins/axivion/images/button-sv@2x.png
Normal file
After Width: | Height: | Size: 315 B |