Skip to content

Commit

Permalink
Show more informative error message when VFS hydration fails. Display…
Browse files Browse the repository at this point in the history
… a popup and put an error into activity list. More detailed logs.

Signed-off-by: alex-z <[email protected]>
  • Loading branch information
allexzander committed Oct 20, 2023
1 parent bac61c7 commit 727cd79
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/common/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ public slots:
void beginHydrating();
/// Emitted when the hydration ends
void doneHydrating();
// Emitted when hydration fails
void failureHydrating(int errorCode, int statusCode, const QString &errorString, const QString &fileName);

protected:
/** Setup the plugin for the folder.
Expand Down
3 changes: 3 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ set(client_UI_SRCS
passwordinputdialog.ui
proxyauthdialog.ui
mnemonicdialog.ui
vfsdownloaderrordialog.ui
wizard/flow2authwidget.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
Expand Down Expand Up @@ -158,6 +159,8 @@ set(client_SRCS
thumbnailjob.cpp
userinfo.h
userinfo.cpp
vfsdownloaderrordialog.h
vfsdownloaderrordialog.cpp
accountstate.h
accountstate.cpp
addcertificatedialog.h
Expand Down
18 changes: 18 additions & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "common/vfs.h"
#include "creds/abstractcredentials.h"
#include "settingsdialog.h"
#include "vfsdownloaderrordialog.h"

#include <QTimer>
#include <QUrl>
Expand Down Expand Up @@ -506,6 +507,7 @@ void Folder::startVfs()

connect(_vfs.data(), &Vfs::beginHydrating, this, &Folder::slotHydrationStarts);
connect(_vfs.data(), &Vfs::doneHydrating, this, &Folder::slotHydrationDone);
connect(_vfs.data(), &Vfs::failureHydrating, this, &Folder::slotHydrationFailed);

connect(&_engine->syncFileStatusTracker(), &SyncFileStatusTracker::fileStatusChanged,
_vfs.data(), &Vfs::fileStatusChanged);
Expand Down Expand Up @@ -1510,6 +1512,22 @@ void Folder::slotHydrationDone()
emit syncStateChange();
}

void Folder::slotHydrationFailed(int errorCode, int statusCode, const QString &errorString, const QString &fileName)
{
_syncResult.setStatus(SyncResult::Error);
const auto errorMessageDetails = tr("Virtual file download failed with code \"%1\", status \"%2\" and error message \"%3\"")
.arg(errorCode)
.arg(statusCode)
.arg(errorString);
_syncResult.appendErrorString(errorMessageDetails);

const auto errorMessageBox = new VfsDownloadErrorDialog(fileName, errorMessageDetails);
errorMessageBox->setAttribute(Qt::WA_DeleteOnClose);
errorMessageBox->show();
errorMessageBox->activateWindow();
errorMessageBox->raise();
}

void Folder::slotCapabilitiesChanged()
{
if (_accountState->account()->capabilities().filesLockAvailable()) {
Expand Down
3 changes: 3 additions & 0 deletions src/gui/folder.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ private slots:
/** Unblocks normal sync operation */
void slotHydrationDone();

/* Hydration failed, perform required steps to notify user */
void slotHydrationFailed(int errorCode, int statusCode, const QString &errorString, const QString &fileName);

void slotCapabilitiesChanged();

private:
Expand Down
35 changes: 35 additions & 0 deletions src/gui/vfsdownloaderrordialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*

Check notice on line 1 in src/gui/vfsdownloaderrordialog.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/vfsdownloaderrordialog.cpp

File src/gui/vfsdownloaderrordialog.cpp (lines 17, 21): Code does not conform to Custom style guidelines.
* Copyright (C) 2023 by Oleksandr Zolotov <[email protected]>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#include "vfsdownloaderrordialog.h"
#include "ui_vfsdownloaderrordialog.h"

namespace OCC {

VfsDownloadErrorDialog::VfsDownloadErrorDialog(const QString &fileName, const QString &errorMessage, QWidget *parent)
: QDialog(parent)
, _ui(new Ui::VfsDownloadErrorDialog)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

_ui->setupUi(this);
_ui->descriptionLabel->setText(tr("Error downloading %1").arg(fileName));
_ui->explanationLabel->setText(tr("%1 could not be downloaded.").arg(fileName));
_ui->moreDetailsLabel->setText(errorMessage);
_ui->moreDetailsLabel->setVisible(false);

connect(_ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
}

VfsDownloadErrorDialog::~VfsDownloadErrorDialog() = default;
}
35 changes: 35 additions & 0 deletions src/gui/vfsdownloaderrordialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*

Check notice on line 1 in src/gui/vfsdownloaderrordialog.h

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/vfsdownloaderrordialog.h

File src/gui/vfsdownloaderrordialog.h (lines 18, 20): Code does not conform to Custom style guidelines.
* Copyright (C) 2023 by Oleksandr Zolotov <[email protected]>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#pragma once
#include <QDialog>
#include <QScopedPointer>

namespace OCC {

namespace Ui {
class VfsDownloadErrorDialog;
}

class VfsDownloadErrorDialog : public QDialog
{
Q_OBJECT

public:
explicit VfsDownloadErrorDialog(const QString &fileName, const QString &errorMessage, QWidget *parent = nullptr);
~VfsDownloadErrorDialog() override;

private:
QScopedPointer<Ui::VfsDownloadErrorDialog> _ui;
};
}
166 changes: 166 additions & 0 deletions src/gui/vfsdownloaderrordialog.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OCC::VfsDownloadErrorDialog</class>
<widget class="QDialog" name="OCC::VfsDownloadErrorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>397</width>
<height>155</height>
</rect>
</property>
<property name="windowTitle">
<string>Download error</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="descriptionLabel">
<property name="text">
<string>Error downloading</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="explanationLabel">
<property name="text">
<string>could not be downloaded</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="moreDetailsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&gt; More details</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="moreDetailsLabel">
<property name="text">
<string>More details</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="200">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="200">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="115">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>moreDetailsButton</sender>
<signal>clicked()</signal>
<receiver>moreDetailsLabel</receiver>
<slot>show()</slot>
<hints>
<hint type="sourcelabel">
<x>47</x>
<y>112</y>
</hint>
<hint type="destinationlabel">
<x>198</x>
<y>141</y>
</hint>
</hints>
</connection>
<connection>
<sender>moreDetailsButton</sender>
<signal>clicked()</signal>
<receiver>moreDetailsButton</receiver>
<slot>hide()</slot>
<hints>
<hint type="sourcelabel">
<x>47</x>
<y>63</y>
</hint>
<hint type="destinationlabel">
<x>47</x>
<y>63</y>
</hint>
</hints>
</connection>
</connections>
</ui>
26 changes: 23 additions & 3 deletions src/libsync/vfs/cfapi/hydrationjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,21 @@ OCC::HydrationJob::Status OCC::HydrationJob::status() const
return _status;
}

int OCC::HydrationJob::errorCode() const
{
return _errorCode;
}

int OCC::HydrationJob::statusCode() const
{
return _statusCode;
}

QString OCC::HydrationJob::errorString() const
{
return _errorString;
}

void OCC::HydrationJob::start()
{
Q_ASSERT(_account);
Expand Down Expand Up @@ -334,16 +349,21 @@ void OCC::HydrationJob::finalize(OCC::VfsCfApi *vfs)

void OCC::HydrationJob::onGetFinished()
{
qCInfo(lcHydration) << "GETFileJob finished" << _requestId << _folderPath << _job->reply()->error();
_errorCode = _job->reply()->error();
_statusCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
_errorString = _job->reply()->errorString();

const auto isGetJobResultError = _job->reply()->error();
qCInfo(lcHydration) << "GETFileJob finished" << _requestId << _folderPath << _errorCode << _statusCode << _errorString;
// GETFileJob deletes itself after this signal was handled
_job = nullptr;
if (_isCancelled) {
_errorCode = 0;
_statusCode = 0;
_errorString.clear();
return;
}

if (isGetJobResultError) {
if (_errorCode) {
emitFinished(Error);
return;
}
Expand Down
7 changes: 7 additions & 0 deletions src/libsync/vfs/cfapi/hydrationjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class HydrationJob : public QObject

Status status() const;

[[nodiscard]] int errorCode() const;
[[nodiscard]] int statusCode() const;
[[nodiscard]] QString errorString() const;

void start();
void cancel();
void finalize(OCC::VfsCfApi *vfs);
Expand Down Expand Up @@ -114,6 +118,9 @@ public slots:
QLocalSocket *_signalSocket = nullptr;
GETFileJob *_job = nullptr;
Status _status = Success;
int _errorCode = 0;
int _statusCode = 0;
QString _errorString;
};

} // namespace OCC
3 changes: 3 additions & 0 deletions src/libsync/vfs/cfapi/vfs_cfapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ void VfsCfApi::onHydrationJobFinished(HydrationJob *job)
Q_ASSERT(d->hydrationJobs.contains(job));
qCInfo(lcCfApi) << "Hydration job finished" << job->requestId() << job->folderPath() << job->status();
emit hydrationRequestFinished(job->requestId());
if (!job->errorString().isEmpty()) {
emit failureHydrating(job->errorCode(), job->statusCode(), job->errorString(), job->folderPath());
}
}

int VfsCfApi::finalizeHydrationJob(const QString &requestId)
Expand Down

0 comments on commit 727cd79

Please sign in to comment.