1 /*
2 SPDX-FileCopyrightText: 2011 Andi Fischer <andi.fischer@hispeed.ch>
3 SPDX-FileCopyrightText: 2012 Ralf Habacker <ralf.habacker@freenet.de>
4
5 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
6 */
7
8 #include "debug_utils.h"
9
10 #include <KLocalizedString>
11
12 #include <QFileInfo>
13
14 #if QT_VERSION >= 0x050000
15 Q_LOGGING_CATEGORY(UMBRELLO, "umbrello")
16 #endif
17
18 Tracer* Tracer::m_instance = nullptr;
19 Tracer::MapType *Tracer::m_classes = nullptr;
20 Tracer::StateMap *Tracer::m_states = nullptr;
21
instance()22 Tracer* Tracer::instance()
23 {
24 if (m_instance == nullptr) {
25 m_instance = new Tracer();
26 }
27 return m_instance;
28 }
29
30 /**
31 * Constructor.
32 * @param parent the parent widget
33 */
Tracer(QWidget * parent)34 Tracer::Tracer(QWidget *parent)
35 : QTreeWidget(parent)
36 {
37 // in case no one called registerClass() before
38 if (!m_classes)
39 m_classes = new Tracer::MapType;
40 if (!m_states)
41 m_states = new Tracer::StateMap;
42 setRootIsDecorated(true);
43 setAlternatingRowColors(true);
44 setHeaderLabel(i18n("Class Name"));
45 setContextMenuPolicy(Qt::CustomContextMenu);
46 connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(slotItemClicked(QTreeWidgetItem*,int)));
47 }
48
49 /**
50 * Destructor.
51 */
~Tracer()52 Tracer::~Tracer()
53 {
54 clear();
55 delete m_classes;
56 m_classes = nullptr;
57 delete m_states;
58 m_states = nullptr;
59 }
60
61 /**
62 * Return debugging state for a given class
63 * @param name the class name to check
64 */
isEnabled(const QString & name) const65 bool Tracer::isEnabled(const QString& name) const
66 {
67 return (*m_classes)[name].state;
68 }
69
70 /**
71 * Enable debug output for the given class.
72 * @param name class name
73 */
enable(const QString & name)74 void Tracer::enable(const QString& name)
75 {
76 (*m_classes)[name].state = true;
77 update(name);
78 }
79
80 /**
81 * Disable debug output for the given class.
82 * @param name class name
83 */
disable(const QString & name)84 void Tracer::disable(const QString& name)
85 {
86 (*m_classes)[name].state = false;
87 update(name);
88 }
89
enableAll()90 void Tracer::enableAll()
91 {
92 //:TODO:
93 }
94
disableAll()95 void Tracer::disableAll()
96 {
97 //:TODO:
98 }
99
100 /**
101 * Register class for debug output
102 * @param name class name
103 * @param state initial enabled state
104 */
registerClass(const QString & name,bool state,const QString & filePath)105 void Tracer::registerClass(const QString& name, bool state, const QString &filePath)
106 {
107 if (!m_classes)
108 m_classes = new MapType;
109 QFileInfo fi(filePath);
110 QString dirName = fi.absolutePath();
111 QFileInfo f(dirName);
112 QString path = f.fileName();
113 (*m_classes)[name] = MapEntry(path, state);
114 }
115
116 /**
117 * Transfer class state into tree widget.
118 * @param name class name
119 */
update(const QString & name)120 void Tracer::update(const QString &name)
121 {
122 if (!isVisible())
123 return;
124 QList<QTreeWidgetItem*> items = findItems(name, Qt::MatchFixedString);
125 foreach(QTreeWidgetItem* item, items) {
126 item->setCheckState(0, (*m_classes)[name].state ? Qt::Checked : Qt::Unchecked);
127 }
128 }
129
130 /**
131 * Update check box of parent items.
132 *
133 * @param parent parent widget item
134 */
updateParentItemCheckBox(QTreeWidgetItem * parent)135 void Tracer::updateParentItemCheckBox(QTreeWidgetItem* parent)
136 {
137 int selectedCount = 0;
138 for(int i = 0; i < parent->childCount(); i++) {
139 if (parent->child(i)->checkState(0) == Qt::Checked)
140 selectedCount++;
141 }
142 if (selectedCount == parent->childCount())
143 parent->setCheckState(0, Qt::Checked);
144 else if (selectedCount == 0)
145 parent->setCheckState(0, Qt::Unchecked);
146 else
147 parent->setCheckState(0, Qt::PartiallyChecked);
148
149 (*m_states)[parent->text(0)] = parent->checkState(0);
150 }
151
152 /**
153 * Fill tree widget with collected classes.
154 */
showEvent(QShowEvent * e)155 void Tracer::showEvent(QShowEvent* e)
156 {
157 Q_UNUSED(e);
158
159 clear();
160 MapType::const_iterator i = m_classes->constBegin();
161 for(; i != m_classes->constEnd(); i++) {
162 QList<QTreeWidgetItem*> items = findItems(i.value().filePath, Qt::MatchFixedString);
163 QTreeWidgetItem* topLevel = nullptr;
164 if (items.size() == 0) {
165 topLevel = new QTreeWidgetItem(QStringList(i.value().filePath));
166 topLevel->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
167 updateParentItemCheckBox(topLevel);
168 addTopLevelItem(topLevel);
169 }
170 else
171 topLevel = items.first();
172
173 QTreeWidgetItem* item = new QTreeWidgetItem(topLevel, QStringList(i.key()));
174 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
175 item->setCheckState(0, i.value().state ? Qt::Checked : Qt::Unchecked);
176 }
177
178 for(int i = 0; i < topLevelItemCount(); i++)
179 updateParentItemCheckBox(topLevelItem(i));
180 }
181
182 /**
183 */
slotParentItemClicked(QTreeWidgetItem * parent)184 void Tracer::slotParentItemClicked(QTreeWidgetItem* parent)
185 {
186 // @TODO parent->checkState(0) do not return the correct state
187 // Qt::CheckState state = parent->checkState(0);
188 Qt::CheckState state = (*m_states)[parent->text(0)];
189 if (state == Qt::PartiallyChecked || state == Qt::Unchecked) {
190 for(int i = 0; i < parent->childCount(); i++) {
191 QString text = parent->child(i)->text(0);
192 (*m_classes)[text].state = true;
193 parent->child(i)->setCheckState(0, (*m_classes)[text].state ? Qt::Checked : Qt::Unchecked);
194 }
195 } else if (state == Qt::Checked) {
196 for(int i = 0; i < parent->childCount(); i++) {
197 QString text = parent->child(i)->text(0);
198 (*m_classes)[text].state = false;
199 parent->child(i)->setCheckState(0, (*m_classes)[text].state ? Qt::Checked : Qt::Unchecked);
200 }
201 }
202 updateParentItemCheckBox(parent);
203 }
204
205 /**
206 * handle tree widget item selection signal
207 * @param item tree widget item
208 * @param column selected column
209 */
slotItemClicked(QTreeWidgetItem * item,int column)210 void Tracer::slotItemClicked(QTreeWidgetItem* item, int column)
211 {
212 Q_UNUSED(column);
213
214 if (item->parent()) {
215 (*m_classes)[item->text(0)].state = !(*m_classes)[item->text(0)].state;
216 item->setCheckState(0, (*m_classes)[item->text(0)].state ? Qt::Checked : Qt::Unchecked);
217 updateParentItemCheckBox(item->parent());
218 return;
219 }
220 slotParentItemClicked(item);
221 }
222