gui: RPC client, download table model, and a live main window
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
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
// The main window. Lane GUI.
|
||||
//
|
||||
// M1 slice: category tree, dialogs and the tray come later. This is the table driven by
|
||||
// mockd, a status-bar connection dot, an offline banner instead of a modal, and the three
|
||||
// selection actions that need no dialog (pause / resume / cancel).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "rpc/Protocol.hpp"
|
||||
|
||||
class QLabel;
|
||||
class QSortFilterProxyModel;
|
||||
class QTreeView;
|
||||
|
||||
namespace velox::gui {
|
||||
|
||||
class DownloadTableModel;
|
||||
namespace rpc {
|
||||
class RpcClient;
|
||||
} // namespace rpc
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(rpc::RpcClient *client, QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void onConnectionState(rpc::ConnectionState state);
|
||||
void onSpeedGlobal(const QJsonObject ¶ms);
|
||||
void updateCounts();
|
||||
|
||||
void pauseSelection();
|
||||
void resumeSelection();
|
||||
void cancelSelection();
|
||||
|
||||
private:
|
||||
QStringList selectedTaskIds() const;
|
||||
void actOnSelection(const char *methodName);
|
||||
void restoreLayout();
|
||||
void saveLayout();
|
||||
|
||||
rpc::RpcClient *client_;
|
||||
DownloadTableModel *model_;
|
||||
QSortFilterProxyModel *proxy_;
|
||||
QTreeView *view_;
|
||||
|
||||
QLabel *connDot_;
|
||||
QLabel *connText_;
|
||||
QLabel *countsLabel_;
|
||||
QWidget *offlineBanner_;
|
||||
|
||||
qint64 globalDownBps_ = 0;
|
||||
};
|
||||
|
||||
} // namespace velox::gui
|
||||
Reference in New Issue
Block a user