Conversation
…roject-skeleton chore: initial project skeleton with C++/Qt6 structure
…roject-skeleton chore: add project documentation and build system
…qs usage in main.cpp
…i-setup ci: add GitHub Actions build workflow for Fedora
- QProcess tabanlı komut çalıştırma (run) - pkexec ile root yetkilendirme (runAsRoot) - Anlık stdout çıktısı için outputLine sinyali - Hata yönetimi ve timeout desteği
- lspci ile NVIDIA GPU tespiti - nvidia-smi ve modinfo ile sürücü versiyon kontrolü - /proc/modules üzerinden kernel modül durumu (nvidia/nouveau) - GpuInfo struct ile tüm bilgileri döndürme
- CpuMonitor: /proc/stat ile gerçek zamanlı CPU yükü ve hwmon sıcaklık - GpuMonitor: nvidia-smi ile GPU sıcaklık, yük ve VRAM izleme - RamMonitor: /proc/meminfo ile RAM kullanımı takibi - Tüm monitörler QTimer tabanlı polling ile çalışır - QML property binding desteği
- RPM Fusion repo otomatik etkinleştirme - akmod-nvidia kurulumu ve akmods derleme - Sürücü kaldırma (akmod-nvidia + xorg-x11-drv-nvidia) - Deep clean (tüm nvidia paketleri + DNF cache) - progressMessage sinyali ile QML'e anlık ilerleme
…nd-runner feat: implement CommandRunner with pkexec support
…a-detection feat: implement NvidiaDetector for GPU detection
…m-monitors feat: implement system monitors (CPU, GPU, RAM)
…r-install feat: implement NvidiaInstaller for driver management
…idiaUpdater) DnfManager: - rpm -q ile paket kurulu mu kontrolü - DNF install/remove/enableRepo/cleanCache işlemleri - root yetkilendirme (pkexec üzerinden) - rpm -qi ile paket bilgisi sorgulama PolkitHelper: - D-Bus PolicyKit1 Authority üzerinden yetki kontrolü - checkAuthorization (dialog göstermeden) ve requestAuthorization (dialoglu) - QML Q_PROPERTY binding (authorized) - PolicyKit policy XML dosyası eklendi NvidiaUpdater: - dnf check-update ile güncelleme kontrolü - Mevcut/yeni versiyon QML property'leri - Güncelleme uygulama (dnf update + akmods) - QML progressMessage/updateFinished sinyalleri Ek: - Polkit policy dosyası: data/polkit/ - CMakeLists.txt: polkit policy install kuralı
CI clang-format check geçmesi için tüm .cpp ve .h dosyaları LLVM default stil ile formatlandı.
…nd-stubs feat: implement remaining backend stubs (DnfManager, PolkitHelper, NvidiaUpdater)
- .clang-format: LLVM tabanlı explicit format config - tests/CMakeLists.txt: Qt6::Test ile test build altyapısı - test_detector: NvidiaDetector sınıf/struct testleri (donanım bağımsız) - test_monitor: CPU/GPU/RAM monitor construction, start/stop, sinyal testleri - ci.yml: BUILD_TESTS=ON ve ctest adımı eklendi
…s-and-format test: add unit tests and .clang-format config
readyReadStandardOutput was consuming the buffer before Result was constructed, causing result.stdout to always be empty. Now accumulates data in a QByteArray buffer for both signal emission and final result.
…o NvidiaDetector - Add Q_PROPERTY for gpuFound, gpuName, driverVersion, driverLoaded, nouveauActive, secureBootEnabled with infoChanged signal - Add Q_INVOKABLE refresh() for QML to re-scan GPU info - Add detectSecureBoot() using mokutil --sb-state - Initialize GpuInfo struct members with defaults
- QProcess doesn't do shell expansion, so $(rpm -E %fedora) was sent as literal text causing 404. Now runs rpm -E %fedora separately and uses QString::arg() to build the URL. - Add early return if Fedora version detection fails. - Add early return if RPM Fusion repo install fails.
- Register NvidiaDetector, NvidiaInstaller, NvidiaUpdater as QML context properties in main.cpp - Build Main.qml with sidebar navigation + StackLayout - Implement SidebarMenu component with page switching - Build DriverPage with GPU info, driver install/remove/update buttons, Secure Boot warning, and status log panel
There was a problem hiding this comment.
Pull request overview
This PR merges the dev branch into main, bringing in the initial end-to-end ro-Control application: a Qt6/QML UI wired to a C++ backend for NVIDIA driver management, system monitoring, packaging, CI, and contributor documentation.
Changes:
- Adds C++ backend modules for NVIDIA detection/installation/update and CPU/GPU/RAM monitoring, plus shared system utilities (CommandRunner, DNF wrapper, polkit helper).
- Introduces QML UI pages (Driver/Monitor/Settings) and app bootstrap wiring (QML engine + context properties).
- Adds project scaffolding: CMake build, tests, CI/release workflows, RPM packaging, and core documentation.
Reviewed changes
Copilot reviewed 46 out of 47 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_monitor.cpp | Adds basic runtime/range tests for CPU/GPU/RAM monitors. |
| tests/test_detector.cpp | Adds basic non-crash/defaults tests for NvidiaDetector. |
| tests/CMakeLists.txt | Adds Qt6 Test executables and ctest registration. |
| src/qml/pages/SettingsPage.qml | Adds Settings/About UI content. |
| src/qml/pages/MonitorPage.qml | Adds live monitor UI bindings (CPU/GPU/RAM). |
| src/qml/pages/DriverPage.qml | Adds driver management UI and wiring to backend signals. |
| src/qml/components/StatCard.qml | Adds placeholder component stub. |
| src/qml/components/SidebarMenu.qml | Adds sidebar menu component (not yet integrated into Main). |
| src/qml/Main.qml | Adds main window UI layout (tabs + pages). |
| src/main.cpp | Creates QApplication, exposes backend objects to QML, loads root QML. |
| src/backend/system/polkit.h | Introduces PolkitHelper interface and action ID constant. |
| src/backend/system/polkit.cpp | Implements D-Bus CheckAuthorization calls. |
| src/backend/system/dnfmanager.h | Adds DNF wrapper interface for installs/removals/queries. |
| src/backend/system/dnfmanager.cpp | Implements DNF wrapper using CommandRunner. |
| src/backend/system/commandrunner.h | Adds shared command execution interface (run/runAsRoot + outputLine). |
| src/backend/system/commandrunner.cpp | Implements blocking QProcess runner with stdout buffering/streaming. |
| src/backend/nvidia/updater.h | Adds NvidiaUpdater QML-facing API for update check/apply. |
| src/backend/nvidia/updater.cpp | Implements update detection via DNF and update apply flow. |
| src/backend/nvidia/installer.h | Adds NvidiaInstaller QML-facing API and agreement gating fields. |
| src/backend/nvidia/installer.cpp | Implements RPM Fusion enablement, install/remove/deep-clean flows. |
| src/backend/nvidia/detector.h | Adds NvidiaDetector QML-facing properties and detection API. |
| src/backend/nvidia/detector.cpp | Implements GPU/driver/session/Secure Boot detection and report generation. |
| src/backend/monitor/rammonitor.h | Adds RamMonitor QML-facing API and properties. |
| src/backend/monitor/rammonitor.cpp | Implements RAM metrics polling via /proc/meminfo. |
| src/backend/monitor/gpumonitor.h | Adds GpuMonitor QML-facing API and properties. |
| src/backend/monitor/gpumonitor.cpp | Implements GPU polling via nvidia-smi. |
| src/backend/monitor/cpumonitor.h | Adds CpuMonitor QML-facing API and properties. |
| src/backend/monitor/cpumonitor.cpp | Implements CPU usage + temperature polling via /proc/stat + sysfs. |
| packaging/rpm/ro-control.spec | Adds initial Fedora RPM spec. |
| docs/DESIGN.md | Documents UI/UX goals and interaction rules. |
| docs/BUILDING.md | Adds Fedora-focused build instructions and test build steps. |
| docs/ARCHITECTURE.md | Documents QML/C++ split, modules, privilege model, and structure. |
| data/polkit/com.github.AcikKaynakGelistirmeToplulugu.rocontrol.policy | Adds PolicyKit action definition for driver management. |
| data/icons/ro-control.metainfo.xml | Adds AppStream metadata. |
| data/icons/ro-control.desktop | Adds desktop entry. |
| README.tr.md | Adds Turkish project README. |
| README.md | Expands English project README. |
| CONTRIBUTING.md | Adds contribution guidelines and branching strategy. |
| CODE_OF_CONDUCT.md | Adds community code of conduct. |
| CMakeLists.txt | Adds full CMake build, QML module setup, install rules, test option. |
| CHANGELOG.md | Adds initial changelog structure and unreleased entries. |
| .gitignore | Adds ignore rules for build artifacts, IDE files, etc. |
| .github/workflows/release.yml | Adds tag-based GitHub Release workflow. |
| .github/workflows/ci.yml | Adds Fedora container CI build/test/format workflow. |
| .github/ISSUE_TEMPLATE/feature_request.md | Adds feature request template. |
| .github/ISSUE_TEMPLATE/bug_report.md | Adds bug report template. |
| .clang-format | Adds clang-format configuration used by CI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Subject: mevcut prosesin PID'si | ||
| QVariantMap subject; | ||
| subject[QStringLiteral("pid")] = static_cast<quint32>(getpid()); | ||
| subject[QStringLiteral("start-time")] = static_cast<quint64>(0); | ||
|
|
There was a problem hiding this comment.
The PolicyKit unix-process subject includes a start-time field specifically to prevent PID-reuse attacks and identify the process instance. Passing start-time = 0 is unlikely to be accepted by polkit and can make authorization checks unreliable. Consider reading the real process start time (e.g., from /proc/self/stat) and passing that value.
| void GpuMonitor::refresh() { | ||
| QProcess process; | ||
| process.start("nvidia-smi", | ||
| {"--query-gpu=name,temperature.gpu,utilization.gpu,memory.used," | ||
| "memory.total", | ||
| "--format=csv,noheader,nounits"}); | ||
|
|
There was a problem hiding this comment.
GpuMonitor executes nvidia-smi via QProcess directly, which contradicts the CommandRunner contract (“no module calls system commands directly”) and makes command execution behavior inconsistent across backend modules (streaming output, stderr capture, pkexec handling, etc.). Consider switching this to CommandRunner::run() for consistency and easier testing/observability.
| setProprietaryAgreement(false, QString()); | ||
| } | ||
|
|
||
| void NvidiaInstaller::install() { installProprietary(false); } |
There was a problem hiding this comment.
NvidiaInstaller::install() calls installProprietary(false). If the EULA/proprietary agreement is required, this guarantees install() fails even when the user intends a normal install. Either remove/privatize install() (and only expose installProprietary(bool)), or route install() through the same consent mechanism used by the UI.
| void NvidiaInstaller::install() { installProprietary(false); } | |
| void NvidiaInstaller::install() { installProprietary(true); } |
| void NvidiaInstaller::installProprietary(bool agreementAccepted) { | ||
| refreshProprietaryAgreement(); | ||
|
|
||
| if (m_proprietaryAgreementRequired && !agreementAccepted) { | ||
| emit installFinished( | ||
| false, | ||
| QStringLiteral("Kurulumdan once lisans/sozlesme onayi gereklidir.")); | ||
| return; | ||
| } | ||
|
|
||
| CommandRunner runner; | ||
|
|
||
| connect(&runner, &CommandRunner::outputLine, this, | ||
| &NvidiaInstaller::progressMessage); | ||
|
|
There was a problem hiding this comment.
installProprietary() runs long, blocking root operations (DNF installs, akmods, grubby) directly inside a Q_INVOKABLE method called from QML. This will freeze the UI event loop during installs/updates. Consider moving these operations to a worker thread / QtConcurrent or using asynchronous QProcess, and reporting progress via signals as you already do with progressMessage.
| // Ana QML dosyasını yükle | ||
| using namespace Qt::StringLiterals; | ||
| const QUrl url(u"qrc:/rocontrol/src/qml/Main.qml"_s); | ||
|
|
There was a problem hiding this comment.
qt_add_qml_module() resources are normally under the qrc:/qt/qml/<URI>/... prefix. Loading qrc:/rocontrol/src/qml/Main.qml is likely the wrong URL, which would make the app fail to start. Consider using engine.loadFromModule("rocontrol", "Main") (preferred) or update the QRC URL to the actual generated prefix.
| runner.runAsRoot(QStringLiteral("akmods"), {QStringLiteral("--force")}); | ||
|
|
There was a problem hiding this comment.
The result of akmods --force is ignored. If akmods fails, the method still proceeds and may emit a success message, leaving the system in a broken state. Capture and check the return value and fail the install with a clear message when it doesn’t succeed.
| runner.runAsRoot(QStringLiteral("akmods"), {QStringLiteral("--force")}); | |
| result = runner.runAsRoot(QStringLiteral("akmods"), | |
| {QStringLiteral("--force")}); | |
| if (!result.success()) { | |
| emit installFinished(false, | |
| QStringLiteral("Kernel modulu derlenemedi (akmods " | |
| "--force) basarisiz: ") + | |
| result.stderr); | |
| return; | |
| } |
| runner.runAsRoot(QStringLiteral("akmods"), {QStringLiteral("--force")}); | ||
|
|
||
| const QString sessionType = | ||
| qEnvironmentVariable("XDG_SESSION_TYPE").trimmed().toLower(); | ||
| if (sessionType == QStringLiteral("wayland")) { | ||
| emit progressMessage(QStringLiteral( | ||
| "Wayland tespit edildi: nvidia-drm.modeset=1 ayari guncelleniyor...")); | ||
| runner.runAsRoot(QStringLiteral("grubby"), | ||
| {QStringLiteral("--update-kernel=ALL"), | ||
| QStringLiteral("--args=nvidia-drm.modeset=1")}); |
There was a problem hiding this comment.
applyUpdate() ignores failures from the post-update steps (akmods --force and grubby --update-kernel=ALL ...). If either fails, the UI will still report a successful update even though the system may not boot into a working Wayland setup. Capture and validate these command results and surface errors via updateFinished(false, ...).
| runner.runAsRoot(QStringLiteral("akmods"), {QStringLiteral("--force")}); | |
| const QString sessionType = | |
| qEnvironmentVariable("XDG_SESSION_TYPE").trimmed().toLower(); | |
| if (sessionType == QStringLiteral("wayland")) { | |
| emit progressMessage(QStringLiteral( | |
| "Wayland tespit edildi: nvidia-drm.modeset=1 ayari guncelleniyor...")); | |
| runner.runAsRoot(QStringLiteral("grubby"), | |
| {QStringLiteral("--update-kernel=ALL"), | |
| QStringLiteral("--args=nvidia-drm.modeset=1")}); | |
| const auto akmodsResult = | |
| runner.runAsRoot(QStringLiteral("akmods"), {QStringLiteral("--force")}); | |
| if (!akmodsResult.success()) { | |
| emit updateFinished(false, QStringLiteral("Kernel modülü derleme başarısız: ") | |
| + akmodsResult.stderr); | |
| return; | |
| } | |
| const QString sessionType = | |
| qEnvironmentVariable("XDG_SESSION_TYPE").trimmed().toLower(); | |
| if (sessionType == QStringLiteral("wayland")) { | |
| emit progressMessage(QStringLiteral( | |
| "Wayland tespit edildi: nvidia-drm.modeset=1 ayari guncelleniyor...")); | |
| const auto grubbyResult = runner.runAsRoot( | |
| QStringLiteral("grubby"), | |
| {QStringLiteral("--update-kernel=ALL"), | |
| QStringLiteral("--args=nvidia-drm.modeset=1")}); | |
| if (!grubbyResult.success()) { | |
| emit updateFinished( | |
| false, | |
| QStringLiteral("grubby ile kernel parametreleri güncellenemedi: ") | |
| + grubbyResult.stderr); | |
| return; | |
| } |
| StackLayout { | ||
| Layout.fillWidth: true | ||
| Layout.fillHeight: true | ||
| currentIndex: tabs.currentIndex | ||
|
|
||
| DriverPage {} | ||
| MonitorPage {} | ||
| SettingsPage { | ||
| darkMode: root.darkMode | ||
| } |
There was a problem hiding this comment.
DriverPage, MonitorPage, and SettingsPage are referenced as types but Main.qml doesn’t import the local QML module or the pages/ directory. Unless those types are in the same directory/import scope, this will error at runtime with “is not a type”. Add an explicit import (e.g., import "pages" or import the module URI) so these components can be resolved reliably.
|
|
||
| <div align="center"> | ||
|
|
||
|  |
There was a problem hiding this comment.
The Turkish README references data/icons/hicolor/scalable/apps/ro-control.svg, but that file doesn’t exist in the repository (only data/icons/ro-control.desktop and data/icons/ro-control.metainfo.xml are present). Either add the referenced icon file(s) or update the README to point at an existing asset.
|  | |
|  |
| install(FILES data/icons/ro-control.desktop | ||
| DESTINATION ${CMAKE_INSTALL_DATADIR}/applications | ||
| ) | ||
|
|
||
| install(DIRECTORY data/icons/ | ||
| DESTINATION ${CMAKE_INSTALL_DATADIR}/icons | ||
| ) | ||
|
|
||
| install(FILES data/icons/ro-control.metainfo.xml | ||
| DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo | ||
| ) |
There was a problem hiding this comment.
install(DIRECTORY data/icons/ DESTINATION .../icons) currently installs the entire data/icons directory into the icon theme path, but that directory also contains the .desktop file and AppStream metadata. This will place non-icon files under ${datadir}/icons and likely duplicates files also installed via install(FILES ...). Consider reorganizing assets (e.g., data/icons/hicolor/... for icons, data/applications/ for .desktop, data/metainfo/ for AppStream) and only install actual icon theme directories into ${datadir}/icons.
No description provided.