1 /*
2 This file is part of KCachegrind.
3
4 SPDX-FileCopyrightText: 2009-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
5
6 SPDX-License-Identifier: GPL-2.0-only
7 */
8
9 /*
10 * Source annotation directory settings config page
11 */
12
13 #include "sourcesettings.h"
14
15 #include <QTreeWidgetItem>
16 #include <QFileDialog>
17
18 #include "tracedata.h"
19 #include "globalconfig.h"
20
21 //
22 // SourceSettings
23 //
24
SourceSettings(TraceData * data,QWidget * parent)25 SourceSettings::SourceSettings(TraceData* data, QWidget* parent)
26 : ConfigPage(parent,
27 QObject::tr("Source Annotation"),
28 QObject::tr("Directory Settings for Source Annotation"))
29 {
30 ui.setupUi(this);
31
32 ui.dirList->setRootIsDecorated(false);
33
34 GlobalConfig* c = GlobalConfig::config();
35 _always = tr("(always)");
36
37 QTreeWidgetItem* i;
38 QStringList::const_iterator sit = c->generalSourceDirs().constBegin();
39 for(; sit != c->generalSourceDirs().constEnd(); ++sit ) {
40 QString d = (*sit);
41 if (d.isEmpty()) d = QStringLiteral("/");
42 i = new QTreeWidgetItem();
43 i->setText(0, _always);
44 i->setText(1, d);
45 ui.dirList->addTopLevelItem(i);
46 }
47
48 QStringList objItems(_always);
49 if (data) {
50 TraceObjectMap::Iterator oit;
51 for ( oit = data->objectMap().begin();
52 oit != data->objectMap().end(); ++oit ) {
53 QString n = (*oit).name();
54 if (n.isEmpty()) continue;
55 objItems << n;
56
57 const QStringList& dirs = c->objectSourceDirs(n);
58 sit = dirs.constBegin();
59 for(; sit != dirs.constEnd(); ++sit ) {
60 QString d = (*sit);
61 if (d.isEmpty()) d = QStringLiteral("/");
62 i = new QTreeWidgetItem();
63 i->setText(0, n);
64 i->setText(1, d);
65 ui.dirList->addTopLevelItem(i);
66 }
67 }
68 }
69
70 ui.objectBox->addItems(objItems);
71 ui.objectBox->setCurrentIndex(0);
72
73 connect(ui.addDirButton, &QAbstractButton::clicked,
74 this, &SourceSettings::addClicked);
75 connect(ui.deleteDirButton, &QAbstractButton::clicked,
76 this, &SourceSettings::deleteClicked);
77 connect(ui.browseDirButton, &QAbstractButton::clicked,
78 this, &SourceSettings::browseClicked);
79 connect(ui.dirList,
80 &QTreeWidget::currentItemChanged,
81 this,
82 &SourceSettings::dirListItemChanged);
83 connect(ui.objectBox,
84 SIGNAL(currentIndexChanged(QString)),
85 this, SLOT(objectChanged(QString)));
86 connect(ui.dirEdit, SIGNAL(textChanged(QString)),
87 this, SLOT(dirEditChanged(QString)));
88
89 _current = nullptr;
90 update();
91 }
92
activate(QString s)93 void SourceSettings::activate(QString s)
94 {
95 int idx = s.toInt();
96 if ((idx==0) || (idx>ui.dirList->topLevelItemCount())) return;
97
98 ui.dirList->setCurrentItem(ui.dirList->topLevelItem(idx-1));
99 ui.dirEdit->setFocus();
100 }
101
update()102 void SourceSettings::update()
103 {
104 if (!_current) {
105 ui.deleteDirButton->setEnabled(false);
106 ui.objectBox->setEnabled(false);
107 ui.dirEdit->setEnabled(false);
108 ui.browseDirButton->setEnabled(false);
109 return;
110 }
111 ui.deleteDirButton->setEnabled(true);
112 ui.objectBox->setEnabled(true);
113 ui.objectBox->setCurrentIndex(ui.objectBox->findText(_current->text(0)));
114 ui.dirEdit->setEnabled(true);
115 ui.dirEdit->setText(_current->text(1));
116 ui.browseDirButton->setEnabled(true);
117 }
118
addClicked()119 void SourceSettings::addClicked()
120 {
121 int prevItemCount = ui.dirList->topLevelItemCount();
122 QTreeWidgetItem* i = new QTreeWidgetItem();
123 i->setText(0, ui.objectBox->currentText());
124 i->setText(1, tr("<insert valid directory>"));
125 ui.dirList->addTopLevelItem(i);
126 ui.dirList->setCurrentItem(i);
127 if (prevItemCount == 0 && ui.objectBox->currentText() == _always) {
128 // it's not obvious that you have to click browse after adding an item,
129 // but handle the case where we have no items and are looking for the
130 // default. give users an oppurtunity to select for multiple ELF objects
131 browseClicked();
132 }
133 }
134
deleteClicked()135 void SourceSettings::deleteClicked()
136 {
137 if (!_current) return;
138
139 QTreeWidgetItem* i = _current;
140 // the deletion removes the item
141 delete _current;
142 // deletion can trigger a call to dirListItemChanged() !
143 if (_current == i) {
144 _current = nullptr;
145 update();
146 }
147 }
148
browseClicked()149 void SourceSettings::browseClicked()
150 {
151 QString d;
152 d = QFileDialog::getExistingDirectory(this,
153 tr("Choose Source Directory"),
154 ui.dirEdit->text());
155 if (!d.isEmpty())
156 ui.dirEdit->setText(d);
157 }
158
dirListItemChanged(QTreeWidgetItem * current,QTreeWidgetItem *)159 void SourceSettings::dirListItemChanged(QTreeWidgetItem* current,
160 QTreeWidgetItem*)
161 {
162 _current = current;
163 update();
164 }
165
objectChanged(QString obj)166 void SourceSettings::objectChanged(QString obj)
167 {
168 if (!_current) return;
169
170 _current->setText(0, obj);
171 }
172
dirEditChanged(QString dir)173 void SourceSettings::dirEditChanged(QString dir)
174 {
175 if (!_current) return;
176
177 _current->setText(1, dir);
178 }
179
check(QString & errorMsg,QString & errorItem)180 bool SourceSettings::check(QString& errorMsg, QString& errorItem)
181 {
182 for(int idx=0; idx< ui.dirList->topLevelItemCount(); idx++) {
183 QTreeWidgetItem* item = ui.dirList->topLevelItem(idx);
184 QString dir = item->text(1);
185 if (QDir(dir).exists()) continue;
186 errorMsg = tr("Directory does not exist");
187 errorItem = QStringLiteral("%1").arg(idx+1);
188 return false;
189 }
190 return true;
191 }
192
accept()193 void SourceSettings::accept()
194 {
195 GlobalConfig* c = GlobalConfig::config();
196
197 QHash<QString, QStringList> dirs;
198 for(int idx=0; idx< ui.dirList->topLevelItemCount(); idx++) {
199 QTreeWidgetItem* item = ui.dirList->topLevelItem(idx);
200 dirs[item->text(0)] << item->text(1);
201 }
202
203 c->setGeneralSourceDirs(QStringList());
204 c->clearObjectSourceDirs();
205
206 QHash<QString, QStringList>::const_iterator oit = dirs.constBegin();
207 for(;oit != dirs.constEnd(); ++oit) {
208 if (oit.key() == _always)
209 c->setGeneralSourceDirs(oit.value());
210 else
211 c->setObjectSourceDirs(oit.key(), oit.value());
212 }
213 }
214
215