Rewrite FileDialog in C++ && add setting to force async load timelime.
Also fixes repeat section label and empty space when message is redacted. Fixes #27
This commit is contained in:
parent
1e5fda47ab
commit
09fdd52524
|
@ -8,6 +8,8 @@ import "form"
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
property alias lazyLoad: generalForm.lazyLoad
|
property alias lazyLoad: generalForm.lazyLoad
|
||||||
|
property alias asyncMessageDelegate: generalForm.asyncMessageDelegate
|
||||||
|
|
||||||
property alias darkTheme: appearanceForm.darkTheme
|
property alias darkTheme: appearanceForm.darkTheme
|
||||||
property alias miniMode: appearanceForm.miniMode
|
property alias miniMode: appearanceForm.miniMode
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import QtQuick 2.9
|
|
||||||
import QtQuick.Controls 2.2
|
|
||||||
import QtQuick.Dialogs 1.2
|
|
||||||
|
|
||||||
FileDialog {
|
|
||||||
id: locationDialog
|
|
||||||
title: "Please choose a location"
|
|
||||||
folder: shortcuts.home
|
|
||||||
selectFolder: true
|
|
||||||
|
|
||||||
onAccepted: currentRoom.downloadFile(eventId, folder + "/" + currentRoom.fileNameToDownload(eventId))
|
|
||||||
onVisibleChanged: visible ? {} : locationDialog.destroy()
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ Item {
|
||||||
onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {}
|
onDownloadedChanged: downloaded && openOnFinished ? openSavedFile() : {}
|
||||||
|
|
||||||
function saveFileAs() {
|
function saveFileAs() {
|
||||||
Qt.createComponent("DownloadDialog.qml").createObject(this).open()
|
matriqueController.saveFileAs(currentRoom, eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadAndOpen()
|
function downloadAndOpen()
|
||||||
|
|
|
@ -4,7 +4,7 @@ import QtQuick.Controls.Material 2.2
|
||||||
import Matrique 0.1
|
import Matrique 0.1
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: messageDelegate
|
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
|
||||||
|
|
||||||
readonly property bool darkTheme: Material.theme == Material.Dark
|
readonly property bool darkTheme: Material.theme == Material.Dark
|
||||||
readonly property color background: darkTheme ? "#242424" : "lightgrey"
|
readonly property color background: darkTheme ? "#242424" : "lightgrey"
|
||||||
|
@ -12,7 +12,7 @@ Item {
|
||||||
readonly property bool sentByMe: author === currentRoom.localUser
|
readonly property bool sentByMe: author === currentRoom.localUser
|
||||||
readonly property bool isState: eventType === "state" || eventType === "emote"
|
readonly property bool isState: eventType === "state" || eventType === "emote"
|
||||||
|
|
||||||
visible: marks !== EventStatus.Hidden
|
id: messageDelegate
|
||||||
|
|
||||||
z: -5
|
z: -5
|
||||||
width: delegateLoader.width
|
width: delegateLoader.width
|
||||||
|
@ -29,8 +29,10 @@ Item {
|
||||||
Loader {
|
Loader {
|
||||||
id: delegateLoader
|
id: delegateLoader
|
||||||
|
|
||||||
|
asynchronous: setting.asyncMessageDelegate
|
||||||
|
|
||||||
source: {
|
source: {
|
||||||
if (eventType == "redaction") return ""
|
if (eventType == "redaction" || hidden) return ""
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case "state":
|
case "state":
|
||||||
case "emote":
|
case "emote":
|
||||||
|
|
|
@ -191,12 +191,15 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Column {
|
delegate: Column {
|
||||||
|
readonly property bool hidden: marks === EventStatus.Redacted || marks === EventStatus.Hidden
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
height: hidden ? -8 : undefined
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
width: parent.width * 0.8
|
width: parent.width * 0.8
|
||||||
visible: section !== aboveSection
|
visible: section !== aboveSection && !hidden
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
|
@ -300,30 +303,19 @@ Item {
|
||||||
|
|
||||||
contentItem: MaterialIcon { icon: "\ue226" }
|
contentItem: MaterialIcon { icon: "\ue226" }
|
||||||
|
|
||||||
onClicked: fileDialog.visible = true
|
onClicked: {
|
||||||
|
|
||||||
FileDialog {
|
|
||||||
id: fileDialog
|
|
||||||
title: "Please choose a file"
|
|
||||||
folder: shortcuts.home
|
|
||||||
selectMultiple: false
|
|
||||||
onAccepted: {
|
|
||||||
currentRoom.uploadFile(fileUrl, fileUrl, matriqueController.getMIME(fileUrl))
|
|
||||||
var fileTransferProgressCallback = function(id, sent, total) {
|
var fileTransferProgressCallback = function(id, sent, total) {
|
||||||
if (id == fileUrl) { inputField.progress = sent / total }
|
inputField.progress = sent / total
|
||||||
}
|
}
|
||||||
var completedCallback = function(id, localFile, mxcUrl) {
|
var completedCallback = function(id, localFile, mxcUrl) {
|
||||||
if (id == fileUrl) {
|
|
||||||
matriqueController.postFile(currentRoom, localFile, mxcUrl)
|
|
||||||
inputField.progress = 0
|
inputField.progress = 0
|
||||||
currentRoom.fileTransferCompleted.disconnect(fileTransferProgressCallback)
|
currentRoom.fileTransferCompleted.disconnect(fileTransferProgressCallback)
|
||||||
currentRoom.fileTransferCompleted.disconnect(completedCallback)
|
currentRoom.fileTransferCompleted.disconnect(completedCallback)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
currentRoom.fileTransferProgress.connect(fileTransferProgressCallback)
|
currentRoom.fileTransferProgress.connect(fileTransferProgressCallback)
|
||||||
currentRoom.fileTransferCompleted.connect(completedCallback)
|
currentRoom.fileTransferCompleted.connect(completedCallback)
|
||||||
}
|
matriqueController.uploadFile(currentRoom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import QtQuick 2.9
|
|
||||||
|
|
||||||
Item {
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,12 +3,18 @@ import QtQuick.Controls 2.2
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
property alias lazyLoad: lazyLoadSwitch.checked
|
property alias lazyLoad: lazyLoadSwitch.checked
|
||||||
|
property alias asyncMessageDelegate: asyncMessageDelegateSwitch.checked
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Switch {
|
Switch {
|
||||||
id: lazyLoadSwitch
|
id: lazyLoadSwitch
|
||||||
text: "Lazy Load at Initial Sync"
|
text: "Lazy load at initial sync"
|
||||||
}
|
}
|
||||||
|
Switch {
|
||||||
|
id: asyncMessageDelegateSwitch
|
||||||
|
text: "Force loading message delegates asynchronously"
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Invoke GC"
|
text: "Invoke GC"
|
||||||
highlighted: true
|
highlighted: true
|
||||||
|
|
|
@ -33,6 +33,7 @@ ApplicationWindow {
|
||||||
property alias token: matriqueController.token
|
property alias token: matriqueController.token
|
||||||
|
|
||||||
property alias lazyLoad: settingPage.lazyLoad
|
property alias lazyLoad: settingPage.lazyLoad
|
||||||
|
property alias asyncMessageDelegate: settingPage.asyncMessageDelegate
|
||||||
|
|
||||||
property alias darkTheme: settingPage.darkTheme
|
property alias darkTheme: settingPage.darkTheme
|
||||||
property alias miniMode: settingPage.miniMode
|
property alias miniMode: settingPage.miniMode
|
||||||
|
|
2
res.qrc
2
res.qrc
|
@ -23,7 +23,6 @@
|
||||||
<file>qml/component/AvatarContainer.qml</file>
|
<file>qml/component/AvatarContainer.qml</file>
|
||||||
<file>qml/form/RoomListForm.qml</file>
|
<file>qml/form/RoomListForm.qml</file>
|
||||||
<file>qml/component/AudioBubble.qml</file>
|
<file>qml/component/AudioBubble.qml</file>
|
||||||
<file>qml/form/SettingForm.qml</file>
|
|
||||||
<file>qml/Setting.qml</file>
|
<file>qml/Setting.qml</file>
|
||||||
<file>qml/form/SettingAccountForm.qml</file>
|
<file>qml/form/SettingAccountForm.qml</file>
|
||||||
<file>qml/form/SettingAppearanceForm.qml</file>
|
<file>qml/form/SettingAppearanceForm.qml</file>
|
||||||
|
@ -32,6 +31,5 @@
|
||||||
<file>qml/form/SettingGeneralForm.qml</file>
|
<file>qml/form/SettingGeneralForm.qml</file>
|
||||||
<file>qml/component/EmojiPicker.qml</file>
|
<file>qml/component/EmojiPicker.qml</file>
|
||||||
<file>qml/component/EmojiButton.qml</file>
|
<file>qml/component/EmojiButton.qml</file>
|
||||||
<file>qml/component/DownloadDialog.qml</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QMimeDatabase>
|
|
||||||
|
|
||||||
Controller::Controller(QObject* parent) : QObject(parent) {
|
Controller::Controller(QObject* parent) : QObject(parent) {
|
||||||
connect(m_connection, &Connection::connected, this, &Controller::connected);
|
connect(m_connection, &Connection::connected, this, &Controller::connected);
|
||||||
|
@ -74,6 +74,20 @@ void Controller::reconnect() {
|
||||||
m_connection->connectWithToken(userID, token, "");
|
m_connection->connectWithToken(userID, token, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::uploadFile(Room* room) {
|
||||||
|
if (!room) return;
|
||||||
|
auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as"));
|
||||||
|
if (!localFile.isEmpty()) {
|
||||||
|
room->uploadFile(localFile.toString(), localFile, getMIME(localFile));
|
||||||
|
QMetaObject::Connection* const connection = new QMetaObject::Connection;
|
||||||
|
*connection = connect(room, &Room::fileTransferCompleted,
|
||||||
|
[=](QString id, QUrl localFile, QUrl mxcUrl) {
|
||||||
|
disconnect(*connection);
|
||||||
|
postFile(room, localFile, mxcUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Controller::postFile(Room* room, const QUrl& localFile,
|
void Controller::postFile(Room* room, const QUrl& localFile,
|
||||||
const QUrl& mxcUrl) {
|
const QUrl& mxcUrl) {
|
||||||
const QString mime = getMIME(localFile);
|
const QString mime = getMIME(localFile);
|
||||||
|
@ -90,9 +104,7 @@ void Controller::postFile(Room* room, const QUrl& localFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Controller::getMIME(const QUrl& fileUrl) const {
|
QString Controller::getMIME(const QUrl& fileUrl) const {
|
||||||
QMimeDatabase* db = new QMimeDatabase();
|
const QString mime = m_db.mimeTypeForFile(fileUrl.toLocalFile()).name();
|
||||||
const QString mime = db->mimeTypeForFile(fileUrl.toLocalFile()).name();
|
|
||||||
delete db;
|
|
||||||
return mime;
|
return mime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,3 +137,11 @@ void Controller::createDirectChat(const QString& userID) {
|
||||||
void Controller::copyToClipboard(const QString& text) {
|
void Controller::copyToClipboard(const QString& text) {
|
||||||
m_clipboard->setText(text);
|
m_clipboard->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Controller::saveFileAs(Room* room, QString eventId) {
|
||||||
|
if (!room) return;
|
||||||
|
auto fileName = QFileDialog::getSaveFileName(
|
||||||
|
Q_NULLPTR, tr("Save File as"), room->fileNameToDownload(eventId));
|
||||||
|
if (!fileName.isEmpty())
|
||||||
|
room->downloadFile(eventId, QUrl::fromLocalFile(fileName));
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QMimeDatabase>
|
||||||
|
|
||||||
using namespace QMatrixClient;
|
using namespace QMatrixClient;
|
||||||
|
|
||||||
|
@ -84,11 +85,15 @@ class Controller : public QObject {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QClipboard* m_clipboard = QApplication::clipboard();
|
QClipboard* m_clipboard = QApplication::clipboard();
|
||||||
|
QMimeDatabase m_db;
|
||||||
|
|
||||||
void connected();
|
void connected();
|
||||||
void resync();
|
void resync();
|
||||||
void reconnect();
|
void reconnect();
|
||||||
|
|
||||||
|
QString getMIME(const QUrl& fileUrl) const;
|
||||||
|
void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectionChanged();
|
void connectionChanged();
|
||||||
void isLoginChanged();
|
void isLoginChanged();
|
||||||
|
@ -99,13 +104,13 @@ class Controller : public QObject {
|
||||||
void errorOccured();
|
void errorOccured();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void postFile(Room* room, const QUrl& localFile, const QUrl& mxcUrl);
|
void uploadFile(Room* room);
|
||||||
QString getMIME(const QUrl& fileUrl) const;
|
|
||||||
void forgetRoom(const QString& roomID);
|
void forgetRoom(const QString& roomID);
|
||||||
void joinRoom(const QString& alias);
|
void joinRoom(const QString& alias);
|
||||||
void createRoom(const QString& name, const QString& topic);
|
void createRoom(const QString& name, const QString& topic);
|
||||||
void createDirectChat(const QString& userID);
|
void createDirectChat(const QString& userID);
|
||||||
void copyToClipboard(const QString& text);
|
void copyToClipboard(const QString& text);
|
||||||
|
void saveFileAs(Room* room, QString eventId);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTROLLER_H
|
#endif // CONTROLLER_H
|
||||||
|
|
Loading…
Reference in New Issue