2026-04-24 20:20:24 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <QObject>
|
|
|
|
|
#include <QVariantList>
|
2026-04-27 15:06:59 +08:00
|
|
|
#include <QVariantMap>
|
2026-04-24 20:20:24 +08:00
|
|
|
#include "LocalSendCore/DiscoveryManager.h"
|
|
|
|
|
#include "LocalSendCore/HttpServer.h"
|
|
|
|
|
#include "LocalSendCore/HttpClient.h"
|
|
|
|
|
#include "LocalSendCore/SessionManager.h"
|
|
|
|
|
#include "LocalSendCore/SecurityContext.h"
|
|
|
|
|
#include "LocalSendCore/Settings.h"
|
|
|
|
|
|
|
|
|
|
class AppController : public QObject
|
|
|
|
|
{
|
|
|
|
|
Q_OBJECT
|
|
|
|
|
Q_PROPERTY(QString alias READ alias WRITE setAlias NOTIFY aliasChanged)
|
|
|
|
|
Q_PROPERTY(quint16 port READ port WRITE setPort NOTIFY portChanged)
|
|
|
|
|
Q_PROPERTY(QVariantList devices READ devices NOTIFY devicesChanged)
|
|
|
|
|
Q_PROPERTY(bool serverRunning READ serverRunning NOTIFY serverRunningChanged)
|
2026-04-27 15:06:59 +08:00
|
|
|
Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged)
|
|
|
|
|
Q_PROPERTY(bool quickSave READ quickSave WRITE setQuickSave NOTIFY quickSaveChanged)
|
2026-08-24 16:15:41 +08:00
|
|
|
Q_PROPERTY(bool autoFinish READ autoFinish WRITE setAutoFinish NOTIFY autoFinishChanged)
|
2026-04-27 16:08:40 +08:00
|
|
|
Q_PROPERTY(bool sending READ sending NOTIFY sendingChanged)
|
|
|
|
|
Q_PROPERTY(double sendProgress READ sendProgress NOTIFY sendProgressChanged)
|
2026-04-28 15:21:30 +08:00
|
|
|
Q_PROPERTY(QString currentSendFileName READ currentSendFileName NOTIFY sendProgressChanged)
|
|
|
|
|
Q_PROPERTY(int currentSendFileIndex READ currentSendFileIndex NOTIFY sendProgressChanged)
|
|
|
|
|
Q_PROPERTY(int totalSendFiles READ totalSendFiles NOTIFY sendingChanged)
|
2026-04-27 17:38:50 +08:00
|
|
|
Q_PROPERTY(QVariantList pendingFiles READ pendingFiles NOTIFY pendingFilesChanged)
|
|
|
|
|
Q_PROPERTY(bool hasPendingFiles READ hasPendingFiles NOTIFY pendingFilesChanged)
|
2026-04-28 12:01:35 +08:00
|
|
|
Q_PROPERTY(QString receivePin READ receivePin WRITE setReceivePin NOTIFY receivePinChanged)
|
2026-04-28 15:21:30 +08:00
|
|
|
Q_PROPERTY(bool receiving READ receiving NOTIFY receivingChanged)
|
|
|
|
|
Q_PROPERTY(double receiveProgress READ receiveProgress NOTIFY receiveProgressChanged)
|
|
|
|
|
Q_PROPERTY(QString currentReceiveFileName READ currentReceiveFileName NOTIFY receiveProgressChanged)
|
|
|
|
|
Q_PROPERTY(int currentReceiveFileIndex READ currentReceiveFileIndex NOTIFY receiveProgressChanged)
|
|
|
|
|
Q_PROPERTY(int totalReceiveFiles READ totalReceiveFiles NOTIFY receivingChanged)
|
|
|
|
|
Q_PROPERTY(QString currentReceiveSenderAlias READ currentReceiveSenderAlias NOTIFY receivingChanged)
|
2026-05-26 15:38:52 +08:00
|
|
|
Q_PROPERTY(QString deviceType READ deviceType WRITE setDeviceType NOTIFY deviceTypeChanged)
|
2026-05-26 17:30:10 +08:00
|
|
|
Q_PROPERTY(bool https READ https WRITE setHttps NOTIFY httpsChanged)
|
2026-04-24 20:20:24 +08:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit AppController(QObject* parent = nullptr);
|
|
|
|
|
~AppController() override;
|
|
|
|
|
|
|
|
|
|
void initialize();
|
|
|
|
|
|
|
|
|
|
QString alias() const;
|
|
|
|
|
void setAlias(const QString& alias);
|
|
|
|
|
|
|
|
|
|
quint16 port() const;
|
|
|
|
|
void setPort(quint16 port);
|
|
|
|
|
|
2026-04-27 15:06:59 +08:00
|
|
|
QString downloadPath() const;
|
|
|
|
|
void setDownloadPath(const QString& path);
|
|
|
|
|
|
|
|
|
|
bool quickSave() const;
|
|
|
|
|
void setQuickSave(bool enabled);
|
|
|
|
|
|
2026-08-24 16:15:41 +08:00
|
|
|
bool autoFinish() const;
|
|
|
|
|
void setAutoFinish(bool enabled);
|
|
|
|
|
|
2026-04-24 20:20:24 +08:00
|
|
|
QVariantList devices() const;
|
|
|
|
|
bool serverRunning() const;
|
|
|
|
|
|
2026-04-27 16:08:40 +08:00
|
|
|
bool sending() const;
|
|
|
|
|
double sendProgress() const;
|
2026-04-28 15:21:30 +08:00
|
|
|
QString currentSendFileName() const;
|
|
|
|
|
int currentSendFileIndex() const;
|
|
|
|
|
int totalSendFiles() const;
|
2026-04-27 17:38:50 +08:00
|
|
|
QVariantList pendingFiles() const;
|
|
|
|
|
bool hasPendingFiles() const;
|
2026-04-28 12:01:35 +08:00
|
|
|
QString receivePin() const;
|
|
|
|
|
void setReceivePin(const QString& pin);
|
2026-04-27 16:08:40 +08:00
|
|
|
|
2026-04-28 15:21:30 +08:00
|
|
|
bool receiving() const;
|
|
|
|
|
double receiveProgress() const;
|
|
|
|
|
QString currentReceiveFileName() const;
|
|
|
|
|
int currentReceiveFileIndex() const;
|
|
|
|
|
int totalReceiveFiles() const;
|
|
|
|
|
QString currentReceiveSenderAlias() const;
|
|
|
|
|
|
2026-05-26 15:38:52 +08:00
|
|
|
QString deviceType() const;
|
|
|
|
|
void setDeviceType(const QString& type);
|
|
|
|
|
|
2026-05-26 17:30:10 +08:00
|
|
|
bool https() const;
|
|
|
|
|
void setHttps(bool enabled);
|
|
|
|
|
|
2026-04-24 20:20:24 +08:00
|
|
|
Q_INVOKABLE void startDiscovery();
|
|
|
|
|
Q_INVOKABLE void stopDiscovery();
|
|
|
|
|
Q_INVOKABLE void refreshDevices();
|
2026-04-27 15:06:59 +08:00
|
|
|
|
|
|
|
|
Q_INVOKABLE void acceptReceive(const QString& sessionId);
|
|
|
|
|
Q_INVOKABLE void declineReceive(const QString& sessionId);
|
2026-04-28 15:21:30 +08:00
|
|
|
Q_INVOKABLE void cancelReceive();
|
2026-04-27 16:08:40 +08:00
|
|
|
|
|
|
|
|
Q_INVOKABLE void sendFiles(const QString& deviceFingerprint, const QStringList& filePaths);
|
2026-04-27 17:38:50 +08:00
|
|
|
Q_INVOKABLE void sendTo(const QString& deviceFingerprint);
|
2026-05-26 16:33:57 +08:00
|
|
|
Q_INVOKABLE void sendToAddress(const QString& address);
|
2026-04-27 16:08:40 +08:00
|
|
|
Q_INVOKABLE void cancelSend();
|
2026-04-27 17:38:50 +08:00
|
|
|
Q_INVOKABLE void addFiles(const QStringList& filePaths);
|
|
|
|
|
Q_INVOKABLE void removePendingFile(int index);
|
|
|
|
|
Q_INVOKABLE void clearPendingFiles();
|
2026-04-28 12:01:35 +08:00
|
|
|
Q_INVOKABLE void retryWithPin(const QString& pin);
|
2026-08-24 16:15:41 +08:00
|
|
|
Q_INVOKABLE void copyToClipboard(const QString& text);
|
|
|
|
|
Q_INVOKABLE void openLink(const QString& url);
|
2026-04-24 20:20:24 +08:00
|
|
|
|
|
|
|
|
signals:
|
|
|
|
|
void aliasChanged();
|
|
|
|
|
void portChanged();
|
2026-04-27 15:06:59 +08:00
|
|
|
void downloadPathChanged();
|
|
|
|
|
void quickSaveChanged();
|
2026-04-24 20:20:24 +08:00
|
|
|
void devicesChanged();
|
|
|
|
|
void serverRunningChanged();
|
2026-08-24 16:15:41 +08:00
|
|
|
void autoFinishChanged();
|
2026-04-27 16:08:40 +08:00
|
|
|
void sendingChanged();
|
|
|
|
|
void sendProgressChanged();
|
2026-04-27 17:38:50 +08:00
|
|
|
void pendingFilesChanged();
|
2026-04-27 15:06:59 +08:00
|
|
|
void receiveRequest(const QString& sessionId, const QString& senderAlias,
|
2026-08-24 16:15:41 +08:00
|
|
|
const QString& senderIp, const QVariantList& files, const QString& message);
|
2026-04-27 15:06:59 +08:00
|
|
|
void receiveProgress(const QString& sessionId, const QString& fileId, double progress);
|
|
|
|
|
void receiveCompleted(const QString& sessionId);
|
|
|
|
|
void receiveError(const QString& sessionId, const QString& error);
|
2026-04-24 20:20:24 +08:00
|
|
|
void sendCompleted(const QString& sessionId);
|
2026-04-27 16:08:40 +08:00
|
|
|
void sendError(const QString& error);
|
2026-04-28 15:21:30 +08:00
|
|
|
void sendCanceled();
|
2026-04-28 12:01:35 +08:00
|
|
|
void pinRequired(bool firstAttempt);
|
|
|
|
|
void receivePinChanged();
|
2026-04-28 15:21:30 +08:00
|
|
|
void receivingChanged();
|
|
|
|
|
void receiveProgressChanged();
|
2026-05-26 15:38:52 +08:00
|
|
|
void deviceTypeChanged();
|
2026-05-26 17:30:10 +08:00
|
|
|
void httpsChanged();
|
2026-04-24 20:20:24 +08:00
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
|
void onDeviceDiscovered(const LocalSend::Device& device);
|
|
|
|
|
void onDeviceLost(const QString& fingerprint);
|
2026-04-27 15:06:59 +08:00
|
|
|
void onRegisterRequest(const LocalSend::RegisterDto& dto, const QHostAddress& sender);
|
|
|
|
|
void onPrepareUploadRequest(const QString& httpSessionId,
|
|
|
|
|
const LocalSend::PrepareUploadRequestDto& dto,
|
|
|
|
|
const QHostAddress& sender);
|
|
|
|
|
void onUploadRequest(const QString& sessionId, const QString& fileId,
|
|
|
|
|
const QString& token, const QByteArray& data);
|
|
|
|
|
void onSessionAccepted(const QString& sessionId, const QMap<QString, QString>& tokens);
|
|
|
|
|
void onSessionDeclined(const QString& sessionId);
|
|
|
|
|
void onReceiveProgress(const QString& sessionId, const QString& fileId, double progress);
|
|
|
|
|
void onReceiveCompleted(const QString& sessionId);
|
2026-04-27 16:08:40 +08:00
|
|
|
|
|
|
|
|
void onPrepareUploadResponse(const LocalSend::PrepareUploadResponseDto& response);
|
|
|
|
|
void onPrepareUploadError(const QString& error);
|
2026-04-28 12:01:35 +08:00
|
|
|
void onPrepareUploadPinRequired();
|
|
|
|
|
void onPrepareUploadTooManyAttempts();
|
2026-04-27 16:08:40 +08:00
|
|
|
void onUploadProgress(qint64 sent, qint64 total);
|
|
|
|
|
void onUploadCompleted();
|
|
|
|
|
void onUploadError(const QString& error);
|
2026-05-26 16:33:57 +08:00
|
|
|
void onManualRegisterCompleted(const LocalSend::InfoDto& peerInfo);
|
|
|
|
|
void onManualRegisterError(const QString& error);
|
2026-04-24 20:20:24 +08:00
|
|
|
|
2026-04-28 15:21:30 +08:00
|
|
|
void onCancelRequest(const QString& sessionId);
|
|
|
|
|
|
2026-04-24 20:20:24 +08:00
|
|
|
private:
|
|
|
|
|
LocalSend::Settings* m_settings = nullptr;
|
|
|
|
|
LocalSend::SecurityContext* m_security = nullptr;
|
|
|
|
|
LocalSend::DiscoveryManager* m_discovery = nullptr;
|
|
|
|
|
LocalSend::HttpServer* m_server = nullptr;
|
|
|
|
|
LocalSend::SessionManager* m_sessions = nullptr;
|
2026-04-27 16:08:40 +08:00
|
|
|
LocalSend::HttpClient* m_httpClient = nullptr;
|
2026-04-24 20:20:24 +08:00
|
|
|
|
|
|
|
|
QMap<QString, LocalSend::Device> m_devices;
|
|
|
|
|
|
2026-04-27 16:08:40 +08:00
|
|
|
QString m_currentSendSessionId;
|
|
|
|
|
QString m_currentSendFileId;
|
|
|
|
|
QString m_currentSendDeviceFingerprint;
|
2026-04-27 17:38:50 +08:00
|
|
|
QStringList m_pendingSendPaths;
|
|
|
|
|
QVariantList m_pendingFilesList;
|
2026-04-27 16:08:40 +08:00
|
|
|
int m_currentFileIndex = 0;
|
|
|
|
|
double m_sendProgress = 0.0;
|
2026-04-28 12:01:35 +08:00
|
|
|
bool m_pinFirstAttempt = true;
|
2026-04-27 16:08:40 +08:00
|
|
|
|
2026-04-28 15:21:30 +08:00
|
|
|
QString m_currentReceiveSessionId;
|
|
|
|
|
double m_receiveProgressValue = 0.0;
|
|
|
|
|
QString m_currentReceiveFileName;
|
|
|
|
|
int m_currentReceiveFileIndex = 0;
|
|
|
|
|
int m_totalReceiveFiles = 0;
|
|
|
|
|
qint64 m_totalReceiveSize = 0;
|
|
|
|
|
qint64 m_receivedSize = 0;
|
|
|
|
|
QString m_currentReceiveSenderAlias;
|
|
|
|
|
QMap<QString, QString> m_receiveFileNames;
|
|
|
|
|
|
2026-04-24 20:20:24 +08:00
|
|
|
LocalSend::InfoDto buildInfoDto() const;
|
2026-04-27 15:06:59 +08:00
|
|
|
QString generateUniqueFilePath(const QString& baseDir, const QString& fileName) const;
|
2026-04-27 16:08:40 +08:00
|
|
|
void sendNextFile();
|
|
|
|
|
LocalSend::RegisterDto buildRegisterDto() const;
|
2026-04-28 15:21:30 +08:00
|
|
|
void resetSendState();
|
|
|
|
|
void resetReceiveState();
|
2026-05-26 16:33:57 +08:00
|
|
|
|
|
|
|
|
bool m_manualSendPending = false;
|
|
|
|
|
LocalSend::Device m_manualSendDevice;
|
2026-04-24 20:20:24 +08:00
|
|
|
};
|