Files
seer/src/QProcessInfoWidget.cpp
T
2025-08-26 17:26:05 -05:00

241 lines
7.4 KiB
C++

// SPDX-FileCopyrightText: 2021 Ernie Pasveer <epasveer@att.net>
//
// SPDX-License-Identifier: MIT
#include "QProcessInfoWidget.h"
#include "QProcessInfo.h"
#include <QtWidgets/QTreeWidget>
#include <QtWidgets/QTreeWidgetItemIterator>
#include <QtWidgets/QApplication>
#include <QtGui/QFont>
#include <QtCore/QDebug>
#include <QRegularExpression>
//
// Custom tree item with numeric ordering on column 0.
//
class QProcessInfoWidgetItem : public QTreeWidgetItem {
public:
QProcessInfoWidgetItem(QTreeWidget* parent = 0) : QTreeWidgetItem(parent) {
}
private:
bool operator< (const QTreeWidgetItem& other) const {
int column = treeWidget()->sortColumn();
if (column == 0) {
return text(column).toLong() < other.text(column).toLong();
}
return text(column) < other.text(column);
}
};
//
// The main widget starts here.
//
QProcessInfoWidget::QProcessInfoWidget (QWidget* parent) : QWidget(parent) {
// Construct the UI.
setupUi(this);
// Setup the widgets
processTreeWidget->setMouseTracking(true);
processTreeWidget->resizeColumnToContents(0); // PID
processTreeWidget->resizeColumnToContents(1); // User name
processTreeWidget->resizeColumnToContents(2); // Path name
processTreeWidget->resizeColumnToContents(3); // Program name
//processTreeWidget->resizeColumnToContents(4); // Command line
processTreeWidget->setSortingEnabled(true);
processTreeWidget->clear();
systemProcessesCheckBox->setChecked(false);
// Connect things.
QObject::connect(programNameLineEdit, &QLineEdit::textChanged, this, &QProcessInfoWidget::refreshView);
QObject::connect(userNameLineEdit, &QLineEdit::textChanged, this, &QProcessInfoWidget::refreshView);
QObject::connect(systemProcessesCheckBox, &QCheckBox::clicked, this, &QProcessInfoWidget::refreshView);
QObject::connect(refreshToolButton, &QToolButton::clicked, this, &QProcessInfoWidget::refreshList);
QObject::connect(processTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QProcessInfoWidget::handleDoubleClicked);
// Give focus to the program line edit.
programNameLineEdit->setFocus(Qt::OtherFocusReason);
// Load the initial process list.
refreshList();
}
QProcessInfoWidget::~QProcessInfoWidget () {
}
int QProcessInfoWidget::selectedPid () const {
QList<QTreeWidgetItem*> items = processTreeWidget->selectedItems();
if (items.size() == 0) {
return -1;
}
return items[0]->text(0).toLong();
}
QString QProcessInfoWidget::selectedUsername () const {
QList<QTreeWidgetItem*> items = processTreeWidget->selectedItems();
if (items.size() == 0) {
return "";
}
return items[0]->text(1);
}
QString QProcessInfoWidget::selectedName () const {
QList<QTreeWidgetItem*> items = processTreeWidget->selectedItems();
if (items.size() == 0) {
return "";
}
return items[0]->text(3);
}
QString QProcessInfoWidget::selectedFullname () const {
QList<QTreeWidgetItem*> items = processTreeWidget->selectedItems();
if (items.size() == 0) {
return "";
}
return items[0]->text(2) + "/" + items[0]->text(3);
}
QString QProcessInfoWidget::selectedCommandLine () const {
QList<QTreeWidgetItem*> items = processTreeWidget->selectedItems();
if (items.size() == 0) {
return "";
}
return items[0]->text(4);
}
void QProcessInfoWidget::refreshList () {
QApplication::setOverrideCursor(Qt::BusyCursor);
// Scan the /proc file system.
QProcessList list = QProcessInfo::populate();
// Loop through each entry and add it to our view.
processTreeWidget->clear();
for (const QProcessInfo& info : list) {
QTreeWidgetItem* item = new QProcessInfoWidgetItem;
item->setText(0, QString::number(info.pid()));
item->setText(1, info.username());
item->setText(2, info.path());
item->setText(3, info.name());
item->setText(4, info.commandLine());
processTreeWidget->addTopLevelItem(item);
}
// Adjust the column widths.
processTreeWidget->clearSelection();
processTreeWidget->resizeColumnToContents(0);
processTreeWidget->resizeColumnToContents(1);
processTreeWidget->resizeColumnToContents(2);
processTreeWidget->resizeColumnToContents(3);
//processTreeWidget->resizeColumnToContents(4);
// Don't clear the line edits.
// programNameLineEdit->clear();
// userNameLineEdit->clear();
refreshView();
QApplication::restoreOverrideCursor();
}
void QProcessInfoWidget::refreshView () {
// Get this list of program name matches. Or all if there is no program name provided.
QList<QTreeWidgetItem*> programNameMatches;
if (programNameLineEdit->text() == "") {
programNameMatches = processTreeWidget->findItems("*", Qt::MatchWildcard | Qt::MatchRecursive, 3);
}else{
if (programNameLineEdit->text().contains('*')) {
programNameMatches = processTreeWidget->findItems(programNameLineEdit->text(), Qt::MatchWildcard | Qt::MatchRecursive, 3);
}else{
programNameMatches = processTreeWidget->findItems(programNameLineEdit->text(), Qt::MatchStartsWith | Qt::MatchRecursive, 3);
}
}
// Get this list of user name matches. Or all if there is no user name provided.
QList<QTreeWidgetItem*> userNameMatches;
if (userNameLineEdit->text() == "") {
userNameMatches = processTreeWidget->findItems("*", Qt::MatchWildcard | Qt::MatchRecursive, 1);
}else{
if (userNameLineEdit->text().contains('*')) {
userNameMatches = processTreeWidget->findItems(userNameLineEdit->text(), Qt::MatchWildcard | Qt::MatchRecursive, 1);
}else{
userNameMatches = processTreeWidget->findItems(userNameLineEdit->text(), Qt::MatchStartsWith | Qt::MatchRecursive, 1);
}
}
// Get this list of process matches. Include one's with [xxx]) or not.
QList<QTreeWidgetItem*> processMatches;
if (systemProcessesCheckBox->isChecked() == true) {
processMatches = processTreeWidget->findItems("*", Qt::MatchWildcard | Qt::MatchRecursive, 3);
//qDebug() << "Checkbox is on." << processMatches.size();
}else{
// To find [xxx] processes : "^(\\[).*(\\])$"
// To exclude [xxx] processes: "^(?!\\[).*(?!\\])$"
processMatches = processTreeWidget->findItems("^(?!\\[).*(?!\\])$", Qt::MatchRegularExpression | Qt::MatchRecursive, 3);
//qDebug() << "Checkbox is off." << processMatches.size();
}
// Go through each item in the tree. If it's in the user, program, and process matches, show it.
// Otherwise, hide it.
QTreeWidgetItemIterator it(processTreeWidget);
while (*it) {
if (programNameMatches.contains(*it) && userNameMatches.contains(*it) && processMatches.contains(*it)) {
(*it)->setHidden(false);
}else{
(*it)->setHidden(true);
}
++it;
}
// Resize the columns.
processTreeWidget->resizeColumnToContents(0);
processTreeWidget->resizeColumnToContents(1);
processTreeWidget->resizeColumnToContents(2);
processTreeWidget->resizeColumnToContents(3);
//processTreeWidget->resizeColumnToContents(4);
}
void QProcessInfoWidget::handleDoubleClicked () {
emit pidSelected(selectedPid());
}