From 0ba1e17797e399b618056d08e35aed0c435f2a9b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 19 Jan 2024 13:47:03 +0100 Subject: [PATCH] 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 --- src/plugins/axivion/axivion.qrc | 12 ++ src/plugins/axivion/axivionoutputpane.cpp | 129 +++++++++++++++++++- src/plugins/axivion/axivionplugin.cpp | 15 +++ src/plugins/axivion/axivionplugin.h | 6 + src/plugins/axivion/images/button-av.png | Bin 0 -> 163 bytes src/plugins/axivion/images/button-av@2x.png | Bin 0 -> 255 bytes src/plugins/axivion/images/button-cl.png | Bin 0 -> 159 bytes src/plugins/axivion/images/button-cl@2x.png | Bin 0 -> 231 bytes src/plugins/axivion/images/button-cy.png | Bin 0 -> 189 bytes src/plugins/axivion/images/button-cy@2x.png | Bin 0 -> 328 bytes src/plugins/axivion/images/button-de.png | Bin 0 -> 221 bytes src/plugins/axivion/images/button-de@2x.png | Bin 0 -> 454 bytes src/plugins/axivion/images/button-mv.png | Bin 0 -> 173 bytes src/plugins/axivion/images/button-mv@2x.png | Bin 0 -> 283 bytes src/plugins/axivion/images/button-sv.png | Bin 0 -> 174 bytes src/plugins/axivion/images/button-sv@2x.png | Bin 0 -> 315 bytes 16 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 src/plugins/axivion/images/button-av.png create mode 100644 src/plugins/axivion/images/button-av@2x.png create mode 100644 src/plugins/axivion/images/button-cl.png create mode 100644 src/plugins/axivion/images/button-cl@2x.png create mode 100644 src/plugins/axivion/images/button-cy.png create mode 100644 src/plugins/axivion/images/button-cy@2x.png create mode 100644 src/plugins/axivion/images/button-de.png create mode 100644 src/plugins/axivion/images/button-de@2x.png create mode 100644 src/plugins/axivion/images/button-mv.png create mode 100644 src/plugins/axivion/images/button-mv@2x.png create mode 100644 src/plugins/axivion/images/button-sv.png create mode 100644 src/plugins/axivion/images/button-sv@2x.png 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 0000000000000000000000000000000000000000..d3ab34f81c428b74e6c1300bfd555142912be4a1 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqWO=$chDe0Ro-pKda1dyH zxU<*WqUn+w$LiR*%@)(+RQVj%T)urI#u=E+Q)zHz=w>;ys%GK(AH{chrJOfCl+L`lz~J^@Hr9!&SRZU>uE~CJg7>>fUS3j3^P6-BG@|iC2{3(x*?f!C~#WeWx{38tp ziobkc^D{A&@CJk{xWzV#eYfLwDW8;owCQ3%{<)^E&?ftO) z&!!@Q6Lt)u7N+7#zx8Fc3MvdkYT3dXzrVLz$dNK_s=u?~35V-ULKd4id>=S_RI_u4 zoNwX!^Zzp+&%QtHoD7bNQ`)$f9A-)2*>PY=(uVz9%MY;pTg=Gdp!=ZmUfd3SkjCAc;$_bg#O9>b||L(#9EHHte>^h}_0@CA)I&2wUnenejs`7>L# kdCtS2u>Z>TpOaV_c&1hVeR}!9OOOvdUHx3vIVCg!0F)kJp8x;= literal 0 HcmV?d00001 diff --git a/src/plugins/axivion/images/button-cy.png b/src/plugins/axivion/images/button-cy.png new file mode 100644 index 0000000000000000000000000000000000000000..7d0bc31bb4e00f92b18e716c6050d6606aceb1a4 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rqw0OEWhDc0J{=v@}Fa6I^ zf+wKy|LxEJoLK+Ky?)EUxZS4X!0wKj=I@#uj$HfyJ)ePvpZdc1Mkecj^&jtYmED~8BUWJloXPpD ryK8T<&v@RK^50d0=iA$PM>!Z7R^NSC-{m6r3gj+NS3j3^P617A8-m^6*==g7jZwWnG55!8l~QS!@~4g>dj#{`3J>n*`S?1)&6UN)vHh042y3O% z^#6-B3UZt#?pLb(XTOSR=F}DQ{``{nZ9K5={|!bT#{d5k*DmOp&~&84gmwF!`wKNT zymJaIaMt2e-Fh!|PsgGMvr-Plr~I@(_wE9Va=nC0yr{q1#QKLzzlc~~j1${zTgt}Q zr{njau%=VuqT$E; zYllvpIFgy4$n^csGW-Ak|NnkB;iy2P{Jr%GUH?VjuyX4}b6) z@BbMlzW(3bvi@)Xe@-Ednt$MCE5yFFd~T-G@yGywqMhG9Vf literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..00cca8ed1eea9a56a0964b996b2b5528bc98065b GIT binary patch literal 454 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(3rUQZXt5R22vKl~XCCM|X72e~ztsa9l<@jEyms*_DqiZvWf=1|m6=9{An=!FFcP{tNR@e$blLBz5eK zxyQ46MbF~87bWPOE(%%xSM!lg|B?rC>CC$x|KGX#pPR;su%FEj_Z~lU`T^HJPm=^r zhV2eJntt;v-=Hx=fi-+X|3gVJ)@;eT10p#|3_G8%GMs(hTA}uC%h}hu6YLIskXn{t zeVAP#^XP#C6WEvJHkO!0d@=SpXxL`$5X7PJkZXx+;}+owac4e>FMD8lSW!WeeaZ}; zCBltgSQPHA?BQUa8Kv-Xt6c({M&CYD79Zx9rF{+>CoUb}S&_b`qv2P5`)Xn370f2} z3a-~eo*m8L`gFs8flImY=`@j_R@>HQaH@IprRcHz`Tu`HC1+Ka)u|89_H#3{O!;&F z&>!~LgO+X8|NV2?8nXXSFG^Z+ay3u*ggFM`49*9wkJ)-~MQt&dym#u&YtrBEGaj71 zJAAsw)C8>^?~fc|V1840f5X!?>&ws2vE2Os%uMd@^^<3tpA2STNPVC6e&VlRuRsyx M>FVdQ&MBb@0HVFlDgXcg literal 0 HcmV?d00001 diff --git a/src/plugins/axivion/images/button-mv.png b/src/plugins/axivion/images/button-mv.png new file mode 100644 index 0000000000000000000000000000000000000000..39eb7bedb9a1502a4e9e3272063c69ce36273f64 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rqlz6&0hDd}bulU)|B_X1H zk>!xu!Y%^|pSk@?hXlU8wC~~wI9e|vxS&g3L&-sOxz_~O1}(pzR}?!NLe9hmcM2qO z)D&fX`)?}x|Nr^s4uctbR#P`-g}SKvu&j9WI8WdQlPKe=hT9xsi68u&nZBL=XZ**V Znc?I~J-+|| literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..159f0a4e1e8178f95312b48233fb89eb44a4170c GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=N1iT@Ar_}wCobeWWFXLX zUT=lrNn?R8I`22I&tPPa6fo#_zxv?gi;oNvLOe{(iXKge-|grtySt$Lx9{2M>*IqD z>~YC#_?vl?vB5)N0^8;wmNHib3yvH6zBM_UABZUs*s#-fV}k51$N6gxOH3%Ok!ErK z+GVcvdIRs8!zMNn?U@0R&kcCFjE*HrT~UbnAaPna2L<5ihuT9V>q6=*L${tf_;qb{TyqK7p>Y)I-iyQ7yKp0bWAu+ kS%E!a7Kb*+iwN}(jBZ^4R*d5B7J+>2>FVdQ&MBb@022Cb1^@s6 literal 0 HcmV?d00001 diff --git a/src/plugins/axivion/images/button-sv.png b/src/plugins/axivion/images/button-sv.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a61bb7fd959ebbb5d9a1d4b1d27b5d3c8499ab GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqlzO^2hDcma{?X4SA#i58 zqkkYvTw6?UO_Rz8qc2DQJMFJ8U=-M&lzXUr2E&Z|qC2IRv7YHa{g1;~+}Dx30FvddQ*S5s^####-|fwZi)O5>-<0eVfH1xqhC+d&CIy>LF#Dn>wRy0+8ZaY c*w@OyU=(t%&-3Vs5RgMWUHx3vIVCg!02E9}D*ylh literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..72ab9ae8e6e48cf4d539bfbe80a93d8b6f571d20 GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2ACQlc~5R22vKl~XCCag}l z$@7P6+QyCN4=hhm{k