1 /*
2 This file is part of GammaRay, the Qt application inspection and
3 manipulation tool.
4
5 Copyright (C) 2012-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
6 Author: Volker Krause <volker.krause@kdab.com>
7
8 Licensees holding valid commercial KDAB GammaRay licenses may use this file in
9 accordance with GammaRay Commercial License Agreement provided with the Software.
10
11 Contact info@kdab.com if any conditions of this licensing are not clear to you.
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include "paintanalyzerwidget.h"
28 #include "ui_paintanalyzerwidget.h"
29 #include "paintbufferclientmodel.h"
30
31 #include <ui/clientpropertymodel.h>
32 #include <ui/contextmenuextension.h>
33 #include <ui/searchlinecontroller.h>
34 #include <ui/propertyeditor/propertyeditordelegate.h>
35 #include <ui/uiresources.h>
36
37 #include <common/paintanalyzerinterface.h>
38 #include <common/paintbuffermodelroles.h>
39 #include <common/objectbroker.h>
40 #include <common/sourcelocation.h>
41
42 #include <QComboBox>
43 #include <QDebug>
44 #include <QLabel>
45 #include <QMenu>
46 #include <QToolBar>
47
48 using namespace GammaRay;
49
PaintAnalyzerWidget(QWidget * parent)50 PaintAnalyzerWidget::PaintAnalyzerWidget(QWidget *parent)
51 : QWidget(parent)
52 , ui(new Ui::PaintAnalyzerWidget)
53 , m_iface(nullptr)
54 {
55 ui->setupUi(this);
56 ui->commandView->header()->setObjectName("commandViewHeader");
57 ui->commandView->setItemDelegate(new PropertyEditorDelegate(this));
58 ui->commandView->setStretchLastSection(false);
59 ui->commandView->setDeferredResizeMode(0, QHeaderView::ResizeToContents);
60 ui->commandView->setDeferredResizeMode(1, QHeaderView::Stretch);
61 ui->commandView->setDeferredResizeMode(2, QHeaderView::ResizeToContents);
62
63 ui->argumentView->setItemDelegate(new PropertyEditorDelegate(this));
64 ui->argumentView->header()->setObjectName("argumentViewHeader");
65 ui->stackTraceView->setItemDelegate(new PropertyEditorDelegate(this));
66 ui->stackTraceView->header()->setObjectName("stackTraceViewHeader");
67
68 auto toolbar = new QToolBar;
69 // Our icons are 16x16 and support hidpi, so let force iconSize on every styles
70 toolbar->setIconSize(QSize(16, 16));
71 toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
72 ui->replayContainer->setMenuBar(toolbar);
73
74 foreach (auto action, ui->replayWidget->interactionModeActions()->actions())
75 toolbar->addAction(action);
76 toolbar->addSeparator();
77
78 toolbar->addAction(ui->replayWidget->zoomOutAction());
79 auto zoom = new QComboBox;
80 zoom->setModel(ui->replayWidget->zoomLevelModel());
81 toolbar->addWidget(zoom);
82 toolbar->addAction(ui->replayWidget->zoomInAction());
83 toolbar->addSeparator();
84 toolbar->addAction(ui->actionShowClipArea);
85
86 ui->replayWidget->setSupportedInteractionModes(
87 RemoteViewWidget::ViewInteraction | RemoteViewWidget::Measuring | RemoteViewWidget::ColorPicking);
88
89 ui->paintAnalyzerSplitter->setStretchFactor(0, 1);
90 ui->paintAnalyzerSplitter->setStretchFactor(1, 2);
91
92 connect(zoom, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
93 ui->replayWidget, &RemoteViewWidget::setZoomLevel);
94 connect(ui->replayWidget, &RemoteViewWidget::zoomLevelChanged, zoom, &QComboBox::setCurrentIndex);
95 zoom->setCurrentIndex(ui->replayWidget->zoomLevelIndex());
96
97 ui->actionShowClipArea->setIcon(UIResources::themedIcon(QLatin1String("visualize-clipping.png")));
98 connect(ui->actionShowClipArea, &QAction::toggled, ui->replayWidget, &PaintAnalyzerReplayView::setShowClipArea);
99 ui->actionShowClipArea->setChecked(ui->replayWidget->showClipArea());
100
101 connect(ui->commandView, &QWidget::customContextMenuRequested, this, &PaintAnalyzerWidget::commandContextMenu);
102 connect(ui->stackTraceView, &QWidget::customContextMenuRequested, this, &PaintAnalyzerWidget::stackTraceContextMenu);
103 }
104
105 PaintAnalyzerWidget::~PaintAnalyzerWidget() = default;
106
setBaseName(const QString & name)107 void PaintAnalyzerWidget::setBaseName(const QString &name)
108 {
109 auto model = ObjectBroker::model(name + QStringLiteral(".paintBufferModel"));
110 auto proxy = new PaintBufferClientModel(this);
111 proxy->setSourceModel(model);
112 ui->commandView->setModel(proxy);
113 ui->commandView->setSelectionModel(ObjectBroker::selectionModel(proxy));
114 new SearchLineController(ui->commandSearchLine, proxy);
115
116 auto clientPropModel = new ClientPropertyModel(this);
117 clientPropModel->setSourceModel(ObjectBroker::model(name + QStringLiteral(".argumentProperties")));
118 ui->argumentView->setModel(clientPropModel);
119 ui->stackTraceView->setModel(ObjectBroker::model(name + QStringLiteral(".stackTrace")));
120
121 ui->replayWidget->setName(name + QStringLiteral(".remoteView"));
122
123 m_iface = ObjectBroker::object<PaintAnalyzerInterface*>(name);
124 connect(m_iface, &PaintAnalyzerInterface::hasArgumentDetailsChanged, this, &PaintAnalyzerWidget::detailsChanged);
125 connect(m_iface, &PaintAnalyzerInterface::hasStackTraceChanged, this, &PaintAnalyzerWidget::detailsChanged);
126 detailsChanged();
127 }
128
detailsChanged()129 void PaintAnalyzerWidget::detailsChanged()
130 {
131 const auto hasAnyDetails = m_iface->hasArgumentDetails() || m_iface->hasStackTrace();
132 ui->detailsTabWidget->setVisible(hasAnyDetails);
133 if (!hasAnyDetails)
134 return;
135
136 const auto hasAllDetails = m_iface->hasArgumentDetails() && m_iface->hasStackTrace();
137 ui->detailsTabWidget->tabBar()->setVisible(hasAllDetails);
138 if (hasAllDetails)
139 return;
140
141 ui->detailsTabWidget->setCurrentWidget(m_iface->hasArgumentDetails() ? ui->argumentTab : ui->stackTraceTab);
142 }
143
commandContextMenu(QPoint pos)144 void PaintAnalyzerWidget::commandContextMenu(QPoint pos)
145 {
146 const auto idx = ui->commandView->indexAt(pos);
147 if (!idx.isValid())
148 return;
149
150 const auto objectId = idx.data(PaintBufferModelRoles::ObjectIdRole).value<ObjectId>();
151
152 QMenu contextMenu;
153 ContextMenuExtension cme(objectId);
154 cme.populateMenu(&contextMenu);
155 contextMenu.exec(ui->commandView->viewport()->mapToGlobal(pos));
156 }
157
stackTraceContextMenu(QPoint pos)158 void PaintAnalyzerWidget::stackTraceContextMenu(QPoint pos)
159 {
160 const auto idx = ui->stackTraceView->indexAt(pos);
161 if (!idx.isValid())
162 return;
163
164 const auto loc = idx.sibling(idx.row(), 1).data().value<SourceLocation>();
165 if (!loc.isValid())
166 return;
167
168 QMenu contextMenu;
169 ContextMenuExtension cme;
170 cme.setLocation(ContextMenuExtension::ShowSource, loc);
171 cme.populateMenu(&contextMenu);
172 contextMenu.exec(ui->stackTraceView->viewport()->mapToGlobal(pos));
173 }
174