File indexing completed on 2022-11-29 20:24:01

0001 /*
0002     SPDX-FileCopyrightText: 2015-2022 Laurent Montel <montel@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 
0006 */
0007 
0008 #include "kdebugsettingsdialog.h"
0009 #include "categorywarning.h"
0010 #include "customdebugsettingspage.h"
0011 #include "environmentsettingsrulespage.h"
0012 #include "groupmanagementdialog.h"
0013 #include "kdeapplicationdebugsettingpage.h"
0014 #include "kdebugsettings_debug.h"
0015 #include "kdebugsettingsutil.h"
0016 #include "loadgroupmenu.h"
0017 #include "loadtoolbutton.h"
0018 #include "saverulesjob.h"
0019 #include "savetoolbutton.h"
0020 
0021 #include <KConfigGroup>
0022 #include <KLocalizedString>
0023 #include <KMessageBox>
0024 #include <KSharedConfig>
0025 #include <KWindowConfig>
0026 
0027 #include <QDesktopServices>
0028 #include <QDialogButtonBox>
0029 #include <QDir>
0030 #include <QFileDialog>
0031 #include <QInputDialog>
0032 #include <QPushButton>
0033 #include <QTabWidget>
0034 #include <QUrl>
0035 #include <QVBoxLayout>
0036 #include <QWindow>
0037 namespace
0038 {
0039 constexpr char KDebugSettingsDialogGroupName[] = "KDebugSettingsDialog";
0040 }
0041 KDebugSettingsDialog::KDebugSettingsDialog(QWidget *parent)
0042     : QDialog(parent)
0043 {
0044     auto mainLayout = new QVBoxLayout(this);
0045 
0046     mCategoryWarning = new CategoryWarning(this);
0047     mCategoryWarning->setObjectName(QStringLiteral("categorywarning"));
0048     mainLayout->addWidget(mCategoryWarning);
0049 
0050     mTabWidget = new QTabWidget(this);
0051     mTabWidget->setObjectName(QStringLiteral("tabwidget"));
0052     mainLayout->addWidget(mTabWidget);
0053 
0054     mKdeApplicationSettingsPage = new KDEApplicationDebugSettingPage(this);
0055     mKdeApplicationSettingsPage->setObjectName(QStringLiteral("kdeapplicationsettingspage"));
0056     mCustomSettingsPage = new CustomDebugSettingsPage(this);
0057     mCustomSettingsPage->setObjectName(QStringLiteral("customsettingspage"));
0058     mEnvironmentSettingsRulesPage = new EnvironmentSettingsRulesPage(this);
0059     mEnvironmentSettingsRulesPage->setObjectName(QStringLiteral("environmentsettingsrulespage"));
0060     mTabWidget->addTab(mKdeApplicationSettingsPage, i18n("KDE Application"));
0061     mTabWidget->addTab(mCustomSettingsPage, i18n("Custom Rules"));
0062     mTabWidget->addTab(mEnvironmentSettingsRulesPage, i18n("Rules Settings With Environment Variable"));
0063     mTabWidget->setFocusPolicy(Qt::NoFocus);
0064 
0065     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help
0066                                               | QDialogButtonBox::Apply,
0067                                           this);
0068     buttonBox->setObjectName(QStringLiteral("buttonbox"));
0069 
0070     auto saveAs = new SaveToolButton(this);
0071     saveAs->setText(i18n("Save As..."));
0072     saveAs->setObjectName(QStringLiteral("saveas_button"));
0073     buttonBox->addButton(saveAs, QDialogButtonBox::ActionRole);
0074     connect(saveAs, &SaveToolButton::saveAsFile, this, &KDebugSettingsDialog::slotSaveAs);
0075     connect(saveAs, &SaveToolButton::saveAsGroup, this, &KDebugSettingsDialog::slotSaveAsGroup);
0076 
0077     mLoadToolButton = new LoadToolButton(this);
0078     mLoadToolButton->setObjectName(QStringLiteral("load_button"));
0079     buttonBox->addButton(mLoadToolButton, QDialogButtonBox::ActionRole);
0080     connect(mLoadToolButton, &LoadToolButton::loadFromFile, this, &KDebugSettingsDialog::slotLoad);
0081     connect(mLoadToolButton, &LoadToolButton::loadGroupRequested, this, &KDebugSettingsDialog::slotLoadGroup);
0082     connect(mLoadToolButton, &LoadToolButton::manageGroupRequested, this, &KDebugSettingsDialog::slotManageGroup);
0083     connect(this, &KDebugSettingsDialog::updateLoadGroupMenu, mLoadToolButton, &LoadToolButton::updateLoadGroupMenu);
0084 
0085     auto insertCategories = new QPushButton(i18n("Insert..."), this);
0086     insertCategories->setObjectName(QStringLiteral("insert_button"));
0087     buttonBox->addButton(insertCategories, QDialogButtonBox::ActionRole);
0088     connect(insertCategories, &QPushButton::clicked, this, &KDebugSettingsDialog::slotInsertCategories);
0089 
0090     connect(buttonBox, &QDialogButtonBox::accepted, this, &KDebugSettingsDialog::slotAccepted);
0091     connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
0092     connect(buttonBox, &QDialogButtonBox::helpRequested, this, &KDebugSettingsDialog::slotHelpRequested);
0093     connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &KDebugSettingsDialog::slotApply);
0094     connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, &KDebugSettingsDialog::slotRestoreDefault);
0095     mainLayout->addWidget(buttonBox);
0096     readConfig();
0097     readQtLoggingFile();
0098     mKdeApplicationSettingsPage->forceFocus();
0099 }
0100 
0101 KDebugSettingsDialog::~KDebugSettingsDialog()
0102 {
0103     saveConfig();
0104 }
0105 
0106 void KDebugSettingsDialog::readConfig()
0107 {
0108     create(); // ensure a window is created
0109     windowHandle()->resize(QSize(600, 300));
0110     KConfigGroup group(KSharedConfig::openStateConfig(), KDebugSettingsDialogGroupName);
0111     KWindowConfig::restoreWindowSize(windowHandle(), group);
0112     resize(windowHandle()->size()); // workaround for QTBUG-40584
0113 }
0114 
0115 void KDebugSettingsDialog::saveConfig()
0116 {
0117     KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1String(KDebugSettingsDialogGroupName));
0118     KWindowConfig::saveWindowSize(windowHandle(), group);
0119 }
0120 
0121 void KDebugSettingsDialog::slotLoadGroup(const QString &fullPath)
0122 {
0123     if (!fullPath.isEmpty()) {
0124         mLoggings.readCategoriesFiles(fullPath);
0125         updateLoggingCategories();
0126     }
0127 }
0128 
0129 void KDebugSettingsDialog::readQtLoggingFile()
0130 {
0131     mLoggings.readQtLoggingFile();
0132     updateLoggingCategories();
0133 }
0134 
0135 void KDebugSettingsDialog::updateLoggingCategories()
0136 {
0137     if (!mLoggings.environmentrules().isEmpty()) {
0138         mEnvironmentSettingsRulesPage->setRules(mLoggings.environmentrules());
0139     }
0140     const LoggingCategory::List customCategories = mLoggings.customCategories();
0141     const LoggingCategory::List qtKdeCategories = mLoggings.qtKdeCategories();
0142     const bool foundOverrideRule = mLoggings.foundOverrideRule();
0143 
0144     mKdeApplicationSettingsPage->fillList(qtKdeCategories);
0145     mCustomSettingsPage->fillList(customCategories);
0146     if (foundOverrideRule) {
0147         mCategoryWarning->animatedShow();
0148     }
0149     mCategoriesList = mLoggings.categoriesList();
0150 }
0151 
0152 bool KDebugSettingsDialog::saveRules(const QString &path, bool forceSavingAllRules)
0153 {
0154     SaveRulesJob job;
0155     job.setFileName(path);
0156     job.setListCustom(mCustomSettingsPage->rules());
0157     job.setListKde(mKdeApplicationSettingsPage->rules(forceSavingAllRules));
0158     if (!job.start()) {
0159         KMessageBox::error(this, i18n("\'%1\' cannot be opened. Please verify it.", path));
0160         return false;
0161     }
0162     return true;
0163 }
0164 
0165 bool KDebugSettingsDialog::saveInQtLogging()
0166 {
0167     return saveRules(KDebugSettingsUtil::qtFileName());
0168 }
0169 
0170 void KDebugSettingsDialog::slotAccepted()
0171 {
0172     if (saveInQtLogging()) {
0173         accept();
0174     }
0175 }
0176 
0177 void KDebugSettingsDialog::slotHelpRequested()
0178 {
0179     QDesktopServices::openUrl(QUrl(QStringLiteral("https://doc.qt.io/qt-5/qloggingcategory.html#details")));
0180 }
0181 
0182 void KDebugSettingsDialog::slotApply()
0183 {
0184     saveInQtLogging();
0185 }
0186 
0187 void KDebugSettingsDialog::slotInsertCategories()
0188 {
0189     const QString path =
0190         QFileDialog::getOpenFileName(this, i18n("Insert Categories"), QString(), QStringLiteral("%1 (*.categories)").arg(i18n("Categories Files")));
0191     if (!path.isEmpty()) {
0192         const KdeLoggingCategory::List insertCategoriesList = KDebugSettingsUtil::readLoggingCategoriesForInserting(path, mCategoriesList);
0193         LoggingCategory::List newCategories;
0194         for (const KdeLoggingCategory &cat : std::as_const(insertCategoriesList)) {
0195             LoggingCategory loggingCat;
0196             loggingCat.description = cat.description;
0197             loggingCat.categoryName = cat.categoryName;
0198             loggingCat.defaultSeverityType = KDebugSettingsUtil::convertCategoryTypeFromString(cat.defaultSeverity);
0199             if (loggingCat.isValid()) {
0200                 newCategories.append(loggingCat);
0201             }
0202         }
0203         mKdeApplicationSettingsPage->insertCategories(newCategories);
0204         KMessageBox::information(this, i18n("Categories from file \'%1\' inserted.", path), i18n("Insert Categories"));
0205     }
0206 }
0207 
0208 void KDebugSettingsDialog::slotSaveAsGroup()
0209 {
0210     const QString groupPath = LoadGroupMenu::defaultWritableGroupPath();
0211     bool ok = false;
0212     const QString name = QInputDialog::getText(this, i18n("Group Name"), i18n("Name:"), QLineEdit::Normal, QString(), &ok);
0213     if (ok) {
0214         const QString trimmedName = name.trimmed();
0215         if (!trimmedName.isEmpty()) {
0216             if (mLoadToolButton->groupNames().contains(trimmedName)) {
0217                 KMessageBox::error(this, i18n("\'%1\' is already used as a group name.\nPlease save as another name.", trimmedName));
0218             } else {
0219                 if (!QDir().mkpath(groupPath)) {
0220                     qCWarning(KDEBUGSETTINGS_LOG) << "Unable to create folder: " << groupPath;
0221                 }
0222                 saveRules(groupPath + QLatin1Char('/') + trimmedName, true);
0223                 Q_EMIT updateLoadGroupMenu();
0224             }
0225         } else {
0226             KMessageBox::error(this, i18n("Can not save as empty name. Please use a new one."));
0227         }
0228     }
0229 }
0230 
0231 void KDebugSettingsDialog::slotSaveAs()
0232 {
0233     const QString path = QFileDialog::getSaveFileName(this, i18n("Save As"), QString(), i18n("KDebugSettings File (*.kdebugsettingsrules)"));
0234     if (!path.isEmpty()) {
0235         saveRules(path, true);
0236     }
0237 }
0238 
0239 void KDebugSettingsDialog::slotLoad()
0240 {
0241     const QString path = QFileDialog::getOpenFileName(this, i18n("Load Debug Settings Files"), QString(), i18n("KDebugSettings File (*.kdebugsettingsrules)"));
0242     if (!path.isEmpty()) {
0243         mLoggings.readCategoriesFiles(path);
0244         updateLoggingCategories();
0245     }
0246 }
0247 
0248 void KDebugSettingsDialog::slotRestoreDefault()
0249 {
0250     mKdeApplicationSettingsPage->restoreToDefault();
0251 }
0252 
0253 void KDebugSettingsDialog::slotManageGroup()
0254 {
0255     auto groupManagementDialog = new GroupManagementDialog(this);
0256     connect(groupManagementDialog, &GroupManagementDialog::groupsChanged, this, &KDebugSettingsDialog::updateLoadGroupMenu);
0257     groupManagementDialog->exec();
0258     delete groupManagementDialog;
0259 }