App icons
This commit is contained in:
parent
fc2335f138
commit
3a66939627
@ -2,6 +2,12 @@
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QUrl>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
|
||||
AppListModel::AppListModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
@ -30,6 +36,8 @@ QVariant AppListModel::data(const QModelIndex &index, int role) const
|
||||
return QString::fromStdString(app.exec);
|
||||
case IdRole:
|
||||
return QString::fromStdString(app.id);
|
||||
case IconRole:
|
||||
return getIconUrl(app);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@ -41,6 +49,7 @@ QHash<int, QByteArray> AppListModel::roleNames() const
|
||||
roles[NameRole] = "name";
|
||||
roles[ExecRole] = "exec";
|
||||
roles[IdRole] = "id";
|
||||
roles[IconRole] = "icon";
|
||||
return roles;
|
||||
}
|
||||
|
||||
@ -105,4 +114,58 @@ void AppListModel::updateFilteredApps()
|
||||
m_filteredIndexes.push_back(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QUrl AppListModel::getIconUrl(const dmenu::DesktopEntry &app) const
|
||||
{
|
||||
QString iconName = QString::fromStdString(app.icon_path);
|
||||
|
||||
if (iconName.isEmpty())
|
||||
return QUrl();
|
||||
|
||||
// If it's already a full path, use it directly
|
||||
if (iconName.startsWith('/')) {
|
||||
if (QFile::exists(iconName)) {
|
||||
return QUrl::fromLocalFile(iconName);
|
||||
}
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
// Use Qt's proper icon theme search which follows XDG spec
|
||||
QIcon icon = QIcon::fromTheme(iconName);
|
||||
if (icon.isNull()) {
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
// Qt doesn't expose the resolved file path directly, so let's use QStandardPaths
|
||||
// to search in the proper system directories
|
||||
QStringList dataDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
|
||||
|
||||
// Common icon subdirectories and sizes (prioritized)
|
||||
QStringList iconSubDirs = {
|
||||
"icons/hicolor/scalable/apps",
|
||||
"icons/hicolor/48x48/apps",
|
||||
"icons/hicolor/64x64/apps",
|
||||
"icons/hicolor/32x32/apps",
|
||||
"icons/hicolor/128x128/apps",
|
||||
"icons/Adwaita/scalable/apps",
|
||||
"icons/Adwaita/48x48/apps",
|
||||
"pixmaps"
|
||||
};
|
||||
|
||||
QStringList extensions = {"", ".png", ".svg", ".xpm"};
|
||||
|
||||
for (const QString &dataDir : dataDirs) {
|
||||
for (const QString &iconSubDir : iconSubDirs) {
|
||||
QString basePath = dataDir + "/" + iconSubDir + "/";
|
||||
for (const QString &ext : extensions) {
|
||||
QString fullPath = basePath + iconName + ext;
|
||||
if (QFile::exists(fullPath)) {
|
||||
return QUrl::fromLocalFile(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QUrl();
|
||||
}
|
@ -16,7 +16,8 @@ public:
|
||||
enum AppRoles {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
ExecRole,
|
||||
IdRole
|
||||
IdRole,
|
||||
IconRole
|
||||
};
|
||||
|
||||
explicit AppListModel(QObject *parent = nullptr);
|
||||
@ -36,6 +37,7 @@ signals:
|
||||
|
||||
private:
|
||||
void updateFilteredApps();
|
||||
QUrl getIconUrl(const dmenu::DesktopEntry &app) const;
|
||||
|
||||
dmenu::DEVec m_apps;
|
||||
std::vector<int> m_filteredIndexes;
|
||||
|
84
src/main.cpp
84
src/main.cpp
@ -30,48 +30,48 @@ std::vector<std::string> split(std::string s, char delimiter)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
dmenu::DEVec apps = dmenu::get_dmenu_app_data();
|
||||
for (auto &app : *apps.get())
|
||||
{
|
||||
std::cout << app.iconPath() << std::endl;
|
||||
// std::cout << std::format("---\nName: {}\nID: {}\nIcon: {}\nExec: {}\nDisp: {}\n---\n", app.id, app.name, app.iconPath(), app.exec, app.display ? "yes" : "no");
|
||||
}
|
||||
|
||||
// QGuiApplication app(argc, argv);
|
||||
// QCoreApplication::setApplicationName("waycast");
|
||||
|
||||
// // Enable system theme support
|
||||
// app.setDesktopSettingsAware(true);
|
||||
|
||||
// QQmlApplicationEngine engine;
|
||||
|
||||
// // Register the AppListModel type with QML
|
||||
// qmlRegisterType<AppListModel>("WayCast", 1, 0, "AppListModel");
|
||||
|
||||
// // Set up layer shell before creating any windows
|
||||
// QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []()
|
||||
// { QCoreApplication::exit(-1); });
|
||||
|
||||
// engine.loadFromModule("WayCast", "Main");
|
||||
|
||||
// // Get the root objects and configure layer shell
|
||||
// auto rootObjects = engine.rootObjects();
|
||||
// if (!rootObjects.isEmpty())
|
||||
// dmenu::DEVec apps = dmenu::get_dmenu_app_data();
|
||||
// for (auto &app : *apps.get())
|
||||
// {
|
||||
// QWindow *window = qobject_cast<QWindow *>(rootObjects.first());
|
||||
// if (window)
|
||||
// {
|
||||
// LayerShellQt::Window *layerWindow = LayerShellQt::Window::get(window);
|
||||
// if (layerWindow)
|
||||
// {
|
||||
// layerWindow->setLayer(LayerShellQt::Window::LayerTop);
|
||||
// layerWindow->setAnchors({});
|
||||
// layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand);
|
||||
|
||||
// // Now show the window after layer shell is configured
|
||||
// window->show();
|
||||
// }
|
||||
// }
|
||||
// std::cout << app.iconPath() << std::endl;
|
||||
// // std::cout << std::format("---\nName: {}\nID: {}\nIcon: {}\nExec: {}\nDisp: {}\n---\n", app.id, app.name, app.iconPath(), app.exec, app.display ? "yes" : "no");
|
||||
// }
|
||||
// return app.exec();
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName("waycast");
|
||||
|
||||
// Enable system theme support
|
||||
app.setDesktopSettingsAware(true);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
// Register the AppListModel type with QML
|
||||
qmlRegisterType<AppListModel>("WayCast", 1, 0, "AppListModel");
|
||||
|
||||
// Set up layer shell before creating any windows
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []()
|
||||
{ QCoreApplication::exit(-1); });
|
||||
|
||||
engine.loadFromModule("WayCast", "Main");
|
||||
|
||||
// Get the root objects and configure layer shell
|
||||
auto rootObjects = engine.rootObjects();
|
||||
if (!rootObjects.isEmpty())
|
||||
{
|
||||
QWindow *window = qobject_cast<QWindow *>(rootObjects.first());
|
||||
if (window)
|
||||
{
|
||||
LayerShellQt::Window *layerWindow = LayerShellQt::Window::get(window);
|
||||
if (layerWindow)
|
||||
{
|
||||
layerWindow->setLayer(LayerShellQt::Window::LayerTop);
|
||||
layerWindow->setAnchors({});
|
||||
layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand);
|
||||
|
||||
// Now show the window after layer shell is configured
|
||||
window->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
return app.exec();
|
||||
}
|
||||
|
22
ui/Main.qml
22
ui/Main.qml
@ -89,16 +89,24 @@ ApplicationWindow {
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
Rectangle {
|
||||
Image {
|
||||
width: 24
|
||||
height: 24
|
||||
color: palette.button
|
||||
radius: 4
|
||||
source: model.icon
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "📱"
|
||||
font.pixelSize: 16
|
||||
// Fallback if icon fails to load
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: palette.button
|
||||
radius: 4
|
||||
visible: parent.status === Image.Error || parent.status === Image.Null
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "📱"
|
||||
font.pixelSize: 16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user