Changeset View
Changeset View
Standalone View
Standalone View
plugins/problemreporter/problemsview.cpp
Show All 29 Lines | |||||
30 | #include <QTimer> | 30 | #include <QTimer> | ||
31 | #include <QVBoxLayout> | 31 | #include <QVBoxLayout> | ||
32 | 32 | | |||
33 | #include <interfaces/icore.h> | 33 | #include <interfaces/icore.h> | ||
34 | #include <interfaces/ilanguagecontroller.h> | 34 | #include <interfaces/ilanguagecontroller.h> | ||
35 | #include <shell/problemconstants.h> | 35 | #include <shell/problemconstants.h> | ||
36 | #include <shell/problemmodelset.h> | 36 | #include <shell/problemmodelset.h> | ||
37 | #include <util/expandablelineedit.h> | 37 | #include <util/expandablelineedit.h> | ||
38 | #include "actionmenu.h" | ||||
38 | #include "problemtreeview.h" | 39 | #include "problemtreeview.h" | ||
39 | #include "problemmodel.h" | 40 | #include "problemmodel.h" | ||
40 | 41 | | |||
41 | namespace KDevelop | 42 | namespace KDevelop | ||
42 | { | 43 | { | ||
43 | 44 | | |||
44 | void ProblemsView::setupActions() | 45 | void ProblemsView::setupActions() | ||
45 | { | 46 | { | ||
46 | { | 47 | { | ||
47 | m_fullUpdateAction = new QAction(this); | 48 | m_fullUpdateAction = new QAction(this); | ||
48 | m_fullUpdateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); | 49 | m_fullUpdateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); | ||
49 | m_fullUpdateAction->setText(i18n("Force Full Update")); | 50 | m_fullUpdateAction->setText(i18n("Force Full Update")); | ||
50 | m_fullUpdateAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | 51 | m_fullUpdateAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | ||
51 | connect(m_fullUpdateAction, &QAction::triggered, this, [this]() { | 52 | connect(m_fullUpdateAction, &QAction::triggered, this, [this]() { | ||
52 | currentView()->model()->forceFullUpdate(); | 53 | currentView()->model()->forceFullUpdate(); | ||
53 | }); | 54 | }); | ||
54 | addAction(m_fullUpdateAction); | 55 | addAction(m_fullUpdateAction); | ||
55 | } | 56 | } | ||
56 | 57 | | |||
57 | { | 58 | { | ||
58 | m_scopeMenu = new KActionMenu(this); | 59 | m_scopeMenu = new ActionMenu(i18n("Scope"), this); | ||
59 | m_scopeMenu->setDelayed(false); | | |||
60 | m_scopeMenu->setToolTip(i18nc("@info:tooltip", "Which files to display the problems for")); | 60 | m_scopeMenu->setToolTip(i18nc("@info:tooltip", "Which files to display the problems for")); | ||
61 | m_scopeMenu->setObjectName(QStringLiteral("scopeMenu")); | 61 | connect(m_scopeMenu, &ActionMenu::actionSelected, this, &ProblemsView::setScope); | ||
62 | 62 | | |||
63 | QActionGroup* scopeActions = new QActionGroup(this); | 63 | m_scopeMenu->addAction( | ||
64 | i18n("Current Document"), | ||||
65 | i18nc("@info:tooltip", "Display problems in current document"), | ||||
66 | CurrentDocument); | ||||
67 | | ||||
68 | m_scopeMenu->addAction( | ||||
69 | i18n("Open Documents"), | ||||
70 | i18nc("@info:tooltip", "Display problems in all open documents"), | ||||
71 | OpenDocuments); | ||||
72 | | ||||
73 | m_scopeMenu->addAction( | ||||
74 | i18n("Current Project"), | ||||
75 | i18nc("@info:tooltip", "Display problems in current project"), | ||||
76 | CurrentProject); | ||||
77 | | ||||
78 | m_scopeMenu->addAction( | ||||
79 | i18n("All Projects"), | ||||
80 | i18nc("@info:tooltip", "Display problems in all projects"), | ||||
81 | AllProjects); | ||||
82 | | ||||
83 | m_showAllAction = m_scopeMenu->addAction( | ||||
84 | i18n("Show All"), | ||||
85 | i18nc("@info:tooltip", "Display ALL problems"), | ||||
86 | BypassScopeFilter); | ||||
64 | 87 | | |||
65 | m_currentDocumentAction = new QAction(this); | | |||
66 | m_currentDocumentAction->setText(i18n("Current Document")); | | |||
67 | m_currentDocumentAction->setToolTip(i18nc("@info:tooltip", "Display problems in current document")); | | |||
68 | | ||||
69 | QAction* openDocumentsAction = new QAction(this); | | |||
70 | openDocumentsAction->setText(i18n("Open Documents")); | | |||
71 | openDocumentsAction->setToolTip(i18nc("@info:tooltip", "Display problems in all open documents")); | | |||
72 | | ||||
73 | QAction* currentProjectAction = new QAction(this); | | |||
74 | currentProjectAction->setText(i18n("Current Project")); | | |||
75 | currentProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in current project")); | | |||
76 | | ||||
77 | QAction* allProjectAction = new QAction(this); | | |||
78 | allProjectAction->setText(i18n("All Projects")); | | |||
79 | allProjectAction->setToolTip(i18nc("@info:tooltip", "Display problems in all projects")); | | |||
80 | | ||||
81 | QVector<QAction*> actions; | | |||
82 | actions.push_back(m_currentDocumentAction); | | |||
83 | actions.push_back(openDocumentsAction); | | |||
84 | actions.push_back(currentProjectAction); | | |||
85 | actions.push_back(allProjectAction); | | |||
86 | | ||||
87 | m_showAllAction = new QAction(this); | | |||
88 | m_showAllAction->setText(i18n("Show All")); | | |||
89 | m_showAllAction->setToolTip(i18nc("@info:tooltip", "Display ALL problems")); | | |||
90 | actions.push_back(m_showAllAction); | | |||
91 | | ||||
92 | foreach (QAction* action, actions) { | | |||
93 | action->setCheckable(true); | | |||
94 | scopeActions->addAction(action); | | |||
95 | m_scopeMenu->addAction(action); | | |||
96 | } | | |||
97 | addAction(m_scopeMenu); | 88 | addAction(m_scopeMenu); | ||
98 | | ||||
99 | QSignalMapper* scopeMapper = new QSignalMapper(this); | | |||
100 | scopeMapper->setMapping(m_currentDocumentAction, CurrentDocument); | | |||
101 | scopeMapper->setMapping(openDocumentsAction, OpenDocuments); | | |||
102 | scopeMapper->setMapping(currentProjectAction, CurrentProject); | | |||
103 | scopeMapper->setMapping(allProjectAction, AllProjects); | | |||
104 | connect(m_currentDocumentAction, &QAction::triggered, scopeMapper, | | |||
105 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
106 | connect(openDocumentsAction, &QAction::triggered, scopeMapper, | | |||
107 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
108 | connect(currentProjectAction, &QAction::triggered, scopeMapper, | | |||
109 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
110 | connect(allProjectAction, &QAction::triggered, scopeMapper, | | |||
111 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
112 | | ||||
113 | { | | |||
114 | scopeMapper->setMapping(actions.last(), BypassScopeFilter); | | |||
115 | connect(actions.last(), &QAction::triggered, scopeMapper, | | |||
116 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
117 | } | | |||
118 | | ||||
119 | connect(scopeMapper, static_cast<void (QSignalMapper::*)(int)>(&QSignalMapper::mapped), | | |||
120 | this, [this](int index) { | | |||
121 | setScope(index); | | |||
122 | }); | | |||
123 | } | 89 | } | ||
124 | 90 | | |||
125 | { | 91 | { | ||
126 | m_showImportsAction = new QAction(this); | 92 | m_showImportsAction = new QAction(this); | ||
127 | addAction(m_showImportsAction); | 93 | addAction(m_showImportsAction); | ||
128 | m_showImportsAction->setCheckable(true); | 94 | m_showImportsAction->setCheckable(true); | ||
129 | m_showImportsAction->setChecked(false); | 95 | m_showImportsAction->setChecked(false); | ||
130 | m_showImportsAction->setText(i18n("Show Imports")); | 96 | m_showImportsAction->setText(i18n("Show Imports")); | ||
Show All 34 Lines | 103 | { | |||
165 | m_errorSeverityAction->setChecked(true); | 131 | m_errorSeverityAction->setChecked(true); | ||
166 | 132 | | |||
167 | connect(m_errorSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | 133 | connect(m_errorSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | ||
168 | connect(m_warningSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | 134 | connect(m_warningSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | ||
169 | connect(m_hintSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | 135 | connect(m_hintSeverityAction, &QAction::toggled, this, &ProblemsView::handleSeverityActionToggled); | ||
170 | } | 136 | } | ||
171 | 137 | | |||
172 | { | 138 | { | ||
173 | m_groupingMenu = new KActionMenu(i18n("Grouping"), this); | 139 | m_groupingMenu = new ActionMenu(i18n("Grouping"), this); | ||
174 | m_groupingMenu->setDelayed(false); | 140 | connect(m_groupingMenu, &ActionMenu::actionSelected, this, &ProblemsView::setGrouping); | ||
175 | 141 | | |||
176 | QActionGroup* groupingActions = new QActionGroup(this); | 142 | m_groupingMenu->addAction( | ||
143 | i18n("None"), | ||||
144 | i18nc("@info:tooltip", "No grouping"), | ||||
145 | NoGrouping); | ||||
146 | | ||||
147 | m_groupingMenu->addAction( | ||||
148 | i18n("Path"), | ||||
149 | i18nc("@info:tooltip", "Group problems by path"), | ||||
150 | PathGrouping); | ||||
151 | | ||||
152 | m_groupingMenu->addAction( | ||||
153 | i18n("Severity"), | ||||
154 | i18nc("@info:tooltip", "Group problems by severity"), | ||||
155 | SeverityGrouping); | ||||
177 | 156 | | |||
178 | QAction* noGroupingAction = new QAction(i18n("None"), this); | | |||
179 | QAction* pathGroupingAction = new QAction(i18n("Path"), this); | | |||
180 | QAction* severityGroupingAction = new QAction(i18n("Severity"), this); | | |||
181 | | ||||
182 | QAction* groupingActionArray[] = { noGroupingAction, pathGroupingAction, severityGroupingAction }; | | |||
183 | for (unsigned i = 0; i < sizeof(groupingActionArray) / sizeof(QAction*); ++i) { | | |||
184 | QAction* action = groupingActionArray[i]; | | |||
185 | action->setCheckable(true); | | |||
186 | groupingActions->addAction(action); | | |||
187 | m_groupingMenu->addAction(action); | | |||
188 | } | | |||
189 | addAction(m_groupingMenu); | 157 | addAction(m_groupingMenu); | ||
190 | | ||||
191 | noGroupingAction->setChecked(true); | | |||
192 | QSignalMapper* groupingMapper = new QSignalMapper(this); | | |||
193 | groupingMapper->setMapping(noGroupingAction, NoGrouping); | | |||
194 | groupingMapper->setMapping(pathGroupingAction, PathGrouping); | | |||
195 | groupingMapper->setMapping(severityGroupingAction, SeverityGrouping); | | |||
196 | | ||||
197 | connect(noGroupingAction, &QAction::triggered, groupingMapper, | | |||
198 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
199 | connect(pathGroupingAction, &QAction::triggered, groupingMapper, | | |||
200 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
201 | connect(severityGroupingAction, &QAction::triggered, groupingMapper, | | |||
202 | static_cast<void (QSignalMapper::*)()>(&QSignalMapper::map)); | | |||
203 | | ||||
204 | connect(groupingMapper, static_cast<void (QSignalMapper::*)(int)>(&QSignalMapper::mapped), | | |||
205 | this, [this](int index) { | | |||
206 | currentView()->model()->setGrouping(index); | | |||
207 | }); | | |||
208 | } | 158 | } | ||
209 | 159 | | |||
210 | { | 160 | { | ||
211 | QTimer* filterTimer = new QTimer(this); | 161 | QTimer* filterTimer = new QTimer(this); | ||
212 | filterTimer->setSingleShot(true); | 162 | filterTimer->setSingleShot(true); | ||
213 | 163 | | |||
214 | connect(filterTimer, &QTimer::timeout, this, [this]() { | 164 | connect(filterTimer, &QTimer::timeout, this, [this]() { | ||
215 | setFilter(m_filterEdit->text()); | 165 | setFilter(m_filterEdit->text()); | ||
Show All 16 Lines | |||||
232 | } | 182 | } | ||
233 | } | 183 | } | ||
234 | 184 | | |||
235 | void ProblemsView::updateActions() | 185 | void ProblemsView::updateActions() | ||
236 | { | 186 | { | ||
237 | auto problemModel = currentView()->model(); | 187 | auto problemModel = currentView()->model(); | ||
238 | Q_ASSERT(problemModel); | 188 | Q_ASSERT(problemModel); | ||
239 | 189 | | |||
240 | m_fullUpdateAction->setVisible(problemModel->features().testFlag(ProblemModel::CanDoFullUpdate)); | 190 | m_fullUpdateAction->setEnabled(problemModel->features().testFlag(ProblemModel::CanDoFullUpdate)); | ||
241 | m_fullUpdateAction->setToolTip(problemModel->fullUpdateTooltip()); | 191 | m_fullUpdateAction->setToolTip(problemModel->fullUpdateTooltip()); | ||
242 | m_showImportsAction->setVisible(problemModel->features().testFlag(ProblemModel::CanShowImports)); | 192 | m_showImportsAction->setEnabled(problemModel->features().testFlag(ProblemModel::CanShowImports)); | ||
243 | m_scopeMenu->setVisible(problemModel->features().testFlag(ProblemModel::ScopeFilter)); | 193 | m_scopeMenu->setEnabled(problemModel->features().testFlag(ProblemModel::ScopeFilter)); | ||
244 | m_severityActions->setVisible(problemModel->features().testFlag(ProblemModel::SeverityFilter)); | 194 | m_severityActions->setEnabled(problemModel->features().testFlag(ProblemModel::SeverityFilter)); | ||
245 | m_groupingMenu->setVisible(problemModel->features().testFlag(ProblemModel::Grouping)); | 195 | m_groupingMenu->setEnabled(problemModel->features().testFlag(ProblemModel::Grouping)); | ||
246 | 196 | | |||
247 | m_showAllAction->setVisible(problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)); | 197 | m_showAllAction->setEnabled(problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)); | ||
248 | 198 | | |||
249 | m_showImportsAction->setChecked(false); | 199 | m_showImportsAction->setChecked(false); | ||
250 | problemModel->setShowImports(false); | 200 | problemModel->setShowImports(false); | ||
251 | 201 | | |||
252 | // Show All should be default if it's supported. It helps with error messages that are otherwise invisible | 202 | // Show All should be default if it's supported. It helps with error messages that are otherwise invisible | ||
253 | if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { | 203 | if (problemModel->features().testFlag(ProblemModel::CanByPassScopeFilter)) { | ||
254 | //actions.last()->setChecked(true); | | |||
255 | setScope(BypassScopeFilter); | 204 | setScope(BypassScopeFilter); | ||
256 | } else { | 205 | } else { | ||
257 | m_currentDocumentAction->setChecked(true); | | |||
258 | setScope(CurrentDocument); | 206 | setScope(CurrentDocument); | ||
259 | } | 207 | } | ||
260 | 208 | | |||
261 | problemModel->setSeverities(IProblem::Error | IProblem::Warning | IProblem::Hint); | 209 | problemModel->setSeverities(IProblem::Error | IProblem::Warning | IProblem::Hint); | ||
262 | 210 | | |||
211 | setGrouping(NoGrouping); | ||||
212 | | ||||
263 | setFocus(); // set focus to default widget (filterEdit) | 213 | setFocus(); // set focus to default widget (filterEdit) | ||
264 | } | 214 | } | ||
265 | 215 | | |||
266 | /// TODO: Move to util? | 216 | /// TODO: Move to util? | ||
267 | /// Note: Support for recursing into child indices would be nice | 217 | /// Note: Support for recursing into child indices would be nice | ||
268 | class ItemViewWalker | 218 | class ItemViewWalker | ||
269 | { | 219 | { | ||
270 | public: | 220 | public: | ||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Line(s) | 369 | { | |||
431 | connect(view, &ProblemTreeView::changed, this, &ProblemsView::onViewChanged); | 381 | connect(view, &ProblemTreeView::changed, this, &ProblemsView::onViewChanged); | ||
432 | connect(model, &ProblemModel::fullUpdateTooltipChanged, | 382 | connect(model, &ProblemModel::fullUpdateTooltipChanged, | ||
433 | this, [this, model]() { | 383 | this, [this, model]() { | ||
434 | if (currentView()->model() == model) { | 384 | if (currentView()->model() == model) { | ||
435 | m_fullUpdateAction->setToolTip(model->fullUpdateTooltip()); | 385 | m_fullUpdateAction->setToolTip(model->fullUpdateTooltip()); | ||
436 | } | 386 | } | ||
437 | }); | 387 | }); | ||
438 | 388 | | |||
389 | connect(model, &ProblemModel::featuresChanged, | ||||
390 | this, [this, model] { | ||||
391 | if (currentView()->model() == model) { | ||||
392 | updateActions(); | ||||
393 | } | ||||
394 | }); | ||||
395 | | ||||
439 | int insertIdx = 0; | 396 | int insertIdx = 0; | ||
440 | if (newData.id != parserId) { | 397 | if (newData.id != parserId) { | ||
441 | for (insertIdx = 0; insertIdx < m_models.size(); ++insertIdx) { | 398 | for (insertIdx = 0; insertIdx < m_models.size(); ++insertIdx) { | ||
442 | const ModelData& currentData = m_models[insertIdx]; | 399 | const ModelData& currentData = m_models[insertIdx]; | ||
443 | 400 | | |||
444 | // Skip first element if it's already occupied by "Parser" model | 401 | // Skip first element if it's already occupied by "Parser" model | ||
445 | if (insertIdx == 0 && currentData.id == parserId) | 402 | if (insertIdx == 0 && currentData.id == parserId) | ||
446 | continue; | 403 | continue; | ||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | |||||
494 | { | 451 | { | ||
495 | currentView()->model()->setSeverities( (m_errorSeverityAction->isChecked() ? IProblem::Error : IProblem::Severities()) | | 452 | currentView()->model()->setSeverities( (m_errorSeverityAction->isChecked() ? IProblem::Error : IProblem::Severities()) | | ||
496 | (m_warningSeverityAction->isChecked() ? IProblem::Warning : IProblem::Severities()) | | 453 | (m_warningSeverityAction->isChecked() ? IProblem::Warning : IProblem::Severities()) | | ||
497 | (m_hintSeverityAction->isChecked() ? IProblem::Hint : IProblem::Severities()) ); | 454 | (m_hintSeverityAction->isChecked() ? IProblem::Hint : IProblem::Severities()) ); | ||
498 | } | 455 | } | ||
499 | 456 | | |||
500 | void ProblemsView::setScope(int scope) | 457 | void ProblemsView::setScope(int scope) | ||
501 | { | 458 | { | ||
502 | m_scopeMenu->setText(i18n("Scope: %1", m_scopeMenu->menu()->actions().at(scope)->text())); | | |||
503 | | ||||
504 | currentView()->model()->setScope(scope); | 459 | currentView()->model()->setScope(scope); | ||
460 | m_scopeMenu->selectAction(scope); | ||||
461 | } | ||||
462 | | ||||
463 | void ProblemsView::setGrouping(int grouping) | ||||
464 | { | ||||
465 | currentView()->model()->setGrouping(grouping); | ||||
466 | m_groupingMenu->selectAction(grouping); | ||||
505 | } | 467 | } | ||
506 | 468 | | |||
507 | void ProblemsView::setFilter(const QString& filterText) | 469 | void ProblemsView::setFilter(const QString& filterText) | ||
508 | { | 470 | { | ||
509 | setFilter(filterText, m_tabWidget->currentIndex()); | 471 | setFilter(filterText, m_tabWidget->currentIndex()); | ||
510 | } | 472 | } | ||
511 | 473 | | |||
512 | void ProblemsView::setFilter(const QString& filterText, int tabIdx) | 474 | void ProblemsView::setFilter(const QString& filterText, int tabIdx) | ||
Show All 16 Lines |