mirror of https://github.com/cutefishos/statusbar
Improved activation item
parent
d4ef3cdf21
commit
27e0cf1cd2
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (C) 2021 CutefishOS Team.
|
||||
*
|
||||
* Author: cutefishos <cutefishos@foxmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "capplications.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QLocale>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QDir>
|
||||
|
||||
static CApplications *SELF = nullptr;
|
||||
static QString s_systemAppFolder = "/usr/share/applications";
|
||||
|
||||
static QByteArray detectDesktopEnvironment()
|
||||
{
|
||||
const QByteArray desktop = qgetenv("XDG_CURRENT_DESKTOP");
|
||||
|
||||
if (!desktop.isEmpty())
|
||||
return desktop.toUpper();
|
||||
|
||||
return QByteArray("UNKNOWN");
|
||||
}
|
||||
|
||||
CApplications *CApplications::self()
|
||||
{
|
||||
if (!SELF)
|
||||
SELF = new CApplications;
|
||||
|
||||
return SELF;
|
||||
}
|
||||
|
||||
CApplications::CApplications(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_watcher(new QFileSystemWatcher(this))
|
||||
{
|
||||
m_watcher->addPath(s_systemAppFolder);
|
||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &CApplications::refresh);
|
||||
refresh();
|
||||
}
|
||||
|
||||
CApplications::~CApplications()
|
||||
{
|
||||
while (!m_items.isEmpty())
|
||||
delete m_items.takeFirst();
|
||||
}
|
||||
|
||||
CAppItem *CApplications::find(const QString &fileName)
|
||||
{
|
||||
for (CAppItem *item : m_items)
|
||||
if (item->path == fileName)
|
||||
return item;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CAppItem *CApplications::matchItem(quint32 pid)
|
||||
{
|
||||
QStringList commands = commandFromPid(pid);
|
||||
QString command = commands.first();
|
||||
QString commandName = commands.last();
|
||||
|
||||
if (command.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
for (CAppItem *item : m_items) {
|
||||
if (item->fullExec == command ||
|
||||
item->exec == command ||
|
||||
item->fullExec == commandName ||
|
||||
item->exec == commandName) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CApplications::refresh()
|
||||
{
|
||||
QStringList addedEntries;
|
||||
for (CAppItem *item : m_items)
|
||||
addedEntries.append(item->path);
|
||||
|
||||
QStringList allEntries;
|
||||
QDirIterator it(s_systemAppFolder, { "*.desktop" }, QDir::NoFilter, QDirIterator::Subdirectories);
|
||||
|
||||
while (it.hasNext()) {
|
||||
const QString &filePath = it.next();
|
||||
|
||||
if (!QFile::exists(filePath))
|
||||
continue;
|
||||
|
||||
allEntries.append(filePath);
|
||||
}
|
||||
|
||||
for (const QString &filePath : allEntries) {
|
||||
if (!addedEntries.contains(filePath)) {
|
||||
addApplication(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
for (CAppItem *item : m_items) {
|
||||
if (!allEntries.contains(item->path)) {
|
||||
removeApplication(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CApplications::addApplication(const QString &filePath)
|
||||
{
|
||||
if (find(filePath))
|
||||
return;
|
||||
|
||||
QSettings desktop(filePath, QSettings::IniFormat);
|
||||
desktop.setIniCodec("UTF-8");
|
||||
desktop.beginGroup("Desktop Entry");
|
||||
|
||||
// Skip...
|
||||
if (desktop.contains("OnlyShowIn")) {
|
||||
const QString &value = desktop.value("OnlyShowIn").toString();
|
||||
if (!value.contains(detectDesktopEnvironment(), Qt::CaseInsensitive)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (desktop.value("NoDisplay").toBool() ||
|
||||
desktop.value("Hidden").toBool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Local Name
|
||||
QString localName = desktop.value(QString("Name[%1]").arg(QLocale::system().name())).toString();
|
||||
if (localName.isEmpty())
|
||||
localName = desktop.value("Name").toString();
|
||||
|
||||
// Exec
|
||||
QString simplifiedExec = desktop.value("Exec").toString();
|
||||
simplifiedExec.remove(QRegularExpression("%."));
|
||||
simplifiedExec.remove(QRegularExpression("^\""));
|
||||
// appExec.remove(QRegularExpression(" *$"));
|
||||
simplifiedExec = simplifiedExec.simplified();
|
||||
|
||||
// New data
|
||||
CAppItem *item = new CAppItem;
|
||||
item->path = filePath;
|
||||
item->localName = localName;
|
||||
item->name = desktop.value("Name").toString();;
|
||||
item->comment = desktop.value("Comment").toString();
|
||||
item->icon = desktop.value("Icon").toString();
|
||||
item->fullExec = desktop.value("Exec").toString();
|
||||
item->exec = simplifiedExec;
|
||||
m_items.append(item);
|
||||
}
|
||||
|
||||
void CApplications::removeApplication(CAppItem *item)
|
||||
{
|
||||
m_items.removeOne(item);
|
||||
delete item;
|
||||
}
|
||||
|
||||
QStringList CApplications::commandFromPid(quint32 pid)
|
||||
{
|
||||
QFile file(QString("/proc/%1/cmdline").arg(pid));
|
||||
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray cmd = file.readAll();
|
||||
|
||||
// ref: https://github.com/KDE/kcoreaddons/blob/230c98aa7e01f9e36a9c2776f3633182e6778002/src/lib/util/kprocesslist_unix.cpp#L137
|
||||
if (!cmd.isEmpty()) {
|
||||
// extract non-truncated name from cmdline
|
||||
int zeroIndex = cmd.indexOf('\0');
|
||||
int processNameStart = cmd.lastIndexOf('/', zeroIndex);
|
||||
if (processNameStart == -1) {
|
||||
processNameStart = 0;
|
||||
} else {
|
||||
processNameStart++;
|
||||
}
|
||||
|
||||
QString name = QString::fromLocal8Bit(cmd.mid(processNameStart, zeroIndex - processNameStart));
|
||||
|
||||
cmd.replace('\0', ' ');
|
||||
QString command = QString::fromLocal8Bit(cmd).trimmed();
|
||||
return { command, name };
|
||||
}
|
||||
}
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2021 CutefishOS Team.
|
||||
*
|
||||
* Author: cutefishos <cutefishos@foxmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CAPPLICATIONS_H
|
||||
#define CAPPLICATIONS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
class CAppItem
|
||||
{
|
||||
public:
|
||||
QString path;
|
||||
QString localName;
|
||||
QString name;
|
||||
QString comment;
|
||||
QString icon;
|
||||
QString fullExec;
|
||||
QString exec;
|
||||
};
|
||||
|
||||
class CApplications : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static CApplications *self();
|
||||
explicit CApplications(QObject *parent = nullptr);
|
||||
~CApplications();
|
||||
|
||||
CAppItem *find(const QString &fileName);
|
||||
CAppItem *matchItem(quint32 pid);
|
||||
|
||||
private:
|
||||
void refresh();
|
||||
void addApplication(const QString &filePath);
|
||||
void removeApplication(CAppItem *item);
|
||||
|
||||
QStringList commandFromPid(quint32 pid);
|
||||
|
||||
private:
|
||||
QFileSystemWatcher *m_watcher;
|
||||
QList<CAppItem *> m_items;
|
||||
};
|
||||
|
||||
#endif // CAPPLICATIONS_H
|
||||
Loading…
Reference in New Issue