初步完成传输列表的UI
parent
9c5d8115cb
commit
ec46100322
|
@ -26,22 +26,6 @@ FluWindow {
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: tool_bar
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 140
|
||||
|
||||
height: 44
|
||||
|
||||
layoutDirection: Qt.RightToLeft
|
||||
|
||||
// Rectangle{
|
||||
// anchors.fill: parent
|
||||
// color: "red"
|
||||
// }
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
|
@ -101,10 +85,7 @@ FluWindow {
|
|||
onReady: {
|
||||
setTitleBarItem(title_bar)
|
||||
moveWindowToDesktopCenter()
|
||||
setHitTestVisible(title_bar.minimizeButton())
|
||||
setHitTestVisible(title_bar.maximizeButton())
|
||||
setHitTestVisible(title_bar.closeButton())
|
||||
setHitTestVisible(title_bar.transferButton())
|
||||
title_bar.setHitTestVisibleItems(framless_helper)
|
||||
title_bar.maximizeButton.visible = true
|
||||
// window.backgroundVisible = false
|
||||
window.show()
|
||||
|
|
|
@ -110,6 +110,15 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
FluIconButton {
|
||||
id: btn_note
|
||||
height: 32
|
||||
width: 32
|
||||
Layout.rightMargin: 10
|
||||
iconSource: FluentIcons.PenPalette
|
||||
iconSize: 14
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.margins: {
|
||||
right: 10
|
||||
|
@ -204,7 +213,10 @@ Rectangle {
|
|||
return btn_close
|
||||
}
|
||||
|
||||
function transferButton() {
|
||||
return btn_transfer
|
||||
function setHitTestVisibleItems(frameless_helper) {
|
||||
frameless_helper.setHitTestVisible(btn_minimize)
|
||||
frameless_helper.setHitTestVisible(btn_maximize)
|
||||
frameless_helper.setHitTestVisible(btn_close)
|
||||
frameless_helper.setHitTestVisible(btn_transfer)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,52 +16,29 @@ Popup {
|
|||
FluShadow {}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.top: parent.top
|
||||
contentItem: FluScrollablePage {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 10
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: -10
|
||||
Repeater {
|
||||
model: FileTransferListModel
|
||||
delegate: ColumnLayout {
|
||||
Layout.bottomMargin: 10
|
||||
spacing: 10
|
||||
width: parent.width
|
||||
Text {
|
||||
text: name
|
||||
}
|
||||
|
||||
ListModel //模型-提供数据
|
||||
{
|
||||
id: itemModel
|
||||
ListElement {
|
||||
|
||||
name: "Apple"
|
||||
progressValue: 0.1
|
||||
}
|
||||
ListElement {
|
||||
name: "Orange"
|
||||
progressValue: 1
|
||||
}
|
||||
ListElement {
|
||||
name: "Banana"
|
||||
progressValue: 0.6
|
||||
}
|
||||
}
|
||||
|
||||
Component //委托-提供一个展示数据的示例(如何展示一个模型中的数据)
|
||||
{
|
||||
id: itemDelegate
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 10
|
||||
width: parent.width
|
||||
Text {
|
||||
Layout.topMargin: 10
|
||||
text: name
|
||||
}
|
||||
|
||||
FluProgressBar {
|
||||
Layout.fillWidth: true
|
||||
progress: progressValue
|
||||
indeterminate: false
|
||||
FluProgressBar {
|
||||
Layout.fillWidth: true
|
||||
progress: completedSize / totalSize
|
||||
indeterminate: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView //视图-设置委托和模型,根据委托提供的展示方式展示模型提供的数据
|
||||
{
|
||||
anchors.fill: parent
|
||||
model: itemModel
|
||||
delegate: itemDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@ import QtQuick.Controls
|
|||
import QtQuick.Controls.Basic
|
||||
import QtWebEngine 1.2
|
||||
import FluentUI
|
||||
import AicsKB.FileTransferManager
|
||||
|
||||
FluArea {
|
||||
id: content_area
|
||||
paddings: 0
|
||||
backgroundColor: "#f9f9f9"
|
||||
property string type: ""
|
||||
property int knowledgeFileId
|
||||
property string knowledgeFileId
|
||||
signal download(string knowledgeFileId)
|
||||
signal clickTags(string tagName)
|
||||
|
||||
|
@ -134,6 +135,7 @@ FluArea {
|
|||
}
|
||||
onClicked: {
|
||||
emit: content_area.download(content_area.knowledgeFileId)
|
||||
FileTransferManager.download(content_area.knowledgeFileId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +150,7 @@ FluArea {
|
|||
id: video_view
|
||||
FluMediaPlayer {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 270
|
||||
implicitHeight: width * 9 / 16.
|
||||
}
|
||||
}
|
||||
Component {
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#include "FileTransferListModel.h"
|
||||
|
||||
FileTransferListModel::FileTransferListModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
m_roleName.insert(kIdRole, "fileId");
|
||||
m_roleName.insert(kNameRole, "name");
|
||||
m_roleName.insert(kCompletedSizeRole, "completedSize");
|
||||
m_roleName.insert(kTotalSizeRole, "totalSize");
|
||||
|
||||
m_data = {
|
||||
{"v", "vivo", 1200, 2000},
|
||||
{"m", "meizu", 1300, 1500},
|
||||
{"a", "apple", 1400, 1400},
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int FileTransferListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
// For list models only the root node (an invalid parent) should return the list's size. For all
|
||||
// other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
QVariant FileTransferListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
switch (role) {
|
||||
case kIdRole:
|
||||
return m_data.value(index.row()).id;
|
||||
case kNameRole:
|
||||
return m_data.value(index.row()).name;
|
||||
case kCompletedSizeRole:
|
||||
return m_data.value(index.row()).completedSize;
|
||||
case kTotalSizeRole:
|
||||
return m_data.value(index.row()).totalSize;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> FileTransferListModel::roleNames() const
|
||||
{
|
||||
return m_roleName;
|
||||
}
|
||||
|
||||
QAbstractItemModel *FileTransferListModel::model()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FileTransferListModel::insertItem(const FileItem &item)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
m_data.push_front(item);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void FileTransferListModel::setItem(const FileItem &item)
|
||||
{
|
||||
auto iter = std::find_if(m_data.begin(), m_data.end(), [&item](FileItem &i) {
|
||||
return i.id == item.id;
|
||||
});
|
||||
|
||||
if (iter != m_data.end()) {
|
||||
int row = iter - m_data.begin();
|
||||
*iter = item;
|
||||
emit dataChanged(createIndex(row, 0), createIndex(row, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef AICSKNOWLEDGEBASE_FILETRANSFERLISTMODEL_H
|
||||
#define AICSKNOWLEDGEBASE_FILETRANSFERLISTMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
struct FileItem
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
int completedSize;
|
||||
int totalSize;
|
||||
};
|
||||
|
||||
|
||||
class FileTransferListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FileTransferListModel(QObject *parent = nullptr);
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void insertItem(const FileItem &item);
|
||||
|
||||
void setItem(const FileItem &item);
|
||||
|
||||
Q_INVOKABLE QAbstractItemModel *model();
|
||||
|
||||
enum FileItemRole
|
||||
{
|
||||
kIdRole = Qt::UserRole + 1,
|
||||
kNameRole,
|
||||
kCompletedSizeRole,
|
||||
kTotalSizeRole
|
||||
};
|
||||
private:
|
||||
QList<FileItem> m_data;
|
||||
QHash<int, QByteArray> m_roleName;
|
||||
};
|
||||
|
||||
#endif // AICSKNOWLEDGEBASE_FILETRANSFERLISTMODEL_H
|
|
@ -5,12 +5,59 @@
|
|||
#include "FileTransferManager.h"
|
||||
#include <QDebug>
|
||||
#include <curl/curl.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
FileTransferManager::FileTransferManager(QObject *parent) : QObject(parent)
|
||||
static const std::string baseUrl = "http://127.0.0.1:4523/m1/2914957-0-default/";
|
||||
|
||||
static size_t writeDataCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
try {
|
||||
size_t realSize = size * nmemb;
|
||||
static int current_index = 0;
|
||||
int content_size = nmemb * size;
|
||||
std::string result = std::string((char *) contents, content_size);
|
||||
auto *pStr = (std::string *) userp;
|
||||
if (pStr) {
|
||||
(*pStr).append(result);
|
||||
}
|
||||
return realSize;
|
||||
}
|
||||
catch (...) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CURLcode httpGet(const std::string &url, std::string &response, int timeout = 3000)
|
||||
{
|
||||
CURLcode res;
|
||||
|
||||
// 获取easy handle
|
||||
CURL *easy_handle = curl_easy_init();
|
||||
if (nullptr == easy_handle) {
|
||||
curl_global_cleanup();
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
// 设置easy handle属性
|
||||
//curl_easy_setopt(easy_handle, CURLOPT_HTTP_VERSION, (long) CURL_HTTP_VERSION_3ONLY);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_URL, (baseUrl + url).c_str());
|
||||
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, writeDataCallback);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_TIMEOUT, timeout);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, (void *) &response);
|
||||
curl_easy_setopt(easy_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
//curl_easy_setopt(easy_handle, CURLOPT_DEFAULT_PROTOCOL, "https");
|
||||
// 执行数据请求
|
||||
res = curl_easy_perform(easy_handle);
|
||||
curl_easy_cleanup(easy_handle);
|
||||
return res;
|
||||
}
|
||||
|
||||
FileTransferManager::FileTransferManager(FileTransferListModel &model, QObject *parent)
|
||||
: model(model), QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FileTransferManager::upload(QUrl fileUrl)
|
||||
{
|
||||
qDebug() << fileUrl.fileName();
|
||||
|
@ -19,7 +66,7 @@ void FileTransferManager::upload(QUrl fileUrl)
|
|||
CURL *curl;
|
||||
CURLcode res;
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
if (curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "http://127.0.0.1:4523/m1/2914957-0-default/");
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
@ -49,3 +96,42 @@ void FileTransferManager::upload(QUrl fileUrl)
|
|||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
void FileTransferManager::download(QString fileId)
|
||||
{
|
||||
static int _fileId = 0;
|
||||
fileId = QString::number(_fileId++);
|
||||
|
||||
QtConcurrent::run([fileId, this] {
|
||||
qDebug() << "Start Get";
|
||||
std::string resData;
|
||||
if (CURLE_OK != httpGet(fileId.toStdString() + "/status", resData))
|
||||
return;
|
||||
|
||||
qDebug() << resData.c_str();
|
||||
auto resJson = QJsonDocument::fromJson(resData.c_str());
|
||||
//if(!resJson["isCompleted"].toBool())
|
||||
// return;
|
||||
|
||||
int size = resJson["size"].toInt();
|
||||
FileItem item{fileId, resJson["md5"].toString(), 0, size};
|
||||
QTimer::singleShot(0, qApp, [this, item]() {
|
||||
model.insertItem(item);
|
||||
});
|
||||
|
||||
while (item.completedSize < item.totalSize) {
|
||||
item.completedSize += 1;
|
||||
QTimer::singleShot(0, qApp, [this, item]() {
|
||||
model.setItem(item);
|
||||
});
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "End Get";
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,20 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include "FileTransferListModel.h"
|
||||
|
||||
class FileTransferManager: public QObject
|
||||
class FileTransferManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileTransferManager(QObject *parent = nullptr);
|
||||
explicit FileTransferManager(FileTransferListModel &model, QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void upload(QUrl fileUrl);
|
||||
|
||||
Q_INVOKABLE void download(QString fileId);
|
||||
|
||||
private:
|
||||
FileTransferListModel &model;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7,13 +7,19 @@
|
|||
#include <QtWebEngineQuick/qtwebenginequickglobal.h>
|
||||
#include <FramelessHelper/Quick/framelessquickmodule.h>
|
||||
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
||||
#include <curl/curl.h>
|
||||
#include "HttpClient.h"
|
||||
#include "FileTransferManager.h"
|
||||
#include "FileTransferListModel.h"
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT))
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
|
||||
//将样式设置为Basic,不然会导致组件显示异常
|
||||
qputenv("QT_QUICK_CONTROLS_STYLE", "Basic");
|
||||
|
||||
|
@ -38,8 +44,12 @@ int main(int argc, char *argv[])
|
|||
|
||||
QQmlApplicationEngine engine;
|
||||
FramelessHelper::Quick::registerTypes(&engine);
|
||||
|
||||
FileTransferListModel fileTransferListModel;
|
||||
engine.rootContext()->setContextProperty("FileTransferListModel", &fileTransferListModel);
|
||||
|
||||
auto httpClient = new HttpClient(engine);
|
||||
auto fileTransferManager = new FileTransferManager();
|
||||
auto fileTransferManager = new FileTransferManager(fileTransferListModel);
|
||||
|
||||
qmlRegisterSingletonInstance<HttpClient>("AicsKB.HttpClient", 1, 0, "HttpClient", httpClient);
|
||||
qmlRegisterSingletonInstance<FileTransferManager>("AicsKB.FileTransferManager", 1, 0, "FileTransferManager",
|
||||
|
@ -56,6 +66,6 @@ int main(int argc, char *argv[])
|
|||
auto result = QGuiApplication::exec();
|
||||
httpClient->deleteLater();
|
||||
fileTransferManager->deleteLater();
|
||||
|
||||
curl_global_cleanup();
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue