diff --git a/src/plugins/axivion/axivion.qrc b/src/plugins/axivion/axivion.qrc index 13d0b616c91..c0d56f8f7b0 100644 --- a/src/plugins/axivion/axivion.qrc +++ b/src/plugins/axivion/axivion.qrc @@ -2,5 +2,17 @@ images/axivion.png images/axivion@2x.png + images/button-av.png + images/button-av@2x.png + images/button-cl.png + images/button-cl@2x.png + images/button-cy.png + images/button-cy@2x.png + images/button-de.png + images/button-de@2x.png + images/button-mv.png + images/button-mv@2x.png + images/button-sv.png + images/button-sv@2x.png diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index a67c524e01c..32d0509a1b7 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -10,9 +10,12 @@ #include #include +#include #include #include +#include #include +#include #include #include #include @@ -168,6 +171,116 @@ void DashboardWidget::updateUi() 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 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 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 &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) : Core::IOutputPane(parent) { @@ -178,6 +291,8 @@ AxivionOutputPane::AxivionOutputPane(QObject *parent) m_outputWidget = new QStackedWidget; DashboardWidget *dashboardWidget = new DashboardWidget(m_outputWidget); m_outputWidget->addWidget(dashboardWidget); + IssuesWidget *issuesWidget = new IssuesWidget(m_outputWidget); + m_outputWidget->addWidget(issuesWidget); QTextBrowser *browser = new QTextBrowser(m_outputWidget); m_outputWidget->addWidget(browser); } @@ -208,6 +323,16 @@ QList AxivionOutputPane::toolBarWidgets() const m_outputWidget->setCurrentIndex(0); }); 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(m_outputWidget->widget(1))) + issues->updateUi(); + }); + buttons.append(showIssues); return buttons; } @@ -264,10 +389,10 @@ void AxivionOutputPane::updateDashboard() void AxivionOutputPane::updateAndShowRule(const QString &ruleHtml) { - if (auto browser = static_cast(m_outputWidget->widget(1))) { + if (auto browser = static_cast(m_outputWidget->widget(2))) { browser->setText(ruleHtml); if (!ruleHtml.isEmpty()) { - m_outputWidget->setCurrentIndex(1); + m_outputWidget->setCurrentIndex(2); popup(Core::IOutputPane::NoModeSwitch); } } diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 08ec997caeb..3b0feac5bdc 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -55,6 +55,20 @@ using namespace Utils; namespace Axivion::Internal { +QIcon iconForIssue(const QString &prefix) +{ + static QHash 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 { public: @@ -94,6 +108,7 @@ AxivionTextMark::AxivionTextMark(const FilePath &filePath, const ShortIssue &iss const QString markText = issue.entity.isEmpty() ? issue.message : issue.entity + ": " + issue.message; setToolTip(issue.errorNumber + " " + markText); + setIcon(iconForIssue("SV")); // FIXME adapt to the issue setPriority(TextEditor::TextMark::NormalPriority); setLineAnnotation(markText); setActionsProvider([this]{ diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h index 202d731b65e..b7a4819a081 100644 --- a/src/plugins/axivion/axivionplugin.h +++ b/src/plugins/axivion/axivionplugin.h @@ -7,6 +7,10 @@ #include +QT_BEGIN_NAMESPACE +class QIcon; +QT_END_NAMESPACE + namespace ProjectExplorer { class Project; } namespace Axivion::Internal { @@ -15,5 +19,7 @@ void fetchProjectInfo(const QString &projectName); std::optional projectInfo(); bool handleCertificateIssue(); +QIcon iconForIssue(const QString &prefix); + } // Axivion::Internal diff --git a/src/plugins/axivion/images/button-av.png b/src/plugins/axivion/images/button-av.png new file mode 100644 index 00000000000..d3ab34f81c4 Binary files /dev/null and b/src/plugins/axivion/images/button-av.png differ diff --git a/src/plugins/axivion/images/button-av@2x.png b/src/plugins/axivion/images/button-av@2x.png new file mode 100644 index 00000000000..e7adf0fa604 Binary files /dev/null and b/src/plugins/axivion/images/button-av@2x.png differ diff --git a/src/plugins/axivion/images/button-cl.png b/src/plugins/axivion/images/button-cl.png new file mode 100644 index 00000000000..d4fd773d894 Binary files /dev/null and b/src/plugins/axivion/images/button-cl.png differ diff --git a/src/plugins/axivion/images/button-cl@2x.png b/src/plugins/axivion/images/button-cl@2x.png new file mode 100644 index 00000000000..c458d34a120 Binary files /dev/null and b/src/plugins/axivion/images/button-cl@2x.png differ diff --git a/src/plugins/axivion/images/button-cy.png b/src/plugins/axivion/images/button-cy.png new file mode 100644 index 00000000000..7d0bc31bb4e Binary files /dev/null and b/src/plugins/axivion/images/button-cy.png differ diff --git a/src/plugins/axivion/images/button-cy@2x.png b/src/plugins/axivion/images/button-cy@2x.png new file mode 100644 index 00000000000..faf72f0e1b2 Binary files /dev/null and b/src/plugins/axivion/images/button-cy@2x.png differ diff --git a/src/plugins/axivion/images/button-de.png b/src/plugins/axivion/images/button-de.png new file mode 100644 index 00000000000..18bed7d5bef Binary files /dev/null and b/src/plugins/axivion/images/button-de.png differ diff --git a/src/plugins/axivion/images/button-de@2x.png b/src/plugins/axivion/images/button-de@2x.png new file mode 100644 index 00000000000..00cca8ed1ee Binary files /dev/null and b/src/plugins/axivion/images/button-de@2x.png differ diff --git a/src/plugins/axivion/images/button-mv.png b/src/plugins/axivion/images/button-mv.png new file mode 100644 index 00000000000..39eb7bedb9a Binary files /dev/null and b/src/plugins/axivion/images/button-mv.png differ diff --git a/src/plugins/axivion/images/button-mv@2x.png b/src/plugins/axivion/images/button-mv@2x.png new file mode 100644 index 00000000000..159f0a4e1e8 Binary files /dev/null and b/src/plugins/axivion/images/button-mv@2x.png differ diff --git a/src/plugins/axivion/images/button-sv.png b/src/plugins/axivion/images/button-sv.png new file mode 100644 index 00000000000..c5a61bb7fd9 Binary files /dev/null and b/src/plugins/axivion/images/button-sv.png differ diff --git a/src/plugins/axivion/images/button-sv@2x.png b/src/plugins/axivion/images/button-sv@2x.png new file mode 100644 index 00000000000..72ab9ae8e6e Binary files /dev/null and b/src/plugins/axivion/images/button-sv@2x.png differ