Added TDLibFile and optimized ProfileThumbnail
Profile images seem to be loading significantly faster after moving file fetching logic to the native code and removing the artificial delay. TDLibFile is a generic object which can hopefully be used elsewhere as an efficient replacement for JavaScript.
This commit is contained in:
parent
9bb24b4862
commit
9e8038b1b6
10 changed files with 549 additions and 67 deletions
|
@ -29,6 +29,7 @@ SOURCES += src/harbour-fernschreiber.cpp \
|
||||||
src/notificationmanager.cpp \
|
src/notificationmanager.cpp \
|
||||||
src/processlauncher.cpp \
|
src/processlauncher.cpp \
|
||||||
src/stickermanager.cpp \
|
src/stickermanager.cpp \
|
||||||
|
src/tdlibfile.cpp \
|
||||||
src/tdlibreceiver.cpp \
|
src/tdlibreceiver.cpp \
|
||||||
src/tdlibwrapper.cpp
|
src/tdlibwrapper.cpp
|
||||||
|
|
||||||
|
@ -141,6 +142,7 @@ HEADERS += \
|
||||||
src/notificationmanager.h \
|
src/notificationmanager.h \
|
||||||
src/processlauncher.h \
|
src/processlauncher.h \
|
||||||
src/stickermanager.h \
|
src/stickermanager.h \
|
||||||
|
src/tdlibfile.h \
|
||||||
src/tdlibreceiver.h \
|
src/tdlibreceiver.h \
|
||||||
src/tdlibsecrets.h \
|
src/tdlibsecrets.h \
|
||||||
src/tdlibwrapper.h
|
src/tdlibwrapper.h
|
||||||
|
|
|
@ -7,9 +7,7 @@ import "../js/functions.js" as Functions
|
||||||
PhotoTextsListItem {
|
PhotoTextsListItem {
|
||||||
id: listItem
|
id: listItem
|
||||||
pictureThumbnail {
|
pictureThumbnail {
|
||||||
// forceElementUpdate: overviewPage.chatListCreated
|
|
||||||
photoData: photo_small
|
photoData: photo_small
|
||||||
// replacementStringHint: primaryText.text
|
|
||||||
}
|
}
|
||||||
property int ownUserId
|
property int ownUserId
|
||||||
property url emojiBase: "../js/emoji/"
|
property url emojiBase: "../js/emoji/"
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
|
import WerkWolf.Fernschreiber 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
||||||
id: profileThumbnail
|
id: profileThumbnail
|
||||||
|
|
||||||
property var photoData;
|
property alias photoData: file.fileInformation
|
||||||
property string replacementStringHint: "X"
|
property string replacementStringHint: "X"
|
||||||
property bool forceElementUpdate: false
|
|
||||||
property int radius: width / 2
|
property int radius: width / 2
|
||||||
property int imageStatus: -1
|
property int imageStatus: -1
|
||||||
|
|
||||||
|
@ -46,52 +46,10 @@ Item {
|
||||||
return replacementStringHint;
|
return replacementStringHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePicture() {
|
TDLibFile {
|
||||||
profileImageLoader.active = false;
|
id: file
|
||||||
replacementThumbnailItem.visible = true;
|
tdlib: tdLibWrapper
|
||||||
if (typeof photoData === "object") {
|
autoLoad: true
|
||||||
if (photoData.local.is_downloading_completed) {
|
|
||||||
profileImageLoader.active = true;
|
|
||||||
replacementThumbnailItem.visible = false;
|
|
||||||
} else {
|
|
||||||
tdLibWrapper.downloadFile(photoData.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: updatePictureTimer
|
|
||||||
interval: 500
|
|
||||||
running: false
|
|
||||||
repeat: false
|
|
||||||
onTriggered: {
|
|
||||||
updatePicture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
updatePictureTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
onPhotoDataChanged: {
|
|
||||||
if (profileThumbnail.forceElementUpdate) {
|
|
||||||
updatePictureTimer.stop();
|
|
||||||
updatePictureTimer.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: tdLibWrapper
|
|
||||||
onFileUpdated: {
|
|
||||||
if (typeof photoData !== "undefined" && fileId === photoData.id) {
|
|
||||||
console.log("File updated, completed? " + fileInformation.local.is_downloading_completed);
|
|
||||||
if (fileInformation.local.is_downloading_completed) {
|
|
||||||
photoData = fileInformation;
|
|
||||||
profileImageLoader.active = true;
|
|
||||||
replacementThumbnailItem.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
@ -99,13 +57,16 @@ Item {
|
||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: width
|
height: width
|
||||||
|
visible: opacity > 0
|
||||||
|
opacity: singleImage.status === Image.Ready ? 1 : 0
|
||||||
|
Behavior on opacity { FadeAnimation {} }
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: singleImage
|
id: singleImage
|
||||||
width: parent.width - Theme.paddingSmall
|
width: parent.width - Theme.paddingSmall
|
||||||
height: parent.height - Theme.paddingSmall
|
height: parent.height - Theme.paddingSmall
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
source: profileThumbnail.photoData.local.path
|
source: file.path
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
autoTransform: true
|
autoTransform: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
@ -126,30 +87,25 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpacityMask {
|
OpacityMask {
|
||||||
id: maskedThumbnail
|
|
||||||
source: singleImage
|
source: singleImage
|
||||||
maskSource: profileThumbnailMask
|
maskSource: profileThumbnailMask
|
||||||
anchors.fill: singleImage
|
anchors.fill: singleImage
|
||||||
visible: singleImage.status === Image.Ready ? true : false
|
|
||||||
opacity: singleImage.status === Image.Ready ? 1 : 0
|
|
||||||
Behavior on opacity { NumberAnimation {} }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: profileImageLoader
|
id: profileImageLoader
|
||||||
active: false
|
active: file.isDownloadingCompleted
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
width: parent.width
|
width: parent.width
|
||||||
sourceComponent: profileImageComponent
|
sourceComponent: profileImageComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: replacementThumbnailItem
|
|
||||||
width: parent.width - Theme.paddingSmall
|
width: parent.width - Theme.paddingSmall
|
||||||
height: parent.height - Theme.paddingSmall
|
height: parent.height - Theme.paddingSmall
|
||||||
visible: true
|
visible: !profileImageLoader.item || !profileImageLoader.item.visible
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: replacementThumbnailBackground
|
id: replacementThumbnailBackground
|
||||||
|
@ -160,14 +116,11 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: replacementThumbnailText
|
|
||||||
anchors.centerIn: replacementThumbnailBackground
|
anchors.centerIn: replacementThumbnailBackground
|
||||||
text: getReplacementString()
|
text: getReplacementString()
|
||||||
color: Theme.primaryColor
|
color: Theme.primaryColor
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: ( profileThumbnail.height >= Theme.itemSizeSmall ) ? Theme.fontSizeLarge : Theme.fontSizeMedium
|
font.pixelSize: ( profileThumbnail.height >= Theme.itemSizeSmall ) ? Theme.fontSizeLarge : Theme.fontSizeMedium
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,6 @@ Page {
|
||||||
|
|
||||||
model: chatListModel
|
model: chatListModel
|
||||||
delegate: ChatListViewItem {
|
delegate: ChatListViewItem {
|
||||||
pictureThumbnail.forceElementUpdate: overviewPage.chatListCreated
|
|
||||||
ownUserId: overviewPage.ownUserId
|
ownUserId: overviewPage.ownUserId
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include "appsettings.h"
|
#include "appsettings.h"
|
||||||
|
#include "tdlibfile.h"
|
||||||
#include "tdlibwrapper.h"
|
#include "tdlibwrapper.h"
|
||||||
#include "chatlistmodel.h"
|
#include "chatlistmodel.h"
|
||||||
#include "chatmodel.h"
|
#include "chatmodel.h"
|
||||||
|
@ -45,13 +46,16 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QQmlContext *context = view.data()->rootContext();
|
QQmlContext *context = view.data()->rootContext();
|
||||||
|
|
||||||
|
const char *uri = "WerkWolf.Fernschreiber";
|
||||||
|
qmlRegisterType<TDLibFile>(uri, 1, 0, "TDLibFile");
|
||||||
|
|
||||||
AppSettings *appSettings = new AppSettings(view.data());
|
AppSettings *appSettings = new AppSettings(view.data());
|
||||||
context->setContextProperty("appSettings", appSettings);
|
context->setContextProperty("appSettings", appSettings);
|
||||||
qmlRegisterUncreatableType<AppSettings>("WerkWolf.Fernschreiber", 1, 0, "AppSettings", QString());
|
qmlRegisterUncreatableType<AppSettings>(uri, 1, 0, "AppSettings", QString());
|
||||||
|
|
||||||
TDLibWrapper *tdLibWrapper = new TDLibWrapper(view.data());
|
TDLibWrapper *tdLibWrapper = new TDLibWrapper(view.data());
|
||||||
context->setContextProperty("tdLibWrapper", tdLibWrapper);
|
context->setContextProperty("tdLibWrapper", tdLibWrapper);
|
||||||
qmlRegisterUncreatableType<TDLibWrapper>("WerkWolf.Fernschreiber", 1, 0, "TelegramAPI", QString());
|
qmlRegisterUncreatableType<TDLibWrapper>(uri, 1, 0, "TelegramAPI", QString());
|
||||||
|
|
||||||
DBusAdaptor *dBusAdaptor = tdLibWrapper->getDBusAdaptor();
|
DBusAdaptor *dBusAdaptor = tdLibWrapper->getDBusAdaptor();
|
||||||
context->setContextProperty("dBusAdaptor", dBusAdaptor);
|
context->setContextProperty("dBusAdaptor", dBusAdaptor);
|
||||||
|
|
|
@ -124,7 +124,7 @@ void StickerManager::handleStickerSetReceived(const QVariantMap &stickerSet)
|
||||||
QVariantMap thumbnailFile = singleSticker.value("thumbnail").toMap().value("photo").toMap();
|
QVariantMap thumbnailFile = singleSticker.value("thumbnail").toMap().value("photo").toMap();
|
||||||
QVariantMap thumbnailLocalFile = thumbnailFile.value("local").toMap();
|
QVariantMap thumbnailLocalFile = thumbnailFile.value("local").toMap();
|
||||||
if (!thumbnailLocalFile.value("is_downloading_completed").toBool()) {
|
if (!thumbnailLocalFile.value("is_downloading_completed").toBool()) {
|
||||||
tdLibWrapper->downloadFile(thumbnailFile.value("id").toString());
|
tdLibWrapper->downloadFile(thumbnailFile.value("id").toInt());
|
||||||
this->reloadNeeded = true;
|
this->reloadNeeded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
367
src/tdlibfile.cpp
Normal file
367
src/tdlibfile.cpp
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2020 Slava Monich at al.
|
||||||
|
|
||||||
|
This file is part of Fernschreiber.
|
||||||
|
|
||||||
|
Fernschreiber is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Fernschreiber is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tdlibfile.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#define LOG(x) qDebug() << "[TDLibFile]" << x
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const QString ID("id");
|
||||||
|
const QString EXPECTED_SIZE("expected_size");
|
||||||
|
const QString SIZE("size");
|
||||||
|
const QString LOCAL("local");
|
||||||
|
const QString CAN_BE_DELETED("can_be_deleted");
|
||||||
|
const QString CAN_BE_DOWNLOADED("can_be_downloaded");
|
||||||
|
const QString DOWNLOAD_OFFSET("download_offset");
|
||||||
|
const QString DOWNLOADED_PREFIX_SIZE("downloaded_prefix_size");
|
||||||
|
const QString DOWNLOADED_SIZE("downloaded_size");
|
||||||
|
const QString IS_DOWNLODING_ACTIVE("is_downloading_active");
|
||||||
|
const QString IS_DOWNLODING_COMPELETED("is_downloading_completed");
|
||||||
|
const QString PATH("path");
|
||||||
|
const QString REMOTE("remote");
|
||||||
|
const QString IS_UPLOADING_ACTIVE("is_uploading_active");
|
||||||
|
const QString IS_UPLOADING_COMPLETED("is_uploading_completed");
|
||||||
|
const QString UNIQUE_ID("unique_id");
|
||||||
|
const QString UPLOADED_SIZE("uploaded_size");
|
||||||
|
|
||||||
|
const QString _TYPE("@type");
|
||||||
|
const QString TYPE_FILE("file");
|
||||||
|
const QString TYPE_LOCAL_FILE("localFile");
|
||||||
|
const QString TYPE_REMOTE_FILE("remoteFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
// s(SignalName,signalName)
|
||||||
|
#define QUEUED_SIGNALS(s) \
|
||||||
|
s(TdLib,tdlib) \
|
||||||
|
s(FileInfo,fileInfo) \
|
||||||
|
s(AutoLoad,autoLoad) \
|
||||||
|
s(Id,id) \
|
||||||
|
s(ExpectedSize,expectedSize) \
|
||||||
|
s(Size,size) \
|
||||||
|
s(Path,path) \
|
||||||
|
s(DownloadOffset,downloadOffset) \
|
||||||
|
s(DownloadedPrefixSize,downloadedPrefixSize) \
|
||||||
|
s(DownloadedSize,downloadedSize) \
|
||||||
|
s(CanBeDeleted,canBeDeleted) \
|
||||||
|
s(CanBeDownloaded,canBeDownloaded) \
|
||||||
|
s(DownloadingActive,downloadingActive) \
|
||||||
|
s(DownloadingCompleted,downloadingCompleted) \
|
||||||
|
s(RemoteId,remoteId) \
|
||||||
|
s(UniqueId,uniqueId) \
|
||||||
|
s(UploadedSize,uploadedSize) \
|
||||||
|
s(UploadingActive,uploadingActive) \
|
||||||
|
s(UploadingCompleted,uploadingCompleted)
|
||||||
|
|
||||||
|
typedef void (TDLibFile::*TDLibFileSignalEmitter)();
|
||||||
|
enum TDLibFileSignal {
|
||||||
|
#define SIGNAL_ENUM_(Name,name) Signal##Name##Changed,
|
||||||
|
QUEUED_SIGNALS(SIGNAL_ENUM_)
|
||||||
|
#undef SIGNAL_ENUM_
|
||||||
|
SignalCount
|
||||||
|
};
|
||||||
|
|
||||||
|
TDLibFile::TDLibFile()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
TDLibFile::TDLibFile(TDLibWrapper *tdlib)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
updateTDLibWrapper(tdlib);
|
||||||
|
// Reset queued signals
|
||||||
|
firstQueuedSignal = SignalCount;
|
||||||
|
queuedSignals = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TDLibFile::TDLibFile(TDLibWrapper *tdlib, const QVariantMap &fileInfo)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
updateTDLibWrapper(tdlib);
|
||||||
|
updateFileInfo(fileInfo);
|
||||||
|
// Reset queued signals
|
||||||
|
firstQueuedSignal = SignalCount;
|
||||||
|
queuedSignals = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::init()
|
||||||
|
{
|
||||||
|
tdLibWrapper = Q_NULLPTR;
|
||||||
|
queuedSignals = 0;
|
||||||
|
firstQueuedSignal = SignalCount;
|
||||||
|
autoLoad = false;
|
||||||
|
id = 0;
|
||||||
|
expected_size = 0;
|
||||||
|
size = 0;
|
||||||
|
download_offset = 0;
|
||||||
|
downloaded_prefix_size = 0;
|
||||||
|
downloaded_size = 0;
|
||||||
|
can_be_deleted = false;
|
||||||
|
can_be_downloaded = false;
|
||||||
|
is_downloading_active = false;
|
||||||
|
is_downloading_completed = false;
|
||||||
|
uploaded_size = 0;
|
||||||
|
is_uploading_active = false;
|
||||||
|
is_uploading_completed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::queueSignal(uint signal)
|
||||||
|
{
|
||||||
|
const uint signalBit = 1 << signal;
|
||||||
|
if (queuedSignals) {
|
||||||
|
queuedSignals |= signalBit;
|
||||||
|
if (firstQueuedSignal > signal) {
|
||||||
|
firstQueuedSignal = signal;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queuedSignals = signalBit;
|
||||||
|
firstQueuedSignal = signal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::emitQueuedSignals()
|
||||||
|
{
|
||||||
|
static const TDLibFileSignalEmitter emitSignal[] = {
|
||||||
|
#define SIGNAL_EMITTER_(Name,name) &TDLibFile::name##Changed,
|
||||||
|
QUEUED_SIGNALS(SIGNAL_EMITTER_)
|
||||||
|
#undef SIGNAL_EMITTER_
|
||||||
|
};
|
||||||
|
if (queuedSignals) {
|
||||||
|
// Reset first queued signal before emitting the signals.
|
||||||
|
// Signal handlers may emit new signals.
|
||||||
|
uint i = firstQueuedSignal;
|
||||||
|
firstQueuedSignal = SignalCount;
|
||||||
|
for (; i < SignalCount && queuedSignals; i++) {
|
||||||
|
const uint signalBit = 1 << i;
|
||||||
|
if (queuedSignals & signalBit) {
|
||||||
|
queuedSignals &= ~signalBit;
|
||||||
|
emit (this->*(emitSignal[i]))();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::setTDLibWrapper(QObject* obj)
|
||||||
|
{
|
||||||
|
updateTDLibWrapper(qobject_cast<TDLibWrapper*>(obj));
|
||||||
|
emitQueuedSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::updateTDLibWrapper(TDLibWrapper* tdlib)
|
||||||
|
{
|
||||||
|
if (tdlib != tdLibWrapper) {
|
||||||
|
if (tdLibWrapper) {
|
||||||
|
tdLibWrapper->disconnect(this);
|
||||||
|
}
|
||||||
|
tdLibWrapper = tdlib;
|
||||||
|
if (tdlib) {
|
||||||
|
connect(tdlib, SIGNAL(fileUpdated(int,QVariantMap)), SLOT(handleFileUpdated(int,QVariantMap)));
|
||||||
|
if (autoLoad) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queueSignal(SignalTdLibChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::setAutoLoad(bool enableAutoLoad)
|
||||||
|
{
|
||||||
|
if (autoLoad != enableAutoLoad) {
|
||||||
|
autoLoad = enableAutoLoad;
|
||||||
|
queueSignal(SignalAutoLoadChanged);
|
||||||
|
if (autoLoad) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
emitQueuedSignals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDLibFile::load()
|
||||||
|
{
|
||||||
|
if (id && tdLibWrapper && !is_downloading_active && !is_downloading_completed && can_be_downloaded) {
|
||||||
|
tdLibWrapper->downloadFile(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::setFileInfo(const QVariantMap &fileInfo)
|
||||||
|
{
|
||||||
|
updateFileInfo(fileInfo);
|
||||||
|
if (autoLoad) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
emitQueuedSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDLibFile::handleFileUpdated(int fileId, const QVariantMap &fileInfo)
|
||||||
|
{
|
||||||
|
if (id == fileId) {
|
||||||
|
LOG("File" << fileId << "updated");
|
||||||
|
setFileInfo(fileInfo);
|
||||||
|
emitQueuedSignals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"@type": "file",
|
||||||
|
"expected_size": 0,
|
||||||
|
"id": 12,
|
||||||
|
"size": 0,
|
||||||
|
"local": {
|
||||||
|
"@type": "localFile",
|
||||||
|
"can_be_deleted": false,
|
||||||
|
"can_be_downloaded": true,
|
||||||
|
"download_offset": 0,
|
||||||
|
"downloaded_prefix_size": 0,
|
||||||
|
"downloaded_size": 0,
|
||||||
|
"is_downloading_active": true,
|
||||||
|
"is_downloading_completed": false,
|
||||||
|
"path": ""
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"@type": "remoteFile",
|
||||||
|
"id": "AQADAgATXYBrly4AAwIAA2E2itkW____9UdPDiSysLQ4fwIAARgE",
|
||||||
|
"is_uploading_active": false,
|
||||||
|
"is_uploading_completed": true,
|
||||||
|
"unique_id": "AQADXYBrly4AAzh_AgAB",
|
||||||
|
"uploaded_size": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void TDLibFile::updateFileInfo(const QVariantMap &file)
|
||||||
|
{
|
||||||
|
if (file.value(_TYPE).toString() == TYPE_FILE) {
|
||||||
|
QString s;
|
||||||
|
qlonglong ll;
|
||||||
|
bool b, fileChanged = false;
|
||||||
|
int i = file.value(ID).toInt();
|
||||||
|
if (id != i) {
|
||||||
|
id = i;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalIdChanged);
|
||||||
|
}
|
||||||
|
ll = file.value(EXPECTED_SIZE).toLongLong();
|
||||||
|
if (expected_size != ll) {
|
||||||
|
expected_size = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalExpectedSizeChanged);
|
||||||
|
}
|
||||||
|
ll = file.value(SIZE).toLongLong();
|
||||||
|
if (size != ll) {
|
||||||
|
size = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalSizeChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVariantMap local(file.value(LOCAL).toMap());
|
||||||
|
if (local.value(_TYPE).toString() == TYPE_LOCAL_FILE) {
|
||||||
|
ll = local.value(DOWNLOAD_OFFSET).toLongLong();
|
||||||
|
if (download_offset != ll) {
|
||||||
|
download_offset = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalDownloadOffsetChanged);
|
||||||
|
}
|
||||||
|
ll = local.value(DOWNLOADED_PREFIX_SIZE).toLongLong();
|
||||||
|
if (downloaded_prefix_size != ll) {
|
||||||
|
downloaded_prefix_size = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalDownloadedPrefixSizeChanged);
|
||||||
|
}
|
||||||
|
ll = local.value(DOWNLOADED_SIZE).toLongLong();
|
||||||
|
if (downloaded_size != ll) {
|
||||||
|
downloaded_size = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalDownloadedSizeChanged);
|
||||||
|
}
|
||||||
|
b = local.value(CAN_BE_DELETED).toBool();
|
||||||
|
if (can_be_deleted != b) {
|
||||||
|
can_be_deleted = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalCanBeDeletedChanged);
|
||||||
|
}
|
||||||
|
b = local.value(CAN_BE_DOWNLOADED).toBool();
|
||||||
|
if (can_be_downloaded != b) {
|
||||||
|
can_be_downloaded = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalCanBeDownloadedChanged);
|
||||||
|
}
|
||||||
|
b = local.value(IS_DOWNLODING_ACTIVE).toBool();
|
||||||
|
if (is_downloading_active != b) {
|
||||||
|
is_downloading_active = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalDownloadingActiveChanged);
|
||||||
|
}
|
||||||
|
b = local.value(IS_DOWNLODING_COMPELETED).toBool();
|
||||||
|
if (is_downloading_completed != b) {
|
||||||
|
is_downloading_completed = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalDownloadingCompletedChanged);
|
||||||
|
}
|
||||||
|
s = local.value(PATH).toString();
|
||||||
|
if (path != s) {
|
||||||
|
path = s;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalPathChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVariantMap remote(file.value(REMOTE).toMap());
|
||||||
|
if (remote.value(_TYPE).toString() == TYPE_REMOTE_FILE) {
|
||||||
|
ll = file.value(UPLOADED_SIZE).toLongLong();
|
||||||
|
if (uploaded_size != ll) {
|
||||||
|
uploaded_size = ll;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalUploadedSizeChanged);
|
||||||
|
}
|
||||||
|
b = file.value(IS_UPLOADING_ACTIVE).toBool();
|
||||||
|
if (is_uploading_active != b) {
|
||||||
|
is_uploading_active = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalUploadingActiveChanged);
|
||||||
|
}
|
||||||
|
b = file.value(IS_UPLOADING_COMPLETED).toBool();
|
||||||
|
if (is_uploading_completed != b) {
|
||||||
|
is_uploading_completed = b;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalUploadingCompletedChanged);
|
||||||
|
}
|
||||||
|
s = local.value(ID).toString();
|
||||||
|
if (remote_id != s) {
|
||||||
|
remote_id = s;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalRemoteIdChanged);
|
||||||
|
}
|
||||||
|
s = local.value(UNIQUE_ID).toString();
|
||||||
|
if (unique_id != s) {
|
||||||
|
unique_id = s;
|
||||||
|
fileChanged = true;
|
||||||
|
queueSignal(SignalUniqueIdChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileChanged) {
|
||||||
|
infoMap = file;
|
||||||
|
queueSignal(SignalFileInfoChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
src/tdlibfile.h
Normal file
159
src/tdlibfile.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2020 Slava Monich at al.
|
||||||
|
|
||||||
|
This file is part of Fernschreiber.
|
||||||
|
|
||||||
|
Fernschreiber is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Fernschreiber is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TDLIBFILE_H
|
||||||
|
#define TDLIBFILE_H
|
||||||
|
|
||||||
|
#include "tdlibwrapper.h"
|
||||||
|
|
||||||
|
class TDLibFile : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QObject* tdlib READ getTDLibWrapper WRITE setTDLibWrapper NOTIFY tdlibChanged)
|
||||||
|
Q_PROPERTY(QVariantMap fileInformation READ getFileInfo WRITE setFileInfo NOTIFY fileInfoChanged)
|
||||||
|
Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
|
||||||
|
Q_PROPERTY(int fileId READ getId NOTIFY idChanged)
|
||||||
|
Q_PROPERTY(qlonglong expectedSize READ getExpectedSize NOTIFY expectedSizeChanged)
|
||||||
|
Q_PROPERTY(qlonglong size READ getSize NOTIFY sizeChanged)
|
||||||
|
Q_PROPERTY(QString path READ getPath NOTIFY pathChanged)
|
||||||
|
Q_PROPERTY(qlonglong downloadOffset READ getDownloadOffset NOTIFY downloadOffsetChanged)
|
||||||
|
Q_PROPERTY(qlonglong downloadedPrefixSize READ getDownloadedPrefixSize NOTIFY downloadedPrefixSizeChanged)
|
||||||
|
Q_PROPERTY(qlonglong downloadedSize READ getDownloadedSize NOTIFY downloadedSizeChanged)
|
||||||
|
Q_PROPERTY(bool canBeDeleted READ canBeDeleted NOTIFY canBeDeletedChanged)
|
||||||
|
Q_PROPERTY(bool canBeDownloaded READ canBeDownloaded NOTIFY canBeDownloadedChanged)
|
||||||
|
Q_PROPERTY(bool isDownloadingActive READ isDownloadingActive NOTIFY downloadingActiveChanged)
|
||||||
|
Q_PROPERTY(bool isDownloadingCompleted READ isDownloadingCompleted NOTIFY downloadingCompletedChanged)
|
||||||
|
Q_PROPERTY(QString remoteId READ getRemoteId NOTIFY remoteIdChanged)
|
||||||
|
Q_PROPERTY(QString uniqueId READ getUniqueId NOTIFY uniqueIdChanged)
|
||||||
|
Q_PROPERTY(qlonglong uploadedSize READ getUploadedSize NOTIFY uploadedSizeChanged)
|
||||||
|
Q_PROPERTY(bool isUploadingActive READ isUploadingActive NOTIFY uploadingActiveChanged)
|
||||||
|
Q_PROPERTY(bool isUploadingCompleted READ isUploadingCompleted NOTIFY uploadingCompletedChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
TDLibFile();
|
||||||
|
TDLibFile(TDLibWrapper *tdlib);
|
||||||
|
TDLibFile(TDLibWrapper *tdlib, const QVariantMap &fileInfo);
|
||||||
|
|
||||||
|
TDLibWrapper *getTDLibWrapper() const;
|
||||||
|
void setTDLibWrapper(QObject* obj);
|
||||||
|
|
||||||
|
const QVariantMap &getFileInfo() const;
|
||||||
|
void setFileInfo(const QVariantMap &fileInfo);
|
||||||
|
|
||||||
|
bool isAutoLoad() const;
|
||||||
|
void setAutoLoad(bool autoLoad);
|
||||||
|
|
||||||
|
int getId() const;
|
||||||
|
qlonglong getExpectedSize() const;
|
||||||
|
qlonglong getSize() const;
|
||||||
|
const QString &getPath() const;
|
||||||
|
qlonglong getDownloadOffset() const;
|
||||||
|
qlonglong getDownloadedPrefixSize() const;
|
||||||
|
qlonglong getDownloadedSize() const;
|
||||||
|
bool canBeDeleted() const;
|
||||||
|
bool canBeDownloaded() const;
|
||||||
|
bool isDownloadingActive() const;
|
||||||
|
bool isDownloadingCompleted() const;
|
||||||
|
const QString &getRemoteId() const;
|
||||||
|
const QString &getUniqueId() const;
|
||||||
|
qlonglong getUploadedSize() const;
|
||||||
|
bool isUploadingActive() const;
|
||||||
|
bool isUploadingCompleted() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE bool load();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void tdlibChanged();
|
||||||
|
void fileInfoChanged();
|
||||||
|
void autoLoadChanged();
|
||||||
|
void idChanged();
|
||||||
|
void expectedSizeChanged();
|
||||||
|
void sizeChanged();
|
||||||
|
void pathChanged();
|
||||||
|
void downloadOffsetChanged();
|
||||||
|
void downloadedPrefixSizeChanged();
|
||||||
|
void downloadedSizeChanged();
|
||||||
|
void canBeDeletedChanged();
|
||||||
|
void canBeDownloadedChanged();
|
||||||
|
void downloadingActiveChanged();
|
||||||
|
void downloadingCompletedChanged();
|
||||||
|
void remoteIdChanged();
|
||||||
|
void uniqueIdChanged();
|
||||||
|
void uploadedSizeChanged();
|
||||||
|
void uploadingActiveChanged();
|
||||||
|
void uploadingCompletedChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleFileUpdated(int fileId, const QVariantMap &fileInfo);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void updateTDLibWrapper(TDLibWrapper* tdlib);
|
||||||
|
void updateFileInfo(const QVariantMap &fileInfo);
|
||||||
|
void queueSignal(uint signal);
|
||||||
|
void emitQueuedSignals();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TDLibWrapper *tdLibWrapper;
|
||||||
|
uint queuedSignals;
|
||||||
|
uint firstQueuedSignal;
|
||||||
|
bool autoLoad;
|
||||||
|
// file
|
||||||
|
QVariantMap infoMap;
|
||||||
|
int id;
|
||||||
|
qlonglong expected_size;
|
||||||
|
qlonglong size;
|
||||||
|
// localFile
|
||||||
|
QString path;
|
||||||
|
qlonglong download_offset;
|
||||||
|
qlonglong downloaded_prefix_size;
|
||||||
|
qlonglong downloaded_size;
|
||||||
|
bool can_be_deleted;
|
||||||
|
bool can_be_downloaded;
|
||||||
|
bool is_downloading_active;
|
||||||
|
bool is_downloading_completed;
|
||||||
|
// remoteFile
|
||||||
|
QString remote_id;
|
||||||
|
QString unique_id;
|
||||||
|
qlonglong uploaded_size;
|
||||||
|
bool is_uploading_active;
|
||||||
|
bool is_uploading_completed;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline TDLibWrapper *TDLibFile::getTDLibWrapper() const { return tdLibWrapper; }
|
||||||
|
inline const QVariantMap &TDLibFile::getFileInfo() const { return infoMap; }
|
||||||
|
inline bool TDLibFile::isAutoLoad() const { return autoLoad; }
|
||||||
|
inline int TDLibFile::getId() const { return id; }
|
||||||
|
inline qlonglong TDLibFile::getExpectedSize() const { return expected_size; }
|
||||||
|
inline qlonglong TDLibFile::getSize() const { return size; }
|
||||||
|
inline const QString &TDLibFile::getPath() const { return path; }
|
||||||
|
inline qlonglong TDLibFile::getDownloadOffset() const { return download_offset; }
|
||||||
|
inline qlonglong TDLibFile::getDownloadedPrefixSize() const { return downloaded_prefix_size; }
|
||||||
|
inline qlonglong TDLibFile::getDownloadedSize() const { return downloaded_size; }
|
||||||
|
inline bool TDLibFile::canBeDeleted() const { return can_be_deleted; }
|
||||||
|
inline bool TDLibFile::canBeDownloaded() const { return can_be_downloaded; }
|
||||||
|
inline bool TDLibFile::isDownloadingActive() const { return is_downloading_active; }
|
||||||
|
inline bool TDLibFile::isDownloadingCompleted() const { return is_downloading_completed; }
|
||||||
|
inline const QString &TDLibFile::getRemoteId() const { return remote_id; }
|
||||||
|
inline const QString &TDLibFile::getUniqueId() const { return unique_id; }
|
||||||
|
inline qlonglong TDLibFile::getUploadedSize() const { return uploaded_size; }
|
||||||
|
inline bool TDLibFile::isUploadingActive() const { return is_uploading_active; }
|
||||||
|
inline bool TDLibFile::isUploadingCompleted() const { return is_uploading_completed; }
|
||||||
|
|
||||||
|
#endif // TDLIBFILE_H
|
|
@ -206,7 +206,7 @@ void TDLibWrapper::getChats()
|
||||||
this->sendRequest(requestObject);
|
this->sendRequest(requestObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDLibWrapper::downloadFile(const QString &fileId)
|
void TDLibWrapper::downloadFile(int fileId)
|
||||||
{
|
{
|
||||||
LOG("Downloading file " << fileId);
|
LOG("Downloading file " << fileId);
|
||||||
QVariantMap requestObject;
|
QVariantMap requestObject;
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
Q_INVOKABLE void setAuthenticationPassword(const QString &authenticationPassword);
|
Q_INVOKABLE void setAuthenticationPassword(const QString &authenticationPassword);
|
||||||
Q_INVOKABLE void registerUser(const QString &firstName, const QString &lastName);
|
Q_INVOKABLE void registerUser(const QString &firstName, const QString &lastName);
|
||||||
Q_INVOKABLE void getChats();
|
Q_INVOKABLE void getChats();
|
||||||
Q_INVOKABLE void downloadFile(const QString &fileId);
|
Q_INVOKABLE void downloadFile(int fileId);
|
||||||
Q_INVOKABLE void openChat(const QString &chatId);
|
Q_INVOKABLE void openChat(const QString &chatId);
|
||||||
Q_INVOKABLE void closeChat(const QString &chatId);
|
Q_INVOKABLE void closeChat(const QString &chatId);
|
||||||
Q_INVOKABLE void joinChat(const QString &chatId);
|
Q_INVOKABLE void joinChat(const QString &chatId);
|
||||||
|
|
Loading…
Reference in a new issue