diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b0cd5f..fba9755 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,123 +1,122 @@ project(KSystemlog) # KDE Application Version, managed by release script set (RELEASE_SERVICE_VERSION_MAJOR "20") set (RELEASE_SERVICE_VERSION_MINOR "07") set (RELEASE_SERVICE_VERSION_MICRO "70") set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}") cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) set (QT_MIN_VERSION "5.7.0") set (KF5_MIN_VERSION "5.30.0") find_package (ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) add_definitions(-DTRANSLATION_DOMAIN="ksystemlog") include(ECMSetupVersion) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(FeatureSummary) ecm_setup_version(${RELEASE_SERVICE_VERSION} VARIABLE_PREFIX KSYSTEMLOG VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/src/ksystemlog_version.h") find_package (Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Concurrent Core Network Widgets Test PrintSupport ) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS XmlGui CoreAddons WidgetsAddons ItemViews - IconThemes KIO Config Archive DocTools I18n Completion TextWidgets ) find_package(Journald) include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) if(WIN32) set(CMAKE_REQUIRED_LIBRARIES ${KDEWIN32_LIBRARIES}) set(CMAKE_REQUIRED_INCLUDES ${KDEWIN32_INCLUDES}) endif(WIN32) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) # Help Eclipse to parse errors more efficiently if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0") endif(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmessage-length=0") endif(CMAKE_COMPILER_IS_GNUCXX) add_custom_target( pkg COMMAND ./build-package.sh ) ## # To specify a different install prefix, use : # cmake -D CMAKE_INSTALL_PREFIX=build . # # To help Eclipse discover include paths, use : # cmake -D CMAKE_VERBOSE_MAKEFILE=true . ## if (${JOURNALD_FOUND}) add_definitions(-DHAVE_JOURNALD) endif (${JOURNALD_FOUND}) ########### Subfolders ########## add_subdirectory(src) add_subdirectory(src/lib) add_subdirectory(src/config) add_subdirectory(src/modes/base) add_subdirectory(src/modes/open) add_subdirectory(src/modes/system) add_subdirectory(src/modes/kernel) add_subdirectory(src/modes/xorg) add_subdirectory(src/modes/cron) add_subdirectory(src/modes/authentication) add_subdirectory(src/modes/daemon) add_subdirectory(src/modes/acpid) add_subdirectory(src/modes/xsession) add_subdirectory(src/modes/apache) add_subdirectory(src/modes/postfix) add_subdirectory(src/modes/samba) add_subdirectory(src/modes/cups) if (${JOURNALD_FOUND}) add_subdirectory(src/modes/journald) endif (${JOURNALD_FOUND}) add_subdirectory(tests) add_subdirectory(doc) find_package(KF5I18n CONFIG REQUIRED) ki18n_install(po) kdoctools_install(po) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/configurationDialog.cpp b/src/configurationDialog.cpp index badf654..5e9ab73 100644 --- a/src/configurationDialog.cpp +++ b/src/configurationDialog.cpp @@ -1,203 +1,202 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "configurationDialog.h" #include #include #include -#include #include "generalConfigurationWidget.h" #include "logModeConfigurationWidget.h" #include "mainWindow.h" #include "globals.h" #include "ksystemlogConfig.h" #include "logging.h" #include "defaults.h" class ConfigurationDialogPrivate { public: GeneralConfigurationWidget *generalConfiguration; QList logModeConfigurations; bool changed; }; ConfigurationDialog::ConfigurationDialog(QWidget *parent) : KConfigDialog(parent, i18n("Settings"), KSystemLogConfig::self()) , d(new ConfigurationDialogPrivate()) { d->changed = false; setupGeneralConfiguration(); setupLogModeConfigurations(); } ConfigurationDialog::~ConfigurationDialog() { // All configuration pages are managed by KConfigDialog delete d; } void ConfigurationDialog::setupLogModeConfigurations() { logDebug() << "Setup Log Mode Configurations..."; foreach (LogMode *logMode, Globals::instance().logModes()) { // Some Log mode does not need a configuration widget if (logMode->logModeConfigurationWidget() == nullptr) { continue; } // The configuration widget could be shared between Log Modes if (d->logModeConfigurations.contains(logMode->logModeConfigurationWidget()) == true) { continue; } d->logModeConfigurations.append(logMode->logModeConfigurationWidget()); } foreach (LogModeConfigurationWidget *logModeConfigurationWidget, d->logModeConfigurations) { logDebug() << "Adding " << logModeConfigurationWidget->itemName() << " configuration..."; addPage(logModeConfigurationWidget, logModeConfigurationWidget->itemName(), logModeConfigurationWidget->iconName(), logModeConfigurationWidget->header(), false); connect(logModeConfigurationWidget, &LogModeConfigurationWidget::configurationChanged, this, &ConfigurationDialog::updateConfiguration); } } void ConfigurationDialog::showConfiguration() { logDebug() << "Showing Configuration dialog..."; show(); } void ConfigurationDialog::setupGeneralConfiguration() { d->generalConfiguration = new GeneralConfigurationWidget(); addPage(d->generalConfiguration, i18n("General"), QStringLiteral("utilities-log-viewer"), i18n("General"), false); connect(d->generalConfiguration, &GeneralConfigurationWidget::configurationChanged, this, &ConfigurationDialog::updateConfiguration); } void ConfigurationDialog::updateSettings() { logDebug() << "Saving configuration..."; d->changed = false; d->generalConfiguration->saveConfig(); foreach (LogModeConfigurationWidget *logModeConfigurationWidget, d->logModeConfigurations) { logModeConfigurationWidget->saveConfig(); } KSystemLogConfig::self()->save(); emit configurationSaved(); logDebug() << "Configuration saved"; } bool ConfigurationDialog::hasChanged() { logDebug() << "Current change status : " << d->changed; return d->changed; } void ConfigurationDialog::updateConfiguration() { logDebug() << "Updating configuration..."; bool valid = d->generalConfiguration->isValid(); if (valid) { foreach (LogModeConfigurationWidget *logModeConfigurationWidget, d->logModeConfigurations) { if (logModeConfigurationWidget->isValid() == false) { valid = false; break; } } } if (valid == true) { buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(true); updateButtons(); } else { buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(false); buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(false); } } void ConfigurationDialog::updateButtons() { logDebug() << "Updating configuration buttons..."; d->changed = true; } void ConfigurationDialog::updateWidgets() { logDebug() << "Reading configuration..."; d->generalConfiguration->readConfig(); foreach (LogModeConfigurationWidget *logModeConfigurationWidget, d->logModeConfigurations) { logModeConfigurationWidget->readConfig(); } d->changed = false; } void ConfigurationDialog::updateWidgetsDefault() { logDebug() << "Loading default configuration..."; d->generalConfiguration->defaultConfig(); foreach (LogModeConfigurationWidget *logModeConfigurationWidget, d->logModeConfigurations) { logModeConfigurationWidget->defaultConfig(); } d->changed = false; } bool ConfigurationDialog::isDefault() { /** * TODO Set this to true and find a way to retrieve defaults value * of the configuration (see defaultConfig() methods of LogModeConfigurations) */ return true; } diff --git a/src/detailDialog.cpp b/src/detailDialog.cpp index e01747d..43626ab 100644 --- a/src/detailDialog.cpp +++ b/src/detailDialog.cpp @@ -1,140 +1,139 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "detailDialog.h" // Qt includes #include -#include #include #include #include #include "logViewWidget.h" #include "logViewWidgetItem.h" #include "logLine.h" #include "logging.h" DetailDialog::DetailDialog(QWidget *parent) : QDialog(parent) , logViewWidget(nullptr) { setupUi(this); previous->setText(i18n("&Previous")); previous->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up"))); connect(previous, &QAbstractButton::clicked, this, &DetailDialog::previousItem); next->setText(i18n("&Next")); next->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down"))); connect(next, &QAbstractButton::clicked, this, &DetailDialog::nextItem); KGuiItem::assign(closeButton, KStandardGuiItem::close()); connect(closeButton, &QAbstractButton::clicked, this, &QWidget::close); } DetailDialog::~DetailDialog() { } void DetailDialog::selectionChanged(LogViewWidget *logViewWidget) { this->logViewWidget = logViewWidget; updateDetails(); } // TODO Try to find a method that reload (an resize) correctly the content of the detail dialog void DetailDialog::updateDetails() { // logDebug() << "Updating Detail Dialog..."; // Get the current-last item selected LogViewWidgetItem *item = logViewWidget->lastSelectedItem(); if (item == nullptr) { logDebug() << "No item found."; return; } icon->setPixmap(item->logLine()->logLevel()->icon().pixmap(style()->pixelMetric(QStyle::PM_LargeIconSize))); header->setText(item->logLine()->formattedText()); message->setText(item->logLine()->logItems().last()); if (logViewWidget->topLevelItem(logViewWidget->indexOfTopLevelItem(item) - 1) == nullptr) previous->setEnabled(false); else previous->setEnabled(true); if (logViewWidget->topLevelItem(logViewWidget->indexOfTopLevelItem(item) + 1) == nullptr) next->setEnabled(false); else next->setEnabled(true); /* header->adjustSize(); this->adjustSize(); */ } void DetailDialog::moveToItem(int direction) { if (direction < 0) logDebug() << "Go to previous item..."; else logDebug() << "Go to next item..."; // Get the current-last item selected LogViewWidgetItem *item = logViewWidget->lastSelectedItem(); if (item == nullptr) { logDebug() << "No item found."; return; } QTreeWidgetItem *destinationItem = logViewWidget->topLevelItem(logViewWidget->indexOfTopLevelItem(item) + direction); if (destinationItem == nullptr) { if (direction < 0) logDebug() << "No previous item found."; else logDebug() << "No next item found."; return; } item->setSelected(false); destinationItem->setSelected(true); logViewWidget->scrollToItem(destinationItem); updateDetails(); } void DetailDialog::previousItem() { moveToItem(-1); } void DetailDialog::nextItem() { moveToItem(1); } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 30b97f0..4d988de 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,61 +1,60 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/../config ) set(ksystemlog_lib_sources analyzer.cpp fileAnalyzer.cpp logModeFactory.cpp logModeConfiguration.cpp logModeConfigurationWidget.cpp logModeItemBuilder.cpp logManager.cpp view.cpp globals.cpp logMode.cpp logLevel.cpp logFile.cpp logFileReader.cpp localLogFileReader.cpp processOutputLogFileReader.cpp kioLogFileReader.cpp logLine.cpp logViewModel.cpp logViewColumn.cpp logViewColumns.cpp logViewWidgetItem.cpp logViewWidget.cpp logViewExport.cpp logViewFilterWidget.cpp logViewSearchWidget.cpp loadingBar.cpp logModeAction.cpp simpleAction.cpp multipleActions.cpp levelPrintPage.cpp ) ki18n_wrap_ui(ksystemlog_lib_sources logViewSearchWidgetBase.ui) add_library(ksystemlog_lib STATIC ${ksystemlog_lib_sources}) add_dependencies( ksystemlog_lib ksystemlog_config ) target_link_libraries(ksystemlog_lib ksystemlog_config Qt5::Widgets Qt5::PrintSupport KF5::I18n KF5::Archive KF5::ConfigWidgets KF5::ItemViews - KF5::IconThemes KF5::KIOCore KF5::Completion ) diff --git a/src/lib/loadingBar.cpp b/src/lib/loadingBar.cpp index b885e02..37917f8 100644 --- a/src/lib/loadingBar.cpp +++ b/src/lib/loadingBar.cpp @@ -1,128 +1,127 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "loadingBar.h" #include #include #include #include #include #include #include #include -#include class LoadingBarPrivate { public: // Attributes managing the position in the files loading of each log int fileCount; int currentFileIndex; bool firstLoading; QLabel *label; QProgressBar *progressBar; }; LoadingBar::LoadingBar(QWidget *parent) : QWidget(parent) , d(new LoadingBarPrivate()) { d->firstLoading = true; QHBoxLayout *widgetLayout = new QHBoxLayout(this); widgetLayout->addStretch(); QVBoxLayout *layout = new QVBoxLayout(); widgetLayout->addLayout(layout); widgetLayout->addStretch(); d->label = new QLabel(i18n("Loading Progress...")); d->label->setMinimumWidth(250); layout->addWidget(d->label, 1, Qt::AlignBottom); d->progressBar = new QProgressBar(); d->progressBar->setRange(0, 100); d->progressBar->setMinimumWidth(250); layout->addWidget(d->progressBar, 1, Qt::AlignCenter | Qt::AlignTop); } LoadingBar::~LoadingBar() { delete d; } QProgressBar *LoadingBar::progressBar() { return d->progressBar; } void LoadingBar::startLoading(const LogMode &logMode, const LogFile &logFile, int fileIndex, int fileCount) { emit displayed(true); d->progressBar->setValue(0); // Several files to load if (fileCount > 1 && fileIndex >= 1) { if (d->firstLoading) d->label->setText(i18np("Loading %2...
%3 - (%4)", "Loading %2...
%3 - (%4/%1 files)", fileCount, logMode.name(), logFile.url().path(), fileIndex)); else d->label->setText(i18np("Reloading %2...
%3 - (%4)", "Reloading %2...
%3 - (%4/%1 files)", fileCount, logMode.name(), logFile.url().path(), fileIndex)); } // Only one file else { if (d->firstLoading) d->label->setText( i18n("Loading %1...
%2", logMode.name(), logFile.url().path())); else d->label->setText( i18n("Reloading %1...
%2", logMode.name(), logFile.url().path())); } } void LoadingBar::endLoading() { emit displayed(false); d->progressBar->setValue(100); // If the endLoading has been called one time, it means it has already been loaded d->firstLoading = false; } void LoadingBar::progressLoading() { d->progressBar->setValue(d->progressBar->value() + 1); // kapp->processEvents(); qApp->processEvents(); } diff --git a/src/lib/logLevel.cpp b/src/lib/logLevel.cpp index 4e6f0d1..fa3b9e5 100644 --- a/src/lib/logLevel.cpp +++ b/src/lib/logLevel.cpp @@ -1,69 +1,68 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logLevel.h" -#include #include class LogLevelPrivate { public: int id; QString name; QColor color; QIcon icon; }; LogLevel::LogLevel(int id, const QString &nm, const QString &ic, const QColor &col, QObject *parent) : QObject(parent), d(new LogLevelPrivate()) { d->id = id; d->name = nm; d->color = col; d->icon = QIcon::fromTheme(ic); } LogLevel::~LogLevel() { delete d; } int LogLevel::id() const { return d->id; } QString LogLevel::name() const { return d->name; } QColor LogLevel::color() const { return d->color; } QIcon LogLevel::icon() const { return d->icon; } diff --git a/src/lib/logMode.cpp b/src/lib/logMode.cpp index 1095f17..253cdd4 100644 --- a/src/lib/logMode.cpp +++ b/src/lib/logMode.cpp @@ -1,108 +1,106 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logMode.h" #include #include -#include - #include "multipleActions.h" #include "logModeItemBuilder.h" LogMode::LogMode(const QString &id, const QString &name, const QString &iconName) : d(new LogModePrivate()) { d->id = id; d->name = name; d->icon = QIcon::fromTheme(iconName); d->logFilesExist = true; } LogMode::~LogMode() { delete d->action; delete d->itemBuilder; delete d; } QString LogMode::id() const { return d->id; } QString LogMode::name() const { return d->name; } QIcon LogMode::icon() const { return d->icon; } QAction *LogMode::action() const { return d->action; } LogModeItemBuilder *LogMode::itemBuilder() const { return d->itemBuilder; } bool LogMode::filesExist() const { return d->logFilesExist; } LogModeConfigurationWidget *LogMode::logModeConfigurationWidget() const { return d->logModeConfigurationWidget; } LogModeConfiguration *LogMode::innerConfiguration() const { return d->logModeConfiguration.data(); } QAction *LogMode::createDefaultAction() { QAction *action = new QAction(d->icon, d->name, this); ActionData data; data.id = d->id; action->setData(QVariant::fromValue(data)); return action; } void LogMode::checkLogFilesPresence(const QStringList &paths) { d->logFilesExist = false; for (const QString &path : paths) { QFileInfo fileInfo(path); if (fileInfo.exists()) d->logFilesExist = true; } } diff --git a/src/lib/logViewColumn.cpp b/src/lib/logViewColumn.cpp index 08fd5cd..e38d333 100644 --- a/src/lib/logViewColumn.cpp +++ b/src/lib/logViewColumn.cpp @@ -1,92 +1,90 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logViewColumn.h" #include #include -#include - class LogViewColumnPrivate { public: QString columnName; bool filtered; bool grouped; }; LogViewColumn::LogViewColumn(const QString &name, bool filtered, bool grouped) : d(new LogViewColumnPrivate()) { d->columnName = name; d->filtered = filtered; d->grouped = grouped; } LogViewColumn::LogViewColumn(const LogViewColumn &column) : d(new LogViewColumnPrivate()) { d->columnName = column.columnName(); d->filtered = column.isFiltered(); d->grouped = column.isGrouped(); } LogViewColumn::~LogViewColumn() { delete d; } QString LogViewColumn::columnName() const { return d->columnName; } bool LogViewColumn::isGrouped() const { return d->grouped; } bool LogViewColumn::isFiltered() const { return d->filtered; } LogViewColumn &LogViewColumn::operator=(const LogViewColumn &column) { d->columnName = column.columnName(); d->grouped = column.isGrouped(); d->filtered = column.isFiltered(); return *this; } QDataStream &operator<<(QDataStream &out, const LogViewColumn &column) { out << column.columnName(); return out; } QDebug &operator<<(QDebug &out, const LogViewColumn &column) { out << column.columnName(); return out; } diff --git a/src/lib/logViewFilterWidget.cpp b/src/lib/logViewFilterWidget.cpp index 890e5f5..9afc785 100644 --- a/src/lib/logViewFilterWidget.cpp +++ b/src/lib/logViewFilterWidget.cpp @@ -1,261 +1,260 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logViewFilterWidget.h" #include "logViewWidget.h" #include "logViewColumn.h" #include "logging.h" #include "logLevel.h" #include #include #include #include #include #include #include #include #include -#include #include class ComboBoxDelegate : public QStyledItemDelegate { public: explicit ComboBoxDelegate(QWidget *parent) : QStyledItemDelegate(parent) { } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { QStyleOptionViewItem &refToNonConstOption = const_cast(option); refToNonConstOption.showDecorationSelected = false; QStyledItemDelegate::paint(painter, refToNonConstOption, index); } }; class LogViewFilterWidgetPrivate { public: LogViewWidgetSearchLine *filterLine; /** * Filter of the column list */ KComboBox *filterList; QComboBox *prioritiesComboBox; QStandardItemModel *prioritiesModel; }; class LogViewWidgetSearchLinePrivate { public: bool priorities[Globals::LOG_LEVEL_NUM]; LogViewWidgetSearchLinePrivate() { // Show all priorities. for (int i = 0; i < Globals::LOG_LEVEL_NUM; i++) priorities[i] = true; } }; LogViewWidgetSearchLine::LogViewWidgetSearchLine() : KTreeWidgetSearchLine() , d(new LogViewWidgetSearchLinePrivate()) { } LogViewWidgetSearchLine::~LogViewWidgetSearchLine() { delete d; } void LogViewWidgetSearchLine::updateSearch(const QString &pattern) { KTreeWidgetSearchLine::updateSearch(pattern); emit treeWidgetUpdated(); } void LogViewWidgetSearchLine::setPriorityEnabled(int priority, bool enabled) { if ((priority < 0) || (priority >= Globals::LOG_LEVEL_NUM)) return; d->priorities[priority] = enabled; updateSearch(QString()); } bool LogViewWidgetSearchLine::itemMatches(const QTreeWidgetItem *item, const QString &pattern) const { // Hide item if its priority is not enabled. int priority = item->data(0, Qt::UserRole).toInt(); if ((priority >= 0) && (priority < Globals::LOG_LEVEL_NUM)) { if (!d->priorities[priority]) return false; } return KTreeWidgetSearchLine::itemMatches(item, pattern); } LogViewFilterWidget::LogViewFilterWidget() : d(new LogViewFilterWidgetPrivate()) { QHBoxLayout *filterBarLayout = new QHBoxLayout(); filterBarLayout->setContentsMargins(0, 0, 0, 0); setLayout(filterBarLayout); d->filterLine = new LogViewWidgetSearchLine(); d->filterLine->setToolTip(i18n("Type your filter here")); d->filterLine->setWhatsThis(i18n("Allows you to only list items that match the content of this text.")); d->filterLine->setPlaceholderText(i18n("Enter your search here...")); QLabel *filterIcon = new QLabel(); - filterIcon->setPixmap(QIcon::fromTheme(QStringLiteral("view-filter")).pixmap(KIconLoader::SizeSmall)); + filterIcon->setPixmap(QIcon::fromTheme(QStringLiteral("view-filter")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); filterIcon->setBuddy(d->filterLine); filterBarLayout->addWidget(filterIcon); QLabel *filterLabel = new QLabel(i18n("Filter:")); filterLabel->setBuddy(d->filterLine); filterBarLayout->addWidget(filterLabel); filterBarLayout->addWidget(d->filterLine); initSearchListFilter(); filterBarLayout->addWidget(d->filterList); d->prioritiesComboBox = new QComboBox(this); ComboBoxDelegate *delegate = new ComboBoxDelegate(d->prioritiesComboBox); d->prioritiesComboBox->setItemDelegate(delegate); filterBarLayout->addWidget(d->prioritiesComboBox); QMetaEnum &metaEnum = Globals::instance().logLevelsMetaEnum(); d->prioritiesModel = new QStandardItemModel(d->prioritiesComboBox); d->prioritiesComboBox->setModel(d->prioritiesModel); QStandardItem *item = new QStandardItem(i18n("Select priorities")); item->setSelectable(false); d->prioritiesModel->appendRow(item); connect(d->prioritiesModel, &QStandardItemModel::itemChanged, this, &LogViewFilterWidget::prioritiesChanged); // Don't add last enum value into combobox. for (int i = 0; i < metaEnum.keyCount() - 1; i++) { int id = metaEnum.value(i); LogLevel *logLevel = Globals::instance().logLevelByPriority(id); QStandardItem *item = new QStandardItem(logLevel->name()); item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item->setData(Qt::Checked, Qt::CheckStateRole); item->setData(metaEnum.value(i), Qt::UserRole); item->setData(QVariant(logLevel->color()), Qt::ForegroundRole); d->prioritiesModel->appendRow(item); } } LogViewFilterWidget::~LogViewFilterWidget() { delete d; } void LogViewFilterWidget::initSearchListFilter() { d->filterList = new KComboBox(); d->filterList->setToolTip(i18n("Choose the filtered column here")); d->filterList->setWhatsThis(i18n( "Allows you to apply the item filter only on the specified column here. \"All\" column means " "no specific filter.")); d->filterList->addItem(i18n("All")); d->filterList->setSizeAdjustPolicy(QComboBox::AdjustToContents); connect(d->filterList, SIGNAL(activated(int)), d->filterLine, SLOT(setFocus())); connect(d->filterList, QOverload::of(&KComboBox::activated), this, &LogViewFilterWidget::changeColumnFilter); connect(d->filterList, SIGNAL(activated(int)), d->filterLine, SLOT(updateSearch())); } void LogViewFilterWidget::updateFilterColumns(const LogViewColumns &columns) { logDebug() << "Changing columns..."; // We first delete all items d->filterList->clear(); // Then we insert the default items d->filterList->addItem(i18n("All")); foreach (const LogViewColumn &column, columns.columns()) { if (column.isFiltered() == true) { d->filterList->addItem(column.columnName()); } } d->filterList->setCurrentIndex(0); } void LogViewFilterWidget::changeColumnFilter(int column) { // The user select all columns if (column == 0) { logDebug() << "Searching on all columns"; d->filterLine->setSearchColumns(QList()); return; } logDebug() << "Searching on " << d->filterList->currentIndex() << " column"; QList filterColumns; // currentIndex() - 1 to do not count the "All" columns item filterColumns.append(d->filterList->currentIndex() - 1); d->filterLine->setSearchColumns(filterColumns); } void LogViewFilterWidget::prioritiesChanged(QStandardItem *item) { int priority = item->data(Qt::UserRole).toInt(); bool priorityEnabled = (item->checkState() == Qt::Checked); d->filterLine->setPriorityEnabled(priority, priorityEnabled); if (priorityEnabled) logDebug() << "Show entries with priority" << priority; else logDebug() << "Hide entries with priority" << priority; } KComboBox *LogViewFilterWidget::filterList() { return d->filterList; } LogViewWidgetSearchLine *LogViewFilterWidget::filterLine() { return d->filterLine; } diff --git a/src/lib/logViewSearchWidget.cpp b/src/lib/logViewSearchWidget.cpp index 5f4ec0c..25093e2 100644 --- a/src/lib/logViewSearchWidget.cpp +++ b/src/lib/logViewSearchWidget.cpp @@ -1,339 +1,338 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logViewSearchWidget.h" #include #include #include #include #include #include -#include #include #include #include "logging.h" #include "logViewWidget.h" #include "logViewWidgetItem.h" class LogViewSearchWidgetPrivate { public: LogViewWidget *logViewWidget; QColor searchLineBaseColor; QColor searchLineTextColor; QTimer *messageHidingTimer; }; LogViewSearchWidget::LogViewSearchWidget() : d(new LogViewSearchWidgetPrivate()) { d->logViewWidget = nullptr; setupUi(this); // Get the searchLine base color to be able to restore it later d->searchLineBaseColor = searchLine->palette().color(QPalette::Base); d->searchLineTextColor = searchLine->palette().color(QPalette::Text); // Default configuration of the hiding message timer d->messageHidingTimer = new QTimer(this); d->messageHidingTimer->setSingleShot(true); d->messageHidingTimer->setInterval(2000); connect(d->messageHidingTimer, &QTimer::timeout, this, &LogViewSearchWidget::hideMessage); // The message widget is hidden by default hideMessage(); closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); connect(closeButton, &QAbstractButton::clicked, this, &QWidget::hide); next->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down"))); connect(next, &QAbstractButton::clicked, this, &LogViewSearchWidget::findNext); previous->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up"))); connect(previous, &QAbstractButton::clicked, this, &LogViewSearchWidget::findPrevious); searchLabel->setBuddy(searchLine); connect(searchLine, SIGNAL(textEdited(QString)), this, SLOT(findFirst(QString))); connect(searchLine, &QLineEdit::textEdited, this, &LogViewSearchWidget::highlightAll); connect(searchLine, &QLineEdit::returnPressed, this, &LogViewSearchWidget::findNext); connect(caseSensitive, SIGNAL(clicked()), this, SLOT(findFirst())); connect(caseSensitive, &QAbstractButton::clicked, this, &LogViewSearchWidget::highlightAll); connect(highlightAllButton, &QAbstractButton::clicked, this, &LogViewSearchWidget::highlightAll); findFirst(searchLine->text()); } LogViewSearchWidget::~LogViewSearchWidget() { // widgets and timer are automatically deleted by Qt delete d; } void LogViewSearchWidget::displaySearch() { searchLine->setFocus(); searchLine->setSelection(0, searchLine->text().length()); show(); } void LogViewSearchWidget::setTreeWidget(LogViewWidget *logViewWidget) { d->logViewWidget = logViewWidget; } void LogViewSearchWidget::findFirst(const QString &text) { bool textIsNotEmpty = !text.isEmpty(); next->setEnabled(textIsNotEmpty); previous->setEnabled(textIsNotEmpty); if (textIsNotEmpty) findFirst(); } void LogViewSearchWidget::findFirst() { internalFind(nullptr, LogViewSearchWidget::Next); } void LogViewSearchWidget::findNext() { logDebug() << "Finding next"; LogViewWidgetItem *lastSelectedItem = d->logViewWidget->lastSelectedItem(); internalFind(lastSelectedItem, LogViewSearchWidget::Next); } void LogViewSearchWidget::findPrevious() { logDebug() << "Finding previous"; LogViewWidgetItem *firstSelectedItem = d->logViewWidget->firstSelectedItem(); internalFind(firstSelectedItem, LogViewSearchWidget::Previous); } void LogViewSearchWidget::internalFind(LogViewWidgetItem *fromItem, Direction direction) { if (searchLine->text().isEmpty()) { return; } QTreeWidgetItemIterator it(d->logViewWidget, QTreeWidgetItemIterator::NotHidden); initIterator(it, direction); // Go to the selected position + 1 (if we already found an item) if (fromItem != nullptr) { while (*it != nullptr) { LogViewWidgetItem *item = static_cast(*it); if (item == fromItem) { iteratorJump(it, direction); break; } iteratorJump(it, direction); } } // Iterates to fromItem +1 to the last item of the list while (*it != nullptr) { LogViewWidgetItem *item = static_cast(*it); bool found = findItem(item); if (found == true) return; iteratorJump(it, direction); } // If we do not begin the search from the beginning, we do it now if (fromItem != nullptr) { it = QTreeWidgetItemIterator(d->logViewWidget, QTreeWidgetItemIterator::NotHidden); initIterator(it, direction); LogViewWidgetItem *item = nullptr; while (*it != nullptr && item != fromItem) { item = static_cast(*it); bool found = findItem(item); if (found == true) { showMessage(i18n("Reached end of list."), QStringLiteral("dialog-information")); return; } iteratorJump(it, direction); } } setSearchLineNotFound(true); } inline void LogViewSearchWidget::initIterator(QTreeWidgetItemIterator &it, Direction direction) { // Previous direction : Go to the last item if (direction == LogViewSearchWidget::Previous) { QTreeWidgetItemIterator testedIterator(it); while (true) { ++testedIterator; if (*testedIterator == nullptr) { break; } ++it; } } } inline void LogViewSearchWidget::iteratorJump(QTreeWidgetItemIterator &it, Direction direction) { if (direction == LogViewSearchWidget::Next) { ++it; } else { --it; } } bool LogViewSearchWidget::compareItem(LogViewWidgetItem *item) { Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive; if (caseSensitive->isChecked()) { caseSensitivity = Qt::CaseSensitive; } if (searchLine->text().isEmpty()) return false; if (item->logLine()->exportToText().contains(searchLine->text(), caseSensitivity)) { return true; } return false; } bool LogViewSearchWidget::findItem(LogViewWidgetItem *item) { if (compareItem(item) == true) { unselectAll(); setSearchLineNotFound(false); item->setSelected(true); d->logViewWidget->setCurrentItem(item); d->logViewWidget->scrollToItem(item); return true; } return false; } void LogViewSearchWidget::setSearchLineNotFound(bool notFound) { QPalette palette = searchLine->palette(); if (notFound == true) { palette.setColor(QPalette::Base, QColor(255, 102, 102)); // or Qt::red or QColor(235, 0, 0) palette.setColor(QPalette::Text, QColor(255, 255, 255)); } else { palette.setColor(QPalette::Base, d->searchLineBaseColor); palette.setColor(QPalette::Text, d->searchLineTextColor); } searchLine->setPalette(palette); if (notFound == true) showMessage(i18n("Phrase not found."), QStringLiteral("dialog-error")); else hideMessage(); } void LogViewSearchWidget::unselectAll() { QList selectedItems = d->logViewWidget->selectedItems(); foreach (QTreeWidgetItem *item, selectedItems) { item->setSelected(false); } } void LogViewSearchWidget::showMessage(const QString &text, const QString &iconText) { message->setText(text); message->show(); - messageIcon->setPixmap(QIcon::fromTheme(iconText).pixmap(KIconLoader::SizeSmall)); + messageIcon->setPixmap(QIcon::fromTheme(iconText).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); messageIcon->show(); d->messageHidingTimer->start(); } void LogViewSearchWidget::hideMessage() { message->hide(); messageIcon->hide(); d->messageHidingTimer->stop(); } void LogViewSearchWidget::highlightAll() { if (highlightAllButton->isChecked()) { unlightAll(); logDebug() << "Highlighting all"; QTreeWidgetItemIterator it(d->logViewWidget, QTreeWidgetItemIterator::All); while (*it != nullptr) { LogViewWidgetItem *item = static_cast(*it); if (compareItem(item) == true) { item->setBackground(item->columnCount() - 1, QColor(255, 255, 16 * 8 + 11)); } ++it; } } else { unlightAll(); } } void LogViewSearchWidget::unlightAll() { logDebug() << "Unlighting all"; QTreeWidgetItemIterator it(d->logViewWidget, QTreeWidgetItemIterator::All); while (*it != nullptr) { LogViewWidgetItem *item = static_cast(*it); // We retrieve the default column background using the first column data, where the background never // changes item->setBackground(item->columnCount() - 1, qvariant_cast(item->data(0, Qt::BackgroundRole))); ++it; } } diff --git a/src/modes/base/fileListHelper.cpp b/src/modes/base/fileListHelper.cpp index 086a011..cc8be5c 100644 --- a/src/modes/base/fileListHelper.cpp +++ b/src/modes/base/fileListHelper.cpp @@ -1,186 +1,185 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "fileListHelper.h" #include #include #include #include #include #include -#include #include "defaults.h" #include "logging.h" FileListHelper::FileListHelper(QWidget *p) : parent(p) { } FileListHelper::~FileListHelper() { } QAction *FileListHelper::prepareButtonAndAction(QPushButton *button, const QIcon &icon) { // Initialize action QAction *action = new QAction(button); action->setIcon(icon); action->setText(button->text()); // Initialize button button->setIcon(icon); // Allow the disabling of the matching action when disabling this button button->addAction(action); // Assert that when an action is triggered, the related button sends a clicked() event //(the button is the QObject which is connected to custom slots) connect(action, &QAction::triggered, button, &QAbstractButton::click); return action; } QAction *FileListHelper::prepareButtonAndAction(QPushButton *button, const QIcon &icon, const QObject *receiver, const char *member) { QAction *action = prepareButtonAndAction(button, icon); connect(button, SIGNAL(clicked(bool)), receiver, member); return action; } void FileListHelper::prepareButton(QPushButton *button, const QIcon &icon, const QObject *receiver, const char *member, QWidget *fileList) { // Initialize action QAction *action = prepareButtonAndAction(button, icon, receiver, member); fileList->addAction(action); } QStringList FileListHelper::findPaths(const QList &urls) { QStringList paths; for (QList::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it) { QUrl url(*it); if (isValidFile(url)) { // If this Url uses a joker (i.e. : "/var/log/apache2/*") if (url.fileName().contains(QLatin1Char('*'))) { const QStringList foundPaths = expandJoker(url); logDebug() << "Found paths of " << url.path() << ":" << foundPaths; foreach (const QString &foundPath, foundPaths) { paths.append(foundPath); } } else { paths.append(url.path()); } } } return paths; } bool FileListHelper::isValidFile(const QUrl &url) { QString message; // If it is not valid if (!url.isValid()) { return false; } // If it is not a local file if (!url.isLocalFile()) { message = i18n("'%1' is not a local file.", url.path()); KMessageBox::error(parent, message, i18n("File selection failed"), KMessageBox::Notify); return false; } // If it's a directory, it's not valid if (QDir(url.path()).exists()) { return false; } return true; } QList FileListHelper::openUrls() { QFileDialog fileDialog(parent, QString(), QStringLiteral(DEFAULT_LOG_FOLDER), QLatin1String("*|") + i18n("All Files (*)") + QLatin1String("\n*.log|") + i18n("Log Files (*.log)")); fileDialog.setWindowTitle(i18n("Choose Log File")); fileDialog.setFileMode(QFileDialog::ExistingFiles); fileDialog.exec(); return fileDialog.selectedUrls(); } QUrl FileListHelper::openUrl(const QString &originPath) { QFileDialog fileDialog(parent, QString(), originPath, QLatin1String("*|") + i18n("All Files (*)") + QLatin1String("\n*.log|") + i18n("Log Files (*.log)")); fileDialog.setWindowTitle(i18n("Choose Log File")); fileDialog.setFileMode(QFileDialog::AnyFile); fileDialog.exec(); QList urls = fileDialog.selectedUrls(); if (!urls.isEmpty()) return fileDialog.selectedUrls().at(0); else return QUrl(); } QStringList FileListHelper::expandJoker(const QUrl &url) { QDir directory = QDir(url.path().left(url.path().count() - url.fileName().count())); logDebug() << "Dir " << directory.path(); QString filename = url.fileName(); if (filename.isEmpty()) { return QStringList(); } QStringList foundPaths; const QStringList files = directory.entryList(QStringList(filename), QDir::Files | QDir::NoSymLinks); foreach (const QString &file, files) { foundPaths.append(directory.absoluteFilePath(file)); } return foundPaths; } void FileListHelper::setEnabledAction(QPushButton *button, bool enabled) { button->setEnabled(enabled); QList actions = button->actions(); foreach (QAction *action, actions) { action->setEnabled(enabled); } } diff --git a/src/modes/base/logLevelSelectionDialog.cpp b/src/modes/base/logLevelSelectionDialog.cpp index acf6f2c..4e50c93 100644 --- a/src/modes/base/logLevelSelectionDialog.cpp +++ b/src/modes/base/logLevelSelectionDialog.cpp @@ -1,48 +1,47 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "logLevelSelectionDialog.h" #include #include -#include LogLevelSelectionDialog::LogLevelSelectionDialog(QWidget *parent) : QDialog(parent) { setupUi(this); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setIcon(KStandardGuiItem::ok().icon()); QPushButton *cancelButton = buttonBox->button(QDialogButtonBox::Cancel); cancelButton->setIcon(KStandardGuiItem::cancel().icon()); } LogLevelSelectionDialog::~LogLevelSelectionDialog() { } QListWidget *LogLevelSelectionDialog::logLevels() const { return logLevelsList; } diff --git a/src/tabLogViewsWidget.cpp b/src/tabLogViewsWidget.cpp index ba530eb..d7dba12 100644 --- a/src/tabLogViewsWidget.cpp +++ b/src/tabLogViewsWidget.cpp @@ -1,445 +1,444 @@ /*************************************************************************** * KSystemLog, a system log viewer tool * * Copyright (C) 2007 by Nicolas Ternisien * * nicolas.ternisien@gmail.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "tabLogViewsWidget.h" #include #include #include #include -#include #include #include "logging.h" #include "view.h" #include "logViewExport.h" #include "logMode.h" #include "defaults.h" #include "logManager.h" #include "tabLogManager.h" #include "logViewWidget.h" class TabLogViewsWidgetPrivate { public: QList tabLogManagers; QMenu *contextMenu; }; TabLogViewsWidget::TabLogViewsWidget(QWidget *parent) : QTabWidget(parent) , d(new TabLogViewsWidgetPrivate()) { d->contextMenu = nullptr; QPushButton *tabNewTabButton = new QPushButton(QIcon::fromTheme(QStringLiteral("tab-new")), QLatin1String(""), this); connect(tabNewTabButton, &QAbstractButton::clicked, this, &TabLogViewsWidget::createTab); tabNewTabButton->setToolTip(i18n("Create a new tab")); tabNewTabButton->setWhatsThis(i18n("Creates a new tab which can display another log.")); QPushButton *tabCloseTabButton = new QPushButton(QIcon::fromTheme(QStringLiteral("tab-close")), QLatin1String(""), this); connect(tabCloseTabButton, &QAbstractButton::clicked, this, &TabLogViewsWidget::closeTab); tabCloseTabButton->setToolTip(i18n("Close the current tab")); tabCloseTabButton->setWhatsThis(i18n("Closes the current tab.")); setCornerWidget(tabNewTabButton, Qt::TopLeftCorner); setCornerWidget(tabCloseTabButton, Qt::TopRightCorner); setUsesScrollButtons(true); // The context menu is managed manually setContextMenuPolicy(Qt::ActionsContextMenu); // connect(this, SIGNAL(mouseDoubleClick()), this, SLOT(createTab())); // connect(this, SIGNAL(contextMenu(QPoint)), this, SLOT(showContextMenu(QPoint))); // connect(this, SIGNAL(contextMenu(QWidget*,QPoint)), this, SLOT(showContextMenu(QWidget*,QPoint))); // TODO Use this (need to connect to movedTab(int, int) signal and update the QList // setTabReorderingEnabled(true); connect(this, &QTabWidget::currentChanged, this, &TabLogViewsWidget::changeCurrentTab); } TabLogViewsWidget::~TabLogViewsWidget() { QList copy = d->tabLogManagers; foreach (TabLogManager *tabLogManager, copy) { d->tabLogManagers.removeAll(tabLogManager); delete tabLogManager; } delete d; } void TabLogViewsWidget::newTab(View *view) { logDebug() << "Inserting to a new tab the view "; // Add a tab at the end of the widget insertTab(count(), view, QIcon::fromTheme(QStringLiteral(NO_MODE_ICON)), i18n("No Log")); if (count() > 1) tabBar()->show(); else tabBar()->hide(); } void TabLogViewsWidget::changeTab(View *view, const QIcon &icon, const QString &label) { logDebug() << "Changing tab " << label; int index = indexOf(view); setTabIcon(index, icon); setTabText(index, label); } QList TabLogViewsWidget::logManagers() { QList logManagers; foreach (TabLogManager *tabLogManager, d->tabLogManagers) { logManagers.append(tabLogManager->logManager()); } return logManagers; } LogManager *TabLogViewsWidget::findRelatedLogManager(View *view) { return findRelatedTabLogManager(view)->logManager(); } TabLogManager *TabLogViewsWidget::findRelatedTabLogManager(View *view) { foreach (TabLogManager *tabLogManager, d->tabLogManagers) { if (tabLogManager->logManager()->usedView() == view) { return tabLogManager; } } logCritical() << "No log manager found"; return nullptr; } TabLogManager *TabLogViewsWidget::activeTabLogManager() { View *currentView = static_cast(currentWidget()); return findRelatedTabLogManager(currentView); } LogManager *TabLogViewsWidget::activeLogManager() { TabLogManager *tabLogManager = activeTabLogManager(); if (tabLogManager) return tabLogManager->logManager(); return nullptr; } LogManager *TabLogViewsWidget::createTab() { logDebug() << "Creating a new tab"; return newTabLogManager()->logManager(); } void TabLogViewsWidget::moveTabLeft() { logDebug() << "Duplicate tab to the left"; TabLogManager *currentTabLogManager = activeTabLogManager(); int position = indexOf(currentTabLogManager->logManager()->usedView()); if (position <= 0) { logCritical() << "Tab Position <= 0 : " << position; return; } d->tabLogManagers.removeAt(position); d->tabLogManagers.insert(position - 1, currentTabLogManager); tabBar()->moveTab(position, position - 1); } void TabLogViewsWidget::moveTabRight() { logDebug() << "Duplicate tab to the right"; TabLogManager *currentTabLogManager = activeTabLogManager(); int position = indexOf(currentTabLogManager->logManager()->usedView()); if (position >= count() - 1) { logCritical() << "Tab Position >= count()-1 : " << position; return; } d->tabLogManagers.removeAt(position); d->tabLogManagers.insert(position + 1, currentTabLogManager); tabBar()->moveTab(position, position + 1); } LogManager *TabLogViewsWidget::duplicateTab() { logDebug() << "Duplicate current tab"; TabLogManager *currentManager = activeTabLogManager(); TabLogManager *tabLogManager = newTabLogManager(); LogMode *mode = currentManager->logManager()->logMode(); load(mode, tabLogManager->logManager()); // Returns the newly created LogManager return tabLogManager->logManager(); } TabLogManager *TabLogViewsWidget::newTabLogManager() { logDebug() << "Creating new View..."; View *view = new View(this); logDebug() << "Creating new LogManager..."; LogManager *logManager = new LogManager(view); // Signals from LogManager to Main Class connect(logManager, &LogManager::tabTitleChanged, this, &TabLogViewsWidget::changeTab); connect(logManager, &LogManager::logUpdated, this, &TabLogViewsWidget::changeTitleAddedLines); TabLogManager *tabLogManager = new TabLogManager(logManager); d->tabLogManagers.append(tabLogManager); logDebug() << "New LogManager created"; // Finally add the view to the tabs newTab(view); emit logManagerCreated(logManager); setCurrentIndex(count() - 1); // Set focus to the list view->logViewWidget()->setFocus(); // Returns the newly created TabLogManager return tabLogManager; } void TabLogViewsWidget::closeTab() { if (count() == 1) { logCritical() << "Cannot close tab, one tab left"; return; } TabLogManager *currentTabLogManager = activeTabLogManager(); d->tabLogManagers.removeAll(currentTabLogManager); removeTab(indexOf(currentTabLogManager->logManager()->usedView())); if (count() == 1) { tabBar()->hide(); } delete currentTabLogManager; } void TabLogViewsWidget::load(LogMode *logMode, LogManager *manager, const QVariant &analyzerOptions) { logDebug() << "Loading a new mode : " << logMode->name(); if (manager == nullptr || logMode == nullptr) { logCritical() << "Error while loading a manager "; return; } // The manager is now using the Log mode passed in parameter manager->initialize(logMode, analyzerOptions); // Launch the reading manager->reload(); } void TabLogViewsWidget::reloadCurrent() { logDebug() << "Reloading current log manager..."; LogManager *manager = activeLogManager(); if (manager != nullptr) { manager->reload(); } } void TabLogViewsWidget::reloadAll() { logDebug() << "Reloading all tabs..."; foreach (TabLogManager *tabLogManager, d->tabLogManagers) { // Log manager without log mode does not need to be reloaded if (tabLogManager->logManager()->logMode() == nullptr) { continue; } // Do a simple reload if it is an open log mode if (tabLogManager->logManager()->logMode()->id() == QLatin1String("openLogMode")) { tabLogManager->logManager()->reload(); continue; } // Do a full loading of other log modes (needed if log files have been modified) load(tabLogManager->logManager()->logMode(), tabLogManager->logManager(), tabLogManager->logManager()->analyzerOptions()); } } void TabLogViewsWidget::changeCurrentTab(int index) { logDebug() << "Changing current tab..."; if (index == -1) return; TabLogManager *tabLogManager = activeTabLogManager(); // Reinit the new lines count since last selection tabLogManager->initNewLinesCount(); // If the tab displayed the new added line count, rename it to the default log mode name changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); logDebug() << "Current tab changed"; } void TabLogViewsWidget::changeReloadingTab(View *view, bool reloading) { TabLogManager *tabLogManager = findRelatedTabLogManager(view); if (reloading == true) changeTab(tabLogManager->logManager()->usedView(), QIcon::fromTheme(QStringLiteral("view-refresh")), tabLogManager->title()); else changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); } void TabLogViewsWidget::changeTitleAddedLines(View *view, int addedLinesSinceLastUpdate) { logDebug() << "Changing title" << addedLinesSinceLastUpdate << " added lines..."; LogManager *currentManager = activeLogManager(); // Only display added line on tab title if this is not an update of the current tab if (currentManager->usedView() != view) { TabLogManager *tabLogManager = findRelatedTabLogManager(view); tabLogManager->addNewLinesCount(addedLinesSinceLastUpdate); // Update the tab title changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); } } void TabLogViewsWidget::expandAllCurrentView() { activeLogManager()->usedView()->logViewWidget()->expandAll(); } void TabLogViewsWidget::collapseAllCurrentView() { activeLogManager()->usedView()->logViewWidget()->collapseAll(); } void TabLogViewsWidget::selectAllCurrentView() { activeLogManager()->usedView()->logViewWidget()->selectAll(); } void TabLogViewsWidget::fileSaveCurrentView() { LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); logViewExport.fileSave(); } void TabLogViewsWidget::copyToClipboardCurrentView() { LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); logViewExport.copyToClipboard(); } void TabLogViewsWidget::sendMailCurrentView() { LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); logViewExport.sendMail(); } void TabLogViewsWidget::printSelectionCurrentView() { LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); logViewExport.printSelection(); } QIcon TabLogViewsWidget::logModeIcon(LogMode *logMode) { if (logMode == nullptr) return QIcon::fromTheme(QStringLiteral(NO_MODE_ICON)); else return logMode->icon(); } void TabLogViewsWidget::prepareContextMenu(bool /*onTab*/) { if (d->contextMenu == nullptr) { d->contextMenu = new QMenu(this); d->contextMenu->addActions(actions()); } // TODO Disable some actions, depending of the onTab value } void TabLogViewsWidget::showContextMenu(const QPoint &cursorPosition) { logDebug() << "Showing context menu at " << cursorPosition; prepareContextMenu(false); d->contextMenu->popup(cursorPosition); } void TabLogViewsWidget::showContextMenu(QWidget *tab, const QPoint &cursorPosition) { logDebug() << "Showing context menu at " << cursorPosition << " at " << tab->objectName(); prepareContextMenu(true); d->contextMenu->popup(cursorPosition); }