1 /*
2 * Copyright (c) 2018 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19
20 #include "LogDockerDock.h"
21
22 #include <QHBoxLayout>
23 #include <QToolButton>
24 #include <QScrollBar>
25 #include <QStandardPaths>
26 #include <QDateTime>
27 #include <QCheckBox>
28
29 #include <klocalizedstring.h>
30 #include <ksharedconfig.h>
31 #include <kconfiggroup.h>
32
33 #include <KisPart.h>
34 #include <KoDialog.h>
35 #include <KoCanvasBase.h>
36 #include <KoIcon.h>
37 #include <KoFileDialog.h>
38
39 #include "kis_canvas2.h"
40 #include "KisViewManager.h"
41 #include "kis_config.h"
42
43 MessageSender *LogDockerDock::s_messageSender {new MessageSender()};
44 QTextCharFormat LogDockerDock::s_debug;
45 QTextCharFormat LogDockerDock::s_info;
46 QTextCharFormat LogDockerDock::s_warning;
47 QTextCharFormat LogDockerDock::s_critical;
48 QTextCharFormat LogDockerDock::s_fatal;
49
LogDockerDock()50 LogDockerDock::LogDockerDock( )
51 : QDockWidget(i18n("Log Viewer"))
52 {
53 QWidget *page = new QWidget(this);
54 setupUi(page);
55 setWidget(page);
56
57 bnToggle->setIcon(koIcon("view-list-text"));
58 connect(bnToggle, SIGNAL(clicked(bool)), SLOT(toggleLogging(bool)));
59 bnToggle->setChecked(KisConfig(true).readEntry<bool>("logviewer_enabled", false));
60 toggleLogging(KisConfig(true).readEntry<bool>("logviewer_enabled", false));
61
62 bnClear->setIcon(koIcon("edit-clear"));
63 connect(bnClear, SIGNAL(clicked(bool)), SLOT(clearLog()));
64
65 bnSave->setIcon(koIcon("document-save"));
66 connect(bnSave, SIGNAL(clicked(bool)), SLOT(saveLog()));
67
68 bnSettings->setIcon(koIcon("configure"));
69 connect(bnSettings, SIGNAL(clicked(bool)), SLOT(settings()));
70
71 qRegisterMetaType<QtMsgType>("QtMsgType");
72 connect(s_messageSender, SIGNAL(emitMessage(QtMsgType,QString)), this, SLOT(insertMessage(QtMsgType,QString)), Qt::AutoConnection);
73
74 applyCategories();
75 changeTheme();
76 }
77
setCanvas(KoCanvasBase *)78 void LogDockerDock::setCanvas(KoCanvasBase *)
79 {
80 setEnabled(true);
81 }
82
setViewManager(KisViewManager * kisview)83 void LogDockerDock::setViewManager(KisViewManager *kisview)
84 {
85 connect(static_cast<KisMainWindow*>(kisview->mainWindow()), SIGNAL(themeChanged()), SLOT(changeTheme()));
86 }
87
toggleLogging(bool toggle)88 void LogDockerDock::toggleLogging(bool toggle)
89 {
90 KisConfig(false).writeEntry<bool>("logviewer_enabled", toggle);
91 if (toggle) {
92 qInstallMessageHandler(messageHandler);
93 applyCategories();
94 }
95 else {
96 qInstallMessageHandler(0);
97 }
98
99 }
100
clearLog()101 void LogDockerDock::clearLog()
102 {
103 txtLogViewer->document()->clear();
104 }
105
saveLog()106 void LogDockerDock::saveLog()
107 {
108 KoFileDialog fileDialog(this, KoFileDialog::SaveFile, "logfile");
109 fileDialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + QString("krita_%1.log").arg(QDateTime::currentDateTime().toString()));
110 QString filename = fileDialog.filename();
111 if (!filename.isEmpty()) {
112 QFile f(filename);
113 f.open(QFile::WriteOnly);
114 f.write(txtLogViewer->document()->toPlainText().toUtf8());
115 f.close();
116 }
117 }
118
settings()119 void LogDockerDock::settings()
120 {
121 KoDialog dlg(this);
122 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
123 dlg.setCaption(i18n("Log Settings"));
124 QWidget *page = new QWidget(&dlg);
125 dlg.setMainWidget(page);
126 QVBoxLayout *layout = new QVBoxLayout(page);
127
128 KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker");
129
130 QCheckBox *chkKrita = new QCheckBox(i18n("General"), page);
131 chkKrita->setChecked(cfg.readEntry("krita_41000", false));
132 layout->addWidget(chkKrita);
133
134 QCheckBox *chkResources = new QCheckBox(i18n("Resource Management"), page);
135 chkResources->setChecked(cfg.readEntry("resources_30009", false));
136 layout->addWidget(chkResources);
137
138 QCheckBox *chkImage = new QCheckBox(i18n("Image Core"), page);
139 chkImage->setChecked(cfg.readEntry("image_41001", false));
140 layout->addWidget(chkImage);
141
142 QCheckBox *chkRegistry = new QCheckBox(i18n("Registries"), page);
143 chkRegistry->setChecked(cfg.readEntry("registry_41002", false));
144 layout->addWidget(chkRegistry);
145
146 QCheckBox *chkTools = new QCheckBox(i18n("Tools"), page);
147 chkTools->setChecked(cfg.readEntry("tools_41003", false));
148 layout->addWidget(chkTools);
149
150 QCheckBox *chkTiles = new QCheckBox(i18n("Tile Engine"), page);
151 chkTiles->setChecked(cfg.readEntry("tiles_41004", false));
152 layout->addWidget(chkTiles);
153
154 QCheckBox *chkFilters = new QCheckBox(i18n("Filters"), page);
155 chkFilters->setChecked(cfg.readEntry("filters_41005", false));
156 layout->addWidget(chkFilters);
157
158 QCheckBox *chkPlugins = new QCheckBox(i18n("Plugin Management"), page);
159 chkPlugins->setChecked(cfg.readEntry("plugins_41006", false));
160 layout->addWidget(chkPlugins);
161
162 QCheckBox *chkUi = new QCheckBox(i18n("User Interface"), page);
163 chkUi->setChecked(cfg.readEntry("ui_41007", false));
164 layout->addWidget(chkUi);
165
166 QCheckBox *chkFile = new QCheckBox(i18n("File loading and saving"), page);
167 chkFile->setChecked(cfg.readEntry("file_41008", false));
168 layout->addWidget(chkFile);
169
170 QCheckBox *chkMath = new QCheckBox(i18n("Mathematics and calculations"), page);
171 chkMath->setChecked(cfg.readEntry("math_41009", false));
172 layout->addWidget(chkMath);
173
174 QCheckBox *chkRender = new QCheckBox(i18n("Image Rendering"), page);
175 chkRender->setChecked(cfg.readEntry("render_41010", false));
176 layout->addWidget(chkRender);
177
178 QCheckBox *chkScript = new QCheckBox(i18n("Scripting"), page);
179 chkScript->setChecked(cfg.readEntry("script_41011", false));
180 layout->addWidget(chkScript);
181
182 QCheckBox *chkInput = new QCheckBox(i18n("Input handling"), page);
183 chkInput->setChecked(cfg.readEntry("input_41012", false));
184 layout->addWidget(chkInput);
185
186 QCheckBox *chkAction = new QCheckBox(i18n("Actions"), page);
187 chkAction->setChecked(cfg.readEntry("action_41013", false));
188 layout->addWidget(chkAction);
189
190 QCheckBox *chkTablet = new QCheckBox(i18n("Tablet Handling"), page);
191 chkTablet->setChecked(cfg.readEntry("tablet_41014", false));
192 layout->addWidget(chkTablet);
193
194 QCheckBox *chkOpenGL = new QCheckBox(i18n("GPU Canvas"), page);
195 chkOpenGL->setChecked(cfg.readEntry("opengl_41015", false));
196 layout->addWidget(chkOpenGL);
197
198 QCheckBox *chkMetaData = new QCheckBox(i18n("Metadata"), page);
199 chkMetaData->setChecked(cfg.readEntry("metadata_41016", false));
200 layout->addWidget(chkMetaData);
201
202 QCheckBox *chkPigment = new QCheckBox(i18n("Color Management"), page);
203 chkPigment->setChecked(cfg.readEntry("pigment", false));
204 layout->addWidget(chkPigment);
205
206
207 if (dlg.exec()) {
208 // Apply the new settings
209 cfg.writeEntry("resources_30009", chkResources->isChecked());
210 cfg.writeEntry("krita_41000", chkKrita->isChecked());
211 cfg.writeEntry("image_41001", chkImage->isChecked());
212 cfg.writeEntry("registry_41002", chkRegistry->isChecked());
213 cfg.writeEntry("tools_41003", chkTools->isChecked());
214 cfg.writeEntry("tiles_41004", chkTiles->isChecked());
215 cfg.writeEntry("filters_41005", chkFilters->isChecked());
216 cfg.writeEntry("plugins_41006", chkPlugins->isChecked());
217 cfg.writeEntry("ui_41007", chkUi->isChecked());
218 cfg.writeEntry("file_41008", chkFile->isChecked());
219 cfg.writeEntry("math_41009", chkMath->isChecked());
220 cfg.writeEntry("render_41010", chkRender->isChecked());
221 cfg.writeEntry("script_41011", chkScript->isChecked());
222 cfg.writeEntry("input_41012", chkInput->isChecked());
223 cfg.writeEntry("action_41013", chkAction->isChecked());
224 cfg.writeEntry("tablet_41014", chkTablet->isChecked());
225 cfg.writeEntry("opengl_41015", chkOpenGL->isChecked());
226 cfg.writeEntry("metadata_41016", chkMetaData->isChecked());
227 cfg.writeEntry("pigment", chkPigment->isChecked());
228
229 applyCategories();
230 }
231
232 }
233
cfgToString(QString tpl,bool cfg)234 QString cfgToString(QString tpl, bool cfg)
235 {
236 return tpl.arg(cfg ? "true" : "false");
237 }
238
applyCategories()239 void LogDockerDock::applyCategories()
240 {
241 QStringList filters;
242 KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker");
243
244 filters << cfgToString("krita.general=%1", cfg.readEntry("krita_41000", false));
245 filters << cfgToString("krita.lib.resources=%1", cfg.readEntry("resources_30009", false));
246 filters << cfgToString("krita.core=%1", cfg.readEntry("image_41001", false));
247 filters << cfgToString("krita.registry=%1", cfg.readEntry("registry_41002", false));
248
249 filters << cfgToString("krita.tools=%1", cfg.readEntry("tools_41003", false));
250 filters << cfgToString("krita.lib.flake=%1", cfg.readEntry("tools_41003", false));
251
252 filters << cfgToString("krita.tiles=%1", cfg.readEntry("tiles_41004", false));
253 filters << cfgToString("krita.filters=%1", cfg.readEntry("filters_41005", false));
254
255 filters << cfgToString("krita.plugins=%1", cfg.readEntry("plugins_41006", false));
256 filters << cfgToString("krita.lib.plugin=%1", cfg.readEntry("plugins_41006", false));
257
258 filters << cfgToString("krita.ui=%1", cfg.readEntry("ui_41007", false));
259 filters << cfgToString("krita.widgets=%1", cfg.readEntry("ui_41007", false));
260 filters << cfgToString("krita.widgetutils=%1", cfg.readEntry("ui_41007", false));
261
262 filters << cfgToString("krita.file=%1", cfg.readEntry("file_41008", false));
263 filters << cfgToString("krita.lib.store=%1", cfg.readEntry("file_41008", false));
264 filters << cfgToString("krita.lib.odf=%1", cfg.readEntry("file_41008", false));
265
266 filters << cfgToString("krita.math=%1", cfg.readEntry("math_41009", false));
267 filters << cfgToString("krita.grender=%1", cfg.readEntry("render_41010", false));
268 filters << cfgToString("krita.scripting=%1", cfg.readEntry("script_41011", false));
269 filters << cfgToString("krita.input=%1", cfg.readEntry("input_41012", false));
270 filters << cfgToString("krita.action=%1", cfg.readEntry("action_41013", false));
271 filters << cfgToString("krita.tablet=%1", cfg.readEntry("tablet_41014", false));
272 filters << cfgToString("krita.opengl=%1", cfg.readEntry("opengl_41015", false));
273 filters << cfgToString("krita.metadata=%1", cfg.readEntry("metadata_41016", false));
274
275 filters << cfgToString("krita.lib.pigment=%1", cfg.readEntry("pigment", false));
276
277 QLoggingCategory::setFilterRules(filters.join("\n"));
278 }
279
messageHandler(QtMsgType type,const QMessageLogContext &,const QString & msg)280 void LogDockerDock::messageHandler(QtMsgType type, const QMessageLogContext &/*context*/, const QString &msg)
281 {
282 s_messageSender->sendMessage(type, msg);
283 }
284
insertMessage(QtMsgType type,const QString & msg)285 void LogDockerDock::insertMessage(QtMsgType type, const QString &msg)
286 {
287 QTextDocument *doc = txtLogViewer->document();
288 QTextCursor cursor(doc);
289 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
290 cursor.beginEditBlock();
291
292 switch (type) {
293 case QtDebugMsg:
294 cursor.insertText(msg + "\n", s_debug);
295 break;
296 case QtInfoMsg:
297 cursor.insertText(msg + "\n", s_info);
298 break;
299 case QtWarningMsg:
300 cursor.insertText(msg + "\n", s_warning);
301 break;
302 case QtCriticalMsg:
303 cursor.insertText(msg + "\n", s_critical);
304 break;
305 case QtFatalMsg:
306 cursor.insertText(msg + "\n", s_fatal);
307 break;
308 }
309
310 cursor.endEditBlock();
311 txtLogViewer->verticalScrollBar()->setValue(txtLogViewer->verticalScrollBar()->maximum());
312 }
313
changeTheme()314 void LogDockerDock::changeTheme()
315 {
316 clearLog();
317 QColor background = qApp->palette().window().color();
318 if (background.value() > 100) {
319 s_debug.setForeground(Qt::black);
320 s_info.setForeground(Qt::darkGreen);
321 s_warning.setForeground(Qt::darkYellow);
322 s_critical.setForeground(Qt::darkRed);
323 s_fatal.setForeground(Qt::darkRed);
324 }
325 else {
326 s_debug.setForeground(Qt::white);
327 s_info.setForeground(Qt::green);
328 s_warning.setForeground(Qt::yellow);
329 s_critical.setForeground(Qt::red);
330 s_fatal.setForeground(Qt::red);
331 }
332 s_fatal.setFontWeight(QFont::Bold);
333 }
334
sendMessage(QtMsgType type,const QString & msg)335 void MessageSender::sendMessage(QtMsgType type, const QString &msg)
336 {
337 emit emitMessage(type, msg);
338 }
339