Compare commits
No commits in common. "d725a54bd8fa09991e3c45276c773ec1ed35c34a" and "bee1586af953859db2baca0fad2e30e25f871304" have entirely different histories.
d725a54bd8
...
bee1586af9
@ -21,46 +21,37 @@ namespace dmenu
|
|||||||
DesktopEntry(std::string path)
|
DesktopEntry(std::string path)
|
||||||
{
|
{
|
||||||
GDesktopAppInfo *info = g_desktop_app_info_new_from_filename(path.c_str());
|
GDesktopAppInfo *info = g_desktop_app_info_new_from_filename(path.c_str());
|
||||||
if (!info)
|
if (!info) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to create desktop app info for: " << path << std::endl;
|
std::cerr << "Failed to create desktop app info for: " << path << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GAppInfo *app = G_APP_INFO(info);
|
GAppInfo *app = G_APP_INFO(info);
|
||||||
if (!app)
|
if (!app) {
|
||||||
{
|
|
||||||
std::cerr << "Failed to get app info for: " << path << std::endl;
|
std::cerr << "Failed to get app info for: " << path << std::endl;
|
||||||
g_object_unref(info);
|
g_object_unref(info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *app_id = g_app_info_get_id(app);
|
const char *app_id = g_app_info_get_id(app);
|
||||||
if (app_id)
|
if (app_id) id = app_id;
|
||||||
id = app_id;
|
|
||||||
|
|
||||||
const char *app_name = g_app_info_get_name(app);
|
const char *app_name = g_app_info_get_name(app);
|
||||||
if (app_name)
|
if (app_name) name = app_name;
|
||||||
name = app_name;
|
|
||||||
|
|
||||||
GIcon *icon = g_app_info_get_icon(app);
|
GIcon *icon = g_app_info_get_icon(app);
|
||||||
if (icon)
|
if (icon) {
|
||||||
{
|
char* icon_str = g_icon_to_string(icon);
|
||||||
char *icon_str = g_icon_to_string(icon);
|
if (icon_str) {
|
||||||
if (icon_str)
|
|
||||||
{
|
|
||||||
icon_path = icon_str;
|
icon_path = icon_str;
|
||||||
g_free(icon_str);
|
g_free(icon_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *ex = g_desktop_app_info_get_string(info, "Exec");
|
const char *ex = g_app_info_get_executable(app);
|
||||||
if (ex)
|
if (ex)
|
||||||
{
|
|
||||||
exec = ex;
|
exec = ex;
|
||||||
g_free((gpointer)ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
display = g_desktop_app_info_get_boolean(info, "NoDisplay") ? false : true;
|
display = g_desktop_app_info_get_boolean(info, "NoDisplay") ? false : true;
|
||||||
g_object_unref(info);
|
g_object_unref(info);
|
||||||
}
|
}
|
||||||
@ -89,9 +80,8 @@ namespace dmenu
|
|||||||
inline DEVec get_dmenu_app_data()
|
inline DEVec get_dmenu_app_data()
|
||||||
{
|
{
|
||||||
DEVec out = std::make_unique<std::vector<DesktopEntry>>();
|
DEVec out = std::make_unique<std::vector<DesktopEntry>>();
|
||||||
const char *env_dirs = std::getenv("XDG_DATA_DIRS");
|
const char* env_dirs = std::getenv("XDG_DATA_DIRS");
|
||||||
if (!env_dirs)
|
if (!env_dirs) {
|
||||||
{
|
|
||||||
std::cerr << "XDG_DATA_DIRS environment variable not set" << std::endl;
|
std::cerr << "XDG_DATA_DIRS environment variable not set" << std::endl;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -107,8 +97,7 @@ namespace dmenu
|
|||||||
for (const auto &dfile : desktopFiles)
|
for (const auto &dfile : desktopFiles)
|
||||||
{
|
{
|
||||||
DesktopEntry entry(dfile.string());
|
DesktopEntry entry(dfile.string());
|
||||||
if (entry.display)
|
if (entry.display) {
|
||||||
{
|
|
||||||
out->push_back(std::move(entry));
|
out->push_back(std::move(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "AppListModel.hpp"
|
#include "AppListModel.hpp"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QProcess>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
|
|
||||||
AppListModel::AppListModel(QObject *parent)
|
AppListModel::AppListModel(QObject *parent)
|
||||||
: QAbstractListModel(parent)
|
: QAbstractListModel(parent)
|
||||||
@ -12,16 +10,15 @@ AppListModel::AppListModel(QObject *parent)
|
|||||||
int AppListModel::rowCount(const QModelIndex &parent) const
|
int AppListModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
return static_cast<int>(m_filteredIndexes.size());
|
return m_apps ? static_cast<int>(m_apps->size()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant AppListModel::data(const QModelIndex &index, int role) const
|
QVariant AppListModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid() || !m_apps || index.row() >= static_cast<int>(m_filteredIndexes.size()))
|
if (!index.isValid() || !m_apps || index.row() >= static_cast<int>(m_apps->size()))
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
int appIndex = m_filteredIndexes[index.row()];
|
const dmenu::DesktopEntry &app = (*m_apps)[index.row()];
|
||||||
const dmenu::DesktopEntry &app = (*m_apps)[appIndex];
|
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case NameRole:
|
case NameRole:
|
||||||
@ -48,61 +45,5 @@ void AppListModel::loadApps()
|
|||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_apps = dmenu::get_dmenu_app_data();
|
m_apps = dmenu::get_dmenu_app_data();
|
||||||
updateFilteredApps();
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
|
||||||
|
|
||||||
void AppListModel::launchApp(int index)
|
|
||||||
{
|
|
||||||
if (!m_apps || index < 0 || index >= static_cast<int>(m_filteredIndexes.size()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int appIndex = m_filteredIndexes[index];
|
|
||||||
const dmenu::DesktopEntry &app = (*m_apps)[appIndex];
|
|
||||||
|
|
||||||
// Parse exec command (remove %f, %u, %F, %U field codes if present)
|
|
||||||
QString command = QString::fromStdString(app.exec);
|
|
||||||
QRegularExpression fieldCodes("%[fuFU]");
|
|
||||||
command = command.replace(fieldCodes, "").trimmed();
|
|
||||||
|
|
||||||
qDebug() << "Launching:" << command;
|
|
||||||
|
|
||||||
// Use nohup and redirect output to /dev/null for proper detachment
|
|
||||||
QString detachedCommand = QString("nohup %1 >/dev/null 2>&1 &").arg(command);
|
|
||||||
QProcess::startDetached("/bin/sh", QStringList() << "-c" << detachedCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AppListModel::searchText() const
|
|
||||||
{
|
|
||||||
return m_searchText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppListModel::setSearchText(const QString &searchText)
|
|
||||||
{
|
|
||||||
if (m_searchText == searchText)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_searchText = searchText;
|
|
||||||
emit searchTextChanged();
|
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
updateFilteredApps();
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppListModel::updateFilteredApps()
|
|
||||||
{
|
|
||||||
m_filteredIndexes.clear();
|
|
||||||
|
|
||||||
if (!m_apps)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < m_apps->size(); ++i) {
|
|
||||||
const dmenu::DesktopEntry &app = (*m_apps)[i];
|
|
||||||
|
|
||||||
if (m_searchText.isEmpty() ||
|
|
||||||
QString::fromStdString(app.name).contains(m_searchText, Qt::CaseInsensitive)) {
|
|
||||||
m_filteredIndexes.push_back(static_cast<int>(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -10,7 +10,6 @@
|
|||||||
class AppListModel : public QAbstractListModel
|
class AppListModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString searchText READ searchText WRITE setSearchText NOTIFY searchTextChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum AppRoles {
|
enum AppRoles {
|
||||||
@ -26,18 +25,7 @@ public:
|
|||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
Q_INVOKABLE void loadApps();
|
Q_INVOKABLE void loadApps();
|
||||||
Q_INVOKABLE void launchApp(int index);
|
|
||||||
|
|
||||||
QString searchText() const;
|
|
||||||
void setSearchText(const QString &searchText);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void searchTextChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateFilteredApps();
|
|
||||||
|
|
||||||
dmenu::DEVec m_apps;
|
dmenu::DEVec m_apps;
|
||||||
std::vector<int> m_filteredIndexes;
|
|
||||||
QString m_searchText;
|
|
||||||
};
|
};
|
12
ui/Main.qml
12
ui/Main.qml
@ -40,19 +40,12 @@ ApplicationWindow {
|
|||||||
placeholderText: "Type to search applications..."
|
placeholderText: "Type to search applications..."
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
focus: true
|
focus: true
|
||||||
text: appModel.searchText
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
appModel.searchText = text
|
|
||||||
listView.currentIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onDownPressed: listView.incrementCurrentIndex()
|
Keys.onDownPressed: listView.incrementCurrentIndex()
|
||||||
Keys.onUpPressed: listView.decrementCurrentIndex()
|
Keys.onUpPressed: listView.decrementCurrentIndex()
|
||||||
Keys.onReturnPressed: {
|
Keys.onReturnPressed: {
|
||||||
if (listView.currentItem) {
|
if (listView.currentItem) {
|
||||||
appModel.launchApp(listView.currentIndex)
|
console.log("Selected:", appModel.data(appModel.index(listView.currentIndex, 0), Qt.UserRole + 1))
|
||||||
Qt.quit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,8 +105,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
listView.currentIndex = index
|
listView.currentIndex = index
|
||||||
appModel.launchApp(index)
|
console.log("Clicked:", model.name)
|
||||||
Qt.quit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user