First vertical slice of velox-gui, built entirely against tools/mockd (no daemon dependency): - rpc/: RpcConnection runs a QLocalSocket on a worker thread with newline-delimited JSON-RPC framing, drives the session.hello / session.subscribe handshake, and reconnects with exponential backoff (250 ms -> 8 s). RpcClient is the main-thread face: marshals calls onto the worker, delivers replies as main-thread callbacks, re-emits server notifications as typed Qt signals, and issues the one-shot download.list on reaching Connected. - models/DownloadTableModel: QAbstractTableModel over TaskSummary. A progress batch is a row patch with a narrow dataChanged over the value columns only; beginResetModel() is reserved for the initial load and a reconnect resync. - widgets/ProgressDelegate: in-cell progress bar for the Status column. - mainwindow/MainWindow: the table, a status-bar connection dot, an offline banner instead of a modal, dialog-free pause/resume/stop actions, and QSettings column/geometry persistence. - gui/CMakeLists.txt links velox::proto (never velox::core, ADR 0009) and self-guards on the veloxproto target so main keeps configuring if it is ever absent again. - i18n from the first commit: every string via tr(), plus an Arabic .ts stub for the RTL check. - tests/: headless QTest for the model — proves the progress patch is a narrow dataChanged and never resets the model. Verified end-to-end against `mockd --tasks 300`: handshake, initial list, live progress batches applied to the model, and a clean Reconnecting -> Connected recovery when mockd is bounced mid-run. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_016Ne28kx4VreeBWZv82Nksd
74 lines
2.3 KiB
C++
74 lines
2.3 KiB
C++
// The main-thread face of the RPC client. Lane GUI.
|
|
//
|
|
// Everything the rest of the GUI touches. It owns a worker QThread with an RpcConnection
|
|
// on it; calls are marshalled onto that thread and their replies come back as a callback
|
|
// invoked on the main thread. Server notifications are re-emitted as typed Qt signals.
|
|
//
|
|
// On reaching Connected it issues the one-shot download.list itself and emits
|
|
// taskListReset — the table never re-fetches after that, it is maintained from events
|
|
// (docs/03-gui-spec.md §1).
|
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
|
|
#include <QHash>
|
|
#include <QJsonArray>
|
|
#include <QJsonObject>
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QThread>
|
|
|
|
#include "rpc/Protocol.hpp"
|
|
|
|
namespace velox::gui::rpc {
|
|
|
|
class RpcConnection;
|
|
|
|
class RpcClient : public QObject {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit RpcClient(QString socketPath, QObject *parent = nullptr);
|
|
~RpcClient() override;
|
|
|
|
ConnectionState state() const noexcept { return state_; }
|
|
|
|
/// Fire a JSON-RPC call. `cb` runs on the main thread; it always runs exactly once,
|
|
/// with reply.ok() == false if the socket was down or the daemon returned an error.
|
|
void call(const QString &methodName, const QJsonObject ¶ms,
|
|
std::function<void(const RpcReply &)> cb = {});
|
|
|
|
public slots:
|
|
void start();
|
|
void stop();
|
|
|
|
signals:
|
|
void stateChanged(velox::gui::rpc::ConnectionState state);
|
|
/// Full replacement of the table's contents (initial load / reconnect resync).
|
|
void taskListReset(const QJsonArray &items);
|
|
void taskAdded(const QJsonObject &summary);
|
|
void taskProgress(const QJsonArray &tasks);
|
|
void taskStateChanged(const QJsonObject ¶ms);
|
|
void taskRemoved(const QString &taskId);
|
|
void speedGlobal(const QJsonObject ¶ms);
|
|
void notify(const QJsonObject ¶ms);
|
|
|
|
private slots:
|
|
void onConnectionState(int state);
|
|
void onNotification(const QString &methodName, const QJsonObject ¶ms);
|
|
void onCallCompleted(quint64 tag, const QJsonObject &envelope);
|
|
|
|
private:
|
|
void requestInitialList();
|
|
|
|
QThread thread_;
|
|
RpcConnection *conn_ = nullptr; // owned by thread_ affinity, deleted on thread finish
|
|
ConnectionState state_ = ConnectionState::Disconnected;
|
|
|
|
quint64 nextTag_ = 1;
|
|
QHash<quint64, std::function<void(const RpcReply &)>> callbacks_;
|
|
};
|
|
|
|
} // namespace velox::gui::rpc
|