File indexing completed on 2024-04-21 05:46:24

0001 /*
0002     SPDX-FileCopyrightText: 2007 Nicolas Ternisien <nicolas.ternisien@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "mainWindow.h"
0008 
0009 // Qt includes
0010 #include <QAction>
0011 #include <QIcon>
0012 #include <QList>
0013 
0014 // KDE includes
0015 #include <KActionCollection>
0016 #include <KActionMenu>
0017 #include <KLocalizedString>
0018 #include <KStandardAction>
0019 #include <KStandardShortcut>
0020 
0021 // Project includes
0022 #include "ksystemlogConfig.h"
0023 
0024 #include "statusBar.h"
0025 
0026 #include "configurationDialog.h"
0027 #include "logViewWidget.h"
0028 #include "tabLogViewsWidget.h"
0029 
0030 #include "loggerDialog.h"
0031 
0032 #include "detailDialog.h"
0033 
0034 #include "logManager.h"
0035 #include "logModeConfiguration.h"
0036 
0037 #include "logFile.h"
0038 #include "logLevel.h"
0039 #include "logMode.h"
0040 
0041 #include "ksystemlog_debug.h"
0042 
0043 #include "logModePluginsLoader.h"
0044 #include "logViewSearchWidget.h"
0045 #include "view.h"
0046 
0047 #include "globals.h"
0048 
0049 namespace KSystemLog
0050 {
0051 MainWindow::MainWindow()
0052     : KXmlGuiWindow(nullptr)
0053 {
0054     qCDebug(KSYSTEMLOG) << "Starting KSystemLog...";
0055 
0056     // Load log modes plugins
0057     loadLogModePlugins();
0058 
0059     // Create the GUI from XML configuration
0060     qCDebug(KSYSTEMLOG) << "Creating Gui...";
0061     createGUI();
0062 
0063     // TODO Improve the status bar to add a custom widget which shows an history of latest message, and add a
0064     // LogLevel for each ones
0065     // Initialize the Status Bar
0066     setupStatusBar();
0067 
0068     // Setup the main tab bar
0069     setupTabLogViews();
0070 
0071     // Setup the Actions
0072     setupActions();
0073 
0074     // Setup toolbar log actions, needs to be called before setupGUI()
0075     setupLogActions();
0076 
0077     // Apply the create the main window and ask the mainwindow to
0078     // automatically save settings if changed: window size, toolbar
0079     // position, icon size, etc.  Also to add actions for the statusbar
0080     // toolbar, and keybindings if necessary.
0081     qCDebug(KSYSTEMLOG) << "Setup Gui...";
0082     setupGUI();
0083 
0084     // Setup Logs menu, needs to be called after setupGUI()
0085     setupLogModeMenu();
0086 
0087     // Apply the saved mainwindow settings, if any, and ask the main window
0088     // to automatically save settings if changed: window size, tool bar
0089     // position, icon size, etc.
0090     setAutoSaveSettings();
0091 
0092     mConfigurationDialog = new ConfigurationDialog(this);
0093     connect(mConfigurationDialog, &ConfigurationDialog::configurationSaved, mTabs, &TabLogViewsWidget::reloadAll);
0094 
0095     // Show KSystemLog before loading the first log file
0096     show();
0097 
0098     LogManager *firstLogManager = mTabs->createTab();
0099 
0100     // Load selected mode only if its log files exist.
0101     const QString &startupLogMode = KSystemLogConfig::startupLogMode();
0102     if (!startupLogMode.isEmpty()) {
0103         LogMode *mode = Globals::instance().findLogMode(startupLogMode);
0104         if (mode) {
0105             if (mode->filesExist()) {
0106                 mTabs->load(mode, firstLogManager);
0107             } else {
0108                 qCWarning(KSYSTEMLOG) << mode->name() << "is selected by default, but log files do not exist.";
0109             }
0110         }
0111     }
0112 
0113     // Set focus to the list
0114     firstLogManager->usedView()->logViewWidget()->setFocus();
0115 
0116     const auto logModes = Globals::instance().logModes();
0117     for (LogMode *logMode : logModes) {
0118         connect(logMode, &LogMode::menuChanged, this, &MainWindow::recreateActions);
0119     }
0120 }
0121 
0122 void MainWindow::loadLogModePlugins()
0123 {
0124     LogModePluginsLoader pluginsLoader(this);
0125     pluginsLoader.loadPlugins();
0126 }
0127 
0128 void MainWindow::setupTabLogViews()
0129 {
0130     qCDebug(KSYSTEMLOG) << "Creating tab widget...";
0131 
0132     mTabs = new TabLogViewsWidget(this);
0133 
0134     connect(mTabs, &TabLogViewsWidget::statusBarChanged, this, &MainWindow::changeStatusBar);
0135     connect(mTabs, &TabLogViewsWidget::logManagerCreated, this, &MainWindow::prepareCreatedLogManager);
0136     connect(mTabs, &QTabWidget::currentChanged, this, &MainWindow::changeCurrentTab);
0137 
0138     setCentralWidget(mTabs);
0139 }
0140 
0141 MainWindow::~MainWindow()
0142 {
0143     delete mLoggedDialog;
0144 
0145     delete mDetailDialog;
0146 
0147     delete mConfigurationDialog;
0148 }
0149 
0150 void MainWindow::setupStatusBar()
0151 {
0152     mStatusBar = new KSystemLog::StatusBar(this);
0153 
0154     setStatusBar(mStatusBar);
0155 }
0156 
0157 void MainWindow::prepareCreatedLogManager(LogManager *manager)
0158 {
0159     qCDebug(KSYSTEMLOG) << "Connecting to actions the new log manager and view...";
0160 
0161     // Contextual menu Log Manager signals
0162 
0163     manager->usedView()->logViewWidget()->addAction(mReloadAction);
0164     manager->usedView()->logViewWidget()->addAction(mSelectAllAction);
0165 
0166     auto separator = new QAction(this);
0167     separator->setSeparator(true);
0168     manager->usedView()->logViewWidget()->addAction(separator);
0169 
0170     manager->usedView()->logViewWidget()->addAction(mCopyAction);
0171     manager->usedView()->logViewWidget()->addAction(mSaveAction);
0172     manager->usedView()->logViewWidget()->addAction(mSendMailAction);
0173 
0174     separator = new QAction(this);
0175     separator->setSeparator(true);
0176     manager->usedView()->logViewWidget()->addAction(separator);
0177 
0178     manager->usedView()->logViewWidget()->addAction(mTooltipEnabledAction);
0179     manager->usedView()->logViewWidget()->addAction(mNewLinesDisplayedAction);
0180 
0181     separator = new QAction(this);
0182     separator->setSeparator(true);
0183     manager->usedView()->logViewWidget()->addAction(separator);
0184 
0185     manager->usedView()->logViewWidget()->addAction(mDetailAction);
0186 
0187     // Log Manager and View signals
0188     connect(manager, &LogManager::windowTitleChanged, this, &MainWindow::changeWindowTitle);
0189     connect(manager, &LogManager::statusBarChanged, this, &MainWindow::changeStatusBar);
0190     connect(manager, &LogManager::logUpdated, this, &MainWindow::updateStatusBar);
0191     connect(manager, &LogManager::reloaded, this, &MainWindow::changeCurrentTab);
0192 
0193     connect(manager->usedView(), &View::searchFilterChanged, this, &MainWindow::updateStatusBar);
0194     connect(manager->usedView()->logViewWidget(), &QTreeWidget::itemDoubleClicked, this, &MainWindow::showDetailsDialog);
0195     connect(manager->usedView()->logViewWidget(), &QTreeWidget::itemSelectionChanged, this, &MainWindow::updateSelection);
0196     connect(manager->usedView()->logViewWidget()->model(), &LogViewModel::processingMultipleInsertions, this, &MainWindow::updateReloading);
0197 
0198     // Correctly initialize the Status Bar
0199     updateStatusBar();
0200 }
0201 
0202 void MainWindow::updateDetailDialog()
0203 {
0204     LogManager *currentManager = mTabs->activeLogManager();
0205     if (mDetailDialog) {
0206         mDetailDialog->selectionChanged(currentManager->usedView()->logViewWidget());
0207     }
0208 }
0209 
0210 void MainWindow::updateSelection()
0211 {
0212     // qCDebug(KSYSTEMLOG) << "Updating selection...";
0213 
0214     LogManager *currentLogManager = mTabs->activeLogManager();
0215 
0216     updateDetailDialog();
0217 
0218     bool const selection = currentLogManager->usedView()->logViewWidget()->hasItemsSelected();
0219 
0220     mCopyAction->setEnabled(selection);
0221     mSaveAction->setEnabled(selection);
0222     mDetailAction->setEnabled(selection);
0223     mSendMailAction->setEnabled(selection);
0224     mPrintAction->setEnabled(selection);
0225     mPrintPreviewAction->setEnabled(selection);
0226 }
0227 
0228 void MainWindow::updateReloading()
0229 {
0230     View *currentView = mTabs->activeLogManager()->usedView();
0231 
0232     const bool enabled = !currentView->logViewWidget()->model()->isProcessingMultipleInsertions();
0233 
0234     mReloadAction->setEnabled(enabled);
0235     mResumePauseAction->setEnabled(enabled);
0236     mFindAction->setEnabled(enabled);
0237     mFindNextAction->setEnabled(enabled);
0238     mFindPreviousAction->setEnabled(enabled);
0239 
0240     // Enables/Disables all Log Mode actions
0241     // logModesActionGroup->setEnabled(enabled);
0242 
0243     mTabs->changeReloadingTab(currentView, !enabled);
0244 
0245     // Enables/Disables all Log Mode menus (useful for multiple actions menus)
0246     const auto logModeActions{Globals::instance().logModeActions()};
0247     for (LogModeAction *logModeAction : logModeActions) {
0248         logModeAction->actionMenu()->setEnabled(enabled);
0249     }
0250 }
0251 
0252 void MainWindow::closeEvent(QCloseEvent *event)
0253 {
0254     disconnect(mTabs, &QTabWidget::currentChanged, this, &MainWindow::changeCurrentTab);
0255 
0256     LogManager *currentLogManager = mTabs->activeLogManager();
0257     if (currentLogManager) {
0258         currentLogManager->stopWatching();
0259     }
0260     qCDebug(KSYSTEMLOG) << "Saving configuration before exit...";
0261     qCDebug(KSYSTEMLOG) << "Saving configuration before exit...";
0262     // Write the config to the file
0263     KSystemLogConfig::self()->save();
0264     KXmlGuiWindow::closeEvent(event);
0265 }
0266 
0267 TabLogViewsWidget *MainWindow::tabs()
0268 {
0269     return mTabs;
0270 }
0271 
0272 void MainWindow::showDetailsDialog()
0273 {
0274     // Create the Detail dialog if it was not created
0275     if (!mDetailDialog) {
0276         mDetailDialog = new DetailDialog(this);
0277         updateDetailDialog();
0278     }
0279 
0280     mDetailDialog->show();
0281 }
0282 
0283 void MainWindow::toggleItemTooltip(bool enabled)
0284 {
0285     KSystemLogConfig::setTooltipEnabled(enabled);
0286 
0287     const auto logManagers{mTabs->logManagers()};
0288     for (LogManager *manager : logManagers) {
0289         manager->usedView()->logViewWidget()->toggleToolTip(enabled);
0290     }
0291 }
0292 
0293 void MainWindow::toggleNewLinesDisplaying(bool displayed)
0294 {
0295     KSystemLogConfig::setNewLinesDisplayed(displayed);
0296 }
0297 
0298 void MainWindow::updateStatusBar()
0299 {
0300     qCDebug(KSYSTEMLOG) << "Updating status bar...";
0301 
0302     LogManager *currentManager = mTabs->activeLogManager();
0303 
0304     int const itemCount = currentManager->usedView()->logViewWidget()->itemCount();
0305     int const notHiddenItemCount = currentManager->usedView()->logViewWidget()->notHiddenItemCount();
0306 
0307     if (itemCount == notHiddenItemCount) {
0308         mStatusBar->changeLineCountMessage(i18ncp("Total displayed lines", "1 line.", "%1 lines.", currentManager->usedView()->logViewWidget()->itemCount()));
0309     } else {
0310         mStatusBar->changeLineCountMessage(
0311             i18ncp("Line not hidden by search / Total displayed lines", "1 line / %2 total.", "%1 lines / %2 total.", notHiddenItemCount, itemCount));
0312     }
0313 
0314     mStatusBar->changeLastModification(currentManager->lastUpdate());
0315 }
0316 
0317 void MainWindow::toggleResumePauseParsing(bool paused)
0318 {
0319     qCDebug(KSYSTEMLOG) << "Pausing parsing : " << paused;
0320 
0321     LogManager *currentLogManager = mTabs->activeLogManager();
0322     if (currentLogManager) {
0323         currentLogManager->setParsingPaused(paused);
0324     }
0325 
0326     qCDebug(KSYSTEMLOG) << "Parsing paused : " << paused;
0327 }
0328 
0329 void MainWindow::changeResumePauseAction(bool paused)
0330 {
0331     if (paused) {
0332         mResumePauseAction->setText(i18n("Resu&me"));
0333         mResumePauseAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
0334         mResumePauseAction->setToolTip(i18n("Resume the watching of the current log"));
0335         mResumePauseAction->setWhatsThis(
0336             i18n("Resumes the watching of the current log. This action is only available when the user has "
0337                  "already paused the reading."));
0338         mResumePauseAction->setChecked(true);
0339         actionCollection()->setDefaultShortcut(mResumePauseAction, Qt::CTRL | Qt::Key_M);
0340     } else {
0341         mResumePauseAction->setText(i18n("S&top"));
0342         mResumePauseAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-stop")));
0343         mResumePauseAction->setToolTip(i18n("Pause the watching of the current log"));
0344         mResumePauseAction->setWhatsThis(
0345             i18n("Pauses the watching of the current log. This action is particularly useful when the system is "
0346                  "writing too many lines to log files, causing KSystemLog to reload too frequently."));
0347         mResumePauseAction->setChecked(false);
0348         actionCollection()->setDefaultShortcut(mResumePauseAction, Qt::CTRL | Qt::Key_P);
0349     }
0350 
0351     // Be sure that the button will always have a good size
0352     const auto associatedWidgets{mResumePauseAction->associatedObjects()};
0353     for (QObject *obj : associatedWidgets) {
0354         QWidget *widget = qobject_cast<QWidget *>(obj);
0355 
0356         if (widget && (widget->sizeHint().width() > widget->size().width())) {
0357             widget->setMinimumSize(widget->sizeHint());
0358         }
0359     }
0360 }
0361 
0362 void MainWindow::fileOpen()
0363 {
0364     // Launch the actualizing
0365     mTabs->load(Globals::instance().findLogMode(QStringLiteral("openLogMode")), mTabs->activeLogManager());
0366 }
0367 
0368 void MainWindow::showConfigurationDialog()
0369 {
0370     qCDebug(KSYSTEMLOG) << "Showing configuration dialog...";
0371     mConfigurationDialog->showConfiguration();
0372 }
0373 
0374 void MainWindow::showLogMessageDialog()
0375 {
0376     qCDebug(KSYSTEMLOG) << "Launching the Send message dialog box...";
0377 
0378     if (!mLoggedDialog) {
0379         mLoggedDialog = new LoggerDialog(this);
0380     }
0381 
0382     mLoggedDialog->initialize();
0383     mLoggedDialog->exec();
0384 }
0385 
0386 void MainWindow::changeStatusBar(const QString &text)
0387 {
0388     mStatusBar->changeMessage(text);
0389 }
0390 
0391 void MainWindow::changeWindowTitle(const QString &text)
0392 {
0393     // Display this text on the caption
0394     setCaption(text);
0395 }
0396 
0397 void MainWindow::changeCurrentTab()
0398 {
0399     qCDebug(KSYSTEMLOG) << "Tab has changed";
0400 
0401     LogManager *currentManager = mTabs->activeLogManager();
0402 
0403     if (!currentManager) {
0404         return;
0405     }
0406 
0407     // If the tab changed, the selection changes too
0408     updateSelection();
0409 
0410     // Update the status bar
0411     updateStatusBar();
0412 
0413     // Updating the current reloading status
0414     updateReloading();
0415 
0416     bool const enabledReloading = !currentManager->usedView()->logViewWidget()->model()->isProcessingMultipleInsertions();
0417 
0418     bool enabledAction;
0419     // Change the title of the window
0420     if (!currentManager->logMode()) {
0421         changeWindowTitle(i18nc("Newly created tab", "Empty Log"));
0422         enabledAction = false;
0423     } else {
0424         changeWindowTitle(currentManager->title());
0425         enabledAction = true;
0426     }
0427 
0428     if (enabledReloading && enabledAction) {
0429         mReloadAction->setEnabled(true);
0430         mResumePauseAction->setEnabled(true);
0431     } else {
0432         mReloadAction->setEnabled(false);
0433         mResumePauseAction->setEnabled(false);
0434     }
0435 
0436     // Update Resume/Pause action state
0437     if (currentManager->isParsingPaused()) {
0438         changeResumePauseAction(true);
0439     } else {
0440         changeResumePauseAction(false);
0441     }
0442 
0443     // Updating Detail dialog
0444     updateDetailDialog();
0445 
0446     qCDebug(KSYSTEMLOG) << "Tab changing done";
0447 }
0448 
0449 /**
0450  * TODO Implements the session restoring
0451  *
0452  * The 'config' object points to the session managed
0453  * config file.  anything you write here will be available
0454  * later when this app is restored
0455  */
0456 void MainWindow::saveProperties(KConfigGroup & /*configuration*/)
0457 {
0458     qCDebug(KSYSTEMLOG) << "Saving properties...";
0459 }
0460 
0461 /**
0462  * TODO Implements the session restoring
0463  *
0464  * The 'config' object points to the session managed
0465  * config file.  this function is automatically called whenever
0466  * the app is being restored.  read in here whatever you wrote
0467  * in 'saveProperties'
0468  */
0469 void MainWindow::readProperties(const KConfigGroup & /*configuration*/)
0470 {
0471     qCDebug(KSYSTEMLOG) << "Reading properties...";
0472 }
0473 
0474 void MainWindow::toggleFilterBar()
0475 {
0476     qCDebug(KSYSTEMLOG) << "Toggling filter bar..." << mFilterBarAction->isChecked();
0477 
0478     const auto logManagers{mTabs->logManagers()};
0479     for (LogManager *manager : logManagers) {
0480         manager->usedView()->toggleLogViewFilter(mFilterBarAction->isChecked());
0481     }
0482 
0483     KSystemLogConfig::setToggleFilterBar(mFilterBarAction->isChecked());
0484 }
0485 
0486 void MainWindow::findNext()
0487 {
0488     showSearchBar();
0489     mTabs->activeLogManager()->usedView()->logViewSearch()->findNext();
0490 }
0491 
0492 void MainWindow::findPrevious()
0493 {
0494     showSearchBar();
0495     mTabs->activeLogManager()->usedView()->logViewSearch()->findPrevious();
0496 }
0497 
0498 void MainWindow::showSearchBar()
0499 {
0500     qCDebug(KSYSTEMLOG) << "Showing search bar...";
0501 
0502     LogManager *activeLogManager = mTabs->activeLogManager();
0503 
0504     const auto logManagers = mTabs->logManagers();
0505     for (LogManager *manager : logManagers) {
0506         if (manager != activeLogManager) {
0507             manager->usedView()->toggleLogViewSearch(true);
0508         }
0509     }
0510 
0511     // Be sure to display the view search of the active LogManager at last, and focus to it
0512     mTabs->activeLogManager()->usedView()->toggleLogViewSearch(true);
0513 }
0514 
0515 void MainWindow::setupActions()
0516 {
0517     qCDebug(KSYSTEMLOG) << "Creating actions...";
0518 
0519     QAction *fileOpenAction = actionCollection()->addAction(KStandardAction::Open, this, SLOT(fileOpen()));
0520     fileOpenAction->setToolTip(i18n("Open a file in KSystemLog"));
0521     fileOpenAction->setWhatsThis(i18n("Opens a file in KSystemLog and displays its content in the current tab."));
0522 
0523     mPrintAction = actionCollection()->addAction(KStandardAction::Print);
0524     mPrintAction->setText(i18n("&Print Selection..."));
0525     mPrintAction->setToolTip(i18n("Print the selection"));
0526     mPrintAction->setWhatsThis(
0527         i18n("Prints the selection. Simply select the important lines and click on this menu entry to print the "
0528              "selection."));
0529     mPrintAction->setEnabled(false);
0530 
0531     mPrintPreviewAction = actionCollection()->addAction(KStandardAction::PrintPreview);
0532     mPrintPreviewAction->setText(i18n("&Print Preview Selection..."));
0533     mPrintPreviewAction->setToolTip(i18n("Print preview the selection"));
0534     mPrintPreviewAction->setWhatsThis(
0535         i18n("Prints preview the selection. Simply select the important lines and click on this menu entry to print the "
0536              "selection."));
0537     mPrintPreviewAction->setEnabled(false);
0538 
0539     mSaveAction = actionCollection()->addAction(KStandardAction::SaveAs);
0540     // TODO Retrieve the system's shortcut of the save action (and not Save as...)
0541     mSaveAction->setToolTip(i18n("Save the selection to a file"));
0542     mSaveAction->setWhatsThis(
0543         i18n("Saves the selection to a file. This action is useful if you want to create an attachment or a "
0544              "backup of a particular log."));
0545     mSaveAction->setEnabled(false);
0546     actionCollection()->setDefaultShortcut(mSaveAction, Qt::CTRL | Qt::Key_S);
0547 
0548     QAction *fileQuitAction = actionCollection()->addAction(KStandardAction::Quit, qApp, SLOT(quit()));
0549     fileQuitAction->setToolTip(i18n("Quit KSystemLog"));
0550     fileQuitAction->setWhatsThis(i18n("Quits KSystemLog."));
0551 
0552     mCopyAction = actionCollection()->addAction(KStandardAction::Copy);
0553     mCopyAction->setToolTip(i18n("Copy the selection to the clipboard"));
0554     mCopyAction->setWhatsThis(
0555         i18n("Copies the selection to the clipboard. This action is useful if you want to paste the selection in "
0556              "a chat or an email."));
0557     mCopyAction->setEnabled(false);
0558 
0559     mExpandAllAction = actionCollection()->addAction(QStringLiteral("expand_all"));
0560     mExpandAllAction->setText(i18n("Ex&pand All"));
0561     mExpandAllAction->setToolTip(i18n("Expand all categories"));
0562     mExpandAllAction->setWhatsThis(
0563         i18n("This action opens all main categories. This is enabled only if an option has been selected in the "
0564              "<b>Group By</b> menu."));
0565     mExpandAllAction->setEnabled(false);
0566     actionCollection()->setDefaultShortcut(mExpandAllAction, Qt::CTRL | Qt::Key_X);
0567 
0568     mCollapseAllAction = actionCollection()->addAction(QStringLiteral("collapse_all"));
0569     mCollapseAllAction->setText(i18n("Col&lapse All"));
0570     mCollapseAllAction->setToolTip(i18n("Collapse all categories"));
0571     mCollapseAllAction->setWhatsThis(
0572         i18n("This action closes all main categories. This is enabled only if an option has been selected in the "
0573              "<b>Group By</b> menu."));
0574     mCollapseAllAction->setEnabled(false);
0575     actionCollection()->setDefaultShortcut(mCollapseAllAction, Qt::CTRL | Qt::Key_L);
0576 
0577     mSendMailAction = actionCollection()->addAction(QStringLiteral("send_mail"));
0578     mSendMailAction->setText(i18n("&Email Selection..."));
0579     mSendMailAction->setIcon(QIcon::fromTheme(QStringLiteral("mail-message-new")));
0580     mSendMailAction->setToolTip(i18n("Send the selection by mail"));
0581     mSendMailAction->setWhatsThis(
0582         i18n("Sends the selection by mail. Simply select the important lines and click on this menu entry to send "
0583              "the selection to a friend or a mailing list."));
0584     mSendMailAction->setEnabled(false);
0585     actionCollection()->setDefaultShortcut(mSendMailAction, Qt::CTRL | Qt::Key_M);
0586 
0587     mLogMessageAction = actionCollection()->addAction(QStringLiteral("log_message"), this, SLOT(showLogMessageDialog()));
0588     mLogMessageAction->setText(i18n("&Add Log Entry..."));
0589     mLogMessageAction->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
0590     mLogMessageAction->setShortcut(Qt::CTRL | Qt::Key_L);
0591     mLogMessageAction->setToolTip(i18n("Add a log entry to the log system"));
0592     mLogMessageAction->setWhatsThis(i18n("This action will open a dialog which lets you send a message to the log system."));
0593     actionCollection()->setDefaultShortcut(mLogMessageAction, Qt::CTRL | Qt::Key_L);
0594 
0595     mSelectAllAction = actionCollection()->addAction(KStandardAction::SelectAll);
0596     mSelectAllAction->setToolTip(i18n("Select all lines of the current log"));
0597     mSelectAllAction->setWhatsThis(
0598         i18n("Selects all lines of the current log. This action is useful if you want, for example, to save all "
0599              "the content of the current log in a file."));
0600 
0601     mFindAction = actionCollection()->addAction(KStandardAction::Find, this, SLOT(showSearchBar()));
0602     mFindNextAction = actionCollection()->addAction(KStandardAction::FindNext, this, SLOT(findNext()));
0603     mFindPreviousAction = actionCollection()->addAction(KStandardAction::FindPrev, this, SLOT(findPrevious()));
0604 
0605     actionCollection()->addAction(KStandardAction::Preferences, this, SLOT(showConfigurationDialog()));
0606 
0607     // TODO Find a solution to display at the right place this action (see Akregator interface)
0608     mFilterBarAction = actionCollection()->addAction(QStringLiteral("show_quick_filter"), this, SLOT(toggleFilterBar()));
0609     mFilterBarAction->setText(i18n("Show &Filter Bar"));
0610     mFilterBarAction->setEnabled(true);
0611     mFilterBarAction->setCheckable(true);
0612     mFilterBarAction->setChecked(KSystemLogConfig::toggleFilterBar());
0613 
0614     QAction *newTabAction = actionCollection()->addAction(QStringLiteral("new_tab"), mTabs, SLOT(createTab()));
0615     newTabAction->setText(i18n("&New Tab"));
0616     newTabAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
0617     newTabAction->setToolTip(i18n("Create a new tab"));
0618     newTabAction->setWhatsThis(i18n("Creates a new tab which can display another log."));
0619     mTabs->addAction(newTabAction);
0620     actionCollection()->setDefaultShortcut(newTabAction, Qt::CTRL | Qt::Key_T);
0621 
0622     QAction *closeTabAction = actionCollection()->addAction(QStringLiteral("close_tab"), mTabs, SLOT(closeTab()));
0623     closeTabAction->setText(i18n("&Close Tab"));
0624     closeTabAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
0625     closeTabAction->setToolTip(i18n("Close the current tab"));
0626     closeTabAction->setWhatsThis(i18n("Closes the current tab."));
0627     mTabs->addAction(closeTabAction);
0628     actionCollection()->setDefaultShortcut(closeTabAction, Qt::CTRL | Qt::Key_W);
0629 
0630     QAction *duplicateTabAction = actionCollection()->addAction(QStringLiteral("duplicate_tab"), mTabs, SLOT(duplicateTab()));
0631     duplicateTabAction->setText(i18n("&Duplicate Tab"));
0632     duplicateTabAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-duplicate")));
0633     duplicateTabAction->setToolTip(i18n("Duplicate the current tab"));
0634     duplicateTabAction->setWhatsThis(i18n("Duplicates the current tab."));
0635     mTabs->addAction(duplicateTabAction);
0636     actionCollection()->setDefaultShortcut(duplicateTabAction, Qt::SHIFT | Qt::CTRL | Qt::Key_N);
0637 
0638     auto separatorAction = new QAction(this);
0639     separatorAction->setSeparator(true);
0640     mTabs->addAction(separatorAction);
0641 
0642     QAction *moveTabLeftAction = actionCollection()->addAction(QStringLiteral("move_tab_left"), mTabs, SLOT(moveTabLeft()));
0643     moveTabLeftAction->setText(i18n("Move Tab &Left"));
0644     moveTabLeftAction->setIcon(QIcon::fromTheme(QStringLiteral("arrow-left")));
0645     moveTabLeftAction->setToolTip(i18n("Move the current tab to the left"));
0646     moveTabLeftAction->setWhatsThis(i18n("Moves the current tab to the left."));
0647     mTabs->addAction(moveTabLeftAction);
0648     actionCollection()->setDefaultShortcut(moveTabLeftAction, Qt::SHIFT | Qt::CTRL | Qt::Key_Left);
0649 
0650     QAction *moveTabRightAction = actionCollection()->addAction(QStringLiteral("move_tab_right"), mTabs, SLOT(moveTabRight()));
0651     moveTabRightAction->setText(i18n("Move Tab &Right"));
0652     moveTabRightAction->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right")));
0653     moveTabRightAction->setToolTip(i18n("Move the current tab to the right"));
0654     moveTabRightAction->setWhatsThis(i18n("Moves the current tab to the right."));
0655     mTabs->addAction(moveTabRightAction);
0656     actionCollection()->setDefaultShortcut(moveTabRightAction, Qt::SHIFT | Qt::CTRL | Qt::Key_Right);
0657 
0658     mReloadAction = actionCollection()->addAction(QStringLiteral("reload"), mTabs, SLOT(reloadCurrent()));
0659     mReloadAction->setText(i18n("&Reload"));
0660     mReloadAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
0661     mReloadAction->setToolTip(i18n("Reload the current log"));
0662     mReloadAction->setWhatsThis(i18n("Reloads the current log, if you want to be sure that the view is correctly updated."));
0663     actionCollection()->setDefaultShortcut(mReloadAction, Qt::Key_F5);
0664 
0665     mResumePauseAction = actionCollection()->addAction(QStringLiteral("resume_pause_parsing"));
0666     mResumePauseAction->setCheckable(true);
0667     connect(mResumePauseAction, &QAction::toggled, this, &MainWindow::changeResumePauseAction);
0668     connect(mResumePauseAction, &QAction::toggled, this, &MainWindow::toggleResumePauseParsing);
0669     changeResumePauseAction(false);
0670 
0671     mDetailAction = actionCollection()->addAction(QStringLiteral("details"), this, SLOT(showDetailsDialog()));
0672     mDetailAction->setText(i18n("&Details"));
0673     mDetailAction->setIcon(QIcon::fromTheme(QStringLiteral("document-preview")));
0674     mDetailAction->setToolTip(i18n("Display details on the selected line"));
0675     mDetailAction->setWhatsThis(
0676         i18n("Displays a dialog box which contains details on the selected line. You are able to navigate through "
0677              "the logs from this dialog box with the <b>Previous</b> and <b>Next</b> buttons."));
0678     mDetailAction->setEnabled(false);
0679     actionCollection()->setDefaultShortcut(mDetailAction, Qt::ALT | Qt::Key_Return);
0680 
0681     mTooltipEnabledAction = actionCollection()->addAction(QStringLiteral("tooltipEnabled"));
0682     mTooltipEnabledAction->setText(i18n("&Enable Detailed Tooltips"));
0683     mTooltipEnabledAction->setToolTip(i18n("Disable/Enable the tooltip on the current view"));
0684     mTooltipEnabledAction->setWhatsThis(i18n("Disables/Enables the tooltip displayed when the cursor hovers a log line."));
0685     mTooltipEnabledAction->setCheckable(true);
0686     mTooltipEnabledAction->setChecked(KSystemLogConfig::tooltipEnabled());
0687     connect(mTooltipEnabledAction, &QAction::toggled, this, &MainWindow::toggleItemTooltip);
0688 
0689     mNewLinesDisplayedAction = actionCollection()->addAction(QStringLiteral("newLinesDisplayed"));
0690     mNewLinesDisplayedAction->setText(i18n("&Scroll to New Lines"));
0691     mNewLinesDisplayedAction->setToolTip(i18n("Scrolls or not to the new lines when the log changes"));
0692     mNewLinesDisplayedAction->setWhatsThis(
0693         i18n("Scrolls or not to the new lines when the log changes. Check this option if you do not want the "
0694              "application to scroll automatically at the bottom of the log each time it is refreshed."));
0695     mNewLinesDisplayedAction->setCheckable(true);
0696     mNewLinesDisplayedAction->setChecked(KSystemLogConfig::newLinesDisplayed());
0697     connect(mNewLinesDisplayedAction, &QAction::toggled, this, &MainWindow::toggleNewLinesDisplaying);
0698 
0699     // Toolbar and Menu signals
0700     connect(mExpandAllAction, &QAction::triggered, mTabs, &TabLogViewsWidget::expandAllCurrentView);
0701     connect(mCollapseAllAction, &QAction::triggered, mTabs, &TabLogViewsWidget::collapseAllCurrentView);
0702     connect(mSaveAction, &QAction::triggered, mTabs, &TabLogViewsWidget::fileSaveCurrentView);
0703     connect(mCopyAction, &QAction::triggered, mTabs, &TabLogViewsWidget::copyToClipboardCurrentView);
0704     connect(mSendMailAction, &QAction::triggered, mTabs, &TabLogViewsWidget::sendMailCurrentView);
0705     connect(mPrintAction, &QAction::triggered, mTabs, &TabLogViewsWidget::printSelectionCurrentView);
0706     connect(mPrintPreviewAction, &QAction::triggered, mTabs, &TabLogViewsWidget::printPreviewSelectionCurrentView);
0707     connect(mSelectAllAction, &QAction::triggered, mTabs, &TabLogViewsWidget::selectAllCurrentView);
0708 }
0709 
0710 void MainWindow::selectLogModeAction(bool)
0711 {
0712     auto action = qobject_cast<QAction *>(sender());
0713     auto actionData = action->data().value<ActionData>();
0714     QString const selectedModeId = actionData.id;
0715 
0716     qCDebug(KSYSTEMLOG) << "Selected action" << selectedModeId;
0717 
0718     LogMode *currentMode = nullptr;
0719     const auto logModes{Globals::instance().logModes()};
0720     for (LogMode *logMode : logModes) {
0721         if (logMode->id() == selectedModeId) {
0722             currentMode = logMode;
0723             break;
0724         }
0725     }
0726 
0727     if (!currentMode) {
0728         qCCritical(KSYSTEMLOG) << "The selected mode does not exist";
0729         return;
0730     }
0731 
0732     qCDebug(KSYSTEMLOG) << "Selecting " << currentMode->name() << " (" << currentMode->id() << ")";
0733 
0734     mTabs->load(currentMode, mTabs->activeLogManager(), actionData.analyzerOptions);
0735 }
0736 
0737 void MainWindow::recreateActions()
0738 {
0739     unplugActionList(QStringLiteral("log_mode_list"));
0740     Globals::instance().recreateLogModeActions();
0741     setupLogActions();
0742     setupGUI();
0743     setupLogModeMenu();
0744 }
0745 
0746 void MainWindow::setupLogModeMenu()
0747 {
0748     // Sets up the Logs menu.
0749     QList<QAction *> menuLogModeActions;
0750     int serviceItems = 0;
0751     int othersItems = 0;
0752 
0753     auto servicesAction = new KActionMenu(QIcon::fromTheme(QStringLiteral("preferences-system-session-services")), i18n("Services"), this);
0754     auto othersAction = new KActionMenu(QIcon::fromTheme(QStringLiteral("preferences-other")), i18n("Others"), this);
0755 
0756     const auto logModeActions{Globals::instance().logModeActions()};
0757     for (LogModeAction *logModeAction : logModeActions) {
0758         if (logModeAction->category() == LogModeAction::RootCategory) {
0759             menuLogModeActions.append(logModeAction->actionMenu());
0760         } else if (logModeAction->category() == LogModeAction::ServicesCategory) {
0761             serviceItems++;
0762             servicesAction->addAction(logModeAction->actionMenu());
0763         } else if (logModeAction->category() == LogModeAction::OthersCategory) {
0764             othersAction->addAction(logModeAction->actionMenu());
0765             othersItems++;
0766         }
0767     }
0768 
0769     if (serviceItems) {
0770         menuLogModeActions.append(servicesAction);
0771     }
0772 
0773     if (othersItems) {
0774         menuLogModeActions.append(othersAction);
0775     }
0776 
0777     // Menu dynamic action list
0778     unplugActionList(QStringLiteral("log_mode_list"));
0779     plugActionList(QStringLiteral("log_mode_list"), menuLogModeActions);
0780 }
0781 
0782 void MainWindow::setupLogActions()
0783 {
0784     // Sets up log mode actions.
0785     const auto logModeActions{Globals::instance().logModeActions()};
0786     for (LogModeAction *logModeAction : logModeActions) {
0787         const auto innerActions{logModeAction->innerActions()};
0788         for (QAction *action : innerActions) {
0789             auto actionData = action->data().value<ActionData>();
0790             if (actionData.addToActionCollection) {
0791                 qCDebug(KSYSTEMLOG) << "Adding action" << actionData.id;
0792                 action = actionCollection()->addAction(actionData.id, action);
0793             }
0794             connect(action, &QAction::triggered, this, &MainWindow::selectLogModeAction);
0795         }
0796     }
0797 }
0798 }
0799 
0800 #include "moc_mainWindow.cpp"