Compare commits

..

No commits in common. "d725a54bd8fa09991e3c45276c773ec1ed35c34a" and "bee1586af953859db2baca0fad2e30e25f871304" have entirely different histories.

4 changed files with 21 additions and 111 deletions

View File

@ -21,45 +21,36 @@ 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);
@ -90,8 +81,7 @@ namespace dmenu
{ {
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));
} }
} }

View File

@ -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));
}
}
}

View File

@ -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;
}; };

View File

@ -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()
} }
} }
} }