commit 24179fa46465e42a693c4535130cff637bb74c76 Author: www-git-cn <102035872+www-git-cn@users.noreply.github.com> Date: Sun Mar 3 23:55:56 2024 +0800 first commit diff --git a/app.pro b/app.pro new file mode 100644 index 0000000..491b0ab --- /dev/null +++ b/app.pro @@ -0,0 +1,42 @@ +QT += core gui network + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets mqtt + +CONFIG += c++11 +ICON = icon.icns +TARGET = IoTCar + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + datamanager.cpp \ + login.cpp \ + main.cpp \ + protocol.cpp \ + signup.cpp \ + tcpclient.cpp \ + widget.cpp + +HEADERS += \ + datamanager.h \ + login.h \ + protocol.h \ + signup.h \ + tcpclient.h \ + widget.h + +FORMS += \ + login.ui \ + signup.ui \ + widget.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +RESOURCES += \ + imgs/icon.qrc + diff --git a/app.pro.user b/app.pro.user new file mode 100644 index 0000000..fe40358 --- /dev/null +++ b/app.pro.user @@ -0,0 +1,488 @@ + + + + + + EnvironmentId + {d3fed20c-1c94-44fc-8f6a-4dbf39b54775} + + + ProjectExplorer.Project.ActiveTarget + 1 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + 0 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 4 + true + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 6.5.3 MinGW 64-bit + Desktop Qt 6.5.3 MinGW 64-bit + qt.qt6.653.win64_mingw_kit + 0 + 0 + 0 + + 0 + C:\Users\25761\Desktop\build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Debug + C:/Users/25761/Desktop/build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\25761\Desktop\build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Release + C:/Users/25761/Desktop/build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + C:\Users\25761\Desktop\build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Profile + C:/Users/25761/Desktop/build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + 部署 + 部署 + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + + Qt4ProjectManager.Qt4RunConfiguration:C:/Users/25761/Desktop/app/app.pro + C:/Users/25761/Desktop/app/app.pro + false + true + true + true + C:/Users/25761/Desktop/build-app-Desktop_Qt_6_5_3_MinGW_64_bit-Debug + + 1 + + + + ProjectExplorer.Project.Target.1 + + Android.Device.Type + 安卓 Qt 6.5.3 Clang arm64-v8a + 安卓 Qt 6.5.3 Clang arm64-v8a + {7c520419-6b2e-4709-ae24-2a8e3b2ab41b} + 0 + 0 + 0 + + 0 + C:\Users\25761\Desktop\build-app-Qt_6_5_3_Clang_arm64_v8a-Debug + C:/Users/25761/Desktop/build-app-Qt_6_5_3_Clang_arm64_v8a-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + 复制应用程序的数据 + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-33 + + + true + 构建安卓 APK + QmakeProjectManager.AndroidBuildApkStep + + 4 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\25761\Desktop\build-app-Qt_6_5_3_Clang_arm64_v8a-Release + C:/Users/25761/Desktop/build-app-Qt_6_5_3_Clang_arm64_v8a-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + 复制应用程序的数据 + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-33 + + + true + 构建安卓 APK + QmakeProjectManager.AndroidBuildApkStep + + 4 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + + + 0 + C:\Users\25761\Desktop\build-app-Qt_6_5_3_Clang_arm64_v8a-Profile + C:/Users/25761/Desktop/build-app-Qt_6_5_3_Clang_arm64_v8a-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + 复制应用程序的数据 + Qt4ProjectManager.AndroidPackageInstallationStep + + + android-33 + + + true + 构建安卓 APK + QmakeProjectManager.AndroidBuildApkStep + + 4 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + 3 + + + + true + Qt4ProjectManager.AndroidDeployQtStep + + 1 + 部署 + 部署 + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + Qt4ProjectManager.AndroidDeployConfiguration2 + + 1 + + + arm64-v8a + armeabi-v7a + armeabi + + d03ac6da + 33 + + + true + true + 0 + true + + + + + + + + 0 + + false + app + Qt4ProjectManager.AndroidRunConfiguration:C:/Users/25761/Desktop/app/app.pro + C:/Users/25761/Desktop/app/app.pro + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/datamanager.cpp b/datamanager.cpp new file mode 100644 index 0000000..696f4bd --- /dev/null +++ b/datamanager.cpp @@ -0,0 +1,220 @@ +#include "datamanager.h" +// DataManager* DataManager::p_this; +DataManager::DataManager(QObject *parent) + : QObject{parent} +{ + qDebug() << "进入DataManager的构造函数"; + tcpclient = TCPClient::getInstance(); + connect(tcpclient, &TCPClient::TCPClientConnected, this, &DataManager::TCPClientConnected); + connect(tcpclient, &TCPClient::TCPClientDisconnected, this, &DataManager::TCPClientDisconnected); + connect(tcpclient, &TCPClient::recv_data, this, &DataManager::recv_from_server); + tcpclient->setServer("ourdocs.cn",35137); + tcpclient->setTimeOut(500); + tcpclient->configAndrun(); + // tcpclient->setCallBack(recv_from_server); + protocol = Protocol::getInstance(); + // p_this = this; +} + +DataManager *DataManager::getInstance() +{ + static DataManager datamanager_instance; + return &datamanager_instance; +} + +void DataManager::TCPClientConnected() +{ + connect_flag = true; + qDebug() << "emit connect_to_server successfully"; + emit connect_to_server(); +} + +void DataManager::TCPClientDisconnected() +{ + connect_flag = false; + qDebug() << "emit disconnect_from_server successfully"; + // emit p_this->disconnect_from_server(); + emit disconnect_from_server(); +} + + +void DataManager::Register(QString username, QString password) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::REQUEST, QString("register"), QList{"user", username, "password", password}); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送注册信息" << data; +} + +void DataManager::signin_request(QString username, QString password) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::REQUEST, QString("signin"), QList{"user", username, "password", password}); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送登录信息" << data; +} + +void DataManager::account_cancellation(QString username) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::REQUEST, QString("cancellation"), QList{"name",username}); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送注销信息" << data; +} + +void DataManager::update_namelist(QString username) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::REQUEST, QString("update_namelist"),QList{"name",username}); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送更新在线用户列表信息" << data; +} + +void DataManager::parking() +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::CODE, QString("park"), QString("parking_request")); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送存车信息" << data; +} + +void DataManager::pick_up(QString code) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::CODE, QString("pick"), code); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "发送取车信息" << data; +} + + +void DataManager::recv_from_server(QByteArray data) +{ + QByteArray data_decrypt; + data_decrypt = protocol->data_decrypt(data); + QList list = data_decrypt.split('\n'); + for (int i = 0; i < list.count(); i++) + { + QJsonDocument json_data = QJsonDocument::fromJson(list[i]); + if (json_data["type"] == "message") + { + emit new_message(); + QString data, sendname; + sendname = json_data["action"].toString(); + data = json_data["data"].toString(); + emit update_text(sendname, data); + //接收到行车路线类型的消息 + } + if(json_data["type"] == "code") + { + QString data, sendname; + sendname = json_data["action"].toString(); + if(sendname == "pick") + { + data = json_data["data"].toString(); + //取车时向服务端发送,不会接受该类信息 + } + else if (sendname == "park") + { + data = json_data["data"].toString(); + emit update_code(data); + //停车时服务端反馈的随机码 + } + + } + else if (json_data["type"] == "online_users") + { + int count; + QList online_users; + count = json_data["count"].toInt(); + online_users = json_data["users"].toVariant().toStringList(); + emit update_users(count, online_users); + qDebug() << "收到更新在线用户列表的信息" << online_users; + } + else if (json_data["type"] == "response") + { + if (json_data["action"] == "register") + { + bool register_flag; + QJsonObject json = json_data["content"].toObject(); + QString result = json["result"].toString(); + if(result == "true") + { + register_flag = true; + } + else + { + register_flag = false; + } + emit signup_response(register_flag); + qDebug() << "收到服务器响应的注册信息" << register_flag; + } + else if (json_data["action"] == "signin") + { + bool signin_flag; + QJsonObject json = json_data["content"].toObject(); + QString result = json["result"].toString(); + if(result == "true") + { + signin_flag = true; + } + else + { + signin_flag = false; + } + emit signin_response(signin_flag); + qDebug() << "收到服务器响应的登录信息" << signin_flag; + } + } + else + { + qDebug() << "收到未知类型的数据" << list[i]; + return; + } + } +} + + +/* +void DataManager::send_text(QString sendname, QString text) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::MESSAGE, sendname, text); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "群发文本信息" << data; +} + +void DataManager::send_to_user(QString sendname, QString to_user, QString text) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::MESSAGE, sendname, to_user, text); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "私发文本信息" << data; +} + +void DataManager::send_file_to_all(QString sendname, QString filename, QByteArray file) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::FILE, sendname, filename, QString(file.toHex())); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "群发文件"; +} + +void DataManager::send_file_private(QString sendname, QString filename, QByteArray file, QString name) +{ + QByteArray data, data_encrypt; + data = protocol->data_maker(Protocol::FILE, name, sendname, filename, QString(file.toHex())); + data_encrypt = protocol->data_encrypt(data); + tcpclient->sendToserver(data_encrypt); + qDebug() << "私发文件"; +} +*/ + diff --git a/datamanager.h b/datamanager.h new file mode 100644 index 0000000..0ff313f --- /dev/null +++ b/datamanager.h @@ -0,0 +1,62 @@ +#ifndef DATAMANAGER_H +#define DATAMANAGER_H + +#include +#include +#include + +#include "protocol.h" +#include "tcpclient.h" + +class DataManager : public QObject +{ + Q_OBJECT +public: + static DataManager* getInstance(); + +private: + explicit DataManager(QObject *parent = nullptr); + //static void recv_from_server(QString &peerAddress,quint16 peerPort,QByteArray &data); + //static Protocol *protocol; + //static DataManager *p_this; + Protocol *protocol; + TCPClient *tcpclient; + bool connect_flag = false; + +signals: + void connect_to_server(); + void disconnect_from_server(); + void new_message(); + void update_code(QString code); + void signin_response(bool result); + void signup_response(bool result); + void update_text(QString sendname,QString data); + void update_file(QString sendname,QString filename,QString file_data); + void update_file_private(QString sendname,QString filename,QString file_data); + void update_users(int count,QListonline_users); + + +public slots: + /*******ui界面********/ + void Register(QString username,QString password); + void signin_request(QString username,QString password); + + /******WIDGET*****/ + //void send_text(QString sendname,QString text); + //void send_to_user(QString sendname,QString to_user,QString text); + //void send_file_to_all(QString sendname,QString filename,QByteArray file); + //void send_file_private(QString sendname,QString filename,QByteArray file,QString name); + void update_namelist(QString username); + void account_cancellation(QString username); + void pick_up(QString code); + void parking(); + + /******TCPClient******/ + void TCPClientConnected(); + void TCPClientDisconnected(); + void recv_from_server(QByteArray data); + +}; + +#endif // DATAMANAGER_H + diff --git a/imgs/icon.png b/imgs/icon.png new file mode 100644 index 0000000..6587231 Binary files /dev/null and b/imgs/icon.png differ diff --git a/imgs/icon.qrc b/imgs/icon.qrc new file mode 100644 index 0000000..619648d --- /dev/null +++ b/imgs/icon.qrc @@ -0,0 +1,5 @@ + + + icon.png + + diff --git a/login.cpp b/login.cpp new file mode 100644 index 0000000..13c63d0 --- /dev/null +++ b/login.cpp @@ -0,0 +1,232 @@ +#include "login.h" +#include "ui_login.h" + +Login::Login(QWidget *parent) : + QWidget(parent), + ui(new Ui::Login) +{ + ui->setupUi(this); + this->setWindowIcon(QIcon(":/icon.png")); + this->setTabOrder(ui->lineEdit_username,ui->lineEdit_password); + this->setTabOrder(ui->lineEdit_password,ui->btn_signin); + //this->setWindowFlags(Qt::FramelessWindowHint); //无边框 + //this->setAttribute(Qt::WA_TranslucentBackground); + ui->btn_signin->installEventFilter(this); + + /********datamanager********/ + datamanager = DataManager::getInstance(); + connect(datamanager,&DataManager::signin_response,this,&Login::signin_response); + connect(datamanager,&DataManager::signup_response,this,&Login::signup_response); + connect(datamanager,&DataManager::connect_to_server,this,&Login::connected); + connect(datamanager,&DataManager::disconnect_from_server,this,&Login::disconnected); + connect(this,&Login::signin_request,datamanager,&DataManager::signin_request); + connect(this,&Login::Register,datamanager,&DataManager::Register); + + +} + +Login::~Login() +{ +} + +/***************************************SLOTS************************************/ +void Login::on_btn_signin_clicked() +{ + this->zoom_down(ui->btn_signin); + this->zoom_up(ui->btn_signin); + if(connect_flag == true) + { + user = ui->lineEdit_username->text(); + passwd = ui->lineEdit_password->text(); + if(user.isEmpty() || passwd.isEmpty()) + { + QMessageBox::warning(this,tr("错误"),tr("用户名和密码不能为空!")); + return; + } + emit signin_request(user,passwd); + } + else + { + QMessageBox::warning(this, "登录失败", "尚未连接服务器!"); + return; + } +} + +void Login::on_btn_signup_clicked() +{ + this->zoom_down(ui->btn_signup); + this->zoom_up(ui->btn_signup); + signup = new Signup(); + connect(signup,&Signup::show_login_ui,this,&Login::show_login_ui); + connect(signup,&Signup::Register,this,&Login::slot_Register); + this->hide(); + signup->show(); +} + +void Login::on_close_btn_clicked() +{ + this->close(); +} + +void Login::show_login_ui() +{ + this->show(); +} + +//等待服务器验证登陆数据 +void Login::signin_response(bool result) +{ + if(result == true) + { + mainwidget = new Widget(); + + connect(mainwidget,&Widget::account_cancellation,datamanager,&DataManager::account_cancellation); + connect(datamanager,&DataManager::disconnect_from_server,mainwidget,&Widget::disconnect_form_server); + connect(mainwidget,&Widget::exit_client,this,&Login::exit_client); + connect(mainwidget, &Widget::parking, datamanager, &DataManager::); + connect(mainwidget, &Widget::pick_up, datamanager, &DataManager::); + + this->hide(); + mainwidget->show(); + } + else + { + QMessageBox::warning(this,tr("登录失败"),tr("用户名或密码错误!")); + } +} + +//等待服务器注册数据 +void Login::signup_response(bool result) +{ + if(result == true) + { + QString information = QString("请妥善保存您的用户名和密码!"); + QMessageBox::information(signup,tr("注册成功"),information); + signup->close(); + this->show(); + + } + else + { + QMessageBox::warning(signup,tr("错误"),tr("注册失败,请重试!")); + } +} + +//注册界面按下注册按键 +void Login::slot_Register(QString username,QString password) +{ + if(connect_flag == false) + { + QMessageBox::warning(signup, "注册失败", "尚未连接服务器!请连接服务器后重试"); + return; + } + emit Register(username,password); +} + +//连接上服务器 +void Login::connected() +{ + qDebug() << "connect to server"; + connect_flag = true; +} + +//未连上服务器或服务器断开 +void Login::disconnected() +{ + qDebug() << "disconnect from server"; + connect_flag = false; +} + +void Login::exit_client() +{ + this->close(); +} + + +/*****************************Others******************************/ +void Login::zoom_down(QPushButton* btn) +{ + QScopedPointer animalton(new QPropertyAnimation(btn,"geometry")); + //设置间隔时间 + animalton->setDuration(200); + //设置起始位置 + animalton->setStartValue(QRect(btn->x(),btn->y(),btn->width(),btn->height())); + //设置结束位置 + animalton->setEndValue(QRect(btn->x(),btn->y()+5,btn->width(),btn->height())); + //设置动画曲线 + animalton->setEasingCurve(QEasingCurve::OutBounce); + animalton->start(); + +} + +void Login::zoom_up(QPushButton* btn) +{ + QScopedPointeranimalton(new QPropertyAnimation(btn,"geometry")); + animalton->setDuration(200); + animalton->setStartValue(QRect(btn->x(),btn->y()+5,btn->width(),btn->height())); + animalton->setEndValue(QRect(btn->x(),btn->y(),btn->width(),btn->height())); + animalton->setEasingCurve(QEasingCurve::OutBounce); + animalton->start(); +} + +void Login::new_closebutton(QPushButton* btn, QString position,QSize size) +{ + QPixmap pixmap; + pixmap.load(position); + btn->setIconSize(size); + btn->setStyleSheet("QPushButton{border-width: 1px;border-style: solid;border-radius:15px;background-color: rgb(64, 145, 252);}" + "QPushButton:hover{background-color:#999999;}"); + //设置图标 + btn->setIcon(pixmap); +} + +bool Login::eventFilter(QObject *target, QEvent *event) +{ + if(target == ui->btn_signin) //可替换 + { + if(event->type() == QEvent::KeyPress)//回车键 + { + QKeyEvent *k = static_cast(event); + + if(k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter) + { + on_btn_signin_clicked(); //替换为需要响应的函数事件,以这里的按钮为例 + return true; + } + } + } + return QWidget::eventFilter(target,event); +} + +void Login::mousePressEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) + { + point = event->pos(); + } +} + +void Login::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) + { + //当窗口最大化或最小化时也不进行触发 + if (Login::isMaximized() || Login::isMinimized()) + { + return; + } + else + { + //当在按钮之类需要鼠标操作的地方不进行触发(防误触) + if (ui->btn_signin->underMouse() || ui->btn_signup->underMouse()) + { + return; + } + else + { + Login::move(Login::mapToGlobal(event->pos() - point)); + } + } + } + event->accept(); +} diff --git a/login.h b/login.h new file mode 100644 index 0000000..6d865ec --- /dev/null +++ b/login.h @@ -0,0 +1,67 @@ +#ifndef LOGIN_H +#define LOGIN_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "datamanager.h" +#include "signup.h" +#include "widget.h" + +namespace Ui {class Login;} + +class Login : public QWidget +{ + Q_OBJECT + +public: + explicit Login(QWidget *parent = nullptr); + ~Login(); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + +signals: + void signin_request(QString username,QString password); + void Register(QString username,QString password); + +private slots: + void on_btn_signin_clicked(); + void on_btn_signup_clicked(); + void on_close_btn_clicked(); + + void signin_response(bool result); + void signup_response(bool result); + void show_login_ui(); + void slot_Register(QString username,QString password); + void connected(); + void disconnected(); + void exit_client(); + +private: + Ui::Login *ui; + QPoint point; + QString user,passwd; + static Login login_instance; + QPointer login; + QPointer signup; + QPointer mainwidget; + QPointer datamanager; + bool connect_flag = false; + + void new_closebutton(QPushButton* btn, QString position,QSize size); + void zoom_up(QPushButton* btn); + void zoom_down(QPushButton* btn); + bool eventFilter(QObject *target, QEvent *event); +}; + +#endif // LOGIN_H diff --git a/login.ui b/login.ui new file mode 100644 index 0000000..f03a0d7 --- /dev/null +++ b/login.ui @@ -0,0 +1,155 @@ + + + Login + + + + 0 + 0 + 438 + 609 + + + + Form + + + + + 250 + 370 + 79 + 40 + + + + + 50 + 40 + + + + QPushButton +{background-color:qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, +stop:1 rgba(64, 145, 252, 255), +stop:0 rgba(220, 255, 255, 255)); +color: rgb(255, 255, 255); +border:0px groove gray; +border-radius:7px; +padding:2px 4px; +font: 14pt "Candara";} + +QPushButton:pressed +{background-color:#999999;} + + + Sign up + + + + + + 70 + 230 + 289 + 45 + + + + + 0 + 45 + + + + background-color: rgb(247, 247, 247); +border:1px groove gray;border-radius: +7px;padding:2px 4px; +font: 12pt "Candara"; + + + Please input your ID + + + + + + 120 + 160 + 191 + 51 + + + + font: 87 20pt "Arial Black"; +background:transparent; + + + Login Now + + + + + + 100 + 370 + 71 + 40 + + + + + 50 + 40 + + + + QPushButton +{background-color:qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, +stop:1 rgba(64, 145, 252, 255), +stop:0 rgba(220, 255, 255, 255)); +color: rgb(255, 255, 255); +border:0px groove gray; +border-radius:7px; +padding:2px 4px; +font: 14pt "Candara";} + +QPushButton:pressed +{background-color:#999999;} + + + Sign in + + + + + + 70 + 290 + 289 + 45 + + + + + 0 + 45 + + + + background-color: rgb(247, 247, 247); +border:1px groove gray;border-radius: +7px;padding:2px 4px; +font: 12pt "Candara"; + + + QLineEdit::Password + + + Please input your password + + + + + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..efab257 --- /dev/null +++ b/main.cpp @@ -0,0 +1,12 @@ +#include "login.h" + +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); + QApplication a(argc, argv); + Login w; + w.show(); + return a.exec(); +} diff --git a/protocol.cpp b/protocol.cpp new file mode 100644 index 0000000..7cad303 --- /dev/null +++ b/protocol.cpp @@ -0,0 +1,148 @@ +#include "protocol.h" +#include +#include + +Protocol Protocol::protocol_instance; +Protocol::Protocol(QObject *parent) + : QObject{parent} +{ + +} + +Protocol::~Protocol() +{ + +} + +Protocol* Protocol::getInstance() +{ + return &protocol_instance; +} + +QByteArray Protocol::data_builder(QList &args) +{ + QJsonObject data; + switch(args[0].get_data_types()) + { + case MESSAGE: + { + data.insert("type","message"); + data.insert("sendname",args[1].get_string()); + data.insert("data",args[2].get_string()); + break; + } + case CODE: + { + data.insert("type","code"); + data.insert("action",args[1].get_string()); + data.insert("data",args[2].get_string()); + } + case REQUEST: + { + data.insert("type","request"); + data.insert("action",args[1].get_string()); + QList content = args[2].get_list(); + QJsonObject json_content; + for (int i=0; i users = args[2].get_list(); + QJsonArray json_users; + for (auto &user:users) + json_users.append(user); + data.insert("users",json_users); + break; + } + case RESPONSE: + { + data.insert("type","response"); + data.insert("action",args[1].get_string()); + QList content = args[2].get_list(); + QJsonObject json_content; + for (int i=0; i Protocol::data_parser(QByteArray data) +{ + QJsonDocument json_data = QJsonDocument::fromJson(data); + if (json_data["type"] == "message") + return qMakePair(MESSAGE,json_data.object()); + else if (json_data["type"] == "line") + return qMakePair(CODE,json_data.object()); + else if (json_data["type"] == "request") + return qMakePair(REQUEST,json_data.object()); + else if (json_data["type"] == "online_users") + return qMakePair(ONLINEUSERS,json_data.object()); + else if (json_data["type"] == "response") + return qMakePair(RESPONSE,json_data.object()); + else + return qMakePair(RESPONSE,json_data.object()); +} + + +/******************************加解密部分************************************/ +QByteArray Protocol::XOR_En_Decrypt(QByteArray src) +{ + QByteArray result; + for(auto &i:src) + result.append(i ^ cipher_word); + return result; +} + +QByteArray Protocol::Upper_Lower_En_Decrypt(QString src) +{ + QByteArray result; + for(auto &i:src) + { + if(i.isUpper()) + { + QChar word = i.toLower(); + result.append(word.toLatin1()); + } + else if (i.isLower()) + { + QChar word = i.toUpper(); + result.append(word.toLatin1()); + } + else + result.append(i.toLatin1()); + } + return result; +} + +QByteArray Protocol::data_encrypt(QByteArray src) +{ + QByteArray en_base64 = src.toBase64(); + QByteArray result = Upper_Lower_En_Decrypt(en_base64); + return XOR_En_Decrypt(result); +} + +QByteArray Protocol::data_decrypt(QByteArray src) +{ + QByteArray result = XOR_En_Decrypt(src); + //qDebug() << result; + result = Upper_Lower_En_Decrypt(result); + //qDebug() << result; + return QByteArray::fromBase64(result); +} + +void Protocol::set_data_cipher_word(char word) +{ + cipher_word = word; +} + diff --git a/protocol.h b/protocol.h new file mode 100644 index 0000000..8932cd5 --- /dev/null +++ b/protocol.h @@ -0,0 +1,59 @@ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include +#include + +class Protocol : public QObject +{ + Q_OBJECT +public: + static Protocol* getInstance(); + template + QByteArray data_maker(Type type, Args ...args) + { + QList args_list; + args_list.append(any_types(type)); + (void)std::initializer_list {(args_list.append(any_types(args)),0)...}; + return data_builder(args_list); + }; + enum data_types {MESSAGE,CODE,REQUEST,ONLINEUSERS,RESPONSE}; + QPair data_parser(QByteArray data); + QByteArray data_encrypt(QByteArray src); + void set_data_cipher_word(char word); + QByteArray data_decrypt(QByteArray src); +private: + char cipher_word = 'G'; + struct any_types { + enum type {String, Bool, Int, Data_types, List}; + any_types(int e) { m_data.INT = e; m_type = Int;} + any_types(QString e) { m_data.STRING = e; m_type = String;} + any_types(QList e) { m_data.LIST = e; m_type = List;} + any_types(bool e) { m_data.BOOL = e; m_type = Bool;} + any_types(data_types e) { m_data.DATA_TYPES = e; m_type = Data_types;} + type get_type() const { return m_type; } + int get_int() const { return m_data.INT; } + bool get_bool() const { return m_data.BOOL; } + data_types get_data_types() const { return m_data.DATA_TYPES; } + QString get_string() const { return m_data.STRING; } + QList get_list() const { return m_data.LIST; } + private: + type m_type; + struct { + int INT; + bool BOOL; + QString STRING; + QList LIST; + data_types DATA_TYPES; + } m_data; + }; + static Protocol protocol_instance; + explicit Protocol(QObject *parent = nullptr); + ~Protocol(); + QByteArray data_builder(QList &args); + QByteArray XOR_En_Decrypt(QByteArray src); + QByteArray Upper_Lower_En_Decrypt(QString src); +signals: + +}; +#endif // PROTOCOL_H diff --git a/signup.cpp b/signup.cpp new file mode 100644 index 0000000..689d89f --- /dev/null +++ b/signup.cpp @@ -0,0 +1,92 @@ +#include "signup.h" +#include "ui_signup.h" +#include + +Signup::Signup(QWidget *parent) : QWidget(parent), + ui(new Ui::Signup) +{ + ui->setupUi(this); + +} + +Signup::~Signup() +{ + delete ui; +} + +//返回登录按钮 +void Signup::on_btn_return_clicked() +{ + this->close(); + emit show_login_ui(); +} + +//注册按钮 +void Signup::on_btn_sure_clicked() +{ + QString username = ui->lineEdit_username->text(); + QString password = ui->lineEdit_passwd->text(); + QString surepass = ui->lineEdit_surepasswd->text(); + if (username.isEmpty() || password.isEmpty() || surepass.isEmpty()) + { + QMessageBox::warning(this, "注册失败", "输入不能为空!"); + } + + else + { + if (password == surepass) + { + emit Register(username,password); + } + else + { + QMessageBox::information(this, "用户注册", "两次密码输入不一致!"); + } + } +} + +void Signup::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); // 反锯齿; + + painter.setPen(Qt::transparent); + QRect rect = this->rect(); // rect为绘制大小 + rect.setWidth(rect.width() - 1); + rect.setHeight(rect.height() - 1); + painter.drawRoundedRect(rect, 10, 10); // 10为圆角角度 +} + +void Signup::mousePressEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) + { + point = event->pos(); + } +} + +void Signup::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) + { + //当窗口最大化或最小化时也不进行触发 + if (Signup::isMaximized() || Signup::isMinimized()) + { + return; + } + else + { + //当在按钮之类需要鼠标操作的地方不进行触发(防误触) + if (ui->btn_sure->underMouse() || ui->btn_return->underMouse()) + { + return; + } + else + { + Signup::move(Signup::mapToGlobal(event->pos() - point)); //移动 + } + } + } + event->accept(); +} + diff --git a/signup.h b/signup.h new file mode 100644 index 0000000..d5d8147 --- /dev/null +++ b/signup.h @@ -0,0 +1,44 @@ +#ifndef SIGNUP_H +#define SIGNUP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { +class Signup; +} + +class Signup : public QWidget +{ + Q_OBJECT + +public: + explicit Signup(QWidget *parent = nullptr); + ~Signup(); + void paintEvent(QPaintEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + +signals: + void Register(QString username,QString password); + void show_login_ui(); + +private slots: + void on_btn_sure_clicked(); + void on_btn_return_clicked(); + +private: + Ui::Signup *ui; + QPoint point; +}; + +#endif // SIGNUP_H diff --git a/signup.ui b/signup.ui new file mode 100644 index 0000000..9a9c94c --- /dev/null +++ b/signup.ui @@ -0,0 +1,198 @@ + + + Signup + + + + 0 + 0 + 438 + 609 + + + + Form + + + + + 80 + 90 + 161 + 31 + + + + font: 87 20pt "Arial Black"; + + + Hello + + + + + + 80 + 190 + 271 + 344 + + + + + + + font: 10.5pt "Arial"; + + + Username + + + + + + + + 0 + 40 + + + + font: 12pt "Arial"; + + + + + + + font: 11pt "Arial"; + + + Password + + + + + + + + 0 + 40 + + + + font: 12pt "Arial"; + + + + + + + font: 10.5pt "Arial"; + + + Ensure your password: + + + + + + + + 0 + 40 + + + + font: 12pt "Arial"; + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + 0 + 40 + + + + background-color: rgb(29, 123, 255); +color: rgb(255, 255, 255); +font: 26 10pt "Bahnschrift Light"; + + + Sure + + + + + + + + 0 + 40 + + + + background-color: rgb(29, 123, 255); +color: rgb(255, 255, 255); +font: 26 10pt "Bahnschrift Light"; + + + Return login + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 80 + 120 + 301 + 51 + + + + font: 87 20pt "Arial Black"; + + + Welcome to us! + + + + + + diff --git a/tcpclient.cpp b/tcpclient.cpp new file mode 100644 index 0000000..e688c2e --- /dev/null +++ b/tcpclient.cpp @@ -0,0 +1,106 @@ +#include "tcpclient.h" +#include +#include +#include + +using namespace std; +TCPClient TCPClient::tcpclient_instance; +QTcpSocket TCPClient::socket; + +TCPClient::TCPClient(QObject *parent) + : QObject{parent} +{ + +} + +TCPClient::~TCPClient() +{ + +} + +TCPClient* TCPClient::getInstance() +{ + return &tcpclient_instance; +} + +void TCPClient::configAndrun() +{ + qDebug() << "进入configandrun"; + socket.setSocketOption(QAbstractSocket::KeepAliveOption,1); + socket.connectToHost(server_ip, server_port); + connect(&socket,&QTcpSocket::connected,this,&TCPClient::connected); + connect(&socket,&QTcpSocket::disconnected,this,&TCPClient::disconnected); + connect(&socket,&QTcpSocket::readyRead,this,&TCPClient::readSocket); +} + +void TCPClient::sendToserver(QByteArray &data) +{ + if (socket.isOpen()) + { + socket.write(data); + socket.waitForBytesWritten(2000); + } +} + +void TCPClient::setServer(QString IP, quint16 port) +{ + server_ip = IP; + server_port = port; +} + +void TCPClient::connected() +{ + emit TCPClientConnected(); + qDebug() << "emit TCPClientConnected successfully"; + QString addr_t = socket.peerAddress().toString(); + QByteArray addr = addr_t.toLocal8Bit(); + printf("Connected to server at %.*s:%d.\n",addr.size(),addr.data(),socket.peerPort()); +} + +void TCPClient::disconnected() +{ + emit TCPClientDisconnected(); + qDebug() << "emit TCPClientDisconnected successfully"; + printf("Disconnected from server.\n"); +} + +void TCPClient::readSocket() +{ + QByteArray recv; + while(socket.bytesAvailable())//循环接收 + { + recv += socket.readAll(); + if (!socket.waitForReadyRead(_timeout))//超时停止接收 + { + /*QString error = sock->errorString(); + string error_t = error.toStdString(); + log_w("error:%d: %.*s", sock->error(),error_t.length(), error_t.data());*/ + break; + } + } + QString ip = socket.peerAddress().toString(); + string ip_t = ip.toStdString(); + printf("TCPC: Recvd from %.*s:%d\n", ip_t.length(), ip_t.data(), socket.peerPort()); + printf("TCPC Message:%.*s\n",recv.size(),(char *)recv.data()); + if (_callback != nullptr) + _callback(ip, socket.peerPort(),recv); + emit recv_data(recv); +} + +void TCPClient::setTimeOut(int timeout) +{ + _timeout = timeout; +} + + +void TCPClient::setCallBack(void (*callback)(QString &mac, quint16 port, QByteArray &data)) +{ + _callback = callback; +} + +void TCPClient::_sleep(int msec) +{ + QTime dieTime = QTime::currentTime().addMSecs(msec); + while( QTime::currentTime() < dieTime ) + QCoreApplication::processEvents(QEventLoop::AllEvents, 100); +} diff --git a/tcpclient.h b/tcpclient.h new file mode 100644 index 0000000..4ca087f --- /dev/null +++ b/tcpclient.h @@ -0,0 +1,41 @@ +#ifndef TCPCLIENT_H +#define TCPCLIENT_H + +#include +#include +#include + +class TCPClient : public QObject +{ + Q_OBJECT +public: + static TCPClient* getInstance(); + static void sendToserver(QByteArray &data); + void configAndrun(); + void setCallBack(void (*callback)(QString &ip, quint16 port,QByteArray &data)); + void setServer(QString IP, quint16 port); + void setTimeOut(int timeout); +private slots: + void readSocket(); + void connected(); + void disconnected(); +private: + explicit TCPClient(QObject *parent = nullptr); + ~TCPClient(); + static void _sleep(int msec); + static QTcpSocket socket; + static TCPClient tcpclient_instance; + int _timeout = 20; + QString server_ip = "127.0.0.1"; + quint16 server_port = 7890; + bool has_found = false; + void (*_callback) (QString &ip, quint16 port,QByteArray &data)=nullptr; +signals: + void TCPClientConnected(); + void TCPClientDisconnected(); + void recv_data(QByteArray data); + +}; + +#endif // TCPCLIENT_H + diff --git a/widget.cpp b/widget.cpp new file mode 100644 index 0000000..95cfb3c --- /dev/null +++ b/widget.cpp @@ -0,0 +1,136 @@ +#include "widget.h" +#include "ui_widget.h" + + +Widget::Widget(QWidget *parent) + : QWidget(parent) + , ui(new Ui::Widget) +{ + ui->setupUi(this); + ui->log->setEnabled(false); + + //连接mqtt服务器,端口1883 + mqtt_client = new QMqttClient(this); + mqtt_client->setHostname(QHostAddress(QHostAddress::LocalHost).toString()); + mqtt_client->setPort(port); + mqtt_client->setClientId("mobile"); + mqtt_client->setUsername("Phone"); + mqtt_client->setPassword("Phone"); + mqtt_client->connectToHost(); + connect(mqtt_client, &QMqttClient::disconnected, this, &Widget::disconnected_handler); + connect(mqtt_client, &QMqttClient::messageReceived, this, &Widget::received_handler); + connect(mqtt_client, &QMqttClient::pingResponseReceived, this, &Widget::pingresp_handler); + connect(mqtt_client, &QMqttClient::connected, this, &Widget::connected_handler); + connect(mqtt_client, &QMqttClient::errorChanged, this, &Widget::error_handler); + connect(mqtt_client, &QMqttClient::stateChanged, this, &Widget::state_handler); + + connect(ui->pushButton, &QPushButton::clicked, [=]() { + ui->stackedWidget->setCurrentIndex(0); + }); + + connect(ui->pushButton_2, &QPushButton::clicked, [=]() { + ui->stackedWidget->setCurrentIndex(1); + }); + +} + + + +Widget::~Widget() +{ + delete ui; +} + + +//点击存车按钮 +void Widget::on_pushButton_3_clicked() +{ + emit parking(); +} + +//点击取车按钮 +void Widget::on_pushButton_4_clicked() +{ + emit pick_up(ui->code->toPlainText()); +} + +void Widget::connected_handler() +{ + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"MQTT服务器已连接上\n"; + ui->log->insertPlainText(content); + sub = mqtt_client->subscribe(topic,1); + if (sub) + { + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"Topic: "+ topic + QLatin1Char('\n') + +"Qos: "+QLatin1Char(sub->qos()+'0')+QLatin1Char('\n')+ + "已订阅\n"; + ui->log->insertPlainText(content); + } + else + { + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"Topic: "+ topic + QLatin1Char('\n') + +"Qos: "+QLatin1Char(sub->qos()+'0')+QLatin1Char('\n')+ + "订阅失败,请检查网络情况\n"; + ui->log->insertPlainText(content); + } + +} + +void Widget::disconnected_handler() +{ + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"MQTT服务器已断开\n"; + ui->log->insertPlainText(content); + +} + +void Widget::received_handler(const QByteArray &message, const QMqttTopicName &topic) +{ + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"Topic: "+topic.name()+ QLatin1Char('\n') + +"Message: "+message+ QLatin1Char('\n')+ + +"Qos: "+QLatin1Char(sub->qos()+'0')+QLatin1Char('\n'); + ui->log->insertPlainText(content); +} + +void Widget::pingresp_handler() +{ + const QString content = QDateTime::currentDateTime().toString() + + QLatin1Char('\n') + + QLatin1String("MQTT Pong!") + + QLatin1Char('\n'); + ui->log->insertPlainText(content); +} + +void Widget::state_handler() +{ + const QString content = QDateTime::currentDateTime().toString() + + QLatin1Char('\n') + + ":MQTT Client State Change" + + QString::number(mqtt_client->state()) + + u'\n'; + ui->log->insertPlainText(content); +} + +void Widget::error_handler(const QMqttClient::ClientError error) +{ + const QString content = QDateTime::currentDateTime().toString() + +"\n" + +"Error: "+ QString::number(static_cast(error)); + ui->log->insertPlainText(content); +} + + +void Widget::disconnect_form_server() +{ + QMessageBox::critical(this,"连接超时","请检查您的网络连接!"); + qApp->quit(); +} diff --git a/widget.h b/widget.h new file mode 100644 index 0000000..65b8c25 --- /dev/null +++ b/widget.h @@ -0,0 +1,50 @@ +#ifndef WIDGET_H +#define WIDGET_H + +#include +#include +#include +#include +#include "datamanager.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class Widget; } +QT_END_NAMESPACE + +class Widget : public QWidget +{ + Q_OBJECT + +public: + Widget(QWidget *parent = nullptr); + ~Widget(); + + void connected_handler(); + void disconnected_handler(); + void received_handler(const QByteArray &message, const QMqttTopicName &topic); + void pingresp_handler(); + void state_handler(); + void error_handler(const QMqttClient::ClientError error); + + +signals: + void account_cancellation(QString username); + void exit_client(); + void parking(); + void pick_up(QString code); + +public slots: + void on_pushButton_3_clicked(); + + void on_pushButton_4_clicked(); + + void disconnect_form_server(); + +private: + Ui::Widget *ui; + QMqttClient *mqtt_client; + QMqttSubscription* sub = nullptr; + QString topic = "/car"; + quint16 port = 1883; +}; +#endif // WIDGET_H diff --git a/widget.ui b/widget.ui new file mode 100644 index 0000000..409f3b9 --- /dev/null +++ b/widget.ui @@ -0,0 +1,159 @@ + + + Widget + + + + 0 + 0 + 489 + 718 + + + + Widget + + + + + 0 + 0 + 501 + 661 + + + + + + + 40 + 50 + 251 + 71 + + + + + 20 + + + + 欢迎来到停车场 + + + + + + 50 + 150 + 311 + 71 + + + + + 15 + + + + 放置驱车码 + + + + + + 90 + 390 + 93 + 28 + + + + 存车 + + + + + + 280 + 390 + 93 + 28 + + + + 取车 + + + + + + 90 + 266 + 281 + 51 + + + + + + + + + 60 + 60 + 241 + 31 + + + + + 18 + + + + 尊敬的用户您好 + + + + + + 60 + 140 + 341 + 381 + + + + + + + + + 70 + 660 + 93 + 28 + + + + 主页 + + + + + + 310 + 660 + 93 + 28 + + + + 用户 + + + + + +