init commit
This commit is contained in:
151
src/app/AppController.cpp
Normal file
151
src/app/AppController.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "AppController.h"
|
||||
#include <QJsonArray>
|
||||
|
||||
AppController::AppController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_settings(new LocalSend::Settings(this))
|
||||
, m_security(new LocalSend::SecurityContext(this))
|
||||
, m_discovery(new LocalSend::DiscoveryManager(this))
|
||||
, m_server(new LocalSend::HttpServer(this))
|
||||
, m_sessions(new LocalSend::SessionManager(this))
|
||||
{
|
||||
}
|
||||
|
||||
AppController::~AppController()
|
||||
{
|
||||
stopDiscovery();
|
||||
}
|
||||
|
||||
void AppController::initialize()
|
||||
{
|
||||
m_security->initialize();
|
||||
|
||||
LocalSend::InfoDto info = buildInfoDto();
|
||||
m_server->setLocalInfo(info, m_security->fingerprint());
|
||||
m_discovery->setLocalInfo(info, m_security->fingerprint(), m_settings->port(),
|
||||
m_settings->https() ? LocalSend::ProtocolType::Https : LocalSend::ProtocolType::Http);
|
||||
|
||||
if (m_server->start(m_settings->port(), m_settings->https())) {
|
||||
emit serverRunningChanged();
|
||||
}
|
||||
|
||||
connect(m_discovery, &LocalSend::DiscoveryManager::deviceDiscovered,
|
||||
this, &AppController::onDeviceDiscovered);
|
||||
connect(m_discovery, &LocalSend::DiscoveryManager::deviceLost,
|
||||
this, &AppController::onDeviceLost);
|
||||
connect(m_server, &LocalSend::HttpServer::prepareUploadRequest,
|
||||
this, &AppController::onPrepareUploadRequest);
|
||||
|
||||
startDiscovery();
|
||||
}
|
||||
|
||||
LocalSend::InfoDto AppController::buildInfoDto() const
|
||||
{
|
||||
LocalSend::InfoDto info;
|
||||
info.alias = m_settings->alias();
|
||||
info.version = m_settings->version();
|
||||
info.deviceModel = m_settings->deviceModel();
|
||||
info.deviceType = m_settings->deviceType();
|
||||
info.download = false;
|
||||
return info;
|
||||
}
|
||||
|
||||
QString AppController::alias() const
|
||||
{
|
||||
return m_settings->alias();
|
||||
}
|
||||
|
||||
void AppController::setAlias(const QString& alias)
|
||||
{
|
||||
if (m_settings->alias() != alias) {
|
||||
m_settings->setAlias(alias);
|
||||
emit aliasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
quint16 AppController::port() const
|
||||
{
|
||||
return m_settings->port();
|
||||
}
|
||||
|
||||
void AppController::setPort(quint16 port)
|
||||
{
|
||||
if (m_settings->port() != port) {
|
||||
m_settings->setPort(port);
|
||||
emit portChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QVariantList AppController::devices() const
|
||||
{
|
||||
QVariantList result;
|
||||
for (const LocalSend::Device& device : m_devices) {
|
||||
QVariantMap map;
|
||||
map[QStringLiteral("ip")] = device.ip;
|
||||
map[QStringLiteral("port")] = device.port;
|
||||
map[QStringLiteral("alias")] = device.alias;
|
||||
map[QStringLiteral("fingerprint")] = device.fingerprint;
|
||||
map[QStringLiteral("deviceModel")] = device.deviceModel;
|
||||
map[QStringLiteral("deviceType")] = LocalSend::deviceTypeToString(device.deviceType);
|
||||
result.append(map);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AppController::serverRunning() const
|
||||
{
|
||||
return m_server->isRunning();
|
||||
}
|
||||
|
||||
void AppController::startDiscovery()
|
||||
{
|
||||
m_discovery->start();
|
||||
}
|
||||
|
||||
void AppController::stopDiscovery()
|
||||
{
|
||||
m_discovery->stop();
|
||||
}
|
||||
|
||||
void AppController::refreshDevices()
|
||||
{
|
||||
m_discovery->startScan();
|
||||
}
|
||||
|
||||
void AppController::onDeviceDiscovered(const LocalSend::Device& device)
|
||||
{
|
||||
m_devices.insert(device.fingerprint, device);
|
||||
emit devicesChanged();
|
||||
}
|
||||
|
||||
void AppController::onDeviceLost(const QString& fingerprint)
|
||||
{
|
||||
m_devices.remove(fingerprint);
|
||||
emit devicesChanged();
|
||||
}
|
||||
|
||||
void AppController::onPrepareUploadRequest(const LocalSend::PrepareUploadRequestDto& dto,
|
||||
const QHostAddress& sender)
|
||||
{
|
||||
LocalSend::Device device;
|
||||
device.ip = sender.toString();
|
||||
device.alias = dto.info.alias;
|
||||
device.fingerprint = dto.info.fingerprint;
|
||||
device.deviceModel = dto.info.deviceModel;
|
||||
device.deviceType = dto.info.deviceType;
|
||||
device.version = dto.info.version;
|
||||
|
||||
QString sessionId = m_sessions->createReceiveSession(device, dto.files);
|
||||
|
||||
QVariantList filesList;
|
||||
for (auto it = dto.files.constBegin(); it != dto.files.constEnd(); ++it) {
|
||||
QVariantMap file;
|
||||
file[QStringLiteral("id")] = it.key();
|
||||
file[QStringLiteral("fileName")] = it.value().fileName;
|
||||
file[QStringLiteral("size")] = it.value().size;
|
||||
file[QStringLiteral("fileType")] = it.value().fileType;
|
||||
filesList.append(file);
|
||||
}
|
||||
|
||||
emit receiveRequest(sessionId, dto.info.alias, filesList);
|
||||
}
|
||||
63
src/app/AppController.h
Normal file
63
src/app/AppController.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantList>
|
||||
#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)
|
||||
|
||||
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);
|
||||
|
||||
QVariantList devices() const;
|
||||
bool serverRunning() const;
|
||||
|
||||
Q_INVOKABLE void startDiscovery();
|
||||
Q_INVOKABLE void stopDiscovery();
|
||||
Q_INVOKABLE void refreshDevices();
|
||||
|
||||
signals:
|
||||
void aliasChanged();
|
||||
void portChanged();
|
||||
void devicesChanged();
|
||||
void serverRunningChanged();
|
||||
void receiveRequest(const QString& sessionId, const QString& senderAlias, const QVariantList& files);
|
||||
void sendProgress(const QString& sessionId, double progress);
|
||||
void sendCompleted(const QString& sessionId);
|
||||
|
||||
private slots:
|
||||
void onDeviceDiscovered(const LocalSend::Device& device);
|
||||
void onDeviceLost(const QString& fingerprint);
|
||||
void onPrepareUploadRequest(const LocalSend::PrepareUploadRequestDto& dto, const QHostAddress& sender);
|
||||
|
||||
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;
|
||||
|
||||
QMap<QString, LocalSend::Device> m_devices;
|
||||
|
||||
LocalSend::InfoDto buildInfoDto() const;
|
||||
};
|
||||
9
src/app/Application.cpp
Normal file
9
src/app/Application.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "Application.h"
|
||||
|
||||
Application::Application(int& argc, char** argv)
|
||||
: QGuiApplication(argc, argv)
|
||||
{
|
||||
setApplicationName(QStringLiteral("LocalSendQt"));
|
||||
setApplicationVersion(QStringLiteral("1.0.0"));
|
||||
setOrganizationName(QStringLiteral("LocalSend"));
|
||||
}
|
||||
12
src/app/Application.h
Normal file
12
src/app/Application.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QIcon>
|
||||
|
||||
class Application : public QGuiApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Application(int& argc, char** argv);
|
||||
};
|
||||
23
src/app/CMakeLists.txt
Normal file
23
src/app/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
qt_add_executable(LocalSendQt
|
||||
main.cpp
|
||||
Application.cpp
|
||||
AppController.cpp
|
||||
)
|
||||
|
||||
qt_add_qml_module(LocalSendQt
|
||||
URI LocalSend
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
qml/main.qml
|
||||
)
|
||||
|
||||
target_link_libraries(LocalSendQt PRIVATE
|
||||
LocalSendCore
|
||||
Qt6::Quick
|
||||
Qt6::QuickControls2
|
||||
)
|
||||
|
||||
install(TARGETS LocalSendQt
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
33
src/app/main.cpp
Normal file
33
src/app/main.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QQuickStyle>
|
||||
#include <QDir>
|
||||
#include "Application.h"
|
||||
#include "AppController.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Application app(argc, argv);
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
AppController controller;
|
||||
controller.initialize();
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
engine.addImportPath(QStringLiteral("qrc:/"));
|
||||
|
||||
engine.rootContext()->setContextProperty(QStringLiteral("appController"), &controller);
|
||||
|
||||
const QUrl url(u"qrc:/LocalSend/qml/main.qml"_qs);
|
||||
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl) QCoreApplication::exit(-1);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
engine.load(url);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
178
src/app/qml/main.qml
Normal file
178
src/app/qml/main.qml
Normal file
@@ -0,0 +1,178 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
visible: true
|
||||
width: 800
|
||||
height: 600
|
||||
title: qsTr("LocalSend")
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
|
||||
Component.onCompleted: {
|
||||
push(homePageComponent)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: homePageComponent
|
||||
Page {
|
||||
id: homePage
|
||||
|
||||
signal openSettings()
|
||||
|
||||
header: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
text: qsTr("LocalSend")
|
||||
font.bold: true
|
||||
font.pixelSize: 20
|
||||
Layout.leftMargin: 16
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
ToolButton {
|
||||
text: qsTr("Settings")
|
||||
onClicked: homePage.openSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
spacing: 16
|
||||
|
||||
Label {
|
||||
text: qsTr("Nearby Devices")
|
||||
font.bold: true
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: deviceListView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
property var devices: appController.devices
|
||||
model: devices
|
||||
spacing: 8
|
||||
|
||||
delegate: Pane {
|
||||
width: ListView.view.width
|
||||
padding: 12
|
||||
|
||||
background: Rectangle {
|
||||
color: Qt.lighter("gray", 1.8)
|
||||
radius: 8
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
Label {
|
||||
text: modelData.alias || modelData.ip
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
text: "%1:%2".arg(modelData.ip).arg(modelData.port)
|
||||
color: "gray"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: qsTr("Send")
|
||||
onClicked: {
|
||||
// send to this device
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Button {
|
||||
text: qsTr("Refresh")
|
||||
onClicked: appController.refreshDevices()
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
Label {
|
||||
text: qsTr("Alias: %1").arg(appController.alias)
|
||||
color: "gray"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onOpenSettings: stackView.push(settingsPageComponent)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: settingsPageComponent
|
||||
Page {
|
||||
id: settingsPage
|
||||
signal back()
|
||||
|
||||
header: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
ToolButton {
|
||||
text: qsTr("Back")
|
||||
onClicked: settingsPage.back()
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Settings")
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
spacing: 16
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
Label { text: qsTr("Device Alias:") }
|
||||
TextField {
|
||||
id: aliasField
|
||||
text: appController.alias
|
||||
onEditingFinished: appController.alias = text
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label { text: qsTr("Port:") }
|
||||
SpinBox {
|
||||
id: portField
|
||||
value: appController.port
|
||||
from: 1
|
||||
to: 65535
|
||||
onValueChanged: appController.port = value
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
Label {
|
||||
text: qsTr("Server Status: %1").arg(appController.serverRunning ? qsTr("Running") : qsTr("Stopped"))
|
||||
color: appController.serverRunning ? "green" : "red"
|
||||
}
|
||||
}
|
||||
|
||||
onBack: stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user