|
2 | 2 | #include "UnitSelector.hpp" |
3 | 3 |
|
4 | 4 | #include <QMessageBox> |
5 | | -#include <QStringListModel> |
6 | 5 |
|
7 | 6 | #include <RunAsGPU/Shared/GraphicalUnit.hpp> |
8 | 7 | #include <RunAsGPU/Shared/Runner.hpp> |
9 | 8 |
|
| 9 | +#include "Model/AppListModel.hpp" |
| 10 | +#include "Model/AppListDelegate.hpp" |
| 11 | + |
10 | 12 | #include <filesystem> |
11 | 13 | #include <fstream> |
12 | 14 | #include <iostream> |
| 15 | +#include <QProcess> |
13 | 16 |
|
14 | 17 | namespace fs = std::filesystem; |
15 | 18 |
|
16 | | -static QStringListModel appListModel; |
17 | | -static QStringList appEntries; |
| 19 | +AppListModel *model; |
| 20 | +AppListDelegate *delegate; |
| 21 | + |
| 22 | +void save_default_gpu(const std::vector<GraphicalUnit> &gpu_list, int gpu_unit) { |
| 23 | + const char *home_dir = getenv("HOME"); |
| 24 | + if (!home_dir) |
| 25 | + return; |
| 26 | + |
| 27 | + std::string dir_path = std::string(home_dir) + "/.config/RunAsGPU"; |
| 28 | + if (!fs::exists(dir_path)) { |
| 29 | + if (!fs::create_directory(dir_path)) { |
| 30 | + std::cerr << "Failed to create config directory, exiting application" << std::endl; |
| 31 | + std::abort(); |
| 32 | + } |
| 33 | + } |
| 34 | + |
| 35 | + std::string file_path = std::string(home_dir) + "/.config/RunAsGPU/gpu_identifier"; |
| 36 | + std::ofstream file(file_path); |
| 37 | + if (file.is_open()) { |
| 38 | + file << "GPU_VENDOR_ID=" << std::hex << gpu_list[gpu_unit].vendor << std::endl; |
| 39 | + file << "GPU_DEVICE_ID=" << std::hex << gpu_list[gpu_unit].product << std::endl; |
| 40 | + file.close(); |
| 41 | + } else |
| 42 | + std::cerr << "Failed to open file for writing: " << file_path << std::endl; |
| 43 | +} |
18 | 44 |
|
19 | 45 | int get_default_gpu(const std::vector<GraphicalUnit> &gpu_list) { |
20 | 46 | const char *home_dir = getenv("HOME"); |
21 | 47 | if (!home_dir) |
22 | 48 | return -1; |
23 | 49 |
|
24 | 50 | std::string file_path = std::string(home_dir) + "/.config/RunAsGPU/gpu_identifier"; |
25 | | - if (!fs::exists(file_path)) |
| 51 | + if (!fs::exists(file_path)) { |
| 52 | + save_default_gpu(gpu_list, 0); |
26 | 53 | return 0; |
| 54 | + } |
27 | 55 |
|
28 | 56 | std::string VID, DID; |
29 | 57 | std::ifstream file(file_path); |
@@ -52,34 +80,93 @@ int get_default_gpu(const std::vector<GraphicalUnit> &gpu_list) { |
52 | 80 | return 0; |
53 | 81 | } |
54 | 82 |
|
| 83 | +int gpuUnit; |
| 84 | + |
55 | 85 | void Ui_MainWindow::performLogic() const { |
56 | 86 | std::vector<GraphicalUnit> gpu_list = Runner::ListGraphicalUnits(); |
57 | 87 | if (gpu_list.empty()) { |
58 | 88 | std::cerr << "GPU list empty, exiting..." << std::endl; |
59 | 89 | std::abort(); |
60 | | - return; |
61 | 90 | } |
62 | 91 |
|
63 | | - int gpuUnit = get_default_gpu(gpu_list); |
64 | | - |
65 | | - appListModel.setStringList(appEntries); |
66 | | - appList->setModel(&appListModel); |
| 92 | + gpuUnit = get_default_gpu(gpu_list); |
| 93 | + if (gpuUnit == -1) |
| 94 | + gpuUnit = 0; |
| 95 | + |
| 96 | + model = new AppListModel(appList); |
| 97 | + delegate = new AppListDelegate(appList); |
| 98 | + |
| 99 | + appList->setModel(model); |
| 100 | + appList->setItemDelegate(delegate); |
| 101 | + appList->setViewMode(QListView::ListMode); |
| 102 | + appList->setUniformItemSizes(true); |
| 103 | + appList->setSpacing(5); |
| 104 | + appList->setSelectionMode(QAbstractItemView::SingleSelection); |
| 105 | + appList->setEditTriggers(QAbstractItemView::NoEditTriggers); |
| 106 | + appList->setFocusPolicy(Qt::StrongFocus); |
| 107 | + |
| 108 | + model->addItem(Application("Blender", "3D modeling software", "/usr/bin/blender", |
| 109 | + QIcon("/home/bc100dev/.local/share/icons/kora/apps/scalable/blender.svg"))); |
| 110 | + model->addItem(Application("Firefox", "Mozilla Firefox", "/usr/bin/firefox", |
| 111 | + QIcon("/home/bc100dev/.local/share/icons/kora/apps/scalable/firefox.svg"))); |
| 112 | + |
| 113 | + QObject::connect(appList->selectionModel(), &QItemSelectionModel::currentChanged, |
| 114 | + [&](const QModelIndex ¤t, const QModelIndex &) { |
| 115 | + if (current.isValid()) { |
| 116 | + qDebug() << "Selected App:" << current.data(Qt::DisplayRole).toString(); |
| 117 | + } |
| 118 | + }); |
| 119 | + |
| 120 | + QObject::connect(appList, &QListView::doubleClicked, [&](const QModelIndex &index) { |
| 121 | + if (index.isValid()) { |
| 122 | + QString execPath = index.data(Qt::UserRole).toString(); |
| 123 | + if (!execPath.isEmpty()) |
| 124 | + QProcess::startDetached(execPath); |
| 125 | + } |
| 126 | + }); |
67 | 127 |
|
68 | 128 | // "Add Application" button logic |
69 | 129 | QObject::connect(btnApplicationAdd, &QPushButton::clicked, [&]() { |
70 | | - QString appEntry = "New Application Entry"; // Placeholder for actual selection logic |
71 | | - appEntries.append(appEntry); // Add entry to QStringList |
72 | | - appListModel.setStringList(appEntries); // Update QListView |
| 130 | + // TODO: show app selection dialog |
| 131 | + model->addItem( |
| 132 | + Application(QString("Terminator"), QString("Nice looking Terminal"), QString("/usr/bin/terminator"), |
| 133 | + QIcon("/usr/share/icons/HighContrast/16x16/apps/terminator.png"))); |
73 | 134 | }); |
74 | 135 |
|
75 | 136 | // "Run Application" button logic |
76 | 137 | QObject::connect(btnRun, &QPushButton::clicked, [&]() { |
77 | | - if (appEntries.isEmpty()) { |
78 | | - QMessageBox::warning(nullptr, "Run Application", "No application selected."); |
79 | | - } else { |
80 | | - QMessageBox::information(nullptr, "Run Application", "Running: " + appEntries.first()); |
81 | | - // TODO: Implement actual GPU switching logic |
| 138 | + QModelIndex index = appList->currentIndex(); |
| 139 | + if (!index.isValid()) { |
| 140 | + qDebug() << "No application selected"; |
| 141 | + QMessageBox::warning(nullptr, "No Application selected", "Please select an application to run."); |
| 142 | + return; |
| 143 | + } |
| 144 | + |
| 145 | + QString execPath = index.data(Qt::UserRole).toString(); |
| 146 | + if (execPath.isEmpty()) { |
| 147 | + QMessageBox::warning(nullptr, "Invalid application", "The selected application has no executable path."); |
| 148 | + return; |
82 | 149 | } |
| 150 | + |
| 151 | + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); |
| 152 | + env.insert("DRI_PRIME", QString::number(gpuUnit)); |
| 153 | + |
| 154 | + auto *process = new QProcess(); |
| 155 | + process->setProcessEnvironment(env); |
| 156 | + process->setProgram(execPath); |
| 157 | + process->setArguments(QStringList()); |
| 158 | + |
| 159 | + qDebug() << "Running: " << execPath; |
| 160 | + process->start(); |
| 161 | + if (!process->waitForStarted()) { |
| 162 | + QMessageBox::warning(nullptr, "Execution Failed", "Failed to start application: " + execPath); |
| 163 | + delete process; |
| 164 | + return; |
| 165 | + } |
| 166 | + |
| 167 | + |
| 168 | + process->disconnect(); |
| 169 | + process->setParent(nullptr); |
83 | 170 | }); |
84 | 171 |
|
85 | 172 | // "Select GPU" button logic |
|
0 commit comments