File indexing completed on 2024-12-22 04:14:52
0001 /* 0002 * SPDX-FileCopyrightText: 2018 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 0008 #include "LogDockerDock.h" 0009 0010 #include <QHBoxLayout> 0011 #include <QToolButton> 0012 #include <QScrollBar> 0013 #include <QStandardPaths> 0014 #include <QDateTime> 0015 #include <QCheckBox> 0016 0017 #include <klocalizedstring.h> 0018 #include <ksharedconfig.h> 0019 #include <kconfiggroup.h> 0020 0021 #include <KisPart.h> 0022 #include <KoDialog.h> 0023 #include <KoCanvasBase.h> 0024 #include <KoIcon.h> 0025 #include <KoFileDialog.h> 0026 0027 #include "kis_canvas2.h" 0028 #include "KisViewManager.h" 0029 #include "KisMainWindow.h" 0030 #include "kis_config.h" 0031 0032 MessageSender *LogDockerDock::s_messageSender {new MessageSender()}; 0033 QTextCharFormat LogDockerDock::s_debug; 0034 QTextCharFormat LogDockerDock::s_info; 0035 QTextCharFormat LogDockerDock::s_warning; 0036 QTextCharFormat LogDockerDock::s_critical; 0037 QTextCharFormat LogDockerDock::s_fatal; 0038 0039 static QtMessageHandler s_originalMessageHandler{nullptr}; 0040 0041 LogDockerDock::LogDockerDock( ) 0042 : QDockWidget(i18n("Log Viewer")) 0043 { 0044 QWidget *page = new QWidget(this); 0045 setupUi(page); 0046 setWidget(page); 0047 0048 bnToggle->setIcon(koIcon("view-list-text-16")); 0049 connect(bnToggle, SIGNAL(clicked(bool)), SLOT(toggleLogging(bool))); 0050 bnToggle->setChecked(KisConfig(true).readEntry<bool>("logviewer_enabled", false)); 0051 toggleLogging(KisConfig(true).readEntry<bool>("logviewer_enabled", false)); 0052 0053 bnClear->setIcon(koIcon("edit-clear-16")); 0054 connect(bnClear, SIGNAL(clicked(bool)), SLOT(clearLog())); 0055 0056 bnSave->setIcon(koIcon("document-save-16")); 0057 connect(bnSave, SIGNAL(clicked(bool)), SLOT(saveLog())); 0058 0059 bnSettings->setIcon(koIcon("configure-thicker")); 0060 connect(bnSettings, SIGNAL(clicked(bool)), SLOT(settings())); 0061 0062 qRegisterMetaType<QtMsgType>("QtMsgType"); 0063 connect(s_messageSender, SIGNAL(emitMessage(QtMsgType,QString)), this, SLOT(insertMessage(QtMsgType,QString)), Qt::AutoConnection); 0064 0065 changeTheme(); 0066 } 0067 0068 void LogDockerDock::setCanvas(KoCanvasBase *) 0069 { 0070 setEnabled(true); 0071 } 0072 0073 void LogDockerDock::setViewManager(KisViewManager *kisview) 0074 { 0075 connect(kisview->mainWindow(), SIGNAL(themeChanged()), SLOT(changeTheme())); 0076 } 0077 0078 void LogDockerDock::toggleLogging(bool toggle) 0079 { 0080 KisConfig(false).writeEntry<bool>("logviewer_enabled", toggle); 0081 if (toggle) { 0082 const QtMessageHandler oldHandler = qInstallMessageHandler(messageHandler); 0083 if (!s_originalMessageHandler) { 0084 s_originalMessageHandler = oldHandler; 0085 } 0086 applyCategories(); 0087 } 0088 else { 0089 qInstallMessageHandler(nullptr); 0090 QLoggingCategory::setFilterRules(QString()); 0091 } 0092 0093 } 0094 0095 void LogDockerDock::clearLog() 0096 { 0097 txtLogViewer->document()->clear(); 0098 } 0099 0100 void LogDockerDock::saveLog() 0101 { 0102 KoFileDialog fileDialog(this, KoFileDialog::SaveFile, "logfile"); 0103 fileDialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + QString("krita_%1.log").arg(QDateTime::currentDateTime().toString("yyyy-MM-ddThh"))); 0104 QString filename = fileDialog.filename(); 0105 if (!filename.isEmpty()) { 0106 QFile f(filename); 0107 f.open(QFile::WriteOnly); 0108 f.write(txtLogViewer->document()->toPlainText().toUtf8()); 0109 f.close(); 0110 } 0111 } 0112 0113 void LogDockerDock::settings() 0114 { 0115 KoDialog dlg(this); 0116 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel); 0117 dlg.setCaption(i18n("Log Settings")); 0118 QWidget *page = new QWidget(&dlg); 0119 dlg.setMainWidget(page); 0120 QVBoxLayout *layout = new QVBoxLayout(page); 0121 0122 KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker"); 0123 0124 QCheckBox *chkKrita = new QCheckBox(i18n("General"), page); 0125 chkKrita->setChecked(cfg.readEntry("krita_41000", false)); 0126 layout->addWidget(chkKrita); 0127 0128 QCheckBox *chkResources = new QCheckBox(i18n("Resource Management"), page); 0129 chkResources->setChecked(cfg.readEntry("resources_30009", false)); 0130 layout->addWidget(chkResources); 0131 0132 QCheckBox *chkImage = new QCheckBox(i18n("Image Core"), page); 0133 chkImage->setChecked(cfg.readEntry("image_41001", false)); 0134 layout->addWidget(chkImage); 0135 0136 QCheckBox *chkRegistry = new QCheckBox(i18n("Registries"), page); 0137 chkRegistry->setChecked(cfg.readEntry("registry_41002", false)); 0138 layout->addWidget(chkRegistry); 0139 0140 QCheckBox *chkTools = new QCheckBox(i18n("Tools"), page); 0141 chkTools->setChecked(cfg.readEntry("tools_41003", false)); 0142 layout->addWidget(chkTools); 0143 0144 QCheckBox *chkTiles = new QCheckBox(i18n("Tile Engine"), page); 0145 chkTiles->setChecked(cfg.readEntry("tiles_41004", false)); 0146 layout->addWidget(chkTiles); 0147 0148 QCheckBox *chkFilters = new QCheckBox(i18nc("Filter as an effect", "Filters"), page); 0149 chkFilters->setChecked(cfg.readEntry("filters_41005", false)); 0150 layout->addWidget(chkFilters); 0151 0152 QCheckBox *chkPlugins = new QCheckBox(i18n("Plugin Management"), page); 0153 chkPlugins->setChecked(cfg.readEntry("plugins_41006", false)); 0154 layout->addWidget(chkPlugins); 0155 0156 QCheckBox *chkUi = new QCheckBox(i18n("User Interface"), page); 0157 chkUi->setChecked(cfg.readEntry("ui_41007", false)); 0158 layout->addWidget(chkUi); 0159 0160 QCheckBox *chkFile = new QCheckBox(i18n("File loading and saving"), page); 0161 chkFile->setChecked(cfg.readEntry("file_41008", false)); 0162 layout->addWidget(chkFile); 0163 0164 QCheckBox *chkMath = new QCheckBox(i18n("Mathematics and calculations"), page); 0165 chkMath->setChecked(cfg.readEntry("math_41009", false)); 0166 layout->addWidget(chkMath); 0167 0168 QCheckBox *chkRender = new QCheckBox(i18n("Image Rendering"), page); 0169 chkRender->setChecked(cfg.readEntry("render_41010", false)); 0170 layout->addWidget(chkRender); 0171 0172 QCheckBox *chkScript = new QCheckBox(i18n("Scripting"), page); 0173 chkScript->setChecked(cfg.readEntry("script_41011", false)); 0174 layout->addWidget(chkScript); 0175 0176 QCheckBox *chkInput = new QCheckBox(i18n("Input handling"), page); 0177 chkInput->setChecked(cfg.readEntry("input_41012", false)); 0178 layout->addWidget(chkInput); 0179 0180 QCheckBox *chkAction = new QCheckBox(i18n("Actions"), page); 0181 chkAction->setChecked(cfg.readEntry("action_41013", false)); 0182 layout->addWidget(chkAction); 0183 0184 QCheckBox *chkTablet = new QCheckBox(i18n("Tablet Handling"), page); 0185 chkTablet->setChecked(cfg.readEntry("tablet_41014", false)); 0186 layout->addWidget(chkTablet); 0187 0188 QCheckBox *chkOpenGL = new QCheckBox(i18n("GPU Canvas"), page); 0189 chkOpenGL->setChecked(cfg.readEntry("opengl_41015", false)); 0190 layout->addWidget(chkOpenGL); 0191 0192 QCheckBox *chkMetaData = new QCheckBox(i18n("Metadata"), page); 0193 chkMetaData->setChecked(cfg.readEntry("metadata_41016", false)); 0194 layout->addWidget(chkMetaData); 0195 0196 QCheckBox *chkPigment = new QCheckBox(i18n("Color Management"), page); 0197 chkPigment->setChecked(cfg.readEntry("pigment", false)); 0198 layout->addWidget(chkPigment); 0199 0200 0201 if (dlg.exec()) { 0202 // Apply the new settings 0203 cfg.writeEntry("resources_30009", chkResources->isChecked()); 0204 cfg.writeEntry("krita_41000", chkKrita->isChecked()); 0205 cfg.writeEntry("image_41001", chkImage->isChecked()); 0206 cfg.writeEntry("registry_41002", chkRegistry->isChecked()); 0207 cfg.writeEntry("tools_41003", chkTools->isChecked()); 0208 cfg.writeEntry("tiles_41004", chkTiles->isChecked()); 0209 cfg.writeEntry("filters_41005", chkFilters->isChecked()); 0210 cfg.writeEntry("plugins_41006", chkPlugins->isChecked()); 0211 cfg.writeEntry("ui_41007", chkUi->isChecked()); 0212 cfg.writeEntry("file_41008", chkFile->isChecked()); 0213 cfg.writeEntry("math_41009", chkMath->isChecked()); 0214 cfg.writeEntry("render_41010", chkRender->isChecked()); 0215 cfg.writeEntry("script_41011", chkScript->isChecked()); 0216 cfg.writeEntry("input_41012", chkInput->isChecked()); 0217 cfg.writeEntry("action_41013", chkAction->isChecked()); 0218 cfg.writeEntry("tablet_41014", chkTablet->isChecked()); 0219 cfg.writeEntry("opengl_41015", chkOpenGL->isChecked()); 0220 cfg.writeEntry("metadata_41016", chkMetaData->isChecked()); 0221 cfg.writeEntry("pigment", chkPigment->isChecked()); 0222 0223 if (bnToggle->isChecked()) { 0224 applyCategories(); 0225 } 0226 } 0227 0228 } 0229 0230 QString cfgToString(const char *category, bool cfg) 0231 { 0232 if (cfg) { 0233 return QStringLiteral("%0=true").arg(QLatin1String(category)); 0234 } 0235 return QStringLiteral("%0.debug=false").arg(QLatin1String(category)); 0236 } 0237 0238 void LogDockerDock::applyCategories() 0239 { 0240 QStringList filters; 0241 KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker"); 0242 0243 filters << cfgToString("krita.general", cfg.readEntry("krita_41000", false)); 0244 filters << cfgToString("krita.lib.resources", cfg.readEntry("resources_30009", false)); 0245 filters << cfgToString("krita.core", cfg.readEntry("image_41001", false)); 0246 filters << cfgToString("krita.registry", cfg.readEntry("registry_41002", false)); 0247 0248 filters << cfgToString("krita.tools", cfg.readEntry("tools_41003", false)); 0249 filters << cfgToString("krita.lib.flake", cfg.readEntry("tools_41003", false)); 0250 0251 filters << cfgToString("krita.tiles", cfg.readEntry("tiles_41004", false)); 0252 filters << cfgToString("krita.filters", cfg.readEntry("filters_41005", false)); 0253 0254 filters << cfgToString("krita.plugins", cfg.readEntry("plugins_41006", false)); 0255 filters << cfgToString("krita.lib.plugin", cfg.readEntry("plugins_41006", false)); 0256 0257 filters << cfgToString("krita.ui", cfg.readEntry("ui_41007", false)); 0258 filters << cfgToString("krita.widgets", cfg.readEntry("ui_41007", false)); 0259 filters << cfgToString("krita.widgetutils", cfg.readEntry("ui_41007", false)); 0260 0261 filters << cfgToString("krita.file", cfg.readEntry("file_41008", false)); 0262 filters << cfgToString("krita.lib.store", cfg.readEntry("file_41008", false)); 0263 filters << cfgToString("krita.lib.odf", cfg.readEntry("file_41008", false)); 0264 0265 filters << cfgToString("krita.math", cfg.readEntry("math_41009", false)); 0266 filters << cfgToString("krita.grender", cfg.readEntry("render_41010", false)); 0267 filters << cfgToString("krita.scripting", cfg.readEntry("script_41011", false)); 0268 filters << cfgToString("krita.input", cfg.readEntry("input_41012", false)); 0269 filters << cfgToString("krita.action", cfg.readEntry("action_41013", false)); 0270 filters << cfgToString("krita.tablet", cfg.readEntry("tablet_41014", false)); 0271 filters << cfgToString("krita.opengl", cfg.readEntry("opengl_41015", false)); 0272 filters << cfgToString("krita.metadata", cfg.readEntry("metadata_41016", false)); 0273 0274 filters << cfgToString("krita.lib.pigment", cfg.readEntry("pigment", false)); 0275 0276 QLoggingCategory::setFilterRules(filters.join("\n")); 0277 } 0278 0279 void LogDockerDock::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) 0280 { 0281 s_messageSender->sendMessage(type, msg); 0282 if (s_originalMessageHandler) { 0283 s_originalMessageHandler(type, context, msg); 0284 } 0285 } 0286 0287 void LogDockerDock::insertMessage(QtMsgType type, const QString &msg) 0288 { 0289 QTextDocument *doc = txtLogViewer->document(); 0290 QTextCursor cursor(doc); 0291 cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); 0292 cursor.beginEditBlock(); 0293 0294 switch (type) { 0295 case QtDebugMsg: 0296 cursor.insertText(msg + "\n", s_debug); 0297 break; 0298 case QtInfoMsg: 0299 cursor.insertText(msg + "\n", s_info); 0300 break; 0301 case QtWarningMsg: 0302 cursor.insertText(msg + "\n", s_warning); 0303 break; 0304 case QtCriticalMsg: 0305 cursor.insertText(msg + "\n", s_critical); 0306 break; 0307 case QtFatalMsg: 0308 cursor.insertText(msg + "\n", s_fatal); 0309 break; 0310 } 0311 0312 cursor.endEditBlock(); 0313 txtLogViewer->verticalScrollBar()->setValue(txtLogViewer->verticalScrollBar()->maximum()); 0314 } 0315 0316 void LogDockerDock::changeTheme() 0317 { 0318 clearLog(); 0319 QColor background = qApp->palette().window().color(); 0320 if (background.value() > 100) { 0321 s_debug.setForeground(Qt::black); 0322 s_info.setForeground(Qt::darkGreen); 0323 s_warning.setForeground(Qt::darkYellow); 0324 s_critical.setForeground(Qt::darkRed); 0325 s_fatal.setForeground(Qt::darkRed); 0326 } 0327 else { 0328 s_debug.setForeground(Qt::white); 0329 s_info.setForeground(Qt::green); 0330 s_warning.setForeground(Qt::yellow); 0331 s_critical.setForeground(Qt::red); 0332 s_fatal.setForeground(Qt::red); 0333 } 0334 s_fatal.setFontWeight(QFont::Bold); 0335 } 0336 0337 void MessageSender::sendMessage(QtMsgType type, const QString &msg) 0338 { 0339 emit emitMessage(type, msg); 0340 }