Great things coming up
This commit is contained in:
commit
33ab4308d1
16
.envrc
Normal file
16
.envrc
Normal file
@ -0,0 +1,16 @@
|
||||
# Use the Nix shell
|
||||
use nix
|
||||
|
||||
# Optional: Layout for different build types
|
||||
layout() {
|
||||
case $1 in
|
||||
cpp)
|
||||
# Add any C++ specific environment setup here
|
||||
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Debug}
|
||||
export CMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Activate the cpp layout
|
||||
layout cpp
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
build
|
||||
.vscode
|
||||
.zig-cache
|
||||
zig-out
|
74
CLAUDE.md
Normal file
74
CLAUDE.md
Normal file
@ -0,0 +1,74 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
WayCast is a Raycast-like application launcher for Linux, built with C++20 and Qt6. It scans XDG desktop entries to provide a searchable interface for launching applications on Wayland/X11.
|
||||
|
||||
## Build System
|
||||
|
||||
The project supports three build systems:
|
||||
|
||||
### Primary: CMake with Ninja (Recommended)
|
||||
```bash
|
||||
# Configure and build
|
||||
make configure # or: cmake -S . -B build -G Ninja
|
||||
make bld # or: cmake --build build
|
||||
make run # or: ./build/waycast
|
||||
|
||||
# Combined: make br (build + run)
|
||||
# Full rebuild: make all (configure + build + run)
|
||||
```
|
||||
|
||||
### Alternative: Zig Build
|
||||
```bash
|
||||
zig build run
|
||||
```
|
||||
|
||||
### Development Environment: Nix Shell
|
||||
```bash
|
||||
nix-shell # Sets up Qt6, CMake, Ninja, Clang, and required dependencies
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
- **main.cpp**: Entry point, currently configured for CLI testing of desktop entry parsing
|
||||
- **dmenu.hpp/namespace**: Desktop entry parsing using GIO/GLib to read XDG application data
|
||||
- **files.hpp/namespace**: File system utilities for scanning directories and reading files
|
||||
- **ui/Main.qml**: Qt Quick interface (currently minimal, Qt GUI code commented out in main)
|
||||
|
||||
### Key Classes
|
||||
|
||||
- `dmenu::DesktopEntry`: Parses .desktop files using GDesktopAppInfo, extracts app metadata (name, icon, executable, display flags)
|
||||
- `files::findFilesWithExtension()`: Recursively scans directories for files with specific extensions
|
||||
- `DEVec`: Type alias for `std::unique_ptr<std::vector<DesktopEntry>>`
|
||||
|
||||
### Current State
|
||||
|
||||
The application is in active development:
|
||||
- Main Qt GUI loop is commented out in main.cpp:56-64
|
||||
- Currently runs as CLI tool that prints discovered application IDs
|
||||
- Desktop entry scanning logic is functional
|
||||
- Qt QML interface exists but is not connected
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Qt6**: Core, Gui, Qml, Quick, QuickControls2
|
||||
- **GIO/GLib**: For XDG desktop entry parsing
|
||||
- **C++20**: Uses std::format, filesystem, and modern C++ features
|
||||
- **CMake 3.21+**: Build system
|
||||
- **Ninja**: Preferred generator
|
||||
|
||||
## Development Notes
|
||||
|
||||
- Qt resources are bundled via CMakeLists.txt (qt_add_qml_module)
|
||||
- Uses C++20 modules compilation flags for GCC/Clang
|
||||
- Nix shell provides complete development environment with Qt6 Wayland support
|
||||
- Built-in RPATH configuration for Linux runtime library discovery
|
||||
|
||||
## Project Conventions
|
||||
|
||||
- We're not using header files. Prioritize .hpp
|
67
CMakeLists.txt
Normal file
67
CMakeLists.txt
Normal file
@ -0,0 +1,67 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(waycast LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Use Ninja if available (optional)
|
||||
if(NOT CMAKE_GENERATOR)
|
||||
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Qt6 REQUIRED COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Qml
|
||||
Quick
|
||||
QuickControls2
|
||||
)
|
||||
find_package(LayerShellQt REQUIRED)
|
||||
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(waycast)
|
||||
|
||||
include_directories("${CMAKE_SOURCE_DIR}/lib")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/lib")
|
||||
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/src/*.cpp")
|
||||
target_sources(waycast PRIVATE ${SRC_FILES} src/main.cpp)
|
||||
target_include_directories(waycast PRIVATE ${CMAKE_SOURCE_DIR}/lib)
|
||||
# target_include_directories(waycast PRIVATE ${CMAKE_SOURCE_DIR}/lib ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Bundle QML into the app (no runtime QML path headaches)
|
||||
qt_add_qml_module(waycast
|
||||
URI WayCast
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
ui/Main.qml
|
||||
)
|
||||
|
||||
target_link_libraries(waycast PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Qml
|
||||
Qt6::Quick
|
||||
PkgConfig::GIO
|
||||
LayerShellQt::Interface
|
||||
)
|
||||
|
||||
# On Linux, ensure plugins/libs are found at runtime if needed
|
||||
# (usually fine when running inside nix shell)
|
||||
if(UNIX AND NOT APPLE)
|
||||
set_target_properties(waycast PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add -fmodules-ts where needed
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(waycast PRIVATE -fmodules-ts)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_compile_options(waycast PRIVATE -fmodules-ts)
|
||||
endif()
|
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
configure:
|
||||
rm -rf build
|
||||
cmake -S . -B build -G Ninja
|
||||
bld:
|
||||
cmake --build build
|
||||
run:
|
||||
./build/waycast
|
||||
|
||||
br: bld run
|
||||
|
||||
all: configure bld run
|
57
build.zig
Normal file
57
build.zig
Normal file
@ -0,0 +1,57 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
// const target = b.standardTargetOptions(.{});
|
||||
// const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
// Step 1: Generate Qt resources automatically
|
||||
const rcc_cmd = b.addSystemCommand(&.{ "rcc", "ui/resources.qrc", "-o", "qrc_resources.cpp" });
|
||||
|
||||
// Create the executable
|
||||
const mod = b.createModule(.{
|
||||
.target = b.graph.host,
|
||||
});
|
||||
|
||||
mod.addCSourceFiles(.{
|
||||
.files = &.{
|
||||
"main.cpp",
|
||||
"qrc_resources.cpp",
|
||||
},
|
||||
.flags = &.{
|
||||
"-std=c++20",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
},
|
||||
});
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "waycast",
|
||||
.root_module = mod,
|
||||
});
|
||||
|
||||
exe.step.dependOn(&rcc_cmd.step);
|
||||
|
||||
// Link C++ standard library
|
||||
exe.linkLibCpp();
|
||||
// Link Qt6
|
||||
exe.linkSystemLibrary("Qt6Core");
|
||||
exe.linkSystemLibrary("Qt6Quick");
|
||||
exe.linkSystemLibrary("Qt6Gui");
|
||||
exe.linkSystemLibrary("Qt6Qml");
|
||||
|
||||
// Install the executable
|
||||
b.installArtifact(exe);
|
||||
|
||||
// Create a run step
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
// Allow passing arguments to the program
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
// Create the run step
|
||||
const run_step = b.step("run", "Run the application");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
106
lib/dmenu.hpp
Normal file
106
lib/dmenu.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
#include "files.hpp"
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gappinfo.h>
|
||||
#include <gio-unix-2.0/gio/gdesktopappinfo.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace dmenu
|
||||
{
|
||||
class DesktopEntry
|
||||
{
|
||||
public:
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string icon_path;
|
||||
std::string exec;
|
||||
bool display = false;
|
||||
DesktopEntry(std::string path)
|
||||
{
|
||||
GDesktopAppInfo *info = g_desktop_app_info_new_from_filename(path.c_str());
|
||||
if (!info) {
|
||||
std::cerr << "Failed to create desktop app info for: " << path << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
GAppInfo *app = G_APP_INFO(info);
|
||||
if (!app) {
|
||||
std::cerr << "Failed to get app info for: " << path << std::endl;
|
||||
g_object_unref(info);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *app_id = g_app_info_get_id(app);
|
||||
if (app_id) id = app_id;
|
||||
|
||||
const char *app_name = g_app_info_get_name(app);
|
||||
if (app_name) name = app_name;
|
||||
|
||||
GIcon *icon = g_app_info_get_icon(app);
|
||||
if (icon) {
|
||||
char* icon_str = g_icon_to_string(icon);
|
||||
if (icon_str) {
|
||||
icon_path = icon_str;
|
||||
g_free(icon_str);
|
||||
}
|
||||
}
|
||||
|
||||
const char *ex = g_app_info_get_executable(app);
|
||||
if (ex)
|
||||
exec = ex;
|
||||
|
||||
display = g_desktop_app_info_get_boolean(info, "NoDisplay") ? false : true;
|
||||
g_object_unref(info);
|
||||
}
|
||||
|
||||
std::string iconPath()
|
||||
{
|
||||
return icon_path;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::string> split(std::string s, char delimiter)
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
std::string line;
|
||||
std::stringstream ss(s);
|
||||
|
||||
while (std::getline(ss, line, delimiter))
|
||||
{
|
||||
items.push_back(line);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
using DEVec = std::unique_ptr<std::vector<DesktopEntry>>;
|
||||
DEVec get_dmenu_app_data()
|
||||
{
|
||||
DEVec out = std::make_unique<std::vector<DesktopEntry>>();
|
||||
const char* env_dirs = std::getenv("XDG_DATA_DIRS");
|
||||
if (!env_dirs) {
|
||||
std::cerr << "XDG_DATA_DIRS environment variable not set" << std::endl;
|
||||
return out;
|
||||
}
|
||||
std::string dataDirs = env_dirs;
|
||||
std::vector<std::string> paths = split(dataDirs, ':');
|
||||
for (std::string &p : paths)
|
||||
p.append("/applications");
|
||||
|
||||
for (std::string &p : paths)
|
||||
{
|
||||
std::vector<std::filesystem::path> desktopFiles = files::findFilesWithExtension(p, ".desktop");
|
||||
|
||||
for (const auto &dfile : desktopFiles)
|
||||
{
|
||||
out->emplace_back(dfile.string());
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
53
lib/files.hpp
Normal file
53
lib/files.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <system_error>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
namespace files
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::vector<fs::path> findFilesWithExtension(const std::string path, const std::string ext)
|
||||
{
|
||||
std::vector<fs::path> out;
|
||||
std::unordered_set<std::string> seen; // canonicalized paths to dedupe
|
||||
std::error_code ec;
|
||||
fs::path p(path);
|
||||
|
||||
if (!fs::exists(p, ec) || !fs::is_directory(p, ec))
|
||||
return out;
|
||||
|
||||
for (const auto &entry : fs::directory_iterator(p, ec))
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
ec.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &filePath = entry.path();
|
||||
if (filePath.extension() == ext && fs::is_regular_file(filePath, ec))
|
||||
{
|
||||
out.push_back(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string readFile(const std::string &filename)
|
||||
{
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
throw std::runtime_error("Could not open file");
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << in.rdbuf(); // dump entire buffer into string
|
||||
return ss.str();
|
||||
}
|
||||
}
|
35
shell.nix
Normal file
35
shell.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
}:
|
||||
let
|
||||
qt = pkgs.qt6Packages;
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.ninja
|
||||
pkgs.clang_18
|
||||
pkgs.lldb
|
||||
pkgs.ccacheWrapper
|
||||
pkgs.glib
|
||||
pkgs.glib.dev
|
||||
qt.full
|
||||
qt.qtbase
|
||||
qt.qtdeclarative # <- provides QML/Quick + Quick Controls 2 (QtQuick.Controls)
|
||||
qt.qtwayland # <- provides the Wayland platform plugin
|
||||
pkgs.kdePackages.layer-shell-qt # <- provides layer shell support
|
||||
pkgs.kdePackages.layer-shell-qt.dev # <- provides headers
|
||||
pkgs.pkg-config
|
||||
# qt.qttools
|
||||
# qt.qtshadertools
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
export QT_PLUGIN_PATH='${qt.full}'
|
||||
export QML2_IMPORT_PATH='${qt.full}:${pkgs.kdePackages.layer-shell-qt}/lib/qt-6/qml'
|
||||
export QT_QPA_PLATFORM=wayland
|
||||
echo "--------------------------------------------"
|
||||
echo "QT_PLUGIN_PATH: $QT_PLUGIN_PATH"
|
||||
echo "QML2_IMPORT_PATH: $QML2_IMPORT_PATH"
|
||||
'';
|
||||
}
|
72
src/main.cpp
Normal file
72
src/main.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "dmenu.hpp"
|
||||
#include "files.hpp"
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QIcon>
|
||||
#include <QWindow>
|
||||
#include <LayerShellQt/window.h>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <format>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
std::vector<std::string> split(std::string s, char delimiter)
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
std::string line;
|
||||
std::stringstream ss(s);
|
||||
|
||||
while (std::getline(ss, line, delimiter))
|
||||
{
|
||||
items.push_back(line);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// dmenu::DEVec apps = dmenu::get_dmenu_app_data();
|
||||
// for (auto &app : *apps.get())
|
||||
// {
|
||||
// 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;
|
||||
|
||||
// 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();
|
||||
}
|
178
src/qrc_resources.cpp
Normal file
178
src/qrc_resources.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/****************************************************************************
|
||||
** Resource object code
|
||||
**
|
||||
** Created by: The Resource Compiler for Qt version 5.15.17
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost!
|
||||
*****************************************************************************/
|
||||
|
||||
static const unsigned char qt_resource_data[] = {
|
||||
// /home/javi/projects/waycast/ui/main.qml
|
||||
0x0,0x0,0x5,0x8e,
|
||||
0x69,
|
||||
0x6d,0x70,0x6f,0x72,0x74,0x20,0x51,0x74,0x51,0x75,0x69,0x63,0x6b,0x20,0x32,0x2e,
|
||||
0x31,0x35,0xa,0x69,0x6d,0x70,0x6f,0x72,0x74,0x20,0x51,0x74,0x51,0x75,0x69,0x63,
|
||||
0x6b,0x2e,0x57,0x69,0x6e,0x64,0x6f,0x77,0x20,0x32,0x2e,0x31,0x35,0xa,0x69,0x6d,
|
||||
0x70,0x6f,0x72,0x74,0x20,0x51,0x74,0x51,0x75,0x69,0x63,0x6b,0x2e,0x43,0x6f,0x6e,
|
||||
0x74,0x72,0x6f,0x6c,0x73,0x20,0x32,0x2e,0x31,0x35,0xa,0xa,0x41,0x70,0x70,0x6c,
|
||||
0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x57,0x69,0x6e,0x64,0x6f,0x77,0x20,0x7b,0xa,
|
||||
0x20,0x20,0x20,0x20,0x69,0x64,0x3a,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0xa,0x20,
|
||||
0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x36,0x34,0x30,0xa,0x20,0x20,
|
||||
0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x34,0x38,0x30,0xa,0x20,0x20,
|
||||
0x20,0x20,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x3a,0x20,0x74,0x72,0x75,0x65,0xa,
|
||||
0x20,0x20,0x20,0x20,0x74,0x69,0x74,0x6c,0x65,0x3a,0x20,0x71,0x73,0x54,0x72,0x28,
|
||||
0x22,0x51,0x74,0x20,0x51,0x75,0x69,0x63,0x6b,0x20,0x48,0x65,0x6c,0x6c,0x6f,0x20,
|
||||
0x57,0x6f,0x72,0x6c,0x64,0x22,0x29,0xa,0x20,0x20,0x20,0x20,0xa,0x20,0x20,0x20,
|
||||
0x20,0x52,0x65,0x63,0x74,0x61,0x6e,0x67,0x6c,0x65,0x20,0x7b,0xa,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x61,0x6e,0x63,0x68,0x6f,0x72,0x73,0x2e,0x66,0x69,0x6c,
|
||||
0x6c,0x3a,0x20,0x70,0x61,0x72,0x65,0x6e,0x74,0xa,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x67,0x72,0x61,0x64,0x69,0x65,0x6e,0x74,0x3a,0x20,0x47,0x72,0x61,0x64,
|
||||
0x69,0x65,0x6e,0x74,0x20,0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x47,0x72,0x61,0x64,0x69,0x65,0x6e,0x74,0x53,0x74,0x6f,0x70,0x20,
|
||||
0x7b,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x30,0x2e,0x30,0x3b,
|
||||
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x22,0x23,0x34,0x41,0x39,0x30,0x45,0x32,
|
||||
0x22,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x47,0x72,0x61,0x64,0x69,0x65,0x6e,0x74,0x53,0x74,0x6f,0x70,0x20,0x7b,0x20,0x70,
|
||||
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x31,0x2e,0x30,0x3b,0x20,0x63,0x6f,
|
||||
0x6c,0x6f,0x72,0x3a,0x20,0x22,0x23,0x33,0x35,0x37,0x41,0x42,0x44,0x22,0x20,0x7d,
|
||||
0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x43,0x6f,0x6c,0x75,
|
||||
0x6d,0x6e,0x20,0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x61,0x6e,0x63,0x68,0x6f,0x72,0x73,0x2e,0x63,0x65,0x6e,0x74,0x65,0x72,0x49,
|
||||
0x6e,0x3a,0x20,0x70,0x61,0x72,0x65,0x6e,0x74,0xa,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x3a,0x20,0x32,
|
||||
0x30,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xa,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x54,0x65,0x78,0x74,0x20,
|
||||
0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x69,0x64,0x3a,0x20,0x68,0x65,0x6c,0x6c,0x6f,0x54,0x65,0x78,0x74,0xa,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x74,0x65,0x78,0x74,0x3a,0x20,0x22,0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x51,0x74,
|
||||
0x20,0x51,0x75,0x69,0x63,0x6b,0x21,0x22,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2e,0x70,0x69,
|
||||
0x78,0x65,0x6c,0x53,0x69,0x7a,0x65,0x3a,0x20,0x33,0x32,0xa,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x6e,0x74,
|
||||
0x2e,0x62,0x6f,0x6c,0x64,0x3a,0x20,0x74,0x72,0x75,0x65,0xa,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,
|
||||
0x72,0x3a,0x20,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0xa,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x6e,0x63,0x68,0x6f,
|
||||
0x72,0x73,0x2e,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x43,0x65,0x6e,
|
||||
0x74,0x65,0x72,0x3a,0x20,0x70,0x61,0x72,0x65,0x6e,0x74,0x2e,0x68,0x6f,0x72,0x69,
|
||||
0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x43,0x65,0x6e,0x74,0x65,0x72,0xa,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x42,0x75,0x74,0x74,0x6f,0x6e,0x20,0x7b,0xa,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
|
||||
0x74,0x3a,0x20,0x22,0x43,0x6c,0x69,0x63,0x6b,0x20,0x6d,0x65,0x21,0x22,0xa,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x61,
|
||||
0x6e,0x63,0x68,0x6f,0x72,0x73,0x2e,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,
|
||||
0x6c,0x43,0x65,0x6e,0x74,0x65,0x72,0x3a,0x20,0x70,0x61,0x72,0x65,0x6e,0x74,0x2e,
|
||||
0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x43,0x65,0x6e,0x74,0x65,0x72,
|
||||
0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x6f,0x6e,0x43,0x6c,0x69,0x63,0x6b,0x65,0x64,0x3a,0x20,0x7b,0xa,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x68,0x65,0x6c,0x6c,0x6f,0x54,0x65,0x78,0x74,0x2e,0x74,0x65,0x78,
|
||||
0x74,0x20,0x3d,0x20,0x22,0x42,0x75,0x74,0x74,0x6f,0x6e,0x20,0x63,0x6c,0x69,0x63,
|
||||
0x6b,0x65,0x64,0x21,0x22,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x68,0x65,0x6c,0x6c,0x6f,0x54,
|
||||
0x65,0x78,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x22,0x23,0x46,0x46,
|
||||
0x44,0x37,0x30,0x30,0x22,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x42,
|
||||
0x75,0x74,0x74,0x6f,0x6e,0x20,0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x74,0x3a,0x20,0x22,0x52,
|
||||
0x65,0x73,0x65,0x74,0x22,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x6e,0x63,0x68,0x6f,0x72,0x73,0x2e,0x68,0x6f,
|
||||
0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x43,0x65,0x6e,0x74,0x65,0x72,0x3a,0x20,
|
||||
0x70,0x61,0x72,0x65,0x6e,0x74,0x2e,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,
|
||||
0x6c,0x43,0x65,0x6e,0x74,0x65,0x72,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6f,0x6e,0x43,0x6c,0x69,0x63,0x6b,
|
||||
0x65,0x64,0x3a,0x20,0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x68,0x65,0x6c,0x6c,0x6f,0x54,
|
||||
0x65,0x78,0x74,0x2e,0x74,0x65,0x78,0x74,0x20,0x3d,0x20,0x22,0x48,0x65,0x6c,0x6c,
|
||||
0x6f,0x2c,0x20,0x51,0x74,0x20,0x51,0x75,0x69,0x63,0x6b,0x21,0x22,0xa,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x68,0x65,0x6c,0x6c,0x6f,0x54,0x65,0x78,0x74,0x2e,0x63,0x6f,0x6c,0x6f,
|
||||
0x72,0x20,0x3d,0x20,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0xa,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x20,0x20,0x7d,0xa,0x20,0x20,0x20,0x20,0x7d,0xa,0x7d,
|
||||
|
||||
};
|
||||
|
||||
static const unsigned char qt_resource_name[] = {
|
||||
// ui
|
||||
0x0,0x2,
|
||||
0x0,0x0,0x7,0xb9,
|
||||
0x0,0x75,
|
||||
0x0,0x69,
|
||||
// main.qml
|
||||
0x0,0x8,
|
||||
0x8,0x1,0x5a,0x5c,
|
||||
0x0,0x6d,
|
||||
0x0,0x61,0x0,0x69,0x0,0x6e,0x0,0x2e,0x0,0x71,0x0,0x6d,0x0,0x6c,
|
||||
|
||||
};
|
||||
|
||||
static const unsigned char qt_resource_struct[] = {
|
||||
// :
|
||||
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
|
||||
0x0,0x0,0x0,0x49,0x77,0x38,0x70,0x0,
|
||||
// :/ui
|
||||
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
|
||||
0x0,0x0,0x0,0x49,0x77,0x38,0x70,0x0,
|
||||
// :/ui/main.qml
|
||||
0x0,0x0,0x0,0xa,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
|
||||
0x0,0x0,0x0,0x49,0x77,0x38,0x70,0x0,
|
||||
|
||||
};
|
||||
|
||||
#ifdef QT_NAMESPACE
|
||||
# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
|
||||
# define QT_RCC_MANGLE_NAMESPACE0(x) x
|
||||
# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
|
||||
# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
|
||||
# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
|
||||
QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
|
||||
#else
|
||||
# define QT_RCC_PREPEND_NAMESPACE(name) name
|
||||
# define QT_RCC_MANGLE_NAMESPACE(name) name
|
||||
#endif
|
||||
|
||||
#ifdef QT_NAMESPACE
|
||||
namespace QT_NAMESPACE {
|
||||
#endif
|
||||
|
||||
bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
|
||||
bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
|
||||
|
||||
#ifdef QT_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
|
||||
int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
|
||||
{
|
||||
int version = 3;
|
||||
QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
|
||||
(version, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
|
||||
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
|
||||
{
|
||||
int version = 3;
|
||||
QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
|
||||
(version, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct initializer {
|
||||
initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources)(); }
|
||||
~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources)(); }
|
||||
} dummy;
|
||||
}
|
123
ui/Main.qml
Normal file
123
ui/Main.qml
Normal file
@ -0,0 +1,123 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls.Material
|
||||
import QtQuick.Controls.Universal
|
||||
|
||||
ApplicationWindow {
|
||||
id: win
|
||||
visible: false
|
||||
width: 600
|
||||
height: 400
|
||||
flags: Qt.FramelessWindowHint
|
||||
property int timeoutInterval: 5000
|
||||
|
||||
Shortcut {
|
||||
sequence: "Escape"
|
||||
onActivated: Qt.quit()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
forceActiveFocus()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 8
|
||||
border.width: 1
|
||||
border.color: palette.mid
|
||||
color: palette.window
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 5
|
||||
|
||||
TextField {
|
||||
id: searchField
|
||||
width: parent.width
|
||||
placeholderText: "Type to search applications..."
|
||||
selectByMouse: true
|
||||
focus: true
|
||||
|
||||
Keys.onDownPressed: listView.incrementCurrentIndex()
|
||||
Keys.onUpPressed: listView.decrementCurrentIndex()
|
||||
Keys.onReturnPressed: {
|
||||
if (listView.currentItem) {
|
||||
console.log("Selected:", listModel.get(listView.currentIndex).name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
width: parent.width
|
||||
height: parent.height - searchField.height - parent.spacing
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
model: listModel
|
||||
currentIndex: 0
|
||||
highlightFollowsCurrentItem: true
|
||||
|
||||
highlight: Rectangle {
|
||||
color: palette.highlight
|
||||
radius: 4
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: listView.width
|
||||
height: 40
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: parent.hovered ? palette.alternateBase : "transparent"
|
||||
radius: 4
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 10
|
||||
spacing: 10
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
color: palette.button
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "📱"
|
||||
font.pixelSize: 16
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: model.name
|
||||
color: palette.text
|
||||
font.pixelSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
listView.currentIndex = index
|
||||
console.log("Clicked:", model.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: listModel
|
||||
ListElement { name: "Firefox"; exec: "firefox" }
|
||||
ListElement { name: "Terminal"; exec: "gnome-terminal" }
|
||||
ListElement { name: "File Manager"; exec: "nautilus" }
|
||||
ListElement { name: "Text Editor"; exec: "gedit" }
|
||||
ListElement { name: "Calculator"; exec: "gnome-calculator" }
|
||||
}
|
||||
}
|
5
ui/resources.qrc
Normal file
5
ui/resources.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/ui">
|
||||
<file>main.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
Loading…
x
Reference in New Issue
Block a user