Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve 'Handle local file editing' feature. Add loading popup. Add f… #5054

Merged
merged 1 commit into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<file>src/gui/tray/ActivityItemContent.qml</file>
<file>src/gui/tray/TalkReplyTextField.qml</file>
<file>src/gui/tray/CallNotificationDialog.qml</file>
<file>src/gui/tray/EditFileLocallyLoadingDialog.qml</file>
<file>src/gui/tray/NCBusyIndicator.qml</file>
<file>src/gui/tray/NCToolTip.qml</file>
</qresource>
Expand Down
37 changes: 32 additions & 5 deletions src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1473,11 +1473,38 @@ void FolderMan::editFileLocally(const QString &accountDisplayName, const QString
return;
}

// In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl from a separate thread, or, there will be a freeze.
// To avoid searching for a specific folder and checking if the VFS is enabled - we just always call it from a separate thread.
QtConcurrent::run([foundFiles] {
QDesktopServices::openUrl(QUrl::fromLocalFile(foundFiles.first()));
});
const auto localFilePath = foundFiles.first();
const auto folderForFile = folderForPath(localFilePath);

if (!folderForFile) {
showError(accountFound, tr("Could not find a folder to sync."), relPath);
return;
}

const auto relPathSplit = relPath.split(QLatin1Char('/'));
if (relPathSplit.size() > 0) {
Systray::instance()->createEditFileLocallyLoadingDialog(relPathSplit.last());
} else {
showError(accountFound, tr("Could not find a file for local editing. Make sure its path is valid and it is synced locally."), relPath);
return;
}
folderForFile->startSync();
_localFileEditingSyncFinishedConnections.insert(localFilePath, QObject::connect(folderForFile, &Folder::syncFinished, this,
[this, localFilePath](const OCC::SyncResult &result) {
Q_UNUSED(result);
const auto foundConnectionIt = _localFileEditingSyncFinishedConnections.find(localFilePath);
if (foundConnectionIt != std::end(_localFileEditingSyncFinishedConnections) && foundConnectionIt.value()) {
QObject::disconnect(foundConnectionIt.value());
_localFileEditingSyncFinishedConnections.erase(foundConnectionIt);
}
// In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl
// from a separate thread, or, there will be a freeze. To avoid searching for a specific folder and checking
// if the VFS is enabled - we just always call it from a separate thread.
QtConcurrent::run([localFilePath]() {
QDesktopServices::openUrl(QUrl::fromLocalFile(localFilePath));
Systray::instance()->destroyEditFileLocallyLoadingDialog();
});
}));
}

