File: filesuploadoperation.cpp

package info (click to toggle)
qflipper 1.3.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 12,320 kB
  • sloc: cpp: 18,500; sh: 247; ansic: 191; xml: 38; python: 14; makefile: 5
file content (120 lines) | stat: -rw-r--r-- 4,038 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "filesuploadoperation.h"

#include <QDirIterator>
#include <QFileInfo>
#include <QFile>

#include "flipperzero/devicestate.h"
#include "flipperzero/protobufsession.h"
#include "flipperzero/rpc/storagemkdiroperation.h"
#include "flipperzero/rpc/storagewriteoperation.h"

using namespace Flipper;
using namespace Zero;

FilesUploadOperation::FilesUploadOperation(ProtobufSession *rpc, DeviceState *deviceState, const QList<QUrl> &fileUrls, const QByteArray &remotePath, QObject *parent):
    AbstractUtilityOperation(rpc, deviceState, parent),
    m_remotePath(remotePath),
    m_urlList(fileUrls),
    m_totalSize(0)
{}

const QString FilesUploadOperation::description() const
{
    const auto numFiles = m_urlList.size();
    return QStringLiteral("Upload %1 %2 @%3").arg(QString::number(numFiles), (numFiles == 1) ? "entry" : "entries", deviceState()->deviceInfo().name);
}

void FilesUploadOperation::nextStateLogic()
{
    if(operationState() == Ready) {
        setOperationState(ReadingFileList);
        readFileList();

    } else if(operationState() == ReadingFileList) {
        setOperationState(WritingFiles);
        writeFiles();

    } else if(operationState() == WritingFiles) {
        finish();
    }
}

void FilesUploadOperation::readFileList()
{
    for(const auto &url: qAsConst(m_urlList)) {
        const QFileInfo fileInfo(url.adjusted(QUrl::StripTrailingSlash).toLocalFile());
        const QDir topmostDir = fileInfo.dir();

        m_fileList.append({fileInfo, topmostDir});

        if(fileInfo.isFile()) {
            m_totalSize += fileInfo.size();

        } else if(fileInfo.isDir()) {
            QDir dir(fileInfo.absoluteFilePath());
            dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
            dir.setSorting(QDir::Name | QDir::DirsFirst);

            QDirIterator it(dir, QDirIterator::Subdirectories);
            while(it.hasNext()) {
                const QFileInfo fileInfo(it.next());

                m_fileList.append({fileInfo, topmostDir});

                if(fileInfo.isFile()) {
                    m_totalSize += fileInfo.size();
                }
            }
        }
    }

    advanceOperationState();
}

void FilesUploadOperation::writeFiles()
{
    auto fileCountLeft = m_fileList.size();
    auto fileProgress = 0.0;

    for(const auto &entry: qAsConst(m_fileList)) {
        const auto &fileInfo = entry.fileInfo;
        const auto &topmostDir = entry.topmostDir;

        const auto absoluteLocalPath = fileInfo.absoluteFilePath();
        const auto relativeLocalPath = topmostDir.relativeFilePath(absoluteLocalPath);

        const auto absoluteRemotePath = m_remotePath + QByteArrayLiteral("/") + relativeLocalPath.toLocal8Bit();
        const auto sizeRatio = (double)fileInfo.size() / m_totalSize;
        const auto isLastEntry = (--fileCountLeft == 0);

        if(fileInfo.isFile()) {
            auto *file = new QFile(absoluteLocalPath, this);
            auto *operation = rpc()->storageWrite(absoluteRemotePath, file);

            connect(operation, &AbstractOperation::progressChanged, this, [=]() {
                setProgress(fileProgress + operation->progress() * sizeRatio);
            });

            connect(operation, &AbstractOperation::finished, this, [=]() {
                if(operation->isError()) {
                    finishWithError(operation->error(), operation->errorString());
                } else if(isLastEntry) {
                    advanceOperationState();
                }
            });

        } else if(fileInfo.isDir()) {
            auto *operation = rpc()->storageMkdir(absoluteRemotePath);
            connect(operation, &AbstractOperation::finished, this, [=]() {
                if(operation->isError()) {
                    finishWithError(operation->error(), operation->errorString());
                } else if(isLastEntry) {
                    advanceOperationState();
                }
            });
        }

        fileProgress += 100.0 * sizeRatio;
    }
}