File indexing completed on 2024-04-14 14:31:57

0001 // Copyright (c) 2003-2004 Rob Kaper <cap@capsi.com>
0002 //
0003 // This library is free software; you can redistribute it and/or
0004 // modify it under the terms of the GNU Lesser General Public
0005 // License version 2.1 as published by the Free Software Foundation.
0006 //
0007 // This library is distributed in the hope that it will be useful,
0008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0010 // Lesser General Public License for more details.
0011 //
0012 // You should have received a copy of the GNU Lesser General Public License
0013 // along with this library; see the file COPYING.LIB.  If not, write to
0014 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0015 // Boston, MA 02110-1301, USA.
0016 
0017 #include <iostream>
0018 
0019 #include <QLayout>
0020 #include <QDateTime>
0021 #include <QPixmap>
0022 #include <QVBoxLayout>
0023 #include <QHBoxLayout>
0024 #include <QTextStream>
0025 #include <QCloseEvent>
0026 #include <QTreeView>
0027 #include <QHeaderView>
0028 #include <QFileDialog>
0029 #include <QPushButton>
0030 #include <QDialogButtonBox>
0031 
0032 #include <klocalizedstring.h>
0033 #include <kiconloader.h>
0034 #include <kguiitem.h>
0035 #include <ksharedconfig.h>
0036 #include <kwindowconfig.h>
0037 
0038 #include "event.h"
0039 #include "eventlogwidget.h"
0040 
0041 EventLog::EventLog(QObject *parent)
0042     : QAbstractItemModel(parent)
0043 {
0044 }
0045 
0046 EventLog::~EventLog()
0047 {
0048     qDeleteAll(m_events);
0049 }
0050 
0051 void EventLog::addEvent(const QString &description, EventType type)
0052 {
0053     const int oldCount = m_events.count();
0054     beginInsertRows(QModelIndex(), oldCount, oldCount);
0055     Event *event = new Event(QDateTime::currentDateTime(), description, type);
0056     m_events.append(event);
0057     endInsertRows();
0058 }
0059 
0060 void EventLog::clear()
0061 {
0062     beginResetModel();
0063     qDeleteAll(m_events);
0064     m_events.clear();
0065     endResetModel();
0066 }
0067 
0068 void EventLog::saveAsText(QTextStream &stream) const
0069 {
0070     foreach (Event *e, m_events)
0071         stream << e->dateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")) << " " << e->description() << '\n';
0072 }
0073 
0074 int EventLog::columnCount(const QModelIndex &parent) const
0075 {
0076     return parent.isValid() ? 0 : 2;
0077 }
0078 
0079 QVariant EventLog::data(const QModelIndex &index, int role) const
0080 {
0081     if (!index.isValid() || index.row() < 0 || index.row() >= m_events.count()
0082         || index.column() < 0 || index.column() > 1)
0083         return QVariant();
0084 
0085     Event *e = static_cast<Event *>(index.internalPointer());
0086     switch (index.column())
0087     {
0088     case 0:
0089         if (role != Qt::DisplayRole)
0090             return QVariant();
0091         return e->dateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss zzz"));
0092     case 1:
0093         switch (role)
0094         {
0095         case Qt::DecorationRole:
0096             return cachedIcon(e->type());
0097         case Qt::DisplayRole:
0098             return e->description();
0099         }
0100         break;
0101     }
0102 
0103     return QVariant();
0104 }
0105 
0106 QVariant EventLog::headerData(int section, Qt::Orientation orientation, int role) const
0107 {
0108     if (orientation != Qt::Horizontal || role != Qt::DisplayRole
0109         || section < 0 || section > 1)
0110         return QVariant();
0111 
0112     switch (section)
0113     {
0114     case 0:
0115         return i18n("Date/Time");
0116     case 1:
0117         return i18n("Description");
0118     }
0119     return QVariant();
0120 }
0121 
0122 QModelIndex EventLog::index(int row, int column, const QModelIndex &parent) const
0123 {
0124     return parent.isValid() || row < 0 || row >= m_events.count()
0125         || column < 0 || column > 1
0126         ? QModelIndex()
0127         : createIndex(row, column, m_events.at(row));
0128 }
0129 
0130 QModelIndex EventLog::parent(const QModelIndex &) const
0131 {
0132     return QModelIndex();
0133 }
0134 
0135 int EventLog::rowCount(const QModelIndex &parent) const
0136 {
0137     return parent.isValid() ? 0 : m_events.count();
0138 }
0139 
0140 QIcon EventLog::cachedIcon(EventType type) const
0141 {
0142     if (!m_iconCache[type].isNull())
0143         return m_iconCache[type];
0144 
0145     QString name;
0146     switch (type)
0147     {
0148         case ET_Generic:
0149             name = QStringLiteral("atlantik");
0150             break;
0151         case ET_NetIn:
0152             name = QStringLiteral("arrow-left");
0153             break;
0154         case ET_NetOut:
0155             name = QStringLiteral("arrow-right");
0156             break;
0157         case ET_NetGeneric:
0158             name = QStringLiteral("network-disconnect");  // FIXME
0159             break;
0160         case ET_NetConnected:
0161             name = QStringLiteral("network-connect");
0162             break;
0163         case ET_NetError:
0164             name = QStringLiteral("network-disconnect");
0165             break;
0166         case ET_LastEvent:
0167             return QIcon();
0168     };
0169 
0170     const QIcon icon = KDE::icon(name);
0171     m_iconCache[type] = icon;
0172     return icon;
0173 }
0174 
0175 LastMessagesProxyModel::LastMessagesProxyModel(QObject *parent)
0176     : QSortFilterProxyModel(parent)
0177     , m_count(-1)
0178 {
0179 }
0180 
0181 void LastMessagesProxyModel::setMessagesCount(int n)
0182 {
0183     if (n == m_count)
0184         return;
0185 
0186     m_count = n;
0187     invalidateFilter();
0188 }
0189 
0190 void LastMessagesProxyModel::setSourceModel(QAbstractItemModel *model)
0191 {
0192     if (sourceModel())
0193         disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(invalidate()));
0194     QSortFilterProxyModel::setSourceModel(model);
0195     if (sourceModel())
0196         connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(invalidate()));
0197 }
0198 
0199 bool LastMessagesProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
0200 {
0201     if (m_count < 0)
0202         return true;
0203     return source_row + m_count >= sourceModel()->rowCount(source_parent);
0204 }
0205 
0206 EventLogWidget::EventLogWidget(EventLog *eventLog, QWidget *parent)
0207     : QDialog(parent, Qt::WindowContextHelpButtonHint)
0208     , m_eventLog(eventLog)
0209 {
0210     setModal(false);
0211     setAttribute(Qt::WA_DeleteOnClose);
0212 
0213     setWindowTitle(i18nc("@title:window", "Event Log"));
0214 
0215     QVBoxLayout *listCompBox = new QVBoxLayout(this);
0216 
0217     m_eventList = new QTreeView(this);
0218     m_eventList->setObjectName(QStringLiteral("eventList"));
0219     listCompBox->addWidget(m_eventList);
0220 
0221     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
0222     QPushButton *saveButton = buttonBox->addButton(QString(), QDialogButtonBox::ActionRole);
0223     KGuiItem::assign(saveButton, KGuiItem(i18n("&Save As..."), QStringLiteral("document-save-as")));
0224     QPushButton *clearButton = buttonBox->addButton(QString(), QDialogButtonBox::ActionRole);
0225     KGuiItem::assign(clearButton, KGuiItem(i18n("&Clear Log"), QStringLiteral("edit-clear")));
0226     listCompBox->addWidget(buttonBox);
0227 
0228     LastMessagesProxyModel *proxy = new LastMessagesProxyModel(m_eventList);
0229     // FIXME: allow a way to show older messages
0230     proxy->setMessagesCount(25);
0231     proxy->setSourceModel(m_eventLog);
0232 
0233     m_eventList->setModel(proxy);
0234     m_eventList->setRootIsDecorated(false);
0235     m_eventList->header()->setSectionsClickable(false);
0236     m_eventList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0237 
0238     connect(buttonBox, SIGNAL(rejected()), this, SLOT(accept()));
0239     connect(saveButton, SIGNAL(clicked()), this, SLOT(save()));
0240     connect(clearButton, SIGNAL(clicked()), m_eventLog, SLOT(clear()));
0241 }
0242 
0243 void EventLogWidget::restoreSettings()
0244 {
0245     const KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("EventLogWidget"));
0246     KWindowConfig::restoreWindowSize(windowHandle(), group);
0247 }
0248 
0249 EventLogWidget::~EventLogWidget()
0250 {
0251     KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("EventLogWidget"));
0252     KWindowConfig::saveWindowSize(windowHandle(), group);
0253 }
0254 
0255 void EventLogWidget::save()
0256 {
0257     const QString filename = QFileDialog::getSaveFileName(this);
0258     if (filename.isEmpty())
0259         return;
0260 
0261     QFile file(filename);
0262     if ( file.open( QIODevice::WriteOnly ) )
0263     {
0264         QTextStream stream(&file);
0265 
0266         stream << i18n( "Atlantik log file, saved at %1.", QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")) ) << '\n';
0267 
0268         m_eventLog->saveAsText(stream);
0269     }
0270 }
0271 
0272 #include "moc_eventlogwidget.cpp"