mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 02:42:51 +00:00
273 lines
8 KiB
C++
273 lines
8 KiB
C++
![]() |
/*
|
||
|
This file is part of the KDE project
|
||
|
Copyright (C) 2024 Ivailo Monev <xakepa10@gmail.com>
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Library General Public
|
||
|
License version 2, as published by the Free Software Foundation.
|
||
|
|
||
|
This library 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
|
||
|
Library General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Library General Public License
|
||
|
along with this library; see the file COPYING.LIB. If not, write to
|
||
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||
|
Boston, MA 02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
#include "lsof.h"
|
||
|
|
||
|
#include <QMutex>
|
||
|
#include <QTimer>
|
||
|
#include <QProcess>
|
||
|
#include <QTreeWidget>
|
||
|
#include <QHeaderView>
|
||
|
#include <QApplication>
|
||
|
#include <QGraphicsLinearLayout>
|
||
|
#include <Plasma/TreeWidget>
|
||
|
#include <KStandardDirs>
|
||
|
#include <KIcon>
|
||
|
#include <KDebug>
|
||
|
|
||
|
// TODO: option for it
|
||
|
static const int s_updatetimeout = 2000; // ms
|
||
|
static const QStringList s_lsofargs = QStringList() << QLatin1String("-Fftn");
|
||
|
// keeps things interactive, somewhat
|
||
|
static const int s_processtime = 50;
|
||
|
|
||
|
class LsofData
|
||
|
{
|
||
|
public:
|
||
|
LsofData();
|
||
|
|
||
|
QByteArray lsoffd;
|
||
|
QByteArray lsoftype;
|
||
|
QByteArray lsofpid;
|
||
|
QByteArray lsofname;
|
||
|
QTreeWidgetItem* lsofitem;
|
||
|
|
||
|
bool operator==(const LsofData &other) const;
|
||
|
};
|
||
|
|
||
|
LsofData::LsofData()
|
||
|
: lsofitem(nullptr)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool LsofData::operator==(const LsofData &other) const
|
||
|
{
|
||
|
return (
|
||
|
lsoffd == other.lsoffd && lsoftype == other.lsoftype
|
||
|
&& lsofpid == other.lsofpid && lsofname == other.lsofname
|
||
|
&& lsofitem == other.lsofitem
|
||
|
);
|
||
|
}
|
||
|
|
||
|
class LsofWidget : public QGraphicsWidget
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
LsofWidget(Lsof* lsof);
|
||
|
~LsofWidget();
|
||
|
|
||
|
public Q_SLOTS:
|
||
|
void slotUpdateLayout();
|
||
|
|
||
|
private Q_SLOTS:
|
||
|
void slotFinished(int exitcode);
|
||
|
void slotTimeout();
|
||
|
|
||
|
private:
|
||
|
QMutex m_mutex;
|
||
|
Lsof* m_lsof;
|
||
|
QGraphicsLinearLayout* m_layout;
|
||
|
Plasma::TreeWidget* m_treewidget;
|
||
|
QTreeWidget* m_treewidgetnative;
|
||
|
QProcess* m_lsofproc;
|
||
|
QTimer* m_timer;
|
||
|
QString m_lsofexe;
|
||
|
QList<LsofData> m_lsofdata;
|
||
|
};
|
||
|
|
||
|
|
||
|
LsofWidget::LsofWidget(Lsof* lsof)
|
||
|
: QGraphicsWidget(lsof),
|
||
|
m_lsof(lsof),
|
||
|
m_layout(nullptr),
|
||
|
m_treewidget(nullptr),
|
||
|
m_treewidgetnative(nullptr),
|
||
|
m_lsofproc(nullptr)
|
||
|
{
|
||
|
m_layout = new QGraphicsLinearLayout(this);
|
||
|
|
||
|
const QStringList treeheaders = QStringList()
|
||
|
<< i18n("File Descriptor")
|
||
|
<< i18n("Type")
|
||
|
<< i18n("PID")
|
||
|
<< i18n("Name");
|
||
|
m_treewidget = new Plasma::TreeWidget(this);
|
||
|
m_treewidgetnative = m_treewidget->nativeWidget();
|
||
|
m_treewidgetnative->setHeaderLabels(treeheaders);
|
||
|
m_treewidgetnative->setRootIsDecorated(false);
|
||
|
m_treewidgetnative->header()->setMovable(false);
|
||
|
m_treewidgetnative->header()->setStretchLastSection(true);
|
||
|
m_treewidgetnative->header()->setResizeMode(0, QHeaderView::ResizeToContents);
|
||
|
m_treewidgetnative->header()->setResizeMode(1, QHeaderView::ResizeToContents);
|
||
|
m_treewidgetnative->header()->setResizeMode(2, QHeaderView::ResizeToContents);
|
||
|
m_treewidgetnative->header()->setResizeMode(3, QHeaderView::Stretch);
|
||
|
m_layout->addItem(m_treewidget);
|
||
|
|
||
|
setLayout(m_layout);
|
||
|
|
||
|
m_lsofproc = new QProcess(this);
|
||
|
connect(m_lsofproc, SIGNAL(finished(int)), this, SLOT(slotFinished(int)));
|
||
|
|
||
|
m_timer = new QTimer(this);
|
||
|
m_timer->setInterval(s_updatetimeout);
|
||
|
connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
|
||
|
}
|
||
|
|
||
|
LsofWidget::~LsofWidget()
|
||
|
{
|
||
|
m_timer->stop();
|
||
|
}
|
||
|
|
||
|
void LsofWidget::slotUpdateLayout()
|
||
|
{
|
||
|
m_timer->stop();
|
||
|
m_treewidgetnative->clear();
|
||
|
m_lsofexe = KStandardDirs::findExe("lsof");
|
||
|
if (m_lsofexe.isEmpty()) {
|
||
|
m_lsof->showMessage(
|
||
|
KIcon("dialog-warning"),
|
||
|
i18n("Could not find lsof program"),
|
||
|
Plasma::ButtonOk
|
||
|
);
|
||
|
return;
|
||
|
}
|
||
|
m_timer->start();
|
||
|
}
|
||
|
|
||
|
void LsofWidget::slotFinished(int exitcode)
|
||
|
{
|
||
|
kDebug() << "lsof finished" << exitcode;
|
||
|
m_timer->stop();
|
||
|
int lsofcounter = 0;
|
||
|
LsofData lsofdata;
|
||
|
QList<LsofData> currentlsofdata;
|
||
|
QByteArray lsofline = m_lsofproc->readLine();
|
||
|
while (!lsofline.isEmpty()) {
|
||
|
// qDebug() << Q_FUNC_INFO << lsofline;
|
||
|
const char lsoflinetype = lsofline.at(0);
|
||
|
switch (lsoflinetype) {
|
||
|
case 'f': {
|
||
|
lsofdata.lsoffd = lsofline.mid(1, lsofline.size() - 1);
|
||
|
lsofcounter++;
|
||
|
break;
|
||
|
}
|
||
|
case 't': {
|
||
|
lsofdata.lsoftype = lsofline.mid(1, lsofline.size() - 1);
|
||
|
lsofcounter++;
|
||
|
break;
|
||
|
}
|
||
|
case 'p': {
|
||
|
lsofdata.lsofpid = lsofline.mid(1, lsofline.size() - 1);
|
||
|
lsofcounter++;
|
||
|
break;
|
||
|
}
|
||
|
case 'n': {
|
||
|
lsofdata.lsofname = lsofline.mid(1, lsofline.size() - 1);
|
||
|
lsofcounter++;
|
||
|
break;
|
||
|
}
|
||
|
default: {
|
||
|
kWarning() << "invalid lsof line" << lsofline;
|
||
|
lsofcounter = 0;
|
||
|
lsofdata.lsoffd.clear();
|
||
|
lsofdata.lsoftype.clear();
|
||
|
lsofdata.lsofpid.clear();
|
||
|
lsofdata.lsofname.clear();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (lsofcounter >= 4) {
|
||
|
currentlsofdata.append(lsofdata);
|
||
|
}
|
||
|
QApplication::processEvents(QEventLoop::AllEvents, s_processtime);
|
||
|
lsofline = m_lsofproc->readLine();
|
||
|
}
|
||
|
|
||
|
QMutableListIterator<LsofData> iter(m_lsofdata);
|
||
|
while (iter.hasNext()) {
|
||
|
const LsofData itercurrent = iter.next();
|
||
|
if (currentlsofdata.contains(itercurrent)) {
|
||
|
currentlsofdata.removeOne(itercurrent);
|
||
|
QApplication::processEvents(QEventLoop::AllEvents, s_processtime);
|
||
|
continue;
|
||
|
}
|
||
|
iter.remove();
|
||
|
delete itercurrent.lsofitem;
|
||
|
QApplication::processEvents(QEventLoop::AllEvents, s_processtime);
|
||
|
}
|
||
|
|
||
|
foreach (const LsofData lsofdata, currentlsofdata) {
|
||
|
const QStringList lsofitemstrings = QStringList()
|
||
|
<< QString::fromLatin1(lsofdata.lsoffd.constData(), lsofdata.lsoffd.size())
|
||
|
<< QString::fromLatin1(lsofdata.lsoftype.constData(), lsofdata.lsoftype.size())
|
||
|
<< QString::fromLatin1(lsofdata.lsofpid.constData(), lsofdata.lsofpid.size())
|
||
|
<< QString::fromLatin1(lsofdata.lsofname.constData(), lsofdata.lsofname.size());
|
||
|
QTreeWidgetItem* lsofitem = new QTreeWidgetItem(m_treewidgetnative, lsofitemstrings);
|
||
|
lsofitem->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
|
||
|
lsofitem->setTextAlignment(1, Qt::AlignLeft | Qt::AlignVCenter);
|
||
|
lsofitem->setTextAlignment(2, Qt::AlignLeft | Qt::AlignVCenter);
|
||
|
lsofitem->setTextAlignment(3, Qt::AlignLeft | Qt::AlignVCenter);
|
||
|
lsofitem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||
|
m_treewidgetnative->addTopLevelItem(lsofitem);
|
||
|
QApplication::processEvents(QEventLoop::AllEvents, s_processtime);
|
||
|
}
|
||
|
|
||
|
m_lsofdata = currentlsofdata;
|
||
|
m_timer->start();
|
||
|
}
|
||
|
|
||
|
void LsofWidget::slotTimeout()
|
||
|
{
|
||
|
m_lsofproc->terminate();
|
||
|
m_lsofproc->start(m_lsofexe, s_lsofargs);
|
||
|
}
|
||
|
|
||
|
Lsof::Lsof(QObject *parent, const QVariantList &args)
|
||
|
: Plasma::PopupApplet(parent, args),
|
||
|
m_lsofwidget(nullptr)
|
||
|
{
|
||
|
setAspectRatioMode(Plasma::IgnoreAspectRatio);
|
||
|
setPopupIcon("media-playlist-repeat");
|
||
|
// NOTE: no check has to be done if it is installed
|
||
|
setAssociatedApplication("ksysguard");
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
Lsof::~Lsof()
|
||
|
{
|
||
|
delete m_lsofwidget;
|
||
|
}
|
||
|
|
||
|
void Lsof::init()
|
||
|
{
|
||
|
Plasma::PopupApplet::init();
|
||
|
m_lsofwidget = new LsofWidget(this);
|
||
|
QTimer::singleShot(500, m_lsofwidget, SLOT(slotUpdateLayout()));
|
||
|
}
|
||
|
|
||
|
QGraphicsWidget *Lsof::graphicsWidget()
|
||
|
{
|
||
|
return m_lsofwidget;
|
||
|
}
|
||
|
|
||
|
K_EXPORT_PLASMA_APPLET(lsof, Lsof)
|
||
|
|
||
|
#include "moc_lsof.cpp"
|
||
|
#include "lsof.moc"
|