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 "tabLogViewsWidget.h" 0008 0009 #include <QMenu> 0010 #include <QPushButton> 0011 0012 #include <KLocalizedString> 0013 #include <QIcon> 0014 0015 #include "ksystemlog_debug.h" 0016 0017 #include "logViewExport.h" 0018 #include "view.h" 0019 0020 #include "defaults.h" 0021 #include "logManager.h" 0022 #include "logMode.h" 0023 #include "logViewWidget.h" 0024 #include "tabLogManager.h" 0025 0026 TabLogViewsWidget::TabLogViewsWidget(QWidget *parent) 0027 : QTabWidget(parent) 0028 { 0029 auto tabNewTabButton = new QPushButton(QIcon::fromTheme(QStringLiteral("tab-new")), QLatin1String(""), this); 0030 connect(tabNewTabButton, &QAbstractButton::clicked, this, &TabLogViewsWidget::createTab); 0031 0032 tabNewTabButton->setToolTip(i18n("Create a new tab")); 0033 tabNewTabButton->setWhatsThis(i18n("Creates a new tab which can display another log.")); 0034 0035 auto tabCloseTabButton = new QPushButton(QIcon::fromTheme(QStringLiteral("tab-close")), QLatin1String(""), this); 0036 connect(tabCloseTabButton, &QAbstractButton::clicked, this, &TabLogViewsWidget::closeTab); 0037 0038 tabCloseTabButton->setToolTip(i18n("Close the current tab")); 0039 tabCloseTabButton->setWhatsThis(i18n("Closes the current tab.")); 0040 0041 setCornerWidget(tabNewTabButton, Qt::TopLeftCorner); 0042 setCornerWidget(tabCloseTabButton, Qt::TopRightCorner); 0043 0044 setUsesScrollButtons(true); 0045 0046 // The context menu is managed manually 0047 setContextMenuPolicy(Qt::ActionsContextMenu); 0048 0049 // connect(this, SIGNAL(mouseDoubleClick()), this, SLOT(createTab())); 0050 // connect(this, SIGNAL(contextMenu(QPoint)), this, SLOT(showContextMenu(QPoint))); 0051 // connect(this, SIGNAL(contextMenu(QWidget*,QPoint)), this, SLOT(showContextMenu(QWidget*,QPoint))); 0052 0053 // TODO Use this (need to connect to movedTab(int, int) signal and update the QList 0054 // setTabReorderingEnabled(true); 0055 0056 connect(this, &QTabWidget::currentChanged, this, &TabLogViewsWidget::changeCurrentTab); 0057 } 0058 0059 TabLogViewsWidget::~TabLogViewsWidget() 0060 { 0061 const QList<TabLogManager *> copy = mTabLogManagers; 0062 0063 for (TabLogManager *tabLogManager : copy) { 0064 mTabLogManagers.removeAll(tabLogManager); 0065 delete tabLogManager; 0066 } 0067 } 0068 0069 void TabLogViewsWidget::newTab(View *view) 0070 { 0071 qCDebug(KSYSTEMLOG) << "Inserting to a new tab the view "; 0072 0073 // Add a tab at the end of the widget 0074 insertTab(count(), view, QIcon::fromTheme(QStringLiteral(NO_MODE_ICON)), i18n("No Log")); 0075 0076 tabBar()->setVisible(count() > 1); 0077 } 0078 0079 void TabLogViewsWidget::changeTab(View *view, const QIcon &icon, const QString &label) 0080 { 0081 qCDebug(KSYSTEMLOG) << "Changing tab " << label; 0082 const int index = indexOf(view); 0083 setTabIcon(index, icon); 0084 setTabText(index, label); 0085 } 0086 0087 QList<LogManager *> TabLogViewsWidget::logManagers() const 0088 { 0089 QList<LogManager *> logManagers; 0090 const auto tabLogManagers = mTabLogManagers; 0091 logManagers.reserve(tabLogManagers.count()); 0092 for (TabLogManager *tabLogManager : tabLogManagers) { 0093 logManagers.append(tabLogManager->logManager()); 0094 } 0095 0096 return logManagers; 0097 } 0098 0099 LogManager *TabLogViewsWidget::findRelatedLogManager(View *view) 0100 { 0101 return findRelatedTabLogManager(view)->logManager(); 0102 } 0103 0104 TabLogManager *TabLogViewsWidget::findRelatedTabLogManager(View *view) const 0105 { 0106 for (TabLogManager *tabLogManager : std::as_const(mTabLogManagers)) { 0107 if (tabLogManager->logManager()->usedView() == view) { 0108 return tabLogManager; 0109 } 0110 } 0111 0112 qCCritical(KSYSTEMLOG) << "No log manager found"; 0113 return nullptr; 0114 } 0115 0116 TabLogManager *TabLogViewsWidget::activeTabLogManager() const 0117 { 0118 View *currentView = static_cast<View *>(currentWidget()); 0119 0120 return findRelatedTabLogManager(currentView); 0121 } 0122 0123 LogManager *TabLogViewsWidget::activeLogManager() const 0124 { 0125 TabLogManager *tabLogManager = activeTabLogManager(); 0126 if (tabLogManager) { 0127 return tabLogManager->logManager(); 0128 } 0129 return nullptr; 0130 } 0131 0132 LogManager *TabLogViewsWidget::createTab() 0133 { 0134 qCDebug(KSYSTEMLOG) << "Creating a new tab"; 0135 0136 return newTabLogManager()->logManager(); 0137 } 0138 0139 void TabLogViewsWidget::moveTabLeft() 0140 { 0141 qCDebug(KSYSTEMLOG) << "Duplicate tab to the left"; 0142 0143 TabLogManager *currentTabLogManager = activeTabLogManager(); 0144 const int position = indexOf(currentTabLogManager->logManager()->usedView()); 0145 0146 if (position <= 0) { 0147 qCCritical(KSYSTEMLOG) << "Tab Position <= 0 : " << position; 0148 return; 0149 } 0150 0151 mTabLogManagers.removeAt(position); 0152 mTabLogManagers.insert(position - 1, currentTabLogManager); 0153 0154 tabBar()->moveTab(position, position - 1); 0155 } 0156 0157 void TabLogViewsWidget::moveTabRight() 0158 { 0159 qCDebug(KSYSTEMLOG) << "Duplicate tab to the right"; 0160 0161 TabLogManager *currentTabLogManager = activeTabLogManager(); 0162 const int position = indexOf(currentTabLogManager->logManager()->usedView()); 0163 0164 if (position >= count() - 1) { 0165 qCCritical(KSYSTEMLOG) << "Tab Position >= count()-1 : " << position; 0166 return; 0167 } 0168 0169 mTabLogManagers.removeAt(position); 0170 mTabLogManagers.insert(position + 1, currentTabLogManager); 0171 0172 tabBar()->moveTab(position, position + 1); 0173 } 0174 0175 LogManager *TabLogViewsWidget::duplicateTab() 0176 { 0177 qCDebug(KSYSTEMLOG) << "Duplicate current tab"; 0178 0179 TabLogManager *currentManager = activeTabLogManager(); 0180 0181 TabLogManager *tabLogManager = newTabLogManager(); 0182 0183 LogMode *mode = currentManager->logManager()->logMode(); 0184 0185 load(mode, tabLogManager->logManager()); 0186 0187 // Returns the newly created LogManager 0188 return tabLogManager->logManager(); 0189 } 0190 0191 TabLogManager *TabLogViewsWidget::newTabLogManager() 0192 { 0193 qCDebug(KSYSTEMLOG) << "Creating new View..."; 0194 0195 View *view = new View(this); 0196 0197 qCDebug(KSYSTEMLOG) << "Creating new LogManager..."; 0198 0199 auto logManager = new LogManager(view); 0200 0201 // Signals from LogManager to Main Class 0202 connect(logManager, &LogManager::tabTitleChanged, this, &TabLogViewsWidget::changeTab); 0203 connect(logManager, &LogManager::logUpdated, this, &TabLogViewsWidget::changeTitleAddedLines); 0204 0205 auto tabLogManager = new TabLogManager(logManager); 0206 mTabLogManagers.append(tabLogManager); 0207 0208 qCDebug(KSYSTEMLOG) << "New LogManager created"; 0209 0210 // Finally add the view to the tabs 0211 newTab(view); 0212 0213 Q_EMIT logManagerCreated(logManager); 0214 0215 setCurrentIndex(count() - 1); 0216 0217 // Set focus to the list 0218 view->logViewWidget()->setFocus(); 0219 0220 // Returns the newly created TabLogManager 0221 return tabLogManager; 0222 } 0223 0224 void TabLogViewsWidget::closeTab() 0225 { 0226 if (count() == 1) { 0227 qCCritical(KSYSTEMLOG) << "Cannot close tab, one tab left"; 0228 return; 0229 } 0230 0231 TabLogManager *currentTabLogManager = activeTabLogManager(); 0232 0233 mTabLogManagers.removeAll(currentTabLogManager); 0234 0235 removeTab(indexOf(currentTabLogManager->logManager()->usedView())); 0236 if (count() == 1) { 0237 tabBar()->hide(); 0238 } 0239 0240 delete currentTabLogManager; 0241 } 0242 0243 void TabLogViewsWidget::load(LogMode *logMode, LogManager *manager, const QVariant &analyzerOptions) 0244 { 0245 qCDebug(KSYSTEMLOG) << "Loading a new mode : " << logMode->name(); 0246 0247 if (!manager) { 0248 qCCritical(KSYSTEMLOG) << "Error while loading a manager "; 0249 return; 0250 } 0251 0252 // The manager is now using the Log mode passed in parameter 0253 manager->initialize(logMode, analyzerOptions); 0254 0255 // Launch the reading 0256 manager->reload(); 0257 } 0258 0259 void TabLogViewsWidget::reloadCurrent() 0260 { 0261 qCDebug(KSYSTEMLOG) << "Reloading current log manager..."; 0262 0263 LogManager *manager = activeLogManager(); 0264 0265 if (manager) { 0266 manager->reload(); 0267 } 0268 } 0269 0270 void TabLogViewsWidget::reloadAll() 0271 { 0272 qCDebug(KSYSTEMLOG) << "Reloading all tabs..."; 0273 0274 const auto tabLogManagers = mTabLogManagers; 0275 for (TabLogManager *tabLogManager : tabLogManagers) { 0276 // Log manager without log mode does not need to be reloaded 0277 if (!tabLogManager->logManager()->logMode()) { 0278 continue; 0279 } 0280 0281 // Do a simple reload if it is an open log mode 0282 if (tabLogManager->logManager()->logMode()->id() == QLatin1String("openLogMode")) { 0283 tabLogManager->logManager()->reload(); 0284 continue; 0285 } 0286 0287 // Do a full loading of other log modes (needed if log files have been modified) 0288 load(tabLogManager->logManager()->logMode(), tabLogManager->logManager(), tabLogManager->logManager()->analyzerOptions()); 0289 } 0290 } 0291 0292 void TabLogViewsWidget::changeCurrentTab(int index) 0293 { 0294 qCDebug(KSYSTEMLOG) << "Changing current tab..."; 0295 0296 if (index == -1) { 0297 return; 0298 } 0299 0300 TabLogManager *tabLogManager = activeTabLogManager(); 0301 0302 // Reinit the new lines count since last selection 0303 tabLogManager->initNewLinesCount(); 0304 0305 // If the tab displayed the new added line count, rename it to the default log mode name 0306 changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); 0307 0308 qCDebug(KSYSTEMLOG) << "Current tab changed"; 0309 } 0310 0311 void TabLogViewsWidget::changeReloadingTab(View *view, bool reloading) 0312 { 0313 TabLogManager *tabLogManager = findRelatedTabLogManager(view); 0314 0315 if (reloading) { 0316 changeTab(tabLogManager->logManager()->usedView(), QIcon::fromTheme(QStringLiteral("view-refresh")), tabLogManager->title()); 0317 } else { 0318 changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); 0319 } 0320 } 0321 0322 void TabLogViewsWidget::changeTitleAddedLines(View *view, int addedLinesSinceLastUpdate) 0323 { 0324 qCDebug(KSYSTEMLOG) << "Changing title" << addedLinesSinceLastUpdate << " added lines..."; 0325 LogManager *currentManager = activeLogManager(); 0326 0327 // Only display added line on tab title if this is not an update of the current tab 0328 if (currentManager->usedView() != view) { 0329 TabLogManager *tabLogManager = findRelatedTabLogManager(view); 0330 tabLogManager->addNewLinesCount(addedLinesSinceLastUpdate); 0331 0332 // Update the tab title 0333 changeTab(tabLogManager->logManager()->usedView(), logModeIcon(tabLogManager->logManager()->logMode()), tabLogManager->title()); 0334 } 0335 } 0336 0337 void TabLogViewsWidget::expandAllCurrentView() 0338 { 0339 activeLogManager()->usedView()->logViewWidget()->expandAll(); 0340 } 0341 0342 void TabLogViewsWidget::collapseAllCurrentView() 0343 { 0344 activeLogManager()->usedView()->logViewWidget()->collapseAll(); 0345 } 0346 0347 void TabLogViewsWidget::selectAllCurrentView() 0348 { 0349 activeLogManager()->usedView()->logViewWidget()->selectAll(); 0350 } 0351 0352 void TabLogViewsWidget::fileSaveCurrentView() 0353 { 0354 LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); 0355 connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); 0356 logViewExport.fileSave(); 0357 } 0358 0359 void TabLogViewsWidget::copyToClipboardCurrentView() 0360 { 0361 LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); 0362 connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); 0363 logViewExport.copyToClipboard(); 0364 } 0365 0366 void TabLogViewsWidget::sendMailCurrentView() 0367 { 0368 LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); 0369 connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); 0370 logViewExport.sendMail(); 0371 } 0372 0373 void TabLogViewsWidget::printSelectionCurrentView() 0374 { 0375 LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); 0376 connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); 0377 logViewExport.printSelection(); 0378 } 0379 0380 void TabLogViewsWidget::printPreviewSelectionCurrentView() 0381 { 0382 LogViewExport logViewExport(this, activeLogManager()->usedView()->logViewWidget()); 0383 connect(&logViewExport, &LogViewExport::statusBarChanged, this, &TabLogViewsWidget::statusBarChanged); 0384 logViewExport.printPreview(); 0385 } 0386 0387 QIcon TabLogViewsWidget::logModeIcon(LogMode *logMode) const 0388 { 0389 if (!logMode) { 0390 return QIcon::fromTheme(QStringLiteral(NO_MODE_ICON)); 0391 } else { 0392 return logMode->icon(); 0393 } 0394 } 0395 0396 void TabLogViewsWidget::prepareContextMenu(bool /*onTab*/) 0397 { 0398 if (!mContextMenu) { 0399 mContextMenu = new QMenu(this); 0400 mContextMenu->addActions(actions()); 0401 } 0402 0403 // TODO Disable some actions, depending of the onTab value 0404 } 0405 0406 void TabLogViewsWidget::showContextMenu(const QPoint &cursorPosition) 0407 { 0408 qCDebug(KSYSTEMLOG) << "Showing context menu at " << cursorPosition; 0409 0410 prepareContextMenu(false); 0411 0412 mContextMenu->popup(cursorPosition); 0413 } 0414 0415 void TabLogViewsWidget::showContextMenu(QWidget *tab, const QPoint &cursorPosition) 0416 { 0417 qCDebug(KSYSTEMLOG) << "Showing context menu at " << cursorPosition << " at " << tab->objectName(); 0418 0419 prepareContextMenu(true); 0420 0421 mContextMenu->popup(cursorPosition); 0422 } 0423 0424 #include "moc_tabLogViewsWidget.cpp"