File indexing completed on 2024-05-12 05:12:46
0001 /* 0002 SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "logging.h" 0008 #include "loggeradaptor.h" 0009 #include "loggingfiltermodel.h" 0010 #include "loggingmodel.h" 0011 0012 #include <KLocalizedString> 0013 0014 #include <QCheckBox> 0015 #include <QDBusConnection> 0016 #include <QFileDialog> 0017 #include <QHBoxLayout> 0018 #include <QHeaderView> 0019 #include <QLabel> 0020 #include <QMessageBox> 0021 #include <QPushButton> 0022 #include <QStandardItemModel> 0023 #include <QTreeView> 0024 0025 #include <Libkdepim/KCheckComboBox> 0026 0027 #include <KConfigGroup> 0028 #include <KSharedConfig> 0029 0030 #ifndef COMPILE_WITH_UNITY_CMAKE_SUPPORT 0031 Q_DECLARE_METATYPE(LoggingModel::Message) 0032 #endif 0033 #define DBUS_PATH QStringLiteral("/logger") 0034 #define DBUS_INTERFACE QStringLiteral("org.kde.akonadiconsole.logger") 0035 0036 using namespace KPIM; 0037 0038 Logging::Logging(QWidget *parent) 0039 : QWidget(parent) 0040 { 0041 auto l = new QVBoxLayout(this); 0042 setLayout(l); 0043 0044 mEnabledCheckbox = new QCheckBox(i18n("Enable"), this); 0045 connect(mEnabledCheckbox, &QCheckBox::toggled, this, [this](bool toggled) { 0046 Q_EMIT enabledChanged(toggled); 0047 }); 0048 l->addWidget(mEnabledCheckbox); 0049 0050 auto h = new QHBoxLayout; 0051 l->addLayout(h); 0052 0053 h->addWidget(new QLabel(i18n("Programs:"), this)); 0054 h->addWidget(mAppFilter = new KCheckComboBox()); 0055 h->setStretchFactor(mAppFilter, 2); 0056 h->addWidget(new QLabel(i18n("Types:"), this)); 0057 h->addWidget(mTypeFilter = new KCheckComboBox()); 0058 h->setStretchFactor(mTypeFilter, 2); 0059 mTypeFilter->addItem(i18n("Debug"), QtDebugMsg); 0060 mTypeFilter->addItem(i18n("Info"), QtInfoMsg); 0061 mTypeFilter->addItem(i18n("Warning"), QtWarningMsg); 0062 mTypeFilter->addItem(i18n("Critical"), QtCriticalMsg); 0063 mTypeFilter->addItem(i18n("Fatal"), QtFatalMsg); 0064 h->addWidget(new QLabel(i18n("Categories:"))); 0065 h->addWidget(mCategoryFilter = new KCheckComboBox()); 0066 h->setStretchFactor(mCategoryFilter, 2); 0067 0068 mModel = new LoggingModel(this); 0069 0070 auto filterModel = new LoggingFilterModel(this); 0071 filterModel->setAppFilter(mAppFilter); 0072 filterModel->setCategoryFilter(mCategoryFilter); 0073 filterModel->setTypeFilter(mTypeFilter); 0074 filterModel->setSourceModel(mModel); 0075 0076 for (int i = 0; i < mTypeFilter->count(); ++i) { 0077 mTypeFilter->setItemCheckState(i, Qt::Checked); 0078 } 0079 0080 mView = new QTreeView; 0081 mView->setRootIsDecorated(false); 0082 l->addWidget(mView); 0083 mView->setModel(filterModel); 0084 mModel->setAppFilterModel(qobject_cast<QStandardItemModel *>(mAppFilter->model())); 0085 mModel->setCategoryFilterModel(qobject_cast<QStandardItemModel *>(mCategoryFilter->model())); 0086 0087 h = new QHBoxLayout; 0088 l->addLayout(h); 0089 0090 auto btn = new QPushButton(i18n("Save to File..."), this); 0091 connect(btn, &QPushButton::clicked, this, &Logging::saveToFile); 0092 h->addWidget(btn); 0093 h->addStretch(1); 0094 0095 new LoggerAdaptor(this); 0096 QDBusConnection::sessionBus().registerObject(DBUS_PATH, this, QDBusConnection::ExportAdaptors); 0097 0098 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Logging")); 0099 mView->header()->restoreState(config.readEntry<QByteArray>("view", QByteArray())); 0100 } 0101 0102 Logging::~Logging() 0103 { 0104 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Logging")); 0105 config.writeEntry("view", mView->header()->saveState()); 0106 } 0107 0108 bool Logging::enabled() const 0109 { 0110 return mEnabledCheckbox->isChecked(); 0111 } 0112 0113 void Logging::message(qint64 timestamp, 0114 const QString &app, 0115 qint64 pid, 0116 int type, 0117 const QString &category, 0118 const QString &file, 0119 const QString &function, 0120 int line, 0121 int /*version*/, 0122 const QString &msg) 0123 { 0124 mModel->addMessage(timestamp, app, pid, static_cast<QtMsgType>(type), category, file, function, line, msg); 0125 } 0126 0127 void Logging::saveToFile() 0128 { 0129 const auto filename = QFileDialog::getSaveFileName(this, i18n("Save to File...")); 0130 if (filename.isEmpty()) { 0131 return; 0132 } 0133 0134 QFile file(filename); 0135 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { 0136 QMessageBox::warning(this, i18n("Error"), i18n("Failed to open file: %1", file.errorString())); 0137 return; 0138 } 0139 0140 QTextStream stream(&file); 0141 for (int row = 0, cnt = mModel->rowCount(); row < cnt; ++row) { 0142 const auto msg = mModel->data(mModel->index(row, 0), LoggingModel::MessageRole).value<LoggingModel::Message>(); 0143 stream << "[" << QDateTime::fromMSecsSinceEpoch(msg.timestamp, Qt::UTC).toString(Qt::ISODateWithMs) << "] " << msg.app << " "; 0144 if (!msg.category.isEmpty()) { 0145 stream << msg.category << " "; 0146 } 0147 if (!msg.function.isEmpty()) { 0148 stream << msg.function << ": "; 0149 } 0150 stream << msg.message << "\n"; 0151 } 0152 } 0153 0154 #include "moc_logging.cpp"