File indexing completed on 2024-05-05 05:48:58
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 "logViewWidget.h" 0008 0009 #include <QAction> 0010 #include <QActionGroup> 0011 #include <QHeaderView> 0012 0013 #include <KLocalizedString> 0014 #include <QIcon> 0015 0016 #include "ksystemlog_debug.h" 0017 0018 #include "logViewColumn.h" 0019 0020 #include "logLine.h" 0021 #include "logViewModel.h" 0022 #include "logViewWidgetItem.h" 0023 0024 #include "ksystemlogConfig.h" 0025 0026 LogViewWidget::LogViewWidget(QWidget *parent) 0027 : QTreeWidget(parent) 0028 { 0029 // TODO Add this setWhatsThis() to all columns each time they change 0030 // setWhatThis(i18n("<p>This is the main view of KSystemLog. It displays the last lines of the selected 0031 // log. Please see the documentation to discovers the meaning of each icons and existing log.</p><p>Log 0032 // lines in <b>bold</b> are the last added to the list.</p>")); 0033 0034 const QStringList headerLabels{i18n("Date"), i18n("Message")}; 0035 0036 mLogViewModel = new LogViewModel(this); 0037 mHeadersTogglingActions = new QActionGroup(this); 0038 mHeadersTogglingActions->setExclusive(false); 0039 connect(mHeadersTogglingActions, &QActionGroup::triggered, this, &LogViewWidget::toggleHeader); 0040 0041 setHeaderLabels(headerLabels); 0042 0043 // Header 0044 header()->setContextMenuPolicy(Qt::ActionsContextMenu); 0045 // header()->setMovable(true); 0046 header()->setSectionsMovable(true); 0047 0048 setSortingEnabled(true); 0049 sortItems(0, Qt::AscendingOrder); 0050 0051 setAnimated(true); 0052 0053 setRootIsDecorated(false); 0054 0055 setAllColumnsShowFocus(true); 0056 0057 setAlternatingRowColors(true); 0058 0059 setSelectionMode(QAbstractItemView::ExtendedSelection); 0060 0061 setContextMenuPolicy(Qt::ActionsContextMenu); 0062 setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::TopEdge})); 0063 } 0064 0065 LogViewWidget::~LogViewWidget() 0066 { 0067 delete mLogViewModel; 0068 } 0069 0070 void LogViewWidget::setColumns(const LogViewColumns &columns) 0071 { 0072 qCDebug(KSYSTEMLOG) << "Updating columns using " << columns << "..."; 0073 0074 // First, delete all current columns 0075 setColumnCount(0); 0076 0077 setHeaderLabels(columns.toStringList()); 0078 0079 sortItems(0, Qt::AscendingOrder); 0080 0081 // Remove previous header actions 0082 QListIterator<QAction *> it(mHeadersTogglingActions->actions()); 0083 it.toBack(); 0084 while (it.hasPrevious()) { 0085 QAction *action = it.previous(); 0086 0087 header()->removeAction(action); 0088 mHeadersTogglingActions->removeAction(action); 0089 0090 delete action; 0091 } 0092 0093 // Add new actions 0094 int columnIndex = 0; 0095 0096 const auto columnsLst = columns.columns(); 0097 for (const LogViewColumn &column : columnsLst) { 0098 auto action = new QAction(this); 0099 action->setText(column.columnName()); 0100 // helloAction->setIcon(QIcon::fromTheme( QLatin1String( "media-playback-start" ))); 0101 // helloAction->setShortcut(Qt::CTRL | Qt::Key_M); 0102 action->setCheckable(true); 0103 action->setChecked(true); 0104 action->setToolTip(i18n("Display/Hide the '%1' column", column.columnName())); 0105 action->setData(QVariant(columnIndex)); 0106 0107 mHeadersTogglingActions->addAction(action); 0108 0109 ++columnIndex; 0110 } 0111 0112 header()->addActions(mHeadersTogglingActions->actions()); 0113 0114 Q_EMIT columnsChanged(columns); 0115 0116 qCDebug(KSYSTEMLOG) << "Log View Widget updated..."; 0117 } 0118 0119 void LogViewWidget::resizeColumns() 0120 { 0121 // Resize all columns except the last one (which always take the last available space) 0122 for (int i = 0; i < columnCount() - 1; ++i) { 0123 resizeColumnToContents(i); 0124 } 0125 } 0126 0127 void LogViewWidget::selectAll() 0128 { 0129 if (notHiddenItemCount() > 0) { 0130 QTreeWidget::selectAll(); 0131 } 0132 } 0133 0134 int LogViewWidget::itemCount() const 0135 { 0136 return topLevelItemCount(); 0137 } 0138 0139 QList<LogLine *> LogViewWidget::logLines() 0140 { 0141 QList<LogLine *> logLines; 0142 0143 QTreeWidgetItemIterator it(this); 0144 while (*it) { 0145 auto item = static_cast<LogViewWidgetItem *>(*it); 0146 logLines.append(item->logLine()); 0147 ++it; 0148 } 0149 0150 return logLines; 0151 } 0152 0153 LogViewWidgetItem *LogViewWidget::findNewestItem() 0154 { 0155 LogViewWidgetItem *newestItem = nullptr; 0156 0157 QTreeWidgetItemIterator it(this); 0158 while (*it) { 0159 auto item = static_cast<LogViewWidgetItem *>(*it); 0160 if (!newestItem || newestItem->logLine()->isOlderThan(*(item->logLine()))) { 0161 newestItem = item; 0162 } 0163 0164 ++it; 0165 } 0166 0167 return newestItem; 0168 } 0169 0170 LogViewWidgetItem *LogViewWidget::findItem(LogLine *searchedLogLine) 0171 { 0172 QTreeWidgetItemIterator it(this); 0173 while (*it) { 0174 auto item = static_cast<LogViewWidgetItem *>(*it); 0175 if (item->logLine()->equals(*searchedLogLine)) { 0176 return item; 0177 } 0178 0179 ++it; 0180 } 0181 0182 return nullptr; 0183 } 0184 0185 QList<LogViewWidgetItem *> LogViewWidget::items() 0186 { 0187 QList<LogViewWidgetItem *> items; 0188 0189 QTreeWidgetItemIterator it(this); 0190 while (*it) { 0191 items.append(static_cast<LogViewWidgetItem *>(*it)); 0192 ++it; 0193 } 0194 0195 return items; 0196 } 0197 0198 LogViewModel *LogViewWidget::model() const 0199 { 0200 return mLogViewModel; 0201 } 0202 0203 bool LogViewWidget::hasItemsSelected() 0204 { 0205 return !selectedItems().isEmpty(); 0206 } 0207 0208 LogViewWidgetItem *LogViewWidget::firstSelectedItem() 0209 { 0210 QTreeWidgetItemIterator const it(this, QTreeWidgetItemIterator::Selected); 0211 0212 // Returns the first selected item or NULL is there is no item selected 0213 return static_cast<LogViewWidgetItem *>(*it); 0214 } 0215 0216 LogViewWidgetItem *LogViewWidget::lastSelectedItem() 0217 { 0218 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::Selected); 0219 0220 QTreeWidgetItem *item = nullptr; 0221 while (*it) { 0222 item = (*it); 0223 0224 ++it; 0225 } 0226 0227 // Returns the last selected item or NULL is there is no item selected 0228 return static_cast<LogViewWidgetItem *>(item); 0229 } 0230 0231 void LogViewWidget::expandAll() 0232 { 0233 QTreeWidgetItemIterator it(this); 0234 while (*it) { 0235 expandItem(*it); 0236 ++it; 0237 } 0238 } 0239 0240 void LogViewWidget::collapseAll() 0241 { 0242 QTreeWidgetItemIterator it(this); 0243 while (*it) { 0244 collapseItem(*it); 0245 ++it; 0246 } 0247 } 0248 0249 void LogViewWidget::toggleToolTip(bool enabled) 0250 { 0251 qCDebug(KSYSTEMLOG) << "Toggle tool tip " << enabled; 0252 0253 QTreeWidgetItemIterator it(this); 0254 while (*it) { 0255 auto item = static_cast<LogViewWidgetItem *>(*it); 0256 item->toggleToolTip(enabled); 0257 0258 ++it; 0259 } 0260 } 0261 0262 void LogViewWidget::scrollToNewestItem() 0263 { 0264 qCDebug(KSYSTEMLOG) << "Scrolling to the newest item..."; 0265 0266 // Scroll to last item if requested 0267 if (KSystemLogConfig::newLinesDisplayed()) { 0268 LogViewWidgetItem *newestItem = findNewestItem(); 0269 if (newestItem) { 0270 scrollToItem(newestItem); 0271 } 0272 } 0273 } 0274 0275 int LogViewWidget::notHiddenItemCount() 0276 { 0277 int count = 0; 0278 0279 QTreeWidgetItemIterator it(this, QTreeWidgetItemIterator::NotHidden); 0280 while (*it) { 0281 count++; 0282 ++it; 0283 } 0284 0285 return count; 0286 } 0287 0288 void LogViewWidget::toggleHeader(QAction *action) 0289 { 0290 qCDebug(KSYSTEMLOG) << "Toggling header"; 0291 0292 int const columnIndex = action->data().toInt(); 0293 if (header()->isSectionHidden(columnIndex)) { 0294 header()->setSectionHidden(columnIndex, false); 0295 } else { 0296 header()->setSectionHidden(columnIndex, true); 0297 } 0298 } 0299 0300 #include "moc_logViewWidget.cpp"