void FolderMan::trayOverallStatus(const QList<Folder *> &folders,
Expand Down
2 changes: 2 additions & 0 deletions src/gui/folderman.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ private slots:

bool _appRestartRequired = false;

QMap<QString, QMetaObject::Connection> _localFileEditingSyncFinishedConnections;

static FolderMan *_instance;
explicit FolderMan(QObject *parent = nullptr);
friend class OCC::Application;
Expand Down
6 changes: 5 additions & 1 deletion src/gui/iconutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ QImage createSvgImageWithCustomColor(const QString &fileName, const QColor &cust
}();

if (iconBaseColors.contains(customColorName)) {
result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
if (requestedSize.width() > 0 && requestedSize.height() > 0) {
result = QIcon(QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName).pixmap(requestedSize).toImage();
} else {
result = QImage{QString{OCC::Theme::themePrefix} + customColorName + QStringLiteral("/") + fileName};
}
if (!result.isNull()) {
return result;
}
Expand Down
28 changes: 28 additions & 0 deletions src/gui/systray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,34 @@ void Systray::createCallDialog(const Activity &callNotification, const AccountSt
}
}

void Systray::createEditFileLocallyLoadingDialog(const QString &fileName)
{
if (_editFileLocallyLoadingDialog) {
return;
}

qCDebug(lcSystray) << "Opening a file local editing dialog...";

const auto editFileLocallyLoadingDialog = new QQmlComponent(_trayEngine, QStringLiteral("qrc:/qml/src/gui/tray/EditFileLocallyLoadingDialog.qml"));

if (editFileLocallyLoadingDialog->isError()) {
qCWarning(lcSystray) << editFileLocallyLoadingDialog->errorString();
return;
}

_editFileLocallyLoadingDialog = editFileLocallyLoadingDialog->createWithInitialProperties(QVariantMap{{QStringLiteral("fileName"), fileName}});
}

void Systray::destroyEditFileLocallyLoadingDialog()
{
if (!_editFileLocallyLoadingDialog) {
return;
}
qCDebug(lcSystray) << "Closing a file local editing dialog...";
_editFileLocallyLoadingDialog->deleteLater();
_editFileLocallyLoadingDialog = nullptr;
}

void Systray::slotCurrentUserChanged()
{
if (_trayEngine) {
Expand Down
4 changes: 4 additions & 0 deletions src/gui/systray.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class Systray
void showUpdateMessage(const QString &title, const QString &message, const QUrl &webUrl);
void setToolTip(const QString &tip);
void createCallDialog(const Activity &callNotification, const AccountStatePtr accountState);
void createEditFileLocallyLoadingDialog(const QString &fileName);
void destroyEditFileLocallyLoadingDialog();

Q_REQUIRED_RESULT QString windowTitle() const;
Q_REQUIRED_RESULT bool useNormalWindow() const;
Expand Down Expand Up @@ -160,6 +162,8 @@ private slots:
AccessManagerFactory _accessManagerFactory;

QSet<qlonglong> _callsAlreadyNotified;

QPointer<QObject> _editFileLocallyLoadingDialog;
};

} // namespace OCC
Expand Down
81 changes: 81 additions & 0 deletions src/gui/tray/EditFileLocallyLoadingDialog.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import QtQuick 2.15
import QtQuick.Window 2.15
import Style 1.0
import com.nextcloud.desktopclient 1.0
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15

Window {
id: root
flags: Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint

color: "transparent"

width: 320
height: contentLayout.implicitHeight

property string fileName: ""

readonly property real fontPixelSize: Style.topLinePixelSize * 1.5
readonly property real iconWidth: fontPixelSize * 2

Component.onCompleted: {
Systray.forceWindowInit(root);
x = Screen.width / 2 - width / 2
y = Screen.height / 2 - height / 2
root.show();
root.raise();
root.requestActivate();
}

Rectangle {
id: windowBackground
color: Style.backgroundColor
radius: Style.trayWindowRadius
border.color: Style.ncTextColor
anchors.fill: parent
}

ColumnLayout {
id: contentLayout
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.standardSpacing
anchors.rightMargin: Style.standardSpacing
spacing: Style.standardSpacing
NCBusyIndicator {
id: busyIndicator
Layout.topMargin: Style.standardSpacing
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: root.iconWidth
Layout.preferredHeight: root.iconWidth
imageSourceSizeHeight: root.iconWidth
imageSourceSizeWidth: root.iconWidth
padding: 0
color: Style.ncTextColor
running: true
}
Label {
id: labelFileName
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
text: root.fileName
elide: Text.ElideRight
font.bold: true
font.pixelSize: root.fontPixelSize
color: Style.ncTextColor
horizontalAlignment: Text.AlignHCenter
}
Label {
id: labelMessage
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.bottomMargin: Style.standardSpacing
text: qsTr("Opening for local editing")
elide: Text.ElideRight
font.pixelSize: root.fontPixelSize
color: Style.ncTextColor
horizontalAlignment: Text.AlignHCenter
}
}
}
7 changes: 5 additions & 2 deletions src/gui/tray/NCBusyIndicator.qml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ BusyIndicator {
property color color: Style.ncSecondaryTextColor
property string imageSource: "image://svgimage-custom-color/change.svg/"

property int imageSourceSizeWidth: 64
property int imageSourceSizeHeight: 64

contentItem: Image {
id: contentImage

Expand All @@ -31,8 +34,8 @@ BusyIndicator {
verticalAlignment: Image.AlignVCenter

source: colourableImage ? root.imageSource + root.color : root.imageSource
sourceSize.width: 64
sourceSize.height: 64
sourceSize.width: root.imageSourceSizeWidth
sourceSize.height: root.imageSourceSizeHeight
fillMode: Image.PreserveAspectFit

mipmap: true
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
bool fileCanBeUnlocked(SyncJournalDb * const journal, const QString &folderRelativePath) const;

void setTrustCertificates(bool trustCertificates);
[[nodiscard]] bool trustCertificates() const;
bool trustCertificates() const;

public slots:
/// Used when forgetting credentials
Expand Down