Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8176e17

Browse files
committedMar 15, 2024·
Port the FolderStatus to Qml
This prepares the work on the improved accessibility Issue: #11527
1 parent 2695618 commit 8176e17

25 files changed

+895
-806
lines changed
 

‎CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
2020

2121
find_package(QT 6.2 NAMES Qt6 COMPONENTS Core REQUIRED)
2222

23-
find_package(Qt6 COMPONENTS Core Concurrent Network Widgets Xml REQUIRED)
23+
find_package(Qt6 COMPONENTS Core Concurrent Network Widgets Xml Quick QuickWidgets QuickControls2 REQUIRED)
2424
find_package(Qt6LinguistTools REQUIRED)
2525
get_target_property (QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
2626
message(STATUS "Using Qt ${QT_VERSION} (${QT_QMAKE_EXECUTABLE})")
@@ -37,6 +37,9 @@ include(ECMSetupVersion)
3737
include(KDECompilerSettings NO_POLICY_SCOPE)
3838
include(ECMEnableSanitizers)
3939

40+
# while we use qt_add_qml_module instead of ecm_add_qml_module
41+
# include ECMQmlModule to set up the policies
42+
include(ECMQmlModule)
4043

4144
if(UNIT_TESTING)
4245
message(DEPRECATION "Setting UNIT_TESTING is deprecated please use BUILD_TESTING")

‎changelog/unreleased/11491

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Enhancement: New Folder status
2+
3+
We rewrote the Folder status page.
4+
5+
https://github.com/owncloud/client/pull/11491
6+
https://github.com/owncloud/client/issues/11527

‎src/gui/CMakeLists.txt

+13-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ set(client_SRCS
3737
folder.cpp
3838
folderman.cpp
3939
folderstatusmodel.cpp
40-
folderstatusdelegate.cpp
4140
folderwatcher.cpp
4241
generalsettings.cpp
4342
ignorelisteditor.cpp
@@ -102,16 +101,27 @@ add_subdirectory(loginrequireddialog)
102101

103102
add_library(owncloudCore STATIC ${final_src})
104103
set_target_properties(owncloudCore PROPERTIES AUTOUIC ON AUTORCC ON)
104+
# for the generated qml module
105+
target_include_directories(owncloudCore PRIVATE models)
105106
target_link_libraries(owncloudCore
106107
PUBLIC
107-
Qt::Widgets Qt::Network Qt::Xml
108+
Qt::Widgets Qt::Network Qt::Xml Qt::Quick Qt::QuickWidgets Qt::QuickControls2
108109
newwizard folderwizard spaces loginrequireddialog
109110
libsync
110111
Qt6Keychain::Qt6Keychain
111112
)
112113

113114
apply_common_target_settings(owncloudCore)
115+
qt_add_qml_module(owncloudCore
116+
URI org.ownCloud.qmlcomponents
117+
VERSION 1.0
118+
NAMESPACE OCC
119+
QML_FILES
120+
qml/FolderDelegate.qml
121+
qml/FolderError.qml
122+
)
114123

124+
target_link_libraries(owncloudCore PUBLIC owncloudCoreplugin)
115125

116126
add_subdirectory(spaces)
117127

@@ -159,7 +169,7 @@ set_target_properties(owncloud PROPERTIES
159169
AUTORCC ON
160170
)
161171
apply_common_target_settings(owncloud)
162-
target_link_libraries(owncloud owncloudCore owncloudResources KDAB::kdsingleapplication )
172+
target_link_libraries(owncloud PUBLIC owncloudCore owncloudResources KDAB::kdsingleapplication )
163173

164174
MESSAGE(STATUS "OWNCLOUD_SIDEBAR_ICONS: ${APPLICATION_ICON_NAME}: ${OWNCLOUD_SIDEBAR_ICONS}")
165175

‎src/gui/accountsettings.cpp

+123-220
Large diffs are not rendered by default.

‎src/gui/accountsettings.h

+13-15
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@
1515
#ifndef ACCOUNTSETTINGS_H
1616
#define ACCOUNTSETTINGS_H
1717

18-
#include <QWidget>
1918

2019
#include "folder.h"
2120
#include "loginrequireddialog.h"
2221
#include "owncloudgui.h"
2322
#include "progressdispatcher.h"
2423

24+
25+
#include <QSortFilterProxyModel>
26+
#include <QWidget>
27+
2528
class QModelIndex;
2629
class QNetworkReply;
2730
class QLabel;
28-
class QSortFilterProxyModel;
2931

3032
namespace OCC {
3133
class AccountModalWidget;
@@ -49,6 +51,7 @@ class AccountSettings : public QWidget
4951
{
5052
Q_OBJECT
5153
Q_PROPERTY(AccountStatePtr accountState MEMBER _accountState)
54+
Q_PROPERTY(QSortFilterProxyModel *model MEMBER _sortModel CONSTANT)
5255

5356
public:
5457
enum class ModalWidgetSizePolicy { Minimum = QSizePolicy::Minimum, Expanding = QSizePolicy::Expanding };
@@ -62,6 +65,8 @@ class AccountSettings : public QWidget
6265
void addModalLegacyDialog(QWidget *widget, ModalWidgetSizePolicy sizePolicy);
6366
void addModalWidget(AccountModalWidget *widget);
6467

68+
auto model() { return _sortModel; }
69+
6570
signals:
6671
void folderChanged();
6772
void showIssuesList();
@@ -71,18 +76,15 @@ public slots:
7176

7277
protected slots:
7378
void slotAddFolder();
74-
void slotEnableCurrentFolder(bool terminate = false);
75-
void slotScheduleCurrentFolder();
76-
void slotScheduleCurrentFolderForceFullDiscovery();
77-
void slotForceSyncCurrentFolder();
78-
void slotRemoveCurrentFolder();
79-
void slotEnableVfsCurrentFolder();
80-
void slotDisableVfsCurrentFolder();
79+
void slotEnableCurrentFolder(Folder *folder, bool terminate = false);
80+
void slotForceSyncCurrentFolder(Folder *folder);
81+
void slotRemoveCurrentFolder(Folder *folder);
82+
void slotEnableVfsCurrentFolder(Folder *folder);
83+
void slotDisableVfsCurrentFolder(Folder *folder);
8184
void slotFolderWizardAccepted();
8285
void slotDeleteAccount();
8386
void slotToggleSignInState();
84-
void slotCustomContextMenuRequested(const QPoint &);
85-
void slotFolderListClicked(const QModelIndex &indx);
87+
void slotCustomContextMenuRequested(Folder *folder);
8688

8789
private:
8890
void showSelectiveSyncDialog(Folder *folder);
@@ -93,13 +95,9 @@ protected slots:
9395
void createAccountToolbox();
9496
void doForceSyncCurrentFolder(Folder *selectedFolder);
9597

96-
/// Returns the alias of the selected folder, empty string if none
97-
Folder *selectedFolder() const;
98-
9998
Ui::AccountSettings *ui;
10099

101100
FolderStatusModel *_model;
102-
FolderStatusDelegate *_delegate;
103101
QSortFilterProxyModel *_sortModel;
104102
bool _wasDisabledBefore;
105103
AccountStatePtr _accountState;

‎src/gui/accountsettings.ui

+6-14
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,7 @@
147147
<widget class="QWidget" name="folderListPage">
148148
<layout class="QVBoxLayout" name="verticalLayout_6">
149149
<item>
150-
<widget class="QListView" name="_folderList">
151-
<property name="sizePolicy">
152-
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
153-
<horstretch>0</horstretch>
154-
<verstretch>5</verstretch>
155-
</sizepolicy>
156-
</property>
157-
<property name="contextMenuPolicy">
158-
<enum>Qt::CustomContextMenu</enum>
159-
</property>
160-
<property name="editTriggers">
161-
<set>QAbstractItemView::NoEditTriggers</set>
162-
</property>
163-
</widget>
150+
<widget class="QQuickWidget" name="quickWidget"/>
164151
</item>
165152
<item>
166153
<layout class="QHBoxLayout" name="horizontalLayout_5">
@@ -193,6 +180,11 @@
193180
</layout>
194181
</widget>
195182
<customwidgets>
183+
<customwidget>
184+
<class>QQuickWidget</class>
185+
<extends>QWidget</extends>
186+
<header location="global">QtQuickWidgets/QQuickWidget</header>
187+
</customwidget>
196188
<customwidget>
197189
<class>QProgressIndicator</class>
198190
<extends>QWidget</extends>

‎src/gui/folder.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
#include <QDateTime>
2828
#include <QObject>
29-
#include <QStringList>
3029
#include <QUuid>
30+
#include <QtQml/QtQml>
3131

3232
#include <chrono>
3333
#include <memory>
@@ -146,6 +146,7 @@ class FolderDefinition
146146
class Folder : public QObject
147147
{
148148
Q_OBJECT
149+
QML_ELEMENT
149150

150151
public:
151152
enum class ChangeReason {

‎src/gui/folderstatusdelegate.cpp

-316
This file was deleted.

‎src/gui/folderstatusdelegate.h

-57
This file was deleted.

‎src/gui/folderstatusmodel.cpp

+147-146
Large diffs are not rendered by default.

‎src/gui/folderstatusmodel.h

+28-26
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
#include "progressdispatcher.h"
2020

2121
#include <QAbstractItemModel>
22-
#include <QLoggingCategory>
23-
#include <QVector>
2422
#include <QElapsedTimer>
25-
#include <QPointer>
23+
#include <QLoggingCategory>
24+
#include <QQuickImageProvider>
25+
#include <QtQml/QQmlEngine>
2626

2727
class QNetworkReply;
2828

@@ -43,34 +43,22 @@ namespace {
4343
class FolderStatusModel : public QAbstractTableModel
4444
{
4545
Q_OBJECT
46+
QML_ELEMENT
4647
public:
47-
enum class Columns {
48-
HeaderRole, // must be 0 as it is also used from the default delegate
49-
FolderPathRole, // for a SubFolder it's the complete path
50-
FolderSecondPathRole,
51-
FolderConflictMsg,
48+
enum class Roles {
49+
ToolTip = Qt::ToolTipRole,
50+
DisplayName = Qt::UserRole + 1, // must be 0 as it is also used from the default delegate
51+
Subtitle,
5252
FolderErrorMsg,
53-
FolderSyncPaused,
54-
FolderStatusIconRole,
55-
FolderAccountConnected,
56-
FolderImage,
57-
5853
SyncProgressOverallPercent,
5954
SyncProgressOverallString,
6055
SyncProgressItemString,
61-
WarningCount,
62-
SyncRunning,
63-
6456
FolderSyncText,
65-
IsReady, // boolean
66-
IsUsingSpaces, // boolean
67-
68-
Priority, // uint32_t
69-
IsDeployed, // bool
70-
71-
QuotaUsed,
72-
QuotaTotal,
73-
57+
Priority,
58+
Quota,
59+
FolderImageUrl,
60+
FolderStatusUrl,
61+
Folder,
7462
ColumnCount
7563
};
7664
Q_ENUMS(Columns);
@@ -84,6 +72,8 @@ class FolderStatusModel : public QAbstractTableModel
8472
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
8573
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
8674

75+
QHash<int, QByteArray> roleNames() const override;
76+
8777
public slots:
8878
void slotUpdateFolderState(Folder *);
8979
void resetFolders();
@@ -99,6 +89,18 @@ private slots:
9989
std::vector<std::unique_ptr<SubFolderInfo>> _folders;
10090
};
10191

102-
} // namespace OCC
10392

93+
class SpaceImageProvider : public QQuickImageProvider
94+
{
95+
Q_OBJECT
96+
public:
97+
SpaceImageProvider(AccountStatePtr accountStat);
98+
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
99+
100+
101+
private:
102+
AccountStatePtr _accountStat;
103+
};
104+
105+
} // namespace OCC
104106
#endif // FOLDERSTATUSMODEL_H

‎src/gui/qml/FolderDelegate.qml

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* for more details.
13+
*/
14+
15+
import QtQuick
16+
import QtQuick.Controls
17+
import QtQuick.Layouts
18+
import org.ownCloud.qmlcomponents 1.0
19+
20+
Pane {
21+
// TODO: not cool
22+
readonly property real normalSize: 170
23+
24+
ScrollView {
25+
id: scrollView
26+
anchors.fill: parent
27+
clip: true
28+
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
29+
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
30+
31+
ListView {
32+
anchors.fill: parent
33+
model: ctx.model
34+
35+
spacing: 20
36+
37+
delegate: Pane {
38+
id: folderDelegate
39+
40+
required property string displayName
41+
required property string descriptionText
42+
required property url imageUrl
43+
required property url statusUrl
44+
required property double progress
45+
required property string overallText
46+
required property string itemText
47+
required property var errorMsg
48+
required property string quota
49+
required property string toolTip
50+
51+
required property Folder folder
52+
53+
clip: true
54+
width: ListView.view.width - scrollView.ScrollBar.vertical.width - 10
55+
56+
implicitHeight: normalSize
57+
background: Rectangle {
58+
color: scrollView.palette.base
59+
}
60+
61+
hoverEnabled: true
62+
63+
ToolTip.text: folderDelegate.toolTip
64+
ToolTip.visible: hovered
65+
ToolTip.delay: 1000
66+
ToolTip.timeout: 5000
67+
68+
ColumnLayout {
69+
id: colLayout
70+
anchors.fill: parent
71+
spacing: 10
72+
73+
RowLayout {
74+
Layout.alignment: Qt.AlignTop
75+
Layout.fillWidth: true
76+
77+
Pane {
78+
Layout.preferredHeight: normalSize - 20
79+
Layout.preferredWidth: normalSize - 20
80+
Layout.alignment: Qt.AlignTop
81+
background: Rectangle {
82+
color: scrollView.palette.alternateBase
83+
}
84+
Image {
85+
anchors.fill: parent
86+
fillMode: Image.PreserveAspectFit
87+
source: imageUrl
88+
}
89+
}
90+
ColumnLayout {
91+
spacing: 6
92+
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
93+
Layout.fillWidth: true
94+
95+
RowLayout {
96+
Layout.fillWidth: true
97+
Image {
98+
Layout.preferredHeight: 16
99+
Layout.preferredWidth: 16
100+
source: statusUrl
101+
}
102+
Label {
103+
Layout.fillWidth: true
104+
text: folderDelegate.displayName
105+
font.bold: true
106+
font.pointSize: 15
107+
elide: Text.ElideRight
108+
}
109+
}
110+
Label {
111+
Layout.fillWidth: true
112+
text: folderDelegate.descriptionText
113+
elide: Text.ElideRight
114+
}
115+
// we will either display quota or overallText
116+
Label {
117+
Layout.fillWidth: true
118+
text: folderDelegate.quota
119+
elide: Text.ElideRight
120+
visible: folderDelegate.quota && !folderDelegate.overallText
121+
}
122+
123+
Item {
124+
// ensure the progress bar always consumes its space
125+
Layout.preferredHeight: 10
126+
Layout.fillWidth: true
127+
ProgressBar {
128+
anchors.fill: parent
129+
value: folderDelegate.progress
130+
visible: folderDelegate.overallText || folderDelegate.itemText
131+
}
132+
}
133+
134+
Label {
135+
136+
Layout.fillWidth: true
137+
text: folderDelegate.overallText
138+
elide: Text.ElideMiddle
139+
}
140+
141+
Label {
142+
Layout.fillWidth: true
143+
text: folderDelegate.itemText
144+
elide: Text.ElideMiddle
145+
// only display the item text if we don't have errors
146+
// visible: !folderDelegate.errorMsg.length
147+
}
148+
149+
FolderError {
150+
Layout.fillWidth: true
151+
errorMessages: folderDelegate.errorMsg
152+
onCollapsedChanged: {
153+
if (!collapsed) {
154+
// TODO: not cool
155+
folderDelegate.implicitHeight = normalSize + implicitHeight + 10;
156+
} else {
157+
folderDelegate.implicitHeight = normalSize;
158+
}
159+
}
160+
}
161+
}
162+
Button {
163+
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
164+
Layout.maximumHeight: 30
165+
display: AbstractButton.IconOnly
166+
icon.source: "image://ownCloud/core/more"
167+
onClicked: {
168+
ctx.slotCustomContextMenuRequested(folder);
169+
}
170+
}
171+
}
172+
}
173+
174+
MouseArea {
175+
anchors.fill: parent
176+
acceptedButtons: Qt.RightButton
177+
178+
onClicked: {
179+
ctx.slotCustomContextMenuRequested(folder);
180+
}
181+
}
182+
}
183+
}
184+
}
185+
}

‎src/gui/qml/FolderError.qml

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* for more details.
13+
*/
14+
15+
import QtQuick
16+
import QtQuick.Controls
17+
import QtQuick.Layouts
18+
19+
ColumnLayout {
20+
property bool collapsed: true
21+
required property var errorMessages
22+
23+
component ErrorItem: RowLayout {
24+
property alias text: label.text
25+
property alias maximumLineCount: label.maximumLineCount
26+
Image {
27+
Layout.alignment: Qt.AlignTop
28+
source: "image://ownCloud/core/warning"
29+
Layout.maximumHeight: 16
30+
Layout.maximumWidth: 16
31+
}
32+
Label {
33+
id: label
34+
Layout.fillWidth: true
35+
elide: Label.ElideLeft
36+
wrapMode: Label.WordWrap
37+
}
38+
}
39+
40+
Component {
41+
id: expandedError
42+
ColumnLayout {
43+
Layout.fillWidth: true
44+
Repeater {
45+
model: errorMessages
46+
delegate: ErrorItem {
47+
required property string modelData
48+
text: modelData
49+
Layout.fillWidth: true
50+
}
51+
}
52+
Label {
53+
Layout.alignment: Qt.AlignHCenter
54+
text: "<a href='foo'>" + qsTr("Show less") + "</a>"
55+
onLinkActivated: {
56+
collapsed = true;
57+
}
58+
}
59+
}
60+
}
61+
62+
Component {
63+
id: collapsedError
64+
ColumnLayout {
65+
Layout.fillWidth: true
66+
ErrorItem {
67+
Layout.fillWidth: true
68+
text: errorMessages
69+
maximumLineCount: 1
70+
}
71+
Label {
72+
Layout.alignment: Qt.AlignHCenter
73+
text: "<a href='foo'>" + qsTr("Show more") + "</a>"
74+
onLinkActivated: {
75+
collapsed = false;
76+
}
77+
}
78+
}
79+
}
80+
81+
function loadComponent() {
82+
if (errorMessages.length) {
83+
return collapsed ? collapsedError : expandedError;
84+
}
85+
return undefined;
86+
}
87+
88+
Loader {
89+
id: loader
90+
Layout.fillHeight: true
91+
Layout.fillWidth: true
92+
sourceComponent: loadComponent()
93+
}
94+
95+
onCollapsedChanged: {
96+
loader.sourceComponent = loadComponent();
97+
}
98+
}

‎src/libsync/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ target_link_libraries(libsync
8787
Qt::Core
8888
Qt::Network
8989
Qt::Widgets
90+
Qt::QuickControls2
9091

9192
PRIVATE
9293
Qt::Concurrent

‎src/libsync/graphapi/space.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ QUrl Space::imageUrl() const
9595
QIcon Space::image() const
9696
{
9797
if (_image.isNull()) {
98-
return Resources::getCoreIcon(QStringLiteral("folder-sync"));
98+
return Resources::getCoreIcon(QStringLiteral("space"));
9999
}
100100
return _image;
101101
}

‎src/libsync/platform_win.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <QApplication>
2222
#include <QGuiApplication>
2323
#include <QIcon>
24-
#include <QMetaMethod>
24+
#include <QQuickStyle>
2525

2626

2727
#include <chrono>
@@ -67,6 +67,7 @@ void WinPlatform::setApplication(QCoreApplication *application)
6767

6868
if (auto guiApp = qobject_cast<QGuiApplication *>(application)) {
6969
QApplication::setStyle(QStringLiteral("fusion"));
70+
QQuickStyle::setStyle(QStringLiteral("Fusion"));
7071
}
7172
}
7273

‎src/resources/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ generate_theme(owncloudResources OWNCLOUD_SIDEBAR_ICONS)
1010
# make them available to the whole project
1111
set(OWNCLOUD_SIDEBAR_ICONS ${OWNCLOUD_SIDEBAR_ICONS} CACHE INTERNAL "Sidebar icons" FORCE)
1212

13-
target_link_libraries(owncloudResources PUBLIC Qt::Core Qt::Gui)
13+
target_link_libraries(owncloudResources PUBLIC Qt::Core Qt::Gui Qt::Quick)
1414
apply_common_target_settings(owncloudResources)
1515
target_include_directories(owncloudResources PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/..>)
1616
target_compile_definitions(owncloudResources PRIVATE APPLICATION_SHORTNAME="${APPLICATION_SHORTNAME}")

‎src/resources/client.qrc

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
<file alias="resources/dark/undo.svg">font-awesome/dark/undo-solid.svg</file>
4141
<file alias="resources/wizard/style.qss">wizard/style.qss</file>
4242
<file alias="resources/oauth/oauth.html.in">oauth/oauth.html.in</file>
43+
<file alias="resources/dark/space.svg">remixicon/dark/space.svg</file>
44+
<file alias="resources/light/space.svg">remixicon/light/space.svg</file>
4345
<file alias="resources/dark/states/error.svg">font-awesome/dark/states/error.svg</file>
4446
<file alias="resources/dark/states/information.svg">font-awesome/dark/states/information.svg</file>
4547
<file alias="resources/dark/states/offline.svg">font-awesome/dark/states/offline.svg</file>
Loading
Loading

‎src/resources/remixicon/License.txt

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
Apache License
2+
Version 2.0, January 2004
3+
http://www.apache.org/licenses/
4+
5+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6+
7+
1. Definitions.
8+
9+
"License" shall mean the terms and conditions for use, reproduction,
10+
and distribution as defined by Sections 1 through 9 of this document.
11+
12+
"Licensor" shall mean the copyright owner or entity authorized by
13+
the copyright owner that is granting the License.
14+
15+
"Legal Entity" shall mean the union of the acting entity and all
16+
other entities that control, are controlled by, or are under common
17+
control with that entity. For the purposes of this definition,
18+
"control" means (i) the power, direct or indirect, to cause the
19+
direction or management of such entity, whether by contract or
20+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
21+
outstanding shares, or (iii) beneficial ownership of such entity.
22+
23+
"You" (or "Your") shall mean an individual or Legal Entity
24+
exercising permissions granted by this License.
25+
26+
"Source" form shall mean the preferred form for making modifications,
27+
including but not limited to software source code, documentation
28+
source, and configuration files.
29+
30+
"Object" form shall mean any form resulting from mechanical
31+
transformation or translation of a Source form, including but
32+
not limited to compiled object code, generated documentation,
33+
and conversions to other media types.
34+
35+
"Work" shall mean the work of authorship, whether in Source or
36+
Object form, made available under the License, as indicated by a
37+
copyright notice that is included in or attached to the work
38+
(an example is provided in the Appendix below).
39+
40+
"Derivative Works" shall mean any work, whether in Source or Object
41+
form, that is based on (or derived from) the Work and for which the
42+
editorial revisions, annotations, elaborations, or other modifications
43+
represent, as a whole, an original work of authorship. For the purposes
44+
of this License, Derivative Works shall not include works that remain
45+
separable from, or merely link (or bind by name) to the interfaces of,
46+
the Work and Derivative Works thereof.
47+
48+
"Contribution" shall mean any work of authorship, including
49+
the original version of the Work and any modifications or additions
50+
to that Work or Derivative Works thereof, that is intentionally
51+
submitted to Licensor for inclusion in the Work by the copyright owner
52+
or by an individual or Legal Entity authorized to submit on behalf of
53+
the copyright owner. For the purposes of this definition, "submitted"
54+
means any form of electronic, verbal, or written communication sent
55+
to the Licensor or its representatives, including but not limited to
56+
communication on electronic mailing lists, source code control systems,
57+
and issue tracking systems that are managed by, or on behalf of, the
58+
Licensor for the purpose of discussing and improving the Work, but
59+
excluding communication that is conspicuously marked or otherwise
60+
designated in writing by the copyright owner as "Not a Contribution."
61+
62+
"Contributor" shall mean Licensor and any individual or Legal Entity
63+
on behalf of whom a Contribution has been received by Licensor and
64+
subsequently incorporated within the Work.
65+
66+
2. Grant of Copyright License. Subject to the terms and conditions of
67+
this License, each Contributor hereby grants to You a perpetual,
68+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69+
copyright license to reproduce, prepare Derivative Works of,
70+
publicly display, publicly perform, sublicense, and distribute the
71+
Work and such Derivative Works in Source or Object form.
72+
73+
3. Grant of Patent License. Subject to the terms and conditions of
74+
this License, each Contributor hereby grants to You a perpetual,
75+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76+
(except as stated in this section) patent license to make, have made,
77+
use, offer to sell, sell, import, and otherwise transfer the Work,
78+
where such license applies only to those patent claims licensable
79+
by such Contributor that are necessarily infringed by their
80+
Contribution(s) alone or by combination of their Contribution(s)
81+
with the Work to which such Contribution(s) was submitted. If You
82+
institute patent litigation against any entity (including a
83+
cross-claim or counterclaim in a lawsuit) alleging that the Work
84+
or a Contribution incorporated within the Work constitutes direct
85+
or contributory patent infringement, then any patent licenses
86+
granted to You under this License for that Work shall terminate
87+
as of the date such litigation is filed.
88+
89+
4. Redistribution. You may reproduce and distribute copies of the
90+
Work or Derivative Works thereof in any medium, with or without
91+
modifications, and in Source or Object form, provided that You
92+
meet the following conditions:
93+
94+
(a) You must give any other recipients of the Work or
95+
Derivative Works a copy of this License; and
96+
97+
(b) You must cause any modified files to carry prominent notices
98+
stating that You changed the files; and
99+
100+
(c) You must retain, in the Source form of any Derivative Works
101+
that You distribute, all copyright, patent, trademark, and
102+
attribution notices from the Source form of the Work,
103+
excluding those notices that do not pertain to any part of
104+
the Derivative Works; and
105+
106+
(d) If the Work includes a "NOTICE" text file as part of its
107+
distribution, then any Derivative Works that You distribute must
108+
include a readable copy of the attribution notices contained
109+
within such NOTICE file, excluding those notices that do not
110+
pertain to any part of the Derivative Works, in at least one
111+
of the following places: within a NOTICE text file distributed
112+
as part of the Derivative Works; within the Source form or
113+
documentation, if provided along with the Derivative Works; or,
114+
within a display generated by the Derivative Works, if and
115+
wherever such third-party notices normally appear. The contents
116+
of the NOTICE file are for informational purposes only and
117+
do not modify the License. You may add Your own attribution
118+
notices within Derivative Works that You distribute, alongside
119+
or as an addendum to the NOTICE text from the Work, provided
120+
that such additional attribution notices cannot be construed
121+
as modifying the License.
122+
123+
You may add Your own copyright statement to Your modifications and
124+
may provide additional or different license terms and conditions
125+
for use, reproduction, or distribution of Your modifications, or
126+
for any such Derivative Works as a whole, provided Your use,
127+
reproduction, and distribution of the Work otherwise complies with
128+
the conditions stated in this License.
129+
130+
5. Submission of Contributions. Unless You explicitly state otherwise,
131+
any Contribution intentionally submitted for inclusion in the Work
132+
by You to the Licensor shall be under the terms and conditions of
133+
this License, without any additional terms or conditions.
134+
Notwithstanding the above, nothing herein shall supersede or modify
135+
the terms of any separate license agreement you may have executed
136+
with Licensor regarding such Contributions.
137+
138+
6. Trademarks. This License does not grant permission to use the trade
139+
names, trademarks, service marks, or product names of the Licensor,
140+
except as required for reasonable and customary use in describing the
141+
origin of the Work and reproducing the content of the NOTICE file.
142+
143+
7. Disclaimer of Warranty. Unless required by applicable law or
144+
agreed to in writing, Licensor provides the Work (and each
145+
Contributor provides its Contributions) on an "AS IS" BASIS,
146+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147+
implied, including, without limitation, any warranties or conditions
148+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149+
PARTICULAR PURPOSE. You are solely responsible for determining the
150+
appropriateness of using or redistributing the Work and assume any
151+
risks associated with Your exercise of permissions under this License.
152+
153+
8. Limitation of Liability. In no event and under no legal theory,
154+
whether in tort (including negligence), contract, or otherwise,
155+
unless required by applicable law (such as deliberate and grossly
156+
negligent acts) or agreed to in writing, shall any Contributor be
157+
liable to You for damages, including any direct, indirect, special,
158+
incidental, or consequential damages of any character arising as a
159+
result of this License or out of the use or inability to use the
160+
Work (including but not limited to damages for loss of goodwill,
161+
work stoppage, computer failure or malfunction, or any and all
162+
other commercial damages or losses), even if such Contributor
163+
has been advised of the possibility of such damages.
164+
165+
9. Accepting Warranty or Additional Liability. While redistributing
166+
the Work or Derivative Works thereof, You may choose to offer,
167+
and charge a fee for, acceptance of support, warranty, indemnity,
168+
or other liability obligations and/or rights consistent with this
169+
License. However, in accepting such obligations, You may act only
170+
on Your own behalf and on Your sole responsibility, not on behalf
171+
of any other Contributor, and only if You agree to indemnify,
172+
defend, and hold each Contributor harmless for any liability
173+
incurred by, or claims asserted against, such Contributor by reason
174+
of your accepting any such warranty or additional liability.
175+
176+
END OF TERMS AND CONDITIONS
177+
178+
APPENDIX: How to apply the Apache License to your work.
179+
180+
To apply the Apache License to your work, attach the following
181+
boilerplate notice, with the fields enclosed by brackets "[]"
182+
replaced with your own identifying information. (Don't include
183+
the brackets!) The text should be enclosed in the appropriate
184+
comment syntax for the file format. We also recommend that a
185+
file or class name and description of purpose be included on the
186+
same "printed page" as the copyright notice for easier
187+
identification within third-party archives.
188+
189+
Copyright [yyyy] [name of copyright owner]
190+
191+
Licensed under the Apache License, Version 2.0 (the "License");
192+
you may not use this file except in compliance with the License.
193+
You may obtain a copy of the License at
194+
195+
http://www.apache.org/licenses/LICENSE-2.0
196+
197+
Unless required by applicable law or agreed to in writing, software
198+
distributed under the License is distributed on an "AS IS" BASIS,
199+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200+
See the License for the specific language governing permissions and
201+
limitations under the License.
+10
Loading
+10
Loading

‎src/resources/resources.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ constexpr bool isVanilla()
5252
return std::string_view(APPLICATION_SHORTNAME) == "ownCloud";
5353
}
5454

55-
5655
bool hasTheme(IconType type, const QString &theme)
5756
{
5857
// <<is vanilla, theme name>, bool
@@ -79,7 +78,6 @@ bool Resources::hasMonoTheme()
7978
{
8079
// mono icons are only supported in vanilla and if a customer provides them
8180
// no fallback to vanilla
82-
qDebug() << hasTheme(Resources::IconType::BrandedIcon, whiteTheme());
8381
return hasTheme(Resources::IconType::BrandedIcon, whiteTheme());
8482
}
8583

@@ -172,3 +170,29 @@ QIcon OCC::Resources::themeUniversalIcon(const QString &name, IconType iconType)
172170
{
173171
return loadIcon(QStringLiteral("universal"), name, iconType);
174172
}
173+
174+
CoreImageProvider::CoreImageProvider()
175+
: QQuickImageProvider(QQuickImageProvider::Pixmap)
176+
{
177+
}
178+
QPixmap CoreImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
179+
{
180+
const auto [type, path] = [&id] {
181+
const QString type = id.mid(0, id.indexOf(QLatin1Char('/')));
182+
return std::make_tuple(type, id.mid(type.size()));
183+
}();
184+
Q_ASSERT(!path.isEmpty());
185+
QIcon icon;
186+
if (type == QLatin1String("theme")) {
187+
icon = themeIcon(path);
188+
} else if (type == QLatin1String("core")) {
189+
icon = getCoreIcon(path);
190+
} else {
191+
Q_UNREACHABLE();
192+
}
193+
const QSize actualSize = requestedSize.isValid() ? requestedSize : icon.availableSizes().first();
194+
if (size) {
195+
*size = actualSize;
196+
}
197+
return icon.pixmap(actualSize);
198+
}

‎src/resources/resources.h

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <QIcon>
1919
#include <QUrl>
20+
#include <QtQuick/QQuickImageProvider>
2021

2122
namespace OCC::Resources {
2223
Q_NAMESPACE
@@ -48,4 +49,13 @@ QIcon OWNCLOUDRESOURCES_EXPORT themeIcon(const QString &name, IconType iconType
4849
* Returns a universal (non color schema aware) icon.
4950
*/
5051
QIcon OWNCLOUDRESOURCES_EXPORT themeUniversalIcon(const QString &name, IconType iconType = IconType::BrandedIcon);
52+
53+
class OWNCLOUDRESOURCES_EXPORT CoreImageProvider : public QQuickImageProvider
54+
{
55+
Q_OBJECT
56+
public:
57+
CoreImageProvider();
58+
59+
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
60+
};
5161
}

0 commit comments

Comments
 (0)
Please sign in to comment.