diff --git a/src/core/utils/qfieldcloudutils.cpp b/src/core/utils/qfieldcloudutils.cpp index c7fafa1a7f..58dc175ecb 100644 --- a/src/core/utils/qfieldcloudutils.cpp +++ b/src/core/utils/qfieldcloudutils.cpp @@ -77,6 +77,30 @@ const QString QFieldCloudUtils::getProjectId( const QString &fileName ) return QString(); } +QString QFieldCloudUtils::userFriendlyErrorString( const QString &errorString ) +{ + QString resultErrorString = errorString.startsWith( "[QF/" ) ? tr( "A server error has occured, please try again." ) : tr( "A network error has occured, please try again." ); + + if ( errorString.contains( errorCodeOverQuota ) ) + { + resultErrorString = tr( "Your account's available storage is full." ); + } + + return resultErrorString; +} + +QString QFieldCloudUtils::documentationFromErrorString( const QString &errorString ) +{ + QString linkToDocumentation; + + if ( errorString.contains( errorCodeOverQuota ) ) + { + linkToDocumentation = "https://docs.qfield.org/get-started/storage-qfc/#add-qfieldcloud-storage"; + } + + return linkToDocumentation; +} + void QFieldCloudUtils::setProjectSetting( const QString &projectId, const QString &setting, const QVariant &value ) { thread_local QgsSettings settings; diff --git a/src/core/utils/qfieldcloudutils.h b/src/core/utils/qfieldcloudutils.h index e23f1ba9c5..67d42a59f6 100644 --- a/src/core/utils/qfieldcloudutils.h +++ b/src/core/utils/qfieldcloudutils.h @@ -20,6 +20,7 @@ #include #include + class QString; class QFieldCloudProjectsModel; class DeltaFileWrapperTest; @@ -99,6 +100,22 @@ class QFieldCloudUtils : public QObject */ Q_INVOKABLE static const QString getProjectId( const QString &fileName ); + /** + * Returns a user-friendly error message. + * + * @param errorString the error string to be processed. + * @return A user-friendly error message that will be displayed to the user, translated based on received error code. + */ + Q_INVOKABLE static QString userFriendlyErrorString( const QString &errorString ); + + /** + * Returns a documentation page hyperlink related to the provided error string. + * + * @param errorString the error string to be processed + * @return The hyperlink to the documentation page related to the provided error code, or an empty string if no match is found. + */ + Q_INVOKABLE static QString documentationFromErrorString( const QString &errorString ); + //! Sets a \a setting to a given \a value for project with given \a projectId to the permanent storage. static void setProjectSetting( const QString &projectId, const QString &setting, const QVariant &value ); @@ -113,6 +130,9 @@ class QFieldCloudUtils : public QObject //! Adds removes a \a fileName for a given \a projectId to the pending attachments list static void removePendingAttachment( const QString &projectId, const QString &fileName ); + + private: + static inline const QString errorCodeOverQuota { QStringLiteral( "over_quota" ) }; }; #endif // QFIELDCLOUDUTILS_H diff --git a/src/qml/QFieldCloudPopup.qml b/src/qml/QFieldCloudPopup.qml index 5ebc1fd9ba..1a0cd50f6e 100644 --- a/src/qml/QFieldCloudPopup.qml +++ b/src/qml/QFieldCloudPopup.qml @@ -301,7 +301,8 @@ Popup { detailsColor: Theme.secondaryTextColor font: Theme.tipFont - titleText: detailsText.startsWith('[QF/') ? qsTr('A server error has occured, please try again.') : qsTr('A network error has occured, please try again.') + externalLink: QFieldCloudUtils.documentationFromErrorString(detailsText) + titleText: QFieldCloudUtils.userFriendlyErrorString(detailsText) detailsText: '' Connections { diff --git a/src/qml/imports/Theme/QfCollapsibleMessage.qml b/src/qml/imports/Theme/QfCollapsibleMessage.qml index d1b65b55ec..562624e956 100644 --- a/src/qml/imports/Theme/QfCollapsibleMessage.qml +++ b/src/qml/imports/Theme/QfCollapsibleMessage.qml @@ -6,6 +6,7 @@ import Theme 1.0 Item { property bool collapsed: true + property string externalLink: "" property alias color: titleText.color property alias detailsColor: detailsText.color property alias font: titleText.font @@ -26,7 +27,6 @@ Item { Rectangle { id: background anchors.fill: parent - color: "transparent" border.color: titleText.color border.width: 1 @@ -36,28 +36,47 @@ Item { Text { id: titleText - width: parent.width - 5 anchors.top: parent.top anchors.left: parent.left - padding: 5 + leftPadding: 8 + topPadding: 10 + bottomPadding: 10 clip: true - font: Theme.defaultFont color: "black" - - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: Text.AlignLeft wrapMode: Text.WordWrap } + ToolButton { + id: externalLinkButton + z: mainMouseArea.z + 1 + visible: externalLink !== '' + flat: false + text: "?" + anchors.verticalCenter: titleText.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 4 + highlighted: true + Material.accent: Theme.mainBackgroundColor + font.bold: true + onClicked: { + Qt.openUrlExternally(externalLink); + } + background: Rectangle { + implicitWidth: 30 + implicitHeight: 30 + color: titleText.color + radius: background.radius + } + } + Rectangle { id: separator - - width: parent.width - 24 + width: parent.width - 36 anchors.top: titleText.bottom - anchors.left: parent.left - anchors.leftMargin: 12 - + anchors.horizontalCenter: parent.horizontalCenter height: 1 color: titleText.color opacity: 0.25 @@ -65,27 +84,25 @@ Item { Text { id: detailsText - width: parent.width - 5 anchors.top: separator.bottom - anchors.left: parent.left - padding: 5 + anchors.right: externalLinkButton.left + anchors.left: titleText.left + leftPadding: 8 + topPadding: 10 + bottomPadding: 10 clip: true - font.pointSize: titleText.font.pointSize / 1.5 font.weight: titleText.font.weight font.italic: titleText.font.italic font.family: titleText.font.family - color: titleText.color - - horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap } MouseArea { + id: mainMouseArea anchors.fill: parent - onClicked: { parent.collapsed = !parent.collapsed; }