Skip to content

Commit

Permalink
Improve 'Handle local file editing' feature. Add loading popup. Add f…
Browse files Browse the repository at this point in the history
…orce sync before opening a file.'

Signed-off-by: alex-z <blackslayer4@gmail.com>
  • Loading branch information
allexzander committed Oct 7, 2022
1 parent dec66ae commit a8686d0
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 8 deletions.
1 change: 1 addition & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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
43 changes: 38 additions & 5 deletions src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
static const char versionC[] = "version";
static const int maxFoldersVersion = 1;

namespace {
static constexpr auto editFileLocallyName = "editFileLocallyName";
}

namespace OCC {

Q_LOGGING_CATEGORY(lcFolderMan, "nextcloud.gui.folder.manager", QtInfoMsg)
Expand Down Expand Up @@ -1473,11 +1477,24 @@ 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->setProperty(editFileLocallyName, localFilePath);
folderForFile->startSync();
QObject::connect(folderForFile, &Folder::syncFinished, this, &FolderMan::slotSyncFinishedBeforeOpeningForLocalEditing);
}

void FolderMan::trayOverallStatus(const QList<Folder *> &folders,
Expand Down Expand Up @@ -1842,4 +1859,20 @@ void FolderMan::slotConnectToPushNotifications(Account *account)
}
}

void FolderMan::slotSyncFinishedBeforeOpeningForLocalEditing(const OCC::SyncResult &result)
{
Q_UNUSED(result);
const auto folderForFile = qobject_cast<Folder *>(sender());
QObject::disconnect(folderForFile, &Folder::syncFinished, this, &FolderMan::slotSyncFinishedBeforeOpeningForLocalEditing);
const auto localFilePath = folderForFile->property(editFileLocallyName).toString();
folderForFile->setProperty(editFileLocallyName, {});
// 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();
});
}

} // namespace OCC
2 changes: 2 additions & 0 deletions src/gui/folderman.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ private slots:
void slotProcessFilesPushNotification(Account *account);
void slotConnectToPushNotifications(Account *account);

void slotSyncFinishedBeforeOpeningForLocalEditing(const OCC::SyncResult &result);

private:
/** Adds a new folder, does not add it to the account settings and
* does not set an account on the new folder.
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 @@ -257,6 +257,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...";
QMetaObject::invokeMethod(_editFileLocallyLoadingDialog, "closeDialog");
_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
86 changes: 86 additions & 0 deletions src/gui/tray/EditFileLocallyLoadingDialog.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
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

function closeDialog() {
root.close();
Systray.destroyDialog(root);
}

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

0 comments on commit a8686d0

Please sign in to comment.