1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-03 18:11:32 +02:00

Compare commits

..

50 Commits

Author SHA1 Message Date
Matthieu Gallien
50453d9d7e Merge pull request #3718 from nextcloud/release-3.3.2
Release 3.3.2
2021-08-26 11:08:51 +02:00
Matthieu Gallien
2740fea577 release 3.3.2 version
Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
2021-08-26 11:04:41 +02:00
allexzander
02a95b6f57 Merge pull request #3717 from nextcloud/backport/3698/stable-3.3
[stable-3.3] Update nextcloudcmd documentation.
2021-08-26 11:01:53 +03:00
allexzander
3aeeeb56ff Update nextcloudcmd documentation.
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-08-26 07:51:51 +00:00
Nextcloud bot
9e6750f3d2 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-26 03:53:38 +00:00
Nextcloud bot
ff38f1cffc [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-25 03:51:33 +00:00
Matthieu Gallien
58f34bd0c6 Merge pull request #3711 from nextcloud/backport/3709/stable-3.3
[stable-3.3] support server versions for one year after it is end of life
2021-08-24 17:01:14 +02:00
Matthieu Gallien
44f89224b3 support server versions for one year after it is end of life
according to https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
2021-08-24 14:48:33 +00:00
Nextcloud bot
cf8b2c98c7 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-24 03:52:28 +00:00
Matthieu Gallien
35b55d7221 Merge pull request #3706 from nextcloud/backport/3621/stable-3.3
[stable-3.3] Bugfix/nextcloud cmd dav fix
2021-08-23 17:20:14 +02:00
allexzander
9492defbe2 Use separate arguments for a remote root and do not use dav or webdav in the server's URL
Signed-off-by: allexzander <blackslayer4@gmail.com>
2021-08-23 15:11:44 +00:00
Nextcloud bot
8fbc25a0d7 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-23 03:49:39 +00:00
Nextcloud bot
c05136ce50 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-22 03:50:11 +00:00
Nextcloud bot
60542aec87 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-21 03:54:46 +00:00
Nextcloud bot
6155b24c60 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-19 03:50:39 +00:00
Matthieu Gallien
3b75cddefb Merge pull request #3686 from nextcloud/backport/3680/stable-3.3
[stable-3.3] Fix macOS app bundle name in packaging scripts
2021-08-18 11:29:45 +02:00
znerol
75307b70c2 Fix macOS app bundle name in packaging scripts
Signed-off-by: znerol <lo+github@znerol.ch>
2021-08-18 07:54:02 +00:00
Nextcloud bot
23591f385e [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-18 03:52:40 +00:00
Nextcloud bot
82d8c363c5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-17 03:53:23 +00:00
Matthieu Gallien
b05d2d791e Merge pull request #3676 from nextcloud/bugfix/checksumsParseIssue
Bugfix/checksums parse issue
2021-08-16 14:08:41 +02:00
Hannah von Reth
4df0ddcbd5 Add workaround for issue discovered in https://github.com/owncloud/core/pull/38304 2021-08-16 13:05:39 +02:00
Hannah von Reth
26ca566428 Make findBestChecksum case insensitive
Especially the casing of ADLER32 did not match the server.
2021-08-16 13:05:34 +02:00
Nextcloud bot
21caff6dd5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-16 03:51:49 +00:00
Nextcloud bot
5d3cd92631 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-15 03:51:24 +00:00
Nextcloud bot
aa8521c70f [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-14 03:53:15 +00:00
Nextcloud bot
1865bc6881 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-13 03:51:38 +00:00
Matthieu Gallien
cd934ba80c Merge pull request #3656 from nextcloud/backport/3655/stable-3.3
[stable-3.3] Return the login name instead of user id
2021-08-12 15:29:22 +02:00
Felix Weilbach
5202df4407 Return the login name instead of user id
App password and login name need to match. If authResult() returns the
user id the user id will be stored in webdav_user

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-08-12 13:17:57 +00:00
Felix Weilbach
99bcf30f77 Merge pull request #3650 from nextcloud/bump-3.3.1
Bump to version 3.3.1
2021-08-12 10:36:42 +02:00
Felix Weilbach
56e8561e64 Bump to version 3.3.1
Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-08-12 10:35:11 +02:00
Nextcloud bot
05fef8e463 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-12 03:53:16 +00:00
Matthieu Gallien
6f5c61e442 Merge pull request #3648 from nextcloud/backport/3646/stable-3.3
[stable-3.3] Enforce fetching of user id
2021-08-11 18:51:29 +02:00
Felix Weilbach
1e28185ee9 Enforce fetching of user id
With the change of commit 3e61bdc431 and
the relase of v3.3.0 users that had their email address used as login
are not able to login anymore. The dav_user should be empty if users
tried to create a account in the meantime. Therefore we fetch the user
id in the case dav_user (and then Account::_davUser) is empty. We then
store the user id in dav_user.

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-08-11 16:43:11 +00:00
Matthieu Gallien
4d7f72e3a1 Merge pull request #3647 from nextcloud/backport/3632/stable-3.3
[stable-3.3] Ensure that the users id is used for accessing webdav
2021-08-11 16:58:39 +02:00
Felix Weilbach
6a414d5fb3 Ensure that the users id is used for accessing webdav
https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#obtaining-the-login-credentials
states that the email address can be used for login but it's not
allowed to use the email address to access webdav.

Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-08-11 14:18:35 +00:00
Nextcloud bot
694c6e7214 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-11 03:53:48 +00:00
Nextcloud bot
e0e4e9778b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-10 04:09:05 +00:00
Nextcloud bot
7baa66b83e [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-09 03:53:21 +00:00
Nextcloud bot
301bb2024e [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-08 03:48:27 +00:00
Nextcloud bot
f7fce0100b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-07 03:57:06 +00:00
Nextcloud bot
af894485b4 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-06 04:01:23 +00:00
Nextcloud bot
2fb609fa98 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-05 03:53:30 +00:00
Nextcloud bot
c4627c3c04 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-04 03:53:10 +00:00
Nextcloud bot
5f0e8b8268 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-03 03:52:44 +00:00
Nextcloud bot
99c6bee64b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-02 03:26:03 +00:00
Nextcloud bot
853bfed89a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-08-01 03:27:14 +00:00
Nextcloud bot
86dc3fefc8 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-07-31 03:32:43 +00:00
Nextcloud bot
ea800b638d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-07-30 03:24:19 +00:00
Matthieu Gallien
a2e69d8574 Merge pull request #3610 from nextcloud/backport/3609/stable-3.3
[stable-3.3] Update supported server versions
2021-07-29 12:03:32 +02:00
Felix Weilbach
0178b322f9 Update supported server versions
Signed-off-by: Felix Weilbach <felix.weilbach@nextcloud.com>
2021-07-29 10:03:10 +00:00
430 changed files with 39333 additions and 89109 deletions

View File

@@ -12,7 +12,7 @@
BasedOnStyle: WebKit
Standard: Cpp11
ColumnLimit: 120
ColumnLimit: 0
# Disable reflow of qdoc comments: indentation rules are different.
# Translation comments are also excluded
@@ -61,5 +61,3 @@ ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCH
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: false
SpaceBeforeCpp11BracedList: false
Cpp11BracedListStyle: true

View File

@@ -24,7 +24,7 @@ Checks: '-*,
modernize-use-nodiscard,
modernize-use-equals-default,
modernize-use-noexcept,
modernize-use-override,
modernize-user-override,
modernize-use-nullptr,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,

View File

@@ -1,17 +1,17 @@
kind: pipeline
name: qt-5.15
name: qt-5.12
steps:
- name: cmake
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
commands:
- cd /drone/build
- cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror ../src
- cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address ../src
- name: compile
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
@@ -19,7 +19,7 @@ steps:
- cd /drone/build
- make -j$(nproc)
- name: test
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
@@ -27,7 +27,7 @@ steps:
- cd /drone/build
- useradd -m -s /bin/bash test
- chown -R test:test .
- su -c 'ASAN_OPTIONS=detect_leaks=0 xvfb-run ctest --output-on-failure' test
- su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test
volumes:
- name: build
@@ -43,27 +43,27 @@ trigger:
---
kind: pipeline
name: qt-5.15-clang
name: qt-5.12-clang
steps:
- name: cmake
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
commands:
- cd /drone/build
- cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror ../src
- cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clazy -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address ../src
- name: compile
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
commands:
- cd /drone/build
- ninja
- ninja 2>1 | /drone/src/admin/linux/count_compiler_warnings.py /drone/src
- name: test
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
@@ -71,9 +71,9 @@ steps:
- cd /drone/build
- useradd -m -s /bin/bash test
- chown -R test:test .
- su -c 'ASAN_OPTIONS=detect_leaks=0 xvfb-run ctest --output-on-failure' test
- su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test
- name: clang-tidy
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
volumes:
- name: build
path: /drone/build
@@ -98,14 +98,14 @@ name: AppImage
steps:
- name: build
image: ghcr.io/nextcloud/continuous-integration-client-appimage:client-appimage-3
image: ghcr.io/nextcloud/continuous-integration-client-appimage:client-appimage-1
environment:
CI_UPLOAD_GIT_TOKEN:
from_secret: CI_UPLOAD_GIT_TOKEN
CI_UPLOAD_GIT_USERNAME:
from_secret: CI_UPLOAD_GIT_USERNAME
commands:
- BUILDNR=$DRONE_BUILD_NUMBER VERSION_SUFFIX=$DRONE_PULL_REQUEST BUILD_UPDATER=ON DESKTOP_CLIENT_ROOT=$DRONE_WORKSPACE /bin/bash -c "./admin/linux/build-appimage.sh"
- /bin/bash -c "./admin/linux/build-appimage.sh"
- /bin/bash -c "./admin/linux/upload-appimage.sh" || echo "Upload failed, however this is an optional step."
trigger:
branch:

View File

@@ -3,44 +3,25 @@
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Rebase command
on:
issue_comment:
types: created
types: [ created ]
name: Automatic Rebase
jobs:
rebase:
runs-on: ubuntu-latest
name: Rebase
# On pull requests and if the comment starts with `/rebase`
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase')
runs-on: ubuntu-latest
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reaction-type: "+1"
- name: Checkout the latest code
uses: actions/checkout@v2
with:
fetch-depth: 0
token: ${{ secrets.COMMAND_BOT_PAT }}
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@v1
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reaction-type: "-1"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,50 +0,0 @@
name: SonarCloud analysis
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build
runs-on: ubuntu-latest
container: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
env:
SONAR_SERVER_URL: "https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Restore cache
uses: actions/cache@v2
with:
path: /cache
key: ${{ runner.os }}
- name: Run build-wrapper
run: |
mkdir build
cd build
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DBUILD_COVERAGE=ON
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make -j 2
- name: Run tests
run: |
cd build
useradd -m -s /bin/bash test
chown -R test:test .
su -c 'xvfb-run ctest --output-on-failure --output-junit testResult.xml' test
- name: Generate coverage report
run: |
cd build
su -c 'ctest -T Coverage' test
- name: Run sonar-scanner
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
cp sonar-project.properties build
cd build
sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"

1
.gitignore vendored
View File

@@ -184,7 +184,6 @@ compile_commands.json
convert.exe
.dir-locals.el
*-icon.png
*-icon-win-folder.png
*-sidebar.png
*-w10startmenu.png
theme.qrc

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[bg_BG]=@APPLICATION_ICON_NAME@
Name[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
Comment[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
GenericName[bg_BG]=Синхронизиране на папка

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[cy_GB]=@APPLICATION_ICON_NAME@
Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
GenericName[cy_GB]=Cydweddu Ffolder

View File

@@ -21,7 +21,7 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[de]=@APPLICATION_ICON_NAME@
Name[de]=@APPLICATION_NAME@ Desktop
Comment[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung
GenericName[de]=Ordner-Synchronisation
Icon[de_DE]=@APPLICATION_ICON_NAME@
Name[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung
Comment[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisierung
GenericName[de_DE]=Ordnersynchronisierung

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[en_GB]=@APPLICATION_ICON_NAME@
Name[en_GB]=@APPLICATION_NAME@ Desktop
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
GenericName[en_GB]=Folder Sync

View File

@@ -1,24 +0,0 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ Desktop
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
GenericName[id]=Sinkronisasi Folder

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[ko]=@APPLICATION_ICON_NAME@
Name[ko]=@APPLICATION_NAME@ 데스크탑
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
GenericName[ko]=폴더 동기화

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[nb_NO]=@APPLICATION_ICON_NAME@
Name[nb_NO]=@APPLICATION_NAME@ skrivebord
Comment[nb_NO]=@APPLICATION_NAME@ klient for synkroinisering
GenericName[nb_NO]=Mappe synkroinisering

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[oc]=@APPLICATION_ICON_NAME@
Name[oc]=@APPLICATION_NAME@ Burèu
Comment[oc]=@APPLICATION_NAME@ client de sincronizacion
GenericName[oc]=Sincro. dossièr

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[ru]=@APPLICATION_ICON_NAME@
Name[ru]=@APPLICATION_NAME@ Desktop
Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК
GenericName[ru]=Синхронизация папок

View File

@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[sv]=@APPLICATION_ICON_NAME@
Name[sv]=@APPLICATION_NAME@ Skrivbord
Comment[sv]=@APPLICATION_NAME@ desktopssynkroniseringsklient
GenericName[sv]=Mappsynkronisering

View File

@@ -1,27 +0,0 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ Desktop
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
Actions=Quit;
# Translations
[Desktop Action Quit]
Exec=@APPLICATION_EXECUTABLE@ --quit
Name=Quit @APPLICATION_NAME@
Icon=@APPLICATION_EXECUTABLE@
# Translations
Icon[vi]=@APPLICATION_ICON_NAME@
Name[vi]=@APPLICATION_NAME@ Máy tính
Comment[vi]=Ứng dụng đồng bộ @APPLICATION_NAME@ cho máy tính
GenericName[vi]=Đồng bộ thư mục

View File

@@ -42,13 +42,10 @@ if(NOT CRASHREPORTER_EXECUTABLE)
set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter")
endif()
include(Warnings)
set(synclib_NAME "${APPLICATION_EXECUTABLE}sync")
set(csync_NAME "${APPLICATION_EXECUTABLE}_csync")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(-fdiagnostics-color=always)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(-fcolor-diagnostics)
endif()
include(Warnings)
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
# For config.h
@@ -77,9 +74,9 @@ include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
add_definitions(
-DQT_DISABLE_DEPRECATED_BEFORE=0x000000
-DQT_USE_QSTRINGBUILDER
-DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output
-DQT_DEPRECATED_WARNINGS
)
# if we cannot get it from git, directly try .tag (packages)
@@ -96,15 +93,30 @@ endif()
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(SHAREDIR ${CMAKE_INSTALL_FULL_DATADIR})
set(DATADIR ${DATA_INSTALL_DIR})
if(WIN32)
set(DATADIR "share")
endif(WIN32)
set(SHAREDIR ${DATADIR})
# Build MacOS app bundle if wished
if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE)
message(STATUS "Build MacOS app bundle")
#####
## handle BUILD_OWNCLOUD_OSX_BUNDLE
# BUILD_OWNCLOUD_OSX_BUNDLE was not initialized OR set to true on OSX
if(APPLE AND (NOT DEFINED BUILD_OWNCLOUD_OSX_BUNDLE OR BUILD_OWNCLOUD_OSX_BUNDLE))
set(BUILD_OWNCLOUD_OSX_BUNDLE ON)
set(OWNCLOUD_OSX_BUNDLE "${APPLICATION_NAME}.app")
set(LIB_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
set(BIN_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
# BUILD_OWNCLOUD_OSX_BUNDLE was disabled on OSX
elseif(APPLE AND NOT BUILD_OWNCLOUD_OSX_BUNDLE)
message(FATAL_ERROR "Building in non-bundle mode on OSX is currently not supported. Comment this error out if you want to work on/test it.")
# any other platform
else()
set(BUILD_OWNCLOUD_OSX_BUNDLE OFF)
endif()
#####
# this option removes Http authentication, keychain, shibboleth etc and is intended for
# external authentication mechanisms

View File

@@ -11,8 +11,6 @@ set( APPLICATION_SERVER_URL "" CACHE STRING "URL for the server to use. If enter
set( APPLICATION_SERVER_URL_ENFORCE ON ) # If set and APPLICATION_SERVER_URL is defined, the server can only connect to the pre-defined URL
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
set( APPLICATION_VIRTUALFILE_SUFFIX "nextcloud" CACHE STRING "Virtual file suffix (not including the .)")
set( APPLICATION_OCSP_STAPLING_ENABLED OFF )
set( APPLICATION_FORBID_BAD_SSL OFF )
set( LINUX_PACKAGE_SHORTNAME "nextcloud" )
set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}")
@@ -34,9 +32,6 @@ option( BUILD_UPDATER "Build updater" OFF )
option( WITH_PROVIDERS "Build with providers list" ON )
option( ENFORCE_VIRTUAL_FILES_SYNC_FOLDER "Enforce use of virtual files sync folder when available" OFF )
option( DO_NOT_USE_PROXY "Do not use system wide proxy, instead always do a direct connection to server" OFF )
## Theming options
set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color")

View File

@@ -1,7 +1,7 @@
set( MIRALL_VERSION_MAJOR 3 )
set( MIRALL_VERSION_MINOR 4 )
set( MIRALL_VERSION_MINOR 3 )
set( MIRALL_VERSION_PATCH 2 )
set( MIRALL_VERSION_YEAR 2022 )
set( MIRALL_VERSION_YEAR 2021 )
set( MIRALL_SOVERSION 0 )
# Minimum supported server version according to https://docs.nextcloud.com/server/latest/admin_manual/release_schedule.html

View File

@@ -2,88 +2,78 @@
set -xe
export APPNAME=${APPNAME:-nextcloud}
export BUILD_UPDATER=${BUILD_UPDATER:-OFF}
export BUILDNR=${BUILDNR:-0000}
export DESKTOP_CLIENT_ROOT=${DESKTOP_CLIENT_ROOT:-/home/user}
#Set Qt-5.15
export QT_BASE_DIR=/opt/qt5.15
mkdir /app
mkdir /build
#Set Qt-5.12
export QT_BASE_DIR=/opt/qt5.12.10
export QTDIR=$QT_BASE_DIR
export PATH=$QT_BASE_DIR/bin:$PATH
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=$QT_BASE_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
# Set defaults
#Set APPID for .desktop file processing
export LINUX_APPLICATION_ID=com.nextcloud.desktopclient.nextcloud
#set defaults
export SUFFIX=${DRONE_PULL_REQUEST:=master}
if [ $SUFFIX != "master" ]; then
SUFFIX="PR-$SUFFIX"
fi
if [ "$BUILD_UPDATER" != "OFF" ]; then
BUILD_UPDATER=ON
fi
mkdir /app
# QtKeyChain
#QtKeyChain v0.10.0
cd /build
git clone https://github.com/frankosterfeld/qtkeychain.git
cd qtkeychain
git checkout v0.10.0
mkdir build
cd build
cmake -G Ninja -D CMAKE_INSTALL_PREFIX=/app/usr ..
cmake --build . --target all
cmake --build . --target install
cmake -D CMAKE_INSTALL_PREFIX=/usr ../
make -j4
make install
# Build client
#Build client
cd /build
mkdir build-client
cd build-client
cmake \
-G Ninja \
-D CMAKE_INSTALL_PREFIX=/app/usr \
cmake -D CMAKE_INSTALL_PREFIX=/usr \
-D BUILD_TESTING=OFF \
-D BUILD_UPDATER=$BUILD_UPDATER \
-D MIRALL_VERSION_BUILD=$BUILDNR \
-D MIRALL_VERSION_SUFFIX="$VERSION_SUFFIX" \
${DESKTOP_CLIENT_ROOT}
cmake --build . --target all
cmake --build . --target install
-D BUILD_UPDATER=ON \
-DMIRALL_VERSION_SUFFIX=PR-$DRONE_PULL_REQUEST \
-DMIRALL_VERSION_BUILD=$DRONE_BUILD_NUMBER \
$DRONE_WORKSPACE
make -j4
make DESTDIR=/app install
# Move stuff around
cd /app
mv usr/lib/x86_64-linux-gnu/* usr/lib/
mv ./usr/lib/x86_64-linux-gnu/* ./usr/lib/
rm -rf ./usr/lib/cmake
rm -rf ./usr/include
rm -rf ./usr/mkspecs
rm -rf ./usr/lib/x86_64-linux-gnu/
mkdir usr/plugins
mv usr/lib/${APPNAME}sync_vfs_suffix.so usr/plugins
mv usr/lib/${APPNAME}sync_vfs_xattr.so usr/plugins
rm -rf usr/lib/cmake
rm -rf usr/include
rm -rf usr/mkspecs
rm -rf usr/lib/x86_64-linux-gnu/
# Don't bundle nextcloudcmd as we don't run it anyway
rm -rf ./usr/bin/nextcloudcmd
# Don't bundle the explorer extentions as we can't do anything with them in the AppImage
rm -rf usr/share/caja-python/
rm -rf usr/share/nautilus-python/
rm -rf usr/share/nemo-python/
rm -rf ./usr/share/caja-python/
rm -rf ./usr/share/nautilus-python/
rm -rf ./usr/share/nemo-python/
# Move sync exclude to right location
mv usr/etc/*/sync-exclude.lst usr/bin/
rm -rf etc
mv ./etc/Nextcloud/sync-exclude.lst ./usr/bin/
rm -rf ./etc
# com.nextcloud.desktopclient.nextcloud.desktop
DESKTOP_FILE=$(ls /app/usr/share/applications/*.desktop)
DESKTOP_FILE=/app/usr/share/applications/${LINUX_APPLICATION_ID}.desktop
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
# Because distros need to get their shit together
cp -R /usr/lib/x86_64-linux-gnu/libssl.so* ./usr/lib/
cp -R /usr/lib/x86_64-linux-gnu/libcrypto.so* ./usr/lib/
cp -R /lib/x86_64-linux-gnu/libssl.so* ./usr/lib/
cp -R /lib/x86_64-linux-gnu/libcrypto.so* ./usr/lib/
cp -P /usr/local/lib/libssl.so* ./usr/lib/
cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
@@ -91,23 +81,19 @@ cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
cp -P -r /usr/lib/x86_64-linux-gnu/nss ./usr/lib/
# Use linuxdeployqt to deploy
wget --ca-directory=/etc/ssl/certs -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
cd /build
wget --ca-directory=/etc/ssl/certs/ -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
chmod a+x linuxdeployqt*.AppImage
./linuxdeployqt-continuous-x86_64.AppImage --appimage-extract
rm ./linuxdeployqt-continuous-x86_64.AppImage
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/app/usr/lib/
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=${DESKTOP_CLIENT_ROOT}/src/gui
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=$DRONE_WORKSPACE/src/gui
# Set origin
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/lib${APPNAME}sync.so.0
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/libnextcloudsync.so.0
# Build AppImage
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage -updateinformation="gh-releases-zsync|nextcloud-releases|desktop|latest|Nextcloud-*-x86_64.AppImage.zsync"
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage
#move AppImage
if [ ! -z "$DRONE_COMMIT" ]
then
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
fi
mv *.AppImage ${DESKTOP_CLIENT_ROOT}/
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python3
# Small script that counts the warnings which the compiler emits
# and takes care that not more warnings are added.
import sys
import re
import requests
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} REPOSITORY_PATH")
sys.exit(1)
repository_path = sys.argv[1]
warning_regex = re.compile(r'warning:', re.M)
max_allowed_warnings_count_response = requests.get(
"https://nextclouddesktopwarningscount.felixweilbach.de")
if max_allowed_warnings_count_response.status_code != 200:
print('Can not get maximum number of allowed warnings')
sys.exit(1)
max_allowed_warnings_count = int(max_allowed_warnings_count_response.content)
print("Max number of allowed warnings:", max_allowed_warnings_count)
warnings_count = 0
for line in sys.stdin:
if warning_regex.findall(line):
warnings_count += 1
print(line, end="")
if warnings_count > max_allowed_warnings_count:
print("Error: Too many warnings! You probably introduced a new warning!")
sys.exit(1)
print("Total number of warnings:", warnings_count)

View File

@@ -15,10 +15,10 @@ OBS_PROJECT_BETA=home:ivaradi:beta
OBS_PACKAGE=nextcloud-desktop
if test "${DRONE_TARGET_BRANCH}" = "stable-2.6"; then
UBUNTU_DISTRIBUTIONS="bionic focal impish jammy"
UBUNTU_DISTRIBUTIONS="bionic focal hirsute impish"
DEBIAN_DISTRIBUTIONS="buster stretch testing"
else
UBUNTU_DISTRIBUTIONS="focal impish jammy"
UBUNTU_DISTRIBUTIONS="focal hirsute impish"
DEBIAN_DISTRIBUTIONS="testing"
fi

View File

@@ -24,7 +24,6 @@ cd /build
# AppImage
export APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
export UPDATE=$(readlink -f ./Nextcloud*.AppImage.zsync)
export BASENAME=$(basename ${APPIMAGE})
if ! test -e $APPIMAGE ; then
@@ -71,7 +70,6 @@ upload_release_asset()
{
uploadUrl=$1
echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $APPIMAGE)
echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $UPDATE)
}
delete_release_asset()
@@ -134,4 +132,4 @@ if [ $TAG_NAME != "master" ]; then
fi
echo
echo "AppImage link: $browserDownloadUrl"
echo "AppImage link: $browserDownloadUrl"

View File

@@ -9,7 +9,7 @@ else()
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
endif()
find_package(Qt5 5.15 COMPONENTS Core REQUIRED)
find_package(Qt5 5.12 COMPONENTS Core REQUIRED)
configure_file(create_mac.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)

View File

@@ -695,12 +695,7 @@
<key>PROJECT_SETTINGS</key>
<dict>
<key>ADVANCED_OPTIONS</key>
<dict>
<key>installer-script.options:hostArchitectures</key>
<array>
<string>x86_64,arm64</string>
</array>
</dict>
<dict/>
<key>BUILD_FORMAT</key>
<integer>0</integer>
<key>BUILD_PATH</key>

View File

@@ -1,82 +0,0 @@
#!/usr/bin/env python
import sys
import os
import subprocess
# A general note: We first produce a x86_64 and a arm64 app package
# and then merge them together instead of compiling the desktop client
# with the CMake option CMAKE_OSX_ARCHITECTURES="x86_64;arm64" because
# macdeployqt can not handle universal binaries well. In the future
# with Qt6 this might change and this script will become obsolete.
def usage(program_name):
print("Creates a universal app package from a x86_64 and a arm64 app package.")
print("Usage: {} x86_64_app_file arm64_app_file output_directory".format(program_name))
print("Example: {} some_dir/Nextcloud.app some_other_dir/Nextcloud.app output_dir".format(program_name))
def execute(command):
return subprocess.check_output(command)
def path_relative_to_package(app_package_file_path, file_path):
if file_path.startswith(app_package_file_path):
relative_path = file_path[len(app_package_file_path):]
if relative_path.startswith("/"):
return relative_path[1:]
return relative_path
return file_path
def is_executable(file_path):
output = str(execute(["file", file_path]))
if (("Mach-O 64-bit dynamically linked shared library" in output)
or ("Mach-O 64-bit executable" in output)):
return True
return False
if __name__ == "__main__":
if len(sys.argv) != 4:
usage(sys.argv[0])
sys.exit(1)
x86_64_app_file = sys.argv[1]
if not os.path.exists(x86_64_app_file):
print("Can't create universal: Path {} already exists".format(x86_64_app_file))
sys.exit(1)
arm64_app_file = sys.argv[2]
if not os.path.exists(arm64_app_file):
print("Can't create universal: Path {} already exists".format(arm64_app_file))
sys.exit(1)
output_dir = sys.argv[3]
# Copy the Arm64 variant to the output location if possible
if not os.path.exists(output_dir):
os.makedirs(output_dir)
app_file_name = os.path.basename(arm64_app_file)
universal_app_file = os.path.join(output_dir, app_file_name)
if os.path.exists(universal_app_file):
print("Can't create universal: Path {} already exists".format(universal_app_file))
sys.exit(1)
execute(["cp", "-a", arm64_app_file, output_dir])
# Now walk through the copied arm64 version and replace the binaries
for root, dirs, files in os.walk(universal_app_file):
for f in files:
absoulte_file_path = os.path.join(root, f)
root_relative = path_relative_to_package(universal_app_file, root)
x86_64_absolute_path = os.path.join(x86_64_app_file, root_relative, f)
arm64_absolute_path = os.path.join(arm64_app_file, root_relative, f)
if os.path.islink(absoulte_file_path) or not is_executable(absoulte_file_path):
continue
try:
execute(["lipo", "-create", "-output", absoulte_file_path, arm64_absolute_path, x86_64_absolute_path])
except:
print("Could not merge {} with {} into {}!".format(arm64_absolute_path, x86_64_absolute_path, absoulte_file_path))
print("Finished :)")

View File

@@ -26,8 +26,6 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat
Platform.wxi
Nextcloud.wxs
RegistryCleanup.vbs
RegistryCleanupCustomAction.wxs
gui/banner.bmp
gui/dialog.bmp
DESTINATION msi/)

View File

@@ -76,16 +76,12 @@
<!-- Uninstall: Remove sync folders from Explorer's Navigation Pane, only effective for the current user (home users) -->
<Custom Action="RemoveNavigationPaneEntries" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Uninstall: Cleanup the Registry -->
<Custom Action="RegistryCleanupCustomAction" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Schedule Reboot for the Shell Extensions (in silent installation mode only, or if SCHEDULE_REBOOT argument is set-->
<ScheduleReboot After="InstallFinalize">(SCHEDULE_REBOOT=1) OR NOT (UILevel=2)</ScheduleReboot>
</InstallExecuteSequence>
<!-- "Add or Remove" Programs Entries -->
<Property Id="APPNAME">$(var.AppName)</Property>
<Property Id="ARPPRODUCTICON">$(var.AppIcon)</Property>
<Property Id="ARPHELPLINK">$(var.AppHelpLink)</Property>
<Property Id="ARPURLINFOABOUT">$(var.AppInfoLink)</Property>

View File

@@ -1,54 +0,0 @@
On Error goto 0
Const HKEY_LOCAL_MACHINE = &H80000002
Const strObjRegistry = "winmgmts:\\.\root\default:StdRegProv"
Function RegistryDeleteKeyRecursive(regRoot, strKeyPath)
Set objRegistry = GetObject(strObjRegistry)
objRegistry.EnumKey regRoot, strKeyPath, arrSubkeys
If IsArray(arrSubkeys) Then
For Each strSubkey In arrSubkeys
RegistryDeleteKeyRecursive regRoot, strKeyPath & "\" & strSubkey
Next
End If
objRegistry.DeleteKey regRoot, strKeyPath
End Function
Function RegistryListSubkeys(regRoot, strKeyPath)
Set objRegistry = GetObject(strObjRegistry)
objRegistry.EnumKey regRoot, strKeyPath, arrSubkeys
RegistryListSubkeys = arrSubkeys
End Function
Function GetUserSID()
Dim objWshNetwork, objUserAccount
Set objWshNetwork = CreateObject("WScript.Network")
Set objUserAccount = GetObject("winmgmts://" & objWshNetwork.UserDomain & "/root/cimv2").Get("Win32_UserAccount.Domain='" & objWshNetwork.ComputerName & "',Name='" & objWshNetwork.UserName & "'")
GetUserSID = objUserAccount.SID
End Function
Function RegistryCleanupSyncRootManager()
strSyncRootManagerKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SyncRootManager"
arrSubKeys = RegistryListSubkeys(HKEY_LOCAL_MACHINE, strSyncRootManagerKeyPath)
If IsArray(arrSubkeys) Then
arrSubkeys=Filter(arrSubkeys, Session.Property("APPNAME"))
End If
If IsArray(arrSubkeys) Then
arrSubkeys=Filter(arrSubkeys, GetUserSID())
End If
If IsArray(arrSubkeys) Then
For Each strSubkey In arrSubkeys
RegistryDeleteKeyRecursive HKEY_LOCAL_MACHINE, strSyncRootManagerKeyPath & "\" & strSubkey
Next
End If
End Function
Function RegistryCleanup()
RegistryCleanupSyncRootManager()
End Function

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Binary Id="RegistryCleanup" SourceFile="RegistryCleanup.vbs"/>
<CustomAction Id='RegistryCleanupCustomAction' BinaryKey="RegistryCleanup" VBScriptCall="RegistryCleanup" Return="ignore" Execute="immediate"/>
</Fragment>
</Wix>

View File

@@ -17,10 +17,10 @@ Rem Generate collect.wxs
if %ERRORLEVEL% neq 0 exit %ERRORLEVEL%
Rem Compile en-US (https://www.firegiant.com/wix/tutorial/transforms/morphing-installers/)
"%WIX%\bin\candle.exe" -dcodepage=1252 -dPlatform=%BuildArch% -arch %BuildArch% -dHarvestAppDir="%HarvestAppDir%" -ext WixUtilExtension NCMsiHelper.wxs WinShellExt.wxs collect.wxs Nextcloud.wxs RegistryCleanupCustomAction.wxs
"%WIX%\bin\candle.exe" -dcodepage=1252 -dPlatform=%BuildArch% -arch %BuildArch% -dHarvestAppDir="%HarvestAppDir%" -ext WixUtilExtension NCMsiHelper.wxs WinShellExt.wxs collect.wxs Nextcloud.wxs
if %ERRORLEVEL% neq 0 exit %ERRORLEVEL%
Rem Link MSI package
"%WIX%\bin\light.exe" -sw1076 -ext WixUIExtension -ext WixUtilExtension -cultures:en-us NCMsiHelper.wixobj WinShellExt.wixobj collect.wixobj Nextcloud.wixobj RegistryCleanupCustomAction.wixobj -out "@MSI_INSTALLER_FILENAME@"
"%WIX%\bin\light.exe" -sw1076 -ext WixUIExtension -ext WixUtilExtension -cultures:en-us NCMsiHelper.wixobj WinShellExt.wixobj collect.wixobj Nextcloud.wixobj -out "@MSI_INSTALLER_FILENAME@"
exit %ERRORLEVEL%

View File

@@ -32,6 +32,9 @@ install:
build_script:
- ps: |
craft --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
craft --package --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
cp C:\CraftMaster\windows-msvc2019_64-cl\tmp\*.7z $env:APPVEYOR_BUILD_FOLDER
cp C:\CraftMaster\windows-msvc2019_64-cl\tmp\*.exe $env:APPVEYOR_BUILD_FOLDER
test_script:
- ps: |
@@ -40,3 +43,7 @@ test_script:
environment:
matrix:
- TARGET: windows-msvc2019_64-cl
artifacts:
- path: '*.7z'
- path: '*.exe'

View File

@@ -41,7 +41,7 @@
# target does not have the ``WIN32_EXECUTABLE`` property set.
# * One of the tools png2ico (See :find-module:`FindPng2Ico`) or
# icotool (see :find-module:`FindIcoTool`) is required.
# * Supported sizes: 16, 20, 24, 32, 40, 48, 64, 128, 256, 512 and 1024.
# * Supported sizes: 16, 24, 32, 48, 64, 128, 256, 512 and 1024.
#
# Mac OS X notes
# * The executable target must have the ``MACOSX_BUNDLE`` property set.
@@ -102,12 +102,9 @@ include(CMakeParseArguments)
function(ecm_add_app_icon appsources)
set(options)
set(oneValueArgs OUTFILE_BASENAME ICON_INDEX)
set(multiValueArgs ICONS SIDEBAR_ICONS RC_DEPENDENCIES)
set(oneValueArgs OUTFILE_BASENAME)
set(multiValueArgs ICONS SIDEBAR_ICONS)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT ARG_ICON_INDEX)
set(ARG_ICON_INDEX 1)
endif()
if(NOT ARG_ICONS)
message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon")
@@ -141,11 +138,8 @@ function(ecm_add_app_icon appsources)
endforeach()
endif()
if (WIN32)
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;20;24;32;40;48;64;128;256;512;1024")
else()
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024")
endif()
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024")
if(ARG_SIDEBAR_ICONS)
_ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256")
endif()
@@ -174,10 +168,8 @@ function(ecm_add_app_icon appsources)
set(windows_icons ${icons_at_16px}
${icons_at_20px}
${icons_at_24px}
${icons_at_32px}
${icons_at_40px}
${icons_at_48px}
${icons_at_64px}
${icons_at_128px}
@@ -212,12 +204,12 @@ function(ecm_add_app_icon appsources)
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
# this bit's a little hacky to make the dependency stuff work
file(WRITE "${_outfilename}.rc.in" "IDI_ICON${ARG_ICON_INDEX} ICON DISCARDABLE \"${_outfilename}.ico\"\n")
file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n")
add_custom_command(
OUTPUT "${_outfilename}.rc"
COMMAND ${CMAKE_COMMAND}
ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc"
DEPENDS ${ARG_RC_DEPENDENCIES} "${_outfilename}.ico"
DEPENDS "${_outfilename}.ico"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
endfunction()
@@ -234,7 +226,7 @@ function(ecm_add_app_icon appsources)
endif()
endforeach()
foreach(size 16 20 24 32 40 48 64 128 ${maxSize})
foreach(size 16 24 32 48 64 128 ${maxSize})
if(NOT icons_at_${size}px)
continue()
endif()

View File

@@ -0,0 +1,253 @@
#.rst:
# GNUInstallDirs
# --------------
#
# Define GNU standard installation directories
#
# Provides install directory variables as defined for GNU software:
#
# ::
#
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
#
# Inclusion of this module defines the following variables:
#
# ::
#
# CMAKE_INSTALL_<dir> - destination for files of a given type
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
#
# where <dir> is one of:
#
# ::
#
# BINDIR - user executables (bin)
# SBINDIR - system admin executables (sbin)
# LIBEXECDIR - program executables (libexec)
# SYSCONFDIR - read-only single-machine data (etc)
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
# LOCALSTATEDIR - modifiable single-machine data (var)
# LIBDIR - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
# INCLUDEDIR - C header files (include)
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
# DATAROOTDIR - read-only architecture-independent data root (share)
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
# INFODIR - info documentation (DATAROOTDIR/info)
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
# MANDIR - man documentation (DATAROOTDIR/man)
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
#
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION
# options of install() commands for the corresponding file type. If the
# includer does not define a value the above-shown default will be used
# and the value will appear in the cache for editing by the user. Each
# CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
# from the corresponding destination by prepending (if necessary) the
# value of CMAKE_INSTALL_PREFIX.
#=============================================================================
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
# Copyright 2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Installation directories
#
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
endif()
# We check if the variable was manually set and not cached, in order to
# allow projects to set the values as normal variables before including
# GNUInstallDirs to avoid having the entries cached or user-editable. It
# replaces the "if(NOT DEFINED CMAKE_INSTALL_XXX)" checks in all the
# other cases.
# If CMAKE_INSTALL_LIBDIR is defined, if _libdir_set is false, then the
# variable is a normal one, otherwise it is a cache one.
get_property(_libdir_set CACHE CMAKE_INSTALL_LIBDIR PROPERTY TYPE SET)
if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
AND DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
AND NOT "${_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX}" STREQUAL "${CMAKE_INSTALL_PREFIX}"))
# If CMAKE_INSTALL_LIBDIR is not defined, it is always executed.
# Otherwise:
# * if _libdir_set is false it is not executed (meaning that it is
# not a cache variable)
# * if _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX is not defined it is
# not executed
# * if _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX and
# CMAKE_INSTALL_PREFIX are the same string it is not executed.
# _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX is updated after the
# execution, of this part of code, therefore at the next inclusion
# of the file, CMAKE_INSTALL_LIBDIR is defined, and the 2 strings
# are equal, meaning that the if is not executed the code the
# second time.
set(_LIBDIR_DEFAULT "lib")
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
# - we are on a 64 bits system
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
# CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
# and CMAKE_INSTALL_PREFIX is "/usr"
# See http://wiki.debian.org/Multiarch
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX)
set(__LAST_LIBDIR_DEFAULT "lib")
# __LAST_LIBDIR_DEFAULT is the default value that we compute from
# _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX, not a cache entry for
# the value that was last used as the default.
# This value is used to figure out whether the user changed the
# CMAKE_INSTALL_LIBDIR value manually, or if the value was the
# default one. When CMAKE_INSTALL_PREFIX changes, the value is
# updated to the new default, unless the user explicitly changed it.
endif()
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$"
AND NOT CMAKE_CROSSCOMPILING)
if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE)
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
message(AUTHOR_WARNING
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX)
set(__LAST_LIBDIR_DEFAULT "lib64")
endif()
endif()
endif()
endif()
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
elseif(DEFINED __LAST_LIBDIR_DEFAULT
AND "${__LAST_LIBDIR_DEFAULT}" STREQUAL "${CMAKE_INSTALL_LIBDIR}")
set_property(CACHE CMAKE_INSTALL_LIBDIR PROPERTY VALUE "${_LIBDIR_DEFAULT}")
endif()
endif()
# Save for next run
set(_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE INTERNAL "CMAKE_INSTALL_PREFIX during last run")
unset(_libdir_set)
unset(__LAST_LIBDIR_DEFAULT)
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
endif()
#-----------------------------------------------------------------------------
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
# the cache and store the defaults in local variables if the cache values are
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
if(NOT CMAKE_INSTALL_DATADIR)
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(NOT CMAKE_INSTALL_INFODIR)
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
endif()
if(NOT CMAKE_INSTALL_LOCALEDIR)
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
endif()
if(NOT CMAKE_INSTALL_MANDIR)
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
endif()
if(NOT CMAKE_INSTALL_DOCDIR)
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
endif()
#-----------------------------------------------------------------------------
mark_as_advanced(
CMAKE_INSTALL_BINDIR
CMAKE_INSTALL_SBINDIR
CMAKE_INSTALL_LIBEXECDIR
CMAKE_INSTALL_SYSCONFDIR
CMAKE_INSTALL_SHAREDSTATEDIR
CMAKE_INSTALL_LOCALSTATEDIR
CMAKE_INSTALL_LIBDIR
CMAKE_INSTALL_INCLUDEDIR
CMAKE_INSTALL_OLDINCLUDEDIR
CMAKE_INSTALL_DATAROOTDIR
CMAKE_INSTALL_DATADIR
CMAKE_INSTALL_INFODIR
CMAKE_INSTALL_LOCALEDIR
CMAKE_INSTALL_MANDIR
CMAKE_INSTALL_DOCDIR
)
# Result directories
#
foreach(dir
BINDIR
SBINDIR
LIBEXECDIR
SYSCONFDIR
SHAREDSTATEDIR
LOCALSTATEDIR
LIBDIR
INCLUDEDIR
OLDINCLUDEDIR
DATAROOTDIR
DATADIR
INFODIR
LOCALEDIR
MANDIR
DOCDIR
)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
else()
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
endif()
endforeach()

View File

@@ -27,4 +27,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
if(DEFINED MIRALL_FATAL_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif(DEFINED MIRALL_FATAL_WARNINGS)
endif()

View File

@@ -29,11 +29,7 @@
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
#cmakedefine APPLICATION_OCSP_STAPLING_ENABLED "@APPLICATION_OCSP_STAPLING_ENABLED@"
#cmakedefine APPLICATION_FORBID_BAD_SSL "@APPLICATION_FORBID_BAD_SSL@"
#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX
#cmakedefine01 ENFORCE_VIRTUAL_FILES_SYNC_FOLDER
#cmakedefine DO_NOT_USE_PROXY "@DO_NOT_USE_PROXY@"
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@

View File

@@ -406,7 +406,7 @@ Virtual Files
-------------
.. note::
* This feature is currently only available on ``Windows`` by default. ``Linux`` and ``macOS`` implementations are experimental and must be enabled by adding ``showExperimentalOptions=true`` to the ``nextcloud.cfg`` configuration file in the ``App Data`` folder.
* This feature is currently only available on ``Windows`` by default. ``Linux`` implementation is experimental and must be enabled by adding ``showExperimentalOptions=true`` to the ``nextcloud.cfg`` configuration file in the ``App Data`` folder. ``macOS``, at the moment, is using the same backend as ``Linux`` one. It can be enabled with the same ``showExperimentalOptions`` flag.
Oftentimes, users are working with a huge amount of files that are big in size. Synchronizing every such file to a device that's running a Nextcloud desktop client is not always possible due to the user's device storage space limitation.
Let's assume that your desktop client is connected to a server that has 1TB of data. You want all those files at hand, so you can quickly access any file via the file explorer. Your device has 512GB local storage device.
@@ -416,15 +416,8 @@ Needless to say, this is far from being convenient.
That's why, starting from 3.2.0, we are introducing the VFS (Virtual Files) feature. You may have had experience working with a similar feature in other cloud sync clients. This feature is known by different names: Files On-Demand, SmartSync, etc.
The VFS does not occupy much space on the user's storage. It just creates placeholders for each file and folder. These files are quite small and only contain metadata needed to display them properly and to fetch the actual file when needed.
When one tries to open a file, for example by double clicking on a
file in the Windows Explorer, one will see that the file gets
downloaded and becomes available locally. This can be observed by a
small progress-bar popup if the file is large enough.
As soon as the download is complete, the file will then be opened
normally as now it is a real file on the user's storage. It won't
disappear, and, from now on, will always be available, unless it is
manually dehydrated.
One will see a hydration (in other words - file download) process when double-clicking on a file that must become available. There will be a progress-bar popup displayed if the file is large enough. So, the hydration process can be observed and it makes it easy to then find out, how long, it would take to fetch the actual file from the server.
The "Hydration" can be thought of as "downloading" or "fetching" the file contents. As soon as hydration is complete, the file will then be opened normally as now it is a real file on the user's storage. It won't disappear, and, from now on, will always be available, unless it is manually dehydrated.
.. image:: images/vfs_hydration_progress_bar.png
:alt: VFS hydration progress bar

View File

@@ -32,9 +32,10 @@ itself. Should the silent update fail, the client offers a manual download.
macOS
^^^^^
There is no automatic updater on macOS. If a new update is available,
the Nextcloud client initializes a pop-up dialog to alert you of the
update and requesting that you update to the latest version manually.
If a new update is available, the Nextcloud client initializes a pop-up dialog
to alert you of the update and requesting that you update to the latest
version. Due to their use of the Sparkle frameworks, this is the default
process for macOS applications.
Linux
^^^^^
@@ -95,6 +96,14 @@ To prevent automatic updates and disallow manual overrides:
.. note:: branded clients have different key names
Preventing Automatic Updates in macOS Environments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can disable the automatic update mechanism, in the macOS operating system,
by copying the file
``nextcloud.app/Contents/Resources/deny_autoupdate_com.nextcloud.desktopclient.plist``
to ``/Library/Preferences/com.nextcloud.desktopclient.plist``.
Preventing Automatic Updates in Linux Environments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -185,8 +185,6 @@ Then, in Terminal:
.. code-block:: bash
% echo 'export CMAKE_INSTALL_PREFIX=~/Builds' >> ~/.nextcloud_build_variables
# If you want to build a macOS app bundle for distribution
% echo 'export BUILD_OWNCLOUD_OSX_BUNDLE=ON' >> ~/.nextcloud_build_variables
Replace ``~/Builds`` with a different directory if you'd like the build to end up elsewhere.

View File

@@ -48,9 +48,9 @@ copyright = u'2013-2021, The Nextcloud developers'
# built documents.
#
# The short X.Y version.
version = '3.4'
version = '3.3'
# The full version, including alpha/beta/rc tags.
release = '3.4.2'
release = '3.3.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -41,7 +41,7 @@ Some interesting values that can be set on the configuration file are:
| ``chunkSize`` | ``10000000`` (10 MB) | Specifies the chunk size of uploaded files in bytes. |
| | | The client will dynamically adjust this size within the maximum and minimum bounds (see below). |
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``maxChunkSize`` | ``1000000000`` (1000 MB) | Specifies the maximum chunk size of uploaded files in bytes. |
| ``maxChunkSize`` | ``100000000`` (100 MB) | Specifies the maximum chunk size of uploaded files in bytes. |
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
| ``minChunkSize`` | ``1000000`` (1 MB) | Specifies the minimum chunk size of uploaded files in bytes. |
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -31,7 +31,7 @@ download page.
System Requirements
----------------------------------
- Windows 8.1+
- Windows 10+
- macOS 10.12+ (64-bit only)
- Linux
- FreeBSD

View File

@@ -157,35 +157,6 @@ icon.
If a directory includes ignored files that are marked with warning icons
that does not change the status of the parent directories.
Set the user status
-------------------
If you have the user status app installed on your Nextcloud server,
you can set your user status from the desktop client. To do so, open
the main dialog. Then click on your avatar and then click on the three
dots. In the menu that opens click on **Set status**.
.. figure:: images/user_status_selector_main_dialog.png
:alt: Open user status dialog from main dialog.
In the dialog that opens, you can set your online status if
you click on either **Online**, **Away**, **Do not disturb** or
**Invisible**. You can also set a custom status message with the text
field below or choose one of the predefined status messages below. It
is also possible to set a custom emoji if you click on the button with
the emoji beside the text input field. The last thing you might want
to set is when your user status should be cleared. You can choose the
period after which the user status will be cleared by clicking on the
button on the left hand side of the text **Clear status message after**.
.. figure:: images/user_status-selector_dialog.png
:alt: Dialog to set user status.
If you are happy with the status you have created you can enable this
status with the button **Set status message**. If you had already a
status set, you can clear the status by clicking the cutton **Clear
status message**.
Sharing From Your Desktop
-------------------------

View File

@@ -1,27 +1,11 @@
<RCC>
<qresource prefix="/qml">
<file>src/gui/UserStatusSelector.qml</file>
<file>src/gui/UserStatusSelectorDialog.qml</file>
<file>src/gui/EmojiPicker.qml</file>
<file>src/gui/ErrorBox.qml</file>
<file>src/gui/tray/Window.qml</file>
<file>src/gui/tray/UserLine.qml</file>
<file>src/gui/tray/HeaderButton.qml</file>
<file>src/gui/tray/SyncStatus.qml</file>
<file>theme/Style/Style.qml</file>
<file>theme/Style/qmldir</file>
<file>src/gui/tray/ActivityActionButton.qml</file>
<file>src/gui/tray/ActivityItem.qml</file>
<file>src/gui/tray/AutoSizingMenu.qml</file>
<file>src/gui/tray/ActivityList.qml</file>
<file>src/gui/tray/FileActivityDialog.qml</file>
<file>src/gui/tray/UnifiedSearchInputContainer.qml</file>
<file>src/gui/tray/UnifiedSearchResultFetchMoreTrigger.qml</file>
<file>src/gui/tray/UnifiedSearchResultItem.qml</file>
<file>src/gui/tray/UnifiedSearchResultItemSkeleton.qml</file>
<file>src/gui/tray/UnifiedSearchResultItemSkeletonContainer.qml</file>
<file>src/gui/tray/UnifiedSearchResultListItem.qml</file>
<file>src/gui/tray/UnifiedSearchResultNothingFound.qml</file>
<file>src/gui/tray/UnifiedSearchResultSectionItem.qml</file>
</qresource>
</RCC>

View File

@@ -1,26 +1,23 @@
if(APPLE)
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
# The bundle identifier and application group need to have compatible values with the client
# to be able to open a Mach port across the extension's sandbox boundary.
# Pass the info through the xcodebuild command line and make sure that the project uses
# those user-defined settings to build the plist.
add_custom_target( mac_overlayplugin ALL
xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO
-project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
# The bundle identifier and application group need to have compatible values with the client
# to be able to open a Mach port across the extension's sandbox boundary.
# Pass the info through the xcodebuild command line and make sure that the project uses
# those user-defined settings to build the plist.
add_custom_target( mac_overlayplugin ALL
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
COMMENT building Mac Overlay icons
VERBATIM)
add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated
add_dependencies(mac_overlayplugin ${APPLICATION_EXECUTABLE}) # for the ownCloud.icns to be generated
if (BUILD_OWNCLOUD_OSX_BUNDLE)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
USE_SOURCE_PERMISSIONS)
endif()
endif()
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
USE_SOURCE_PERMISSIONS)
endif(APPLE)

View File

@@ -2,7 +2,7 @@ project(dolphin-owncloud)
cmake_minimum_required(VERSION 2.8.12)
set(QT_MIN_VERSION "5.15.0")
set(QT_MIN_VERSION "5.12.0")
set(KF5_MIN_VERSION "5.16.0")
set(KDE_INSTALL_USE_QT_SYS_PATHS ON CACHE BOOL "Install the plugin in the right directory")

View File

@@ -37,7 +37,7 @@ public:
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
: KAbstractFileItemActionPlugin(parent) { }
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) override
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE
{
auto helper = OwncloudDolphinPluginHelper::instance();
if (!helper->isConnected() || !fileItemInfos.isLocal())

View File

@@ -1,6 +1,6 @@
if( UNIX AND NOT APPLE )
SET(ICON_DIR ${CMAKE_INSTALL_DATADIR}/icons/hicolor)
SET(ICON_DIR ${DATADIR}/icons/hicolor)
FOREACH(size 128x128 16x16 256x256 32x32 48x48 64x64 72x72)
file(GLOB files "${size}/*.png")

View File

@@ -41,7 +41,7 @@ macro(libcloudproviders_add_config _sources)
endmacro(libcloudproviders_add_config _sources)
find_package(Qt5 5.15 COMPONENTS DBus)
find_package(Qt5 5.12 COMPONENTS DBus)
IF (Qt5DBus_FOUND)
STRING(TOLOWER "${APPLICATION_VENDOR}" DBUS_VENDOR)
STRING(REGEX REPLACE "[^A-z0-9]" "" DBUS_VENDOR "${DBUS_VENDOR}")

View File

@@ -25,9 +25,9 @@ if( UNIX AND NOT APPLE )
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${CMAKE_INSTALL_DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${CMAKE_INSTALL_DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${CMAKE_INSTALL_DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)

View File

@@ -26,7 +26,7 @@
#pragma once
class RemotePathChecker {
class __declspec(dllexport) RemotePathChecker {
public:
enum FileState {
// Order synced with NCOverlay

View File

@@ -63,7 +63,6 @@
<File Id="NCContextMenu.dll" KeyPath="yes" Source="$(var.HarvestAppDir)\shellext\NCContextMenu.dll">
<Class Id="$(var.ContextMenuGuid)" Context="InprocServer32" Description="$(var.ContextMenuDescription)" ThreadingModel="apartment" />
</File>
<RegistryValue Root="HKCR" Key="CLSID\$(var.ContextMenuGuid)" Name="ContextMenuOptIn" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="AllFileSystemObjects\shellex\ContextMenuHandlers\$(var.ContextMenuRegKeyName)" Value="$(var.ContextMenuGuid)" Type="string" Action="write" />
</Component>

View File

@@ -1,12 +0,0 @@
sonar.projectKey=nextcloud_desktop
sonar.organization=nextcloud
sonar.projectBaseDir=..
sonar.sources=src
sonar.exclusions=3rdparty/**
sonar.language=c++
sonar.cfamily.cache.enabled=false
sonar.sourceEncoding=UTF-8
sonar.cfamily.threads=2
sonar.cfamily.gcov.reportsPath=build/Testing/CoverageInfo
sonar.cfamily.cache.enabled=true,
sonar.cfamily.cache.path=/cache/sonarcloud

View File

@@ -67,8 +67,8 @@ public:
*/
const QColor & color() const { return m_color; }
QSize sizeHint() const override;
int heightForWidth(int w) const override;
virtual QSize sizeHint() const;
int heightForWidth(int w) const;
public slots:
/*! Starts the spin animation.
\sa stopAnimation isAnimated
@@ -98,8 +98,8 @@ public slots:
*/
void setColor(const QColor & color);
protected:
void timerEvent(QTimerEvent * event) override;
void paintEvent(QPaintEvent * event) override;
virtual void timerEvent(QTimerEvent * event);
virtual void paintEvent(QPaintEvent * event);
private:
int m_angle = 0;
int m_timerId = -1;

View File

@@ -1,280 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "wheelhandler.h"
#include <QWheelEvent>
#include <QQuickItem>
#include <QDebug>
class GlobalWheelFilterSingleton
{
public:
GlobalWheelFilter self;
};
Q_GLOBAL_STATIC(GlobalWheelFilterSingleton, privateGlobalWheelFilterSelf)
GlobalWheelFilter::GlobalWheelFilter(QObject *parent)
: QObject(parent)
{
}
GlobalWheelFilter::~GlobalWheelFilter() = default;
GlobalWheelFilter *GlobalWheelFilter::self()
{
return &privateGlobalWheelFilterSelf()->self;
}
void GlobalWheelFilter::setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
{
if (!m_handlersForItem.contains(handler->target())) {
handler->target()->installEventFilter(this);
}
m_handlersForItem.insert(item, handler);
connect(item, &QObject::destroyed, this, [this](QObject *obj) {
auto item = static_cast<QQuickItem *>(obj);
m_handlersForItem.remove(item);
});
connect(handler, &QObject::destroyed, this, [this](QObject *obj) {
auto handler = static_cast<WheelHandler *>(obj);
removeItemHandlerAssociation(handler->target(), handler);
});
}
void GlobalWheelFilter::removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
{
if (!item || !handler) {
return;
}
m_handlersForItem.remove(item, handler);
if (!m_handlersForItem.contains(item)) {
item->removeEventFilter(this);
}
}
bool GlobalWheelFilter::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::Wheel) {
auto item = qobject_cast<QQuickItem *>(watched);
if (!item || !item->isEnabled()) {
return QObject::eventFilter(watched, event);
}
auto we = static_cast<QWheelEvent *>(event);
m_wheelEvent.initializeFromEvent(we);
bool shouldBlock = false;
bool shouldScrollFlickable = false;
for (auto *handler : m_handlersForItem.values(item)) {
if (handler->m_blockTargetWheel) {
shouldBlock = true;
}
if (handler->m_scrollFlickableTarget) {
shouldScrollFlickable = true;
}
emit handler->wheel(&m_wheelEvent);
}
if (shouldScrollFlickable && !m_wheelEvent.isAccepted()) {
manageWheel(item, we);
}
if (shouldBlock) {
return true;
}
}
return QObject::eventFilter(watched, event);
}
void GlobalWheelFilter::manageWheel(QQuickItem *target, QWheelEvent *event)
{
// Duck typing: accept everyhint that has all the properties we need
if (target->metaObject()->indexOfProperty("contentX") == -1
|| target->metaObject()->indexOfProperty("contentY") == -1
|| target->metaObject()->indexOfProperty("contentWidth") == -1
|| target->metaObject()->indexOfProperty("contentHeight") == -1
|| target->metaObject()->indexOfProperty("topMargin") == -1
|| target->metaObject()->indexOfProperty("bottomMargin") == -1
|| target->metaObject()->indexOfProperty("leftMargin") == -1
|| target->metaObject()->indexOfProperty("rightMargin") == -1
|| target->metaObject()->indexOfProperty("originX") == -1
|| target->metaObject()->indexOfProperty("originY") == -1) {
return;
}
qreal contentWidth = target->property("contentWidth").toReal();
qreal contentHeight = target->property("contentHeight").toReal();
qreal contentX = target->property("contentX").toReal();
qreal contentY = target->property("contentY").toReal();
qreal topMargin = target->property("topMargin").toReal();
qreal bottomMargin = target->property("bottomMargin").toReal();
qreal leftMargin = target->property("leftMaring").toReal();
qreal rightMargin = target->property("rightMargin").toReal();
qreal originX = target->property("originX").toReal();
qreal originY = target->property("originY").toReal();
// Scroll Y
if (contentHeight > target->height()) {
int y = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
//if we don't have a pixeldelta, apply the configured mouse wheel lines
if (!event->pixelDelta().y()) {
y *= 3; // Magic copied value from Kirigami::Settings
}
// Scroll one page regardless of delta:
if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
if (y > 0) {
y = target->height();
} else if (y < 0) {
y = -target->height();
}
}
qreal minYExtent = topMargin - originY;
qreal maxYExtent = target->height() - (contentHeight + bottomMargin + originY);
target->setProperty("contentY", qMin(-maxYExtent, qMax(-minYExtent, contentY - y)));
}
//Scroll X
if (contentWidth > target->width()) {
int x = event->pixelDelta().x() != 0 ? event->pixelDelta().x() : event->angleDelta().x() / 8;
// Special case: when can't scroll vertically, scroll horizontally with vertical wheel as well
if (x == 0 && contentHeight <= target->height()) {
x = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
}
//if we don't have a pixeldelta, apply the configured mouse wheel lines
if (!event->pixelDelta().x()) {
x *= 3; // Magic copied value from Kirigami::Settings
}
// Scroll one page regardless of delta:
if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
if (x > 0) {
x = target->width();
} else if (x < 0) {
x = -target->width();
}
}
qreal minXExtent = leftMargin - originX;
qreal maxXExtent = target->width() - (contentWidth + rightMargin + originX);
target->setProperty("contentX", qMin(-maxXExtent, qMax(-minXExtent, contentX - x)));
}
//this is just for making the scrollbar
target->metaObject()->invokeMethod(target, "flick", Q_ARG(double, 0), Q_ARG(double, 1));
target->metaObject()->invokeMethod(target, "cancelFlick");
}
////////////////////////////
KirigamiWheelEvent::KirigamiWheelEvent(QObject *parent)
: QObject(parent)
{}
KirigamiWheelEvent::~KirigamiWheelEvent() = default;
void KirigamiWheelEvent::initializeFromEvent(QWheelEvent *event)
{
m_x = event->position().x();
m_y = event->position().y();
m_angleDelta = event->angleDelta();
m_pixelDelta = event->pixelDelta();
m_buttons = event->buttons();
m_modifiers = event->modifiers();
m_accepted = false;
m_inverted = event->inverted();
}
qreal KirigamiWheelEvent::x() const
{
return m_x;
}
qreal KirigamiWheelEvent::y() const
{
return m_y;
}
QPointF KirigamiWheelEvent::angleDelta() const
{
return m_angleDelta;
}
QPointF KirigamiWheelEvent::pixelDelta() const
{
return m_pixelDelta;
}
int KirigamiWheelEvent::buttons() const
{
return m_buttons;
}
int KirigamiWheelEvent::modifiers() const
{
return m_modifiers;
}
bool KirigamiWheelEvent::inverted() const
{
return m_inverted;
}
bool KirigamiWheelEvent::isAccepted()
{
return m_accepted;
}
void KirigamiWheelEvent::setAccepted(bool accepted)
{
m_accepted = accepted;
}
///////////////////////////////
WheelHandler::WheelHandler(QObject *parent)
: QObject(parent)
{
}
WheelHandler::~WheelHandler() = default;
QQuickItem *WheelHandler::target() const
{
return m_target;
}
void WheelHandler::setTarget(QQuickItem *target)
{
if (m_target == target) {
return;
}
if (m_target) {
GlobalWheelFilter::self()->removeItemHandlerAssociation(m_target, this);
}
m_target = target;
GlobalWheelFilter::self()->setItemHandlerAssociation(target, this);
emit targetChanged();
}
#include "moc_wheelhandler.cpp"

View File

@@ -1,213 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
#pragma once
#include <QtQml>
#include <QPoint>
#include <QQuickItem>
#include <QObject>
class QWheelEvent;
class WheelHandler;
/**
* Describes the mouse wheel event
*/
class KirigamiWheelEvent : public QObject
{
Q_OBJECT
/**
* x: real
*
* X coordinate of the mouse pointer
*/
Q_PROPERTY(qreal x READ x CONSTANT)
/**
* y: real
*
* Y coordinate of the mouse pointer
*/
Q_PROPERTY(qreal y READ y CONSTANT)
/**
* angleDelta: point
*
* The distance the wheel is rotated in degrees.
* The x and y coordinates indicate the horizontal and vertical wheels respectively.
* A positive value indicates it was rotated up/right, negative, bottom/left
* This value is more likely to be set in traditional mice.
*/
Q_PROPERTY(QPointF angleDelta READ angleDelta CONSTANT)
/**
* pixelDelta: point
*
* provides the delta in screen pixels available on high resolution trackpads
*/
Q_PROPERTY(QPointF pixelDelta READ pixelDelta CONSTANT)
/**
* buttons: int
*
* it contains an OR combination of the buttons that were pressed during the wheel, they can be:
* Qt.LeftButton, Qt.MiddleButton, Qt.RightButton
*/
Q_PROPERTY(int buttons READ buttons CONSTANT)
/**
* modifiers: int
*
* Keyboard mobifiers that were pressed during the wheel event, such as:
* Qt.NoModifier (default, no modifiers)
* Qt.ControlModifier
* Qt.ShiftModifier
* ...
*/
Q_PROPERTY(int modifiers READ modifiers CONSTANT)
/**
* inverted: bool
*
* Whether the delta values are inverted
* On some platformsthe returned delta are inverted, so positive values would mean bottom/left
*/
Q_PROPERTY(bool inverted READ inverted CONSTANT)
/**
* accepted: bool
*
* If set, the event shouldn't be managed anymore,
* for instance it can be used to block the handler to manage the scroll of a view on some scenarios
* @code
* // This handler handles automatically the scroll of
* // flickableItem, unless Ctrl is pressed, in this case the
* // app has custom code to handle Ctrl+wheel zooming
* Kirigami.WheelHandler {
* target: flickableItem
* blockTargetWheel: true
* scrollFlickableTarget: true
* onWheel: {
* if (wheel.modifiers & Qt.ControlModifier) {
* wheel.accepted = true;
* // Handle scaling of the view
* }
* }
* }
* @endcode
*
*/
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
public:
KirigamiWheelEvent(QObject *parent = nullptr);
~KirigamiWheelEvent() override;
void initializeFromEvent(QWheelEvent *event);
qreal x() const;
qreal y() const;
QPointF angleDelta() const;
QPointF pixelDelta() const;
int buttons() const;
int modifiers() const;
bool inverted() const;
bool isAccepted();
void setAccepted(bool accepted);
private:
qreal m_x = 0;
qreal m_y = 0;
QPointF m_angleDelta;
QPointF m_pixelDelta;
Qt::MouseButtons m_buttons = Qt::NoButton;
Qt::KeyboardModifiers m_modifiers = Qt::NoModifier;
bool m_inverted = false;
bool m_accepted = false;
};
class GlobalWheelFilter : public QObject
{
Q_OBJECT
public:
GlobalWheelFilter(QObject *parent = nullptr);
~GlobalWheelFilter() override;
static GlobalWheelFilter *self();
void setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
void removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private:
void manageWheel(QQuickItem *target, QWheelEvent *wheel);
QMultiHash<QQuickItem *, WheelHandler *> m_handlersForItem;
KirigamiWheelEvent m_wheelEvent;
};
/**
* This class intercepts the mouse wheel events of its target, and gives them to the user code as a signal, which can be used for custom mouse wheel management code.
* The handler can block completely the wheel events from its target, and if it's a Flickable, it can automatically handle scrolling on it
*/
class WheelHandler : public QObject
{
Q_OBJECT
/**
* target: Item
*
* The target we want to manage wheel events.
* We will receive wheel() signals every time the user moves
* the mouse wheel (or scrolls with the touchpad) on top
* of that item.
*/
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
/**
* blockTargetWheel: bool
*
* If true, the target won't receive any wheel event at all (default true)
*/
Q_PROPERTY(bool blockTargetWheel MEMBER m_blockTargetWheel NOTIFY blockTargetWheelChanged)
/**
* scrollFlickableTarget: bool
* If this property is true and the target is a Flickable, wheel events will cause the Flickable to scroll (default true)
*/
Q_PROPERTY(bool scrollFlickableTarget MEMBER m_scrollFlickableTarget NOTIFY scrollFlickableTargetChanged)
public:
explicit WheelHandler(QObject *parent = nullptr);
~WheelHandler() override;
QQuickItem *target() const;
void setTarget(QQuickItem *target);
Q_SIGNALS:
void targetChanged();
void blockTargetWheelChanged();
void scrollFlickableTargetChanged();
void wheel(KirigamiWheelEvent *wheel);
private:
QPointer<QQuickItem> m_target;
bool m_blockTargetWheel = true;
bool m_scrollFlickableTarget = true;
KirigamiWheelEvent m_wheelEvent;
friend class GlobalWheelFilter;
};

View File

@@ -57,7 +57,7 @@ public:
QtLockedFile();
QtLockedFile(const QString &name);
~QtLockedFile() override;
~QtLockedFile();
bool lock(LockMode mode, bool block = true);
bool unlock();

View File

@@ -44,13 +44,13 @@ class QtSingleApplication : public QApplication
public:
QtSingleApplication(const QString &id, int &argc, char **argv);
~QtSingleApplication() override;
~QtSingleApplication();
bool isRunning(qint64 pid = -1);
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
QWidget* activationWindow() const;
bool event(QEvent *event) override;
bool event(QEvent *event) Q_DECL_OVERRIDE;
QString applicationId() const;
void setBlock(bool value);

View File

@@ -4,8 +4,10 @@ endif()
include(ECMEnableSanitizers)
find_package(Qt5 5.15 COMPONENTS Core Network Xml Concurrent REQUIRED)
find_package(Qt5 5.15 COMPONENTS WebEngineWidgets WebEngine)
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
find_package(Qt5 5.12 COMPONENTS Core Network Xml Concurrent REQUIRED)
find_package(Qt5 5.12 COMPONENTS WebEngineWidgets WebEngine)
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
add_compile_definitions(WITH_WEBENGINE=1)
@@ -59,6 +61,10 @@ elseif(UNIX AND NOT APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
endif()
include_directories(
${CMAKE_SOURCE_DIR}/src/3rdparty
)
set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/theme CACHE STRING "" FORCE)
add_subdirectory(csync)

View File

@@ -1,11 +1,14 @@
project(cmd)
set(CMAKE_AUTOMOC TRUE)
set(cmd_NAME ${APPLICATION_EXECUTABLE}cmd)
add_library(cmdCore STATIC simplesslerrorhandler.cpp netrcparser.cpp)
target_link_libraries(cmdCore
PUBLIC
Nextcloud::sync
"${csync_NAME}"
"${synclib_NAME}"
Qt5::Core
Qt5::Network
)
@@ -24,22 +27,20 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
endif()
if(NOT BUILD_LIBRARIES_ONLY)
add_executable(nextcloudcmd cmd.cpp)
set_target_properties(nextcloudcmd PROPERTIES
RUNTIME_OUTPUT_NAME "${APPLICATION_EXECUTABLE}cmd")
target_link_libraries(nextcloudcmd cmdCore)
add_executable(${cmd_NAME} cmd.cpp)
if(BUILD_OWNCLOUD_OSX_BUNDLE)
set_target_properties(nextcloudcmd PROPERTIES
set_target_properties(${cmd_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS")
else()
set_target_properties(nextcloudcmd PROPERTIES
set_target_properties(${cmd_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY})
install(TARGETS nextcloudcmd
install(TARGETS ${cmd_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
target_link_libraries(${cmd_NAME} cmdCore)
endif()

View File

@@ -142,7 +142,7 @@ public:
{
}
void askFromUser() override
void askFromUser() Q_DECL_OVERRIDE
{
_password = ::queryPassword(user());
_ready = true;
@@ -155,7 +155,7 @@ public:
_sslTrusted = isTrusted;
}
bool sslIsTrusted() override
bool sslIsTrusted() Q_DECL_OVERRIDE
{
return _sslTrusted;
}
@@ -295,10 +295,9 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
bool ok = false;
const auto selectiveSyncList = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
const QSet<QString> oldBlackListSet(selectiveSyncList.begin(), selectiveSyncList.end());
auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok).toSet();
if (ok) {
const QSet<QString> blackListSet(newList.begin(), newList.end());
auto blackListSet = newList.toSet();
const auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
for (const auto &it : changes) {
journal->schedulePathForRemoteDiscovery(it);
@@ -310,9 +309,6 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
int main(int argc, char **argv)
{
#ifdef Q_OS_WIN
SetDllDirectory(L"");
#endif
QCoreApplication app(argc, argv);
#ifdef Q_OS_WIN
@@ -321,6 +317,8 @@ int main(int argc, char **argv)
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
#endif
qsrand(std::random_device()());
CmdOptions options;
options.silent = false;
options.trustSSL = false;
@@ -353,7 +351,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
QUrl hostUrl = QUrl::fromUserInput((options.target_url.endsWith(QLatin1Char('/')) || options.target_url.endsWith(QLatin1Char('\\'))) ? options.target_url.chopped(1) : options.target_url);
QUrl hostUrl = QUrl::fromUserInput(options.target_url);
// Order of retrieval attempt (later attempts override earlier ones):
// 1. From URL
@@ -483,7 +481,7 @@ restart_sync:
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
} else {
// filter out empty lines and comments
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegularExpression("\\S+")).filter(QRegularExpression("^[^#]"));
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegExp("\\S+")).filter(QRegExp("^[^#]"));
for (int i = 0; i < selectiveSyncList.count(); ++i) {
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
@@ -501,9 +499,6 @@ restart_sync:
selectiveSyncFixup(&db, selectiveSyncList);
}
SyncOptions opt;
opt.fillFromEnvironmentVariables();
opt.verifyChunkSizes();
SyncEngine engine(account, options.source_dir, folder, &db);
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
engine.setNetworkLimits(options.uplimit, options.downlimit);

View File

@@ -28,7 +28,7 @@ namespace OCC {
class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler
{
public:
bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr) override;
bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr) Q_DECL_OVERRIDE;
};
}

View File

@@ -144,9 +144,6 @@ QByteArray makeChecksumHeader(const QByteArray &checksumType, const QByteArray &
QByteArray findBestChecksum(const QByteArray &_checksums)
{
if (_checksums.isEmpty()) {
return {};
}
const auto checksums = QString::fromUtf8(_checksums);
int i = 0;
// The order of the searches here defines the preference ordering.
@@ -165,7 +162,7 @@ QByteArray findBestChecksum(const QByteArray &_checksums)
return _checksums.mid(i, end - i);
}
qCWarning(lcChecksums) << "Failed to parse" << _checksums;
return {};
return QByteArray();
}
bool parseChecksumHeader(const QByteArray &header, QByteArray *type, QByteArray *checksum)
@@ -364,11 +361,11 @@ void ValidateChecksumHeader::slotChecksumCalculated(const QByteArray &checksumTy
const QByteArray &checksum)
{
if (checksumType != _expectedChecksumType) {
emit validationFailed(tr("The checksum header contained an unknown checksum type \"%1\"").arg(QString::fromLatin1(_expectedChecksumType)));
emit validationFailed(tr("The checksum header contained an unknown checksum type '%1'").arg(QString::fromLatin1(_expectedChecksumType)));
return;
}
if (checksum != _expectedChecksum) {
emit validationFailed(tr(R"(The downloaded file does not match the checksum, it will be resumed. "%1" != "%2")").arg(QString::fromUtf8(_expectedChecksum), QString::fromUtf8(checksum)));
emit validationFailed(tr("The downloaded file does not match the checksum, it will be resumed. '%1' != '%2'").arg(QString::fromUtf8(_expectedChecksum), QString::fromUtf8(checksum)));
return;
}
emit validated(checksumType, checksum);

View File

@@ -81,7 +81,7 @@ class OCSYNC_EXPORT ComputeChecksum : public QObject
Q_OBJECT
public:
explicit ComputeChecksum(QObject *parent = nullptr);
~ComputeChecksum() override;
~ComputeChecksum();
/**
* Sets the checksum type to be used. The default is empty.

View File

@@ -5,7 +5,6 @@ set(common_SOURCES
${CMAKE_CURRENT_LIST_DIR}/checksums.cpp
${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
${CMAKE_CURRENT_LIST_DIR}/ownsql.cpp
${CMAKE_CURRENT_LIST_DIR}/preparedsqlquerymanager.cpp
${CMAKE_CURRENT_LIST_DIR}/syncjournaldb.cpp
${CMAKE_CURRENT_LIST_DIR}/syncjournalfilerecord.cpp
${CMAKE_CURRENT_LIST_DIR}/utility.cpp

View File

@@ -1,23 +0,0 @@
/*
* Copyright (C) by Oleksandr Zolotov <alex@nextcloud.com>
*
* 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 <QtGlobal>
namespace OCC {
namespace Constants {
constexpr qint32 e2EeTagSize = 16;
}
}

View File

@@ -395,13 +395,13 @@ bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
suffix_number++;
}
if (!file.rename(f.absoluteFilePath(), path + QString::number(suffix_number))) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
.arg(f.absoluteFilePath(), path + QString::number(suffix_number));
return false;
}
} else {
if (!file.rename(f.absoluteFilePath(), trashFilePath + f.fileName())) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
.arg(f.absoluteFilePath(), trashFilePath + f.fileName());
return false;
}

View File

@@ -490,4 +490,18 @@ void SqlQuery::reset_and_clear_bindings()
}
}
bool SqlQuery::initOrReset(const QByteArray &sql, OCC::SqlDatabase &db)
{
ENFORCE(!_sqldb || &db == _sqldb);
_sqldb = &db;
_db = db.sqliteDb();
if (_stmt) {
reset_and_clear_bindings();
return true;
} else {
return prepare(sql) == 0;
}
}
} // namespace OCC

View File

@@ -103,6 +103,12 @@ public:
explicit SqlQuery() = default;
explicit SqlQuery(SqlDatabase &db);
explicit SqlQuery(const QByteArray &sql, SqlDatabase &db);
/**
* Prepare the SqlQuery if it was not prepared yet.
* Otherwise, clear the results and the bindings.
* return false if there is an error
*/
bool initOrReset(const QByteArray &sql, SqlDatabase &db);
/**
* Prepare the SqlQuery.
* If the query was already prepared, this will first call finish(), and re-prepare it.
@@ -155,10 +161,10 @@ public:
const QByteArray &lastQuery() const;
int numRowsAffected();
void reset_and_clear_bindings();
void finish();
private:
void bindValueInternal(int pos, const QVariant &value);
void finish();
SqlDatabase *_sqldb = nullptr;
sqlite3 *_db = nullptr;
@@ -166,9 +172,6 @@ private:
QString _error;
int _errId;
QByteArray _sql;
friend class SqlDatabase;
friend class PreparedSqlQueryManager;
};
} // namespace OCC

View File

@@ -77,7 +77,7 @@ enum class PinState {
*/
Unspecified = 3,
};
Q_ENUM_NS(PinState)
Q_ENUM_NS(PinState);
/** A user-facing version of PinState.
*

View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "preparedsqlquerymanager.h"
#include <sqlite3.h>
using namespace OCC;
PreparedSqlQuery::PreparedSqlQuery(SqlQuery *query, bool ok)
: _query(query)
, _ok(ok)
{
}
PreparedSqlQuery::~PreparedSqlQuery()
{
_query->reset_and_clear_bindings();
}
const PreparedSqlQuery PreparedSqlQueryManager::get(PreparedSqlQueryManager::Key key)
{
auto &query = _queries[key];
ENFORCE(query._stmt)
Q_ASSERT(!sqlite3_stmt_busy(query._stmt));
return { &query };
}
const PreparedSqlQuery PreparedSqlQueryManager::get(PreparedSqlQueryManager::Key key, const QByteArray &sql, SqlDatabase &db)
{
auto &query = _queries[key];
Q_ASSERT(!sqlite3_stmt_busy(query._stmt));
ENFORCE(!query._sqldb || &db == query._sqldb)
if (!query._stmt) {
query._sqldb = &db;
query._db = db.sqliteDb();
return { &query, query.prepare(sql) == 0 };
}
return { &query };
}

View File

@@ -1,119 +0,0 @@
/*
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "ocsynclib.h"
#include "ownsql.h"
#include "common/asserts.h"
namespace OCC {
class OCSYNC_EXPORT PreparedSqlQuery
{
public:
~PreparedSqlQuery();
explicit operator bool() const { return _ok; }
SqlQuery *operator->() const
{
Q_ASSERT(_ok);
return _query;
}
SqlQuery &operator*() const &
{
Q_ASSERT(_ok);
return *_query;
}
private:
PreparedSqlQuery(SqlQuery *query, bool ok = true);
SqlQuery *_query;
bool _ok;
friend class PreparedSqlQueryManager;
};
/**
* @brief Manage PreparedSqlQuery
*/
class OCSYNC_EXPORT PreparedSqlQueryManager
{
public:
enum Key {
GetFileRecordQuery,
GetFileRecordQueryByMangledName,
GetFileRecordQueryByInode,
GetFileRecordQueryByFileId,
GetFilesBelowPathQuery,
GetAllFilesQuery,
ListFilesInPathQuery,
SetFileRecordQuery,
SetFileRecordChecksumQuery,
SetFileRecordLocalMetadataQuery,
GetDownloadInfoQuery,
SetDownloadInfoQuery,
DeleteDownloadInfoQuery,
GetUploadInfoQuery,
SetUploadInfoQuery,
DeleteUploadInfoQuery,
DeleteFileRecordPhash,
DeleteFileRecordRecursively,
GetErrorBlacklistQuery,
SetErrorBlacklistQuery,
GetSelectiveSyncListQuery,
GetChecksumTypeIdQuery,
GetChecksumTypeQuery,
InsertChecksumTypeQuery,
GetDataFingerprintQuery,
SetDataFingerprintQuery1,
SetDataFingerprintQuery2,
SetKeyValueStoreQuery,
GetKeyValueStoreQuery,
DeleteKeyValueStoreQuery,
GetConflictRecordQuery,
SetConflictRecordQuery,
DeleteConflictRecordQuery,
GetRawPinStateQuery,
GetEffectivePinStateQuery,
GetSubPinsQuery,
CountDehydratedFilesQuery,
SetPinStateQuery,
WipePinStateQuery,
PreparedQueryCount
};
PreparedSqlQueryManager() = default;
/**
* The queries are reset in the destructor to prevent wal locks
*/
const PreparedSqlQuery get(Key key);
/**
* Prepare the SqlQuery if it was not prepared yet.
*/
const PreparedSqlQuery get(Key key, const QByteArray &sql, SqlDatabase &db);
private:
SqlQuery _queries[PreparedQueryCount];
Q_DISABLE_COPY(PreparedSqlQueryManager)
};
}

View File

@@ -104,7 +104,6 @@ public:
ASSERT(!_isError);
return _result;
}
T operator*() &&
{
ASSERT(!_isError);
@@ -117,12 +116,6 @@ public:
return &_result;
}
const T &get() const
{
ASSERT(!_isError)
return _result;
}
const Error &error() const &
{
ASSERT(_isError);

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,6 @@
#include "common/utility.h"
#include "common/ownsql.h"
#include "common/preparedsqlquerymanager.h"
#include "common/syncjournalfilerecord.h"
#include "common/result.h"
#include "common/pinstate.h"
@@ -47,7 +46,7 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
Q_OBJECT
public:
explicit SyncJournalDb(const QString &dbFilePath, QObject *parent = nullptr);
~SyncJournalDb() override;
virtual ~SyncJournalDb();
/// Create a journal path for a specific configuration
static QString makeDbName(const QString &localPath,
@@ -70,6 +69,7 @@ public:
void keyValueStoreSet(const QString &key, QVariant value);
qint64 keyValueStoreGetInt(const QString &key, qint64 defaultValue);
QVariant keyValueStoreGet(const QString &key, QVariant defaultValue = {});
void keyValueStoreDelete(const QString &key);
bool deleteFileRecord(const QString &filename, bool recursively = false);
@@ -392,11 +392,51 @@ private:
SqlDatabase _db;
QString _dbFile;
QRecursiveMutex _mutex; // Public functions are protected with the mutex.
QMutex _mutex; // Public functions are protected with the mutex.
QMap<QByteArray, int> _checksymTypeCache;
int _transaction;
bool _metadataTableIsEmpty;
SqlQuery _getFileRecordQuery;
SqlQuery _getFileRecordQueryByMangledName;
SqlQuery _getFileRecordQueryByInode;
SqlQuery _getFileRecordQueryByFileId;
SqlQuery _getFilesBelowPathQuery;
SqlQuery _getAllFilesQuery;
SqlQuery _listFilesInPathQuery;
SqlQuery _setFileRecordQuery;
SqlQuery _setFileRecordChecksumQuery;
SqlQuery _setFileRecordLocalMetadataQuery;
SqlQuery _getDownloadInfoQuery;
SqlQuery _setDownloadInfoQuery;
SqlQuery _deleteDownloadInfoQuery;
SqlQuery _getUploadInfoQuery;
SqlQuery _setUploadInfoQuery;
SqlQuery _deleteUploadInfoQuery;
SqlQuery _deleteFileRecordPhash;
SqlQuery _deleteFileRecordRecursively;
SqlQuery _getErrorBlacklistQuery;
SqlQuery _setErrorBlacklistQuery;
SqlQuery _getSelectiveSyncListQuery;
SqlQuery _getChecksumTypeIdQuery;
SqlQuery _getChecksumTypeQuery;
SqlQuery _insertChecksumTypeQuery;
SqlQuery _getDataFingerprintQuery;
SqlQuery _setDataFingerprintQuery1;
SqlQuery _setDataFingerprintQuery2;
SqlQuery _setKeyValueStoreQuery;
SqlQuery _getKeyValueStoreQuery;
SqlQuery _deleteKeyValueStoreQuery;
SqlQuery _getConflictRecordQuery;
SqlQuery _setConflictRecordQuery;
SqlQuery _deleteConflictRecordQuery;
SqlQuery _getRawPinStateQuery;
SqlQuery _getEffectivePinStateQuery;
SqlQuery _getSubPinsQuery;
SqlQuery _countDehydratedFilesQuery;
SqlQuery _setPinStateQuery;
SqlQuery _wipePinStateQuery;
/* Storing etags to these folders, or their parent folders, is filtered out.
*
* When schedulePathForRemoteDiscovery() is called some etags to _invalid_ in the
@@ -418,8 +458,6 @@ private:
* variable, for specific filesystems, or when WAL fails in a particular way.
*/
QByteArray _journalMode;
PreparedSqlQueryManager _queryManager;
};
bool OCSYNC_EXPORT

View File

@@ -37,7 +37,6 @@
#include <QStandardPaths>
#include <QCollator>
#include <QSysInfo>
#include <qrandom.h>
#ifdef Q_OS_UNIX
@@ -65,13 +64,14 @@ Q_LOGGING_CATEGORY(lcUtility, "nextcloud.sync.utility", QtInfoMsg)
bool Utility::writeRandomFile(const QString &fname, int size)
{
int maxSize = 10 * 10 * 1024;
qsrand(QDateTime::currentMSecsSinceEpoch());
if (size == -1)
size = rand() % maxSize;
size = qrand() % maxSize;
QString randString;
for (int i = 0; i < size; i++) {
int r = rand() % 128;
int r = qrand() % 128;
randString.append(QChar(r));
}
@@ -109,11 +109,6 @@ void Utility::setupFavLink(const QString &folder)
setupFavLink_private(folder);
}
void Utility::removeFavLink(const QString &folder)
{
removeFavLink_private(folder);
}
QString Utility::octetsToString(qint64 octets)
{
#define THE_FACTOR 1024
@@ -264,11 +259,6 @@ QString Utility::escape(const QString &in)
return in.toHtmlEscaped();
}
int Utility::rand()
{
return QRandomGenerator::global()->bounded(0, RAND_MAX);
}
void Utility::sleep(int sec)
{
QThread::sleep(sec);

View File

@@ -50,12 +50,10 @@ Q_DECLARE_LOGGING_CATEGORY(lcUtility)
* @{
*/
namespace Utility {
OCSYNC_EXPORT int rand();
OCSYNC_EXPORT void sleep(int sec);
OCSYNC_EXPORT void usleep(int usec);
OCSYNC_EXPORT QString formatFingerprint(const QByteArray &, bool colonSeparated = true);
OCSYNC_EXPORT void setupFavLink(const QString &folder);
OCSYNC_EXPORT void removeFavLink(const QString &folder);
OCSYNC_EXPORT bool writeRandomFile(const QString &fname, int size = -1);
OCSYNC_EXPORT QString octetsToString(qint64 octets);
OCSYNC_EXPORT QByteArray userAgentString();
@@ -242,11 +240,6 @@ namespace Utility {
*/
OCSYNC_EXPORT bool isPathWindowsDrivePartitionRoot(const QString &path);
/**
* @brief Retrieves current logged-in user name from the OS
*/
OCSYNC_EXPORT QString getCurrentUserName();
#ifdef Q_OS_WIN
OCSYNC_EXPORT bool registryKeyExists(HKEY hRootKey, const QString &subKey);
OCSYNC_EXPORT QVariant registryGetKeyValue(HKEY hRootKey, const QString &subKey, const QString &valueName);

View File

@@ -41,11 +41,6 @@ static void setupFavLink_private(const QString &folder)
CFRelease(urlRef);
}
static void removeFavLink_private(const QString &folder)
{
Q_UNUSED(folder)
}
bool hasLaunchOnStartup_private(const QString &)
{
// this is quite some duplicate code with setLaunchOnStartup, at some point we should fix this FIXME.
@@ -136,9 +131,4 @@ static bool hasDarkSystray_private()
return returnValue;
}
QString Utility::getCurrentUserName()
{
return {};
}
} // namespace OCC

View File

@@ -37,11 +37,6 @@ static void setupFavLink_private(const QString &folder)
}
}
static void removeFavLink_private(const QString &folder)
{
Q_UNUSED(folder)
}
// returns the autostart directory the linux way
// and respects the XDG_CONFIG_HOME env variable
QString getUserAutostartDir_private()
@@ -85,17 +80,17 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
QTextStream ts(&iniFile);
ts.setCodec("UTF-8");
ts << QLatin1String("[Desktop Entry]\n")
<< QLatin1String("Name=") << guiName << QLatin1Char('\n')
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer\n")
<< QLatin1String("Exec=\"") << executablePath << "\" --background\n"
<< QLatin1String("Terminal=") << "false\n"
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << QLatin1Char('\n')
<< QLatin1String("Categories=") << QLatin1String("Network\n")
<< QLatin1String("Type=") << QLatin1String("Application\n")
<< QLatin1String("StartupNotify=") << "false\n"
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true\n"
<< QLatin1String("X-GNOME-Autostart-Delay=10") << Qt::endl;
ts << QLatin1String("[Desktop Entry]") << endl
<< QLatin1String("Name=") << guiName << endl
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer") << endl
<< QLatin1String("Exec=\"") << executablePath << "\" --background" << endl
<< QLatin1String("Terminal=") << "false" << endl
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << endl
<< QLatin1String("Categories=") << QLatin1String("Network") << endl
<< QLatin1String("Type=") << QLatin1String("Application") << endl
<< QLatin1String("StartupNotify=") << "false" << endl
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl
<< QLatin1String("X-GNOME-Autostart-Delay=10") << endl;
} else {
if (!QFile::remove(desktopFileLocation)) {
qCWarning(lcUtility) << "Could not remove autostart desktop file";
@@ -108,9 +103,4 @@ static inline bool hasDarkSystray_private()
return true;
}
QString Utility::getCurrentUserName()
{
return {};
}
} // namespace OCC

View File

@@ -18,10 +18,8 @@
#include "asserts.h"
#include "utility.h"
#include "gui/configgui.h"
#include <comdef.h>
#include <Lmcons.h>
#include <shlguid.h>
#include <shlobj.h>
#include <string>
@@ -49,14 +47,7 @@ static void setupFavLink_private(const QString &folder)
desktopIni.open(QFile::WriteOnly);
desktopIni.write("[.ShellClassInfo]\r\nIconResource=");
desktopIni.write(QDir::toNativeSeparators(qApp->applicationFilePath()).toUtf8());
#ifdef APPLICATION_FOLDER_ICON_INDEX
const auto iconIndex = APPLICATION_FOLDER_ICON_INDEX;
#else
const auto iconIndex = "0";
#endif
desktopIni.write(",");
desktopIni.write(iconIndex);
desktopIni.write("\r\n");
desktopIni.write(",0\r\n");
desktopIni.close();
// Set the folder as system and Desktop.ini as hidden+system for explorer to pick it.
@@ -83,40 +74,6 @@ static void setupFavLink_private(const QString &folder)
qCWarning(lcUtility) << "linking" << folder << "to" << linkName << "failed!";
}
static void removeFavLink_private(const QString &folder)
{
const QDir folderDir(folder);
// #1 Remove the Desktop.ini to reset the folder icon
if (!QFile::remove(folderDir.absoluteFilePath(QLatin1String("Desktop.ini")))) {
qCWarning(lcUtility) << "Remove Desktop.ini from" << folder
<< " has failed. Make sure it exists and is not locked by another process.";
}
// #2 Remove the system file attribute
const auto folderAttrs = GetFileAttributesW(folder.toStdWString().c_str());
if (!SetFileAttributesW(folder.toStdWString().c_str(), folderAttrs & ~FILE_ATTRIBUTE_SYSTEM)) {
qCWarning(lcUtility) << "Remove system file attribute failed for:" << folder;
}
// #3 Remove the link to this folder
PWSTR path;
if (!SHGetKnownFolderPath(FOLDERID_Links, 0, nullptr, &path) == S_OK) {
qCWarning(lcUtility) << "SHGetKnownFolderPath for " << folder << "has failed.";
return;
}
const QDir links(QString::fromWCharArray(path));
CoTaskMemFree(path);
const auto linkName = QDir(links).absoluteFilePath(folderDir.dirName() + QLatin1String(".lnk"));
qCInfo(lcUtility) << "Removing favorite link from" << folder << "to" << linkName;
if (!QFile::remove(linkName)) {
qCWarning(lcUtility) << "Removing a favorite link from" << folder << "to" << linkName << "failed.";
}
}
bool hasSystemLaunchOnStartup_private(const QString &appName)
{
QString runPath = QLatin1String(systemRunPathC);
@@ -389,17 +346,6 @@ QString Utility::formatWinError(long errorCode)
return QStringLiteral("WindowsError: %1: %2").arg(QString::number(errorCode, 16), QString::fromWCharArray(_com_error(errorCode).ErrorMessage()));
}
QString Utility::getCurrentUserName()
{
TCHAR username[UNLEN + 1] = {0};
DWORD len = sizeof(username) / sizeof(TCHAR);
if (!GetUserName(username, &len)) {
qCWarning(lcUtility) << "Could not retrieve Windows user name." << formatWinError(GetLastError());
}
return QString::fromWCharArray(username);
}
Utility::NtfsPermissionLookupRAII::NtfsPermissionLookupRAII()
{

View File

@@ -16,7 +16,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "vfs.h"
#include "plugin.h"
#include "version.h"

View File

@@ -126,7 +126,7 @@ public:
public:
explicit Vfs(QObject* parent = nullptr);
~Vfs() override;
virtual ~Vfs();
virtual Mode mode() const = 0;
@@ -291,7 +291,7 @@ class OCSYNC_EXPORT VfsOff : public Vfs
public:
VfsOff(QObject* parent = nullptr);
~VfsOff() override;
virtual ~VfsOff();
Mode mode() const override { return Vfs::Off; }

View File

@@ -18,9 +18,7 @@
#include <libcrashreporter-gui/CrashReporter.h>
#include <QApplication>
#include <QDir>
#include <QDebug>
#include <QFileInfo>
int main(int argc, char *argv[])
{
@@ -54,14 +52,6 @@ int main(int argc, char *argv[])
reporter.setWindowTitle(CRASHREPORTER_PRODUCT_NAME);
reporter.setText("<html><head/><body><p><span style=\" font-weight:600;\">Sorry!</span> " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.</p></body></html>");
const QFileInfo crashLog(QDir::tempPath() + QStringLiteral("/" CRASHREPORTER_PRODUCT_NAME "-crash.log"));
if (crashLog.exists()) {
QFile inFile(crashLog.filePath());
if (inFile.open(QFile::ReadOnly)) {
reporter.setComment(inFile.readAll());
}
}
reporter.setReportData("BuildID", CRASHREPORTER_BUILD_ID);
reporter.setReportData("ProductName", CRASHREPORTER_PRODUCT_NAME);
reporter.setReportData("Version", CRASHREPORTER_VERSION_STRING);

View File

@@ -58,11 +58,10 @@ endif()
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
add_library(nextcloud_csync SHARED ${common_SOURCES} ${csync_SRCS})
add_library(Nextcloud::csync ALIAS nextcloud_csync)
add_library("${csync_NAME}" SHARED ${common_SOURCES} ${csync_SRCS})
target_include_directories(
nextcloud_csync
"${csync_NAME}"
PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/std
)
@@ -70,26 +69,26 @@ if(USE_OUR_OWN_SQLITE3)
message(STATUS "Using own sqlite3 version")
add_library(sqlite3 STATIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3/sqlite3.c")
target_include_directories(sqlite3 PUBLIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3")
target_link_libraries(nextcloud_csync PUBLIC sqlite3)
target_link_libraries("${csync_NAME}" PUBLIC sqlite3)
else()
target_include_directories(nextcloud_csync PUBLIC ${SQLITE3_INCLUDE_DIR})
target_link_libraries(nextcloud_csync PUBLIC ${SQLITE3_LIBRARIES})
target_include_directories("${csync_NAME}" PUBLIC ${SQLITE3_INCLUDE_DIR})
target_link_libraries("${csync_NAME}" PUBLIC ${SQLITE3_LIBRARIES})
endif()
generate_export_header(nextcloud_csync
generate_export_header("${csync_NAME}"
EXPORT_MACRO_NAME OCSYNC_EXPORT
EXPORT_FILE_NAME ocsynclib.h
)
target_link_libraries(nextcloud_csync
target_link_libraries("${csync_NAME}"
PUBLIC
${CSYNC_REQUIRED_LIBRARIES}
Qt5::Core Qt5::Concurrent
)
if(ZLIB_FOUND)
target_link_libraries(nextcloud_csync PUBLIC ZLIB::ZLIB)
target_link_libraries("${csync_NAME}" PUBLIC ZLIB::ZLIB)
endif(ZLIB_FOUND)
@@ -97,11 +96,11 @@ endif(ZLIB_FOUND)
if (APPLE)
find_library(FOUNDATION_LIBRARY NAMES Foundation)
find_library(CORESERVICES_LIBRARY NAMES CoreServices)
target_link_libraries(nextcloud_csync PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
target_link_libraries("${csync_NAME}" PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
endif()
set_target_properties(
nextcloud_csync
"${csync_NAME}"
PROPERTIES
VERSION
${LIBRARY_VERSION}
@@ -109,15 +108,11 @@ set_target_properties(
${LIBRARY_SOVERSION}
RUNTIME_OUTPUT_DIRECTORY
${BIN_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_NAME
${APPLICATION_EXECUTABLE}_csync
RUNTIME_OUTPUT_NAME
${APPLICATION_EXECUTABLE}_csync
)
if(BUILD_OWNCLOUD_OSX_BUNDLE)
INSTALL(
TARGETS
nextcloud_csync
"${csync_NAME}"
LIBRARY DESTINATION
${LIB_INSTALL_DIR}
ARCHIVE DESTINATION
@@ -128,7 +123,7 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE)
else()
INSTALL(
TARGETS
nextcloud_csync
"${csync_NAME}"
LIBRARY DESTINATION
${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION

View File

@@ -7,6 +7,7 @@ include(CheckCXXSourceCompiles)
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
@@ -22,12 +23,6 @@ if (NOT LINUX)
check_library_exists(rt nanosleep "" HAVE_LIBRT)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
# Systems not using glibc require linker flag for argp
check_library_exists(argp argp_parse "" HAVE_LIBARGP)
if(HAVE_ARGP_H AND HAVE_LIBARGP)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} argp)
endif()
endif (NOT LINUX)
if(WIN32)

View File

@@ -19,7 +19,6 @@
*/
#include "config_csync.h"
#include <qglobal.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -35,8 +34,10 @@
#include <QString>
#include <QFileInfo>
#include <QFile>
#include <QDir>
/** Expands C-like escape sequences (in place)
*/
OCSYNC_EXPORT void csync_exclude_expand_escapes(QByteArray &input)
@@ -198,13 +199,13 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QString &path, bool exclu
}
#endif
/* Do not sync desktop.ini files anywhere in the tree. */
const auto desktopIniFile = QStringLiteral("desktop.ini");
if (blen == static_cast<qsizetype>(desktopIniFile.length()) && bname.compare(desktopIniFile, Qt::CaseInsensitive) == 0) {
return CSYNC_FILE_SILENTLY_EXCLUDED;
/* We create a Desktop.ini on Windows for the sidebar icon, make sure we don't sync it. */
if (blen == 11 && path == bname) {
if (bname.compare(QLatin1String("Desktop.ini"), Qt::CaseInsensitive) == 0) {
return CSYNC_FILE_SILENTLY_EXCLUDED;
}
}
if (excludeConflictFiles && OCC::Utility::isConflictFile(path)) {
return CSYNC_FILE_EXCLUDE_CONFLICT;
}
@@ -230,21 +231,24 @@ ExcludedFiles::ExcludedFiles(const QString &localPath)
// We're in a detached exclude probably coming from a partial sync or test
if (_localPath.isEmpty())
return;
// Load exclude file from base dir
QFileInfo fi(_localPath + QStringLiteral(".sync-exclude.lst"));
if (fi.isReadable())
addInTreeExcludeFilePath(fi.absoluteFilePath());
}
ExcludedFiles::~ExcludedFiles() = default;
void ExcludedFiles::addExcludeFilePath(const QString &path)
{
const QFileInfo excludeFileInfo(path);
const auto fileName = excludeFileInfo.fileName();
const auto basePath = fileName.compare(QStringLiteral("sync-exclude.lst"), Qt::CaseInsensitive) == 0
? _localPath
: leftIncludeLast(path, QLatin1Char('/'));
auto &excludeFilesLocalPath = _excludeFiles[basePath];
if (std::find(excludeFilesLocalPath.cbegin(), excludeFilesLocalPath.cend(), path) == excludeFilesLocalPath.cend()) {
excludeFilesLocalPath.append(path);
}
_excludeFiles[_localPath].append(path);
}
void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
{
BasePathString basePath = leftIncludeLast(path, QLatin1Char('/'));
_excludeFiles[basePath].append(path);
}
void ExcludedFiles::setExcludeConflictFiles(bool onoff)
@@ -284,26 +288,32 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
_clientVersion = version;
}
void ExcludedFiles::loadExcludeFilePatterns(const QString &basePath, QFile &file)
bool ExcludedFiles::loadExcludeFile(const QString &basePath, const QString & file)
{
QFile f(file);
if (!f.open(QIODevice::ReadOnly))
return false;
QStringList patterns;
while (!file.atEnd()) {
QByteArray line = file.readLine().trimmed();
while (!f.atEnd()) {
QByteArray line = f.readLine().trimmed();
if (line.startsWith("#!version")) {
if (!versionDirectiveKeepNextLine(line))
file.readLine();
f.readLine();
}
if (line.isEmpty() || line.startsWith('#'))
continue;
csync_exclude_expand_escapes(line);
patterns.append(QString::fromUtf8(line));
}
_allExcludes[basePath].append(patterns);
_allExcludes.insert(basePath, patterns);
// nothing to prepare if the user decided to not exclude anything
if (!_allExcludes.value(basePath).isEmpty()){
prepare(basePath);
}
return true;
}
bool ExcludedFiles::reloadExcludeFiles()
@@ -320,14 +330,8 @@ bool ExcludedFiles::reloadExcludeFiles()
bool success = true;
const auto keys = _excludeFiles.keys();
for (const auto& basePath : keys) {
for (const auto &excludeFile : _excludeFiles.value(basePath)) {
QFile file(excludeFile);
if (file.exists() && file.open(QIODevice::ReadOnly)) {
loadExcludeFilePatterns(basePath, file);
} else {
success = false;
qWarning() << "System exclude list file could not be opened:" << excludeFile;
}
for (const auto& file : _excludeFiles.value(basePath)) {
success = loadExcludeFile(basePath, file);
}
}
@@ -418,14 +422,11 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
// Directories are guaranteed to be visited before their files
if (filetype == ItemTypeDirectory) {
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
const QString absolutePath = basePath + QStringLiteral(".sync-exclude.lst");
QFileInfo excludeFileInfo(absolutePath);
const auto fi = QFileInfo(basePath + QStringLiteral(".sync-exclude.lst"));
if (excludeFileInfo.isReadable()) {
addExcludeFilePath(absolutePath);
reloadExcludeFiles();
} else {
qWarning() << "System exclude list file could not be read:" << absolutePath;
if (fi.isReadable()) {
addInTreeExcludeFilePath(fi.absoluteFilePath());
loadExcludeFile(basePath, fi.absoluteFilePath());
}
}

View File

@@ -48,7 +48,6 @@ enum CSYNC_EXCLUDE_TYPE {
};
class ExcludedFilesTest;
class QFile;
/**
* Manages file/directory exclusion.
@@ -70,7 +69,7 @@ public:
using Version = std::tuple<int, int, int>;
explicit ExcludedFiles(const QString &localPath = QStringLiteral("/"));
~ExcludedFiles() override;
~ExcludedFiles();
/**
* Adds a new path to a file containing exclude patterns.
@@ -78,6 +77,7 @@ public:
* Does not load the file. Use reloadExcludeFiles() afterwards.
*/
void addExcludeFilePath(const QString &path);
void addInTreeExcludeFilePath(const QString &path);
/**
* Whether conflict files shall be excluded.
@@ -148,7 +148,7 @@ public slots:
/**
* Loads the exclude patterns from file the registered base paths.
*/
void loadExcludeFilePatterns(const QString &basePath, QFile &file);
bool loadExcludeFile(const QString &basePath, const QString &file);
private:
/**

View File

@@ -124,8 +124,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
if (vfs) {
// Directly modifies file_stat->type.
// We can ignore the return value since we're done here anyway.
const auto result = vfs->statTypeVirtualFile(file_stat.get(), &handle->path);
Q_UNUSED(result)
vfs->statTypeVirtualFile(file_stat.get(), &handle->path);
}
return file_stat;

View File

@@ -34,7 +34,6 @@
#include "csync.h"
#include "vio/csync_vio_local.h"
#include "common/filesystembase.h"
#include "common/utility.h"
#include <QtCore/QLoggingCategory>
@@ -53,6 +52,8 @@ struct csync_vio_handle_t {
QString path; // Always ends with '\'
};
static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf);
csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
QScopedPointer<csync_vio_handle_t> handle(new csync_vio_handle_t{});
@@ -174,9 +175,12 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
// path always ends with '\', by construction
QString fullPath;
fullPath.reserve(handle->path.size() + std::wcslen(handle->ffd.cFileName));
fullPath += handle->path; // path always ends with '\', by construction
fullPath += QString::fromWCharArray(handle->ffd.cFileName);
if (csync_vio_local_stat(handle->path + QString::fromWCharArray(handle->ffd.cFileName), file_stat.get()) < 0) {
if (_csync_vio_local_stat_mb(fullPath, file_stat.get()) < 0) {
// Will get excluded by _csync_detect_update.
file_stat->type = ItemTypeSkip;
}
@@ -184,7 +188,14 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
return file_stat;
}
int csync_vio_local_stat(const QString &uri, csync_file_stat_t *buf)
{
int rc = _csync_vio_local_stat_mb(uri, buf);
return rc;
}
static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
{
/* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
But we still need to fetch the file ID.
@@ -195,19 +206,21 @@ int csync_vio_local_stat(const QString &uri, csync_file_stat_t *buf)
BY_HANDLE_FILE_INFORMATION fileInfo;
ULARGE_INTEGER FileIndex;
h = CreateFileW(reinterpret_cast<const wchar_t *>(OCC::FileSystem::longWinPath(uri).utf16()), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
const auto longPath = OCC::FileSystem::longWinPath(path);
h = CreateFileW(longPath.toStdWString().data(), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
nullptr );
if( h == INVALID_HANDLE_VALUE ) {
qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << longPath;
errno = GetLastError();
qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << uri << OCC::Utility::formatWinError(errno);
return -1;
}
if(!GetFileInformationByHandle( h, &fileInfo ) ) {
qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << longPath;
errno = GetLastError();
qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << uri << OCC::Utility::formatWinError(errno);
CloseHandle(h);
return -1;
}

View File

@@ -1,8 +1,5 @@
project(gui)
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 Xml Network)
if (NOT TARGET Qt5::GuiPrivate)
message(FATAL_ERROR "Could not find GuiPrivate component of Qt5. It might be shipped as a separate package, please check that.")
endif()
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2)
if(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DQT_QML_DEBUG)
@@ -21,7 +18,6 @@ set(theme_dir ${CMAKE_SOURCE_DIR}/theme)
set(client_UI_SRCS
accountsettings.ui
conflictdialog.ui
invalidfilenamedialog.ui
foldercreationdialog.ui
folderwizardsourcepage.ui
folderwizardtargetpage.ui
@@ -37,30 +33,19 @@ set(client_UI_SRCS
shareuserline.ui
sslerrordialog.ui
addcertificatedialog.ui
passwordinputdialog.ui
proxyauthdialog.ui
mnemonicdialog.ui
UserStatusSelector.qml
UserStatusSelectorDialog.qml
tray/ActivityActionButton.qml
tray/ActivityItem.qml
tray/ActivityList.qml
tray/Window.qml
tray/UserLine.qml
tray/UnifiedSearchInputContainer.qml
tray/UnifiedSearchResultFetchMoreTrigger.qml
tray/UnifiedSearchResultItem.qml
tray/UnifiedSearchResultItemSkeleton.qml
tray/UnifiedSearchResultItemSkeletonContainer.qml
tray/UnifiedSearchResultListItem.qml
tray/UnifiedSearchResultNothingFound.qml
tray/UnifiedSearchResultSectionItem.qml
wizard/flow2authwidget.ui
wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudoauthcredspage.ui
wizard/owncloudsetupnocredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/webview.ui
wizard/welcomepage.ui
)
@@ -69,7 +54,6 @@ set(client_SRCS
accountmanager.cpp
accountsettings.cpp
application.cpp
invalidfilenamedialog.cpp
conflictdialog.cpp
conflictsolver.cpp
connectionvalidator.cpp
@@ -96,21 +80,21 @@ set(client_SRCS
openfilemanager.cpp
owncloudgui.cpp
owncloudsetupwizard.cpp
passwordinputdialog.cpp
selectivesyncdialog.cpp
settingsdialog.cpp
sharedialog.cpp
sharelinkwidget.cpp
sharemanager.cpp
shareusergroupwidget.cpp
profilepagewidget.cpp
sharee.cpp
socketapi.cpp
sslbutton.cpp
sslerrordialog.cpp
syncrunfilelog.cpp
systray.cpp
thumbnailjob.cpp
userinfo.cpp
userstatus.cpp
accountstate.cpp
addcertificatedialog.cpp
authenticationdialog.cpp
@@ -121,21 +105,13 @@ set(client_SRCS
guiutility.cpp
elidedlabel.cpp
headerbanner.cpp
iconutils.cpp
iconjob.cpp
remotewipe.cpp
userstatusselectormodel.cpp
emojimodel.cpp
fileactivitylistmodel.cpp
tray/svgimageprovider.cpp
tray/syncstatussummary.cpp
tray/activitydata.cpp
tray/activitylistmodel.cpp
tray/unifiedsearchresult.cpp
tray/unifiedsearchresultimageprovider.cpp
tray/unifiedsearchresultslistmodel.cpp
tray/usermodel.cpp
tray/notificationhandler.cpp
tray/notificationcache.cpp
tray/ActivityData.cpp
tray/ActivityListModel.cpp
tray/UserModel.cpp
tray/NotificationHandler.cpp
tray/NotificationCache.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
@@ -153,6 +129,7 @@ set(client_SRCS
wizard/owncloudsetuppage.cpp
wizard/owncloudwizardcommon.cpp
wizard/owncloudwizard.cpp
wizard/owncloudwizardresultpage.cpp
wizard/slideshow.cpp
wizard/welcomepage.cpp
wizard/linklabel.cpp
@@ -175,6 +152,7 @@ endif()
IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm)
if(SPARKLE_FOUND AND BUILD_UPDATER)
@@ -208,7 +186,6 @@ set(3rdparty_SRC
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
../3rdparty/kmessagewidget/kmessagewidget.cpp
../3rdparty/kirigami/wheelhandler.cpp
)
if(NOT WIN32)
@@ -260,39 +237,20 @@ if (NOT DEFINED APPLICATION_ICON_NAME)
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
endif()
if(NOT DEFINED APPLICATION_FOLDER_ICON_INDEX)
set(APPLICATION_FOLDER_ICON_INDEX 0)
endif()
# Generate png icons from svg
find_program(SVG_CONVERTER
NAMES inkscape inkscape.exe rsvg-convert
find_program(INKSCAPE
NAMES inkscape inkscape.exe
REQUIRED
HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV SVG_CONVERTER_DIR)
HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV INKSCAPE_DIR)
# REQUIRED keyword is only supported on CMake 3.18 and above
if (NOT SVG_CONVERTER)
message(FATAL_ERROR "Could not find a suitable svg converter. Set SVG_CONVERTER_DIR to the path of either the inkscape or rsvg-convert executable.")
if (NOT INKSCAPE)
message(FATAL_ERROR "Could not find inkscape. Set INKSCAPE_DIR to the path of executable.")
endif()
function(generate_sized_png_from_svg icon_path size)
set(options)
set(oneValueArgs OUTPUT_ICON_NAME OUTPUT_ICON_PATH)
set(multiValueArgs)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
get_filename_component(icon_name_dir ${icon_path} DIRECTORY)
get_filename_component(icon_name_wle ${icon_path} NAME_WLE)
if (ARG_OUTPUT_ICON_NAME)
set(icon_name_wle ${ARG_OUTPUT_ICON_NAME})
endif ()
if (ARG_OUTPUT_ICON_PATH)
set(icon_name_dir ${ARG_OUTPUT_ICON_PATH})
endif ()
if (EXISTS "${icon_name_dir}/${size}-${icon_name_wle}.png")
return()
endif()
@@ -300,16 +258,16 @@ function(generate_sized_png_from_svg icon_path size)
set(icon_output_name "${size}-${icon_name_wle}.png")
message(STATUS "Generate ${icon_output_name}")
execute_process(COMMAND
"${SVG_CONVERTER}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
"${INKSCAPE}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
WORKING_DIRECTORY "${icon_name_dir}"
RESULT_VARIABLE
SVG_CONVERTER_SIDEBAR_ERROR
INKSCAPE_SIDEBAR_ERROR
OUTPUT_QUIET
ERROR_QUIET)
if (SVG_CONVERTER_SIDEBAR_ERROR)
if (INKSCAPE_SIDEBAR_ERROR)
message(FATAL_ERROR
"${SVG_CONVERTER} could not generate icon: ${SVG_CONVERTER_SIDEBAR_ERROR}")
"inkscape could not generate icon: ${INKSCAPE_SIDEBAR_ERROR}")
else()
endif()
endfunction()
@@ -338,86 +296,22 @@ if(WIN32)
endif()
set(APP_ICON_SVG "${theme_dir}/colored/${APPLICATION_ICON_NAME}-icon.svg")
# generate secondary icon if available (currently for Windows only)--------------------------------------
set(APP_SECONDARY_ICONS "${theme_dir}/colored/icons")
set(APP_ICON_WIN_FOLDER_SVG "${APP_SECONDARY_ICONS}/${APPLICATION_ICON_NAME}-icon-win-folder.svg")
set(RC_DEPENDENCIES "")
if(WIN32)
if (EXISTS ${APP_ICON_WIN_FOLDER_SVG})
get_filename_component(output_icon_name_win ${APP_ICON_WIN_FOLDER_SVG} NAME_WLE)
# Product icon (for smallest size)
foreach(size IN ITEMS 16;20)
generate_sized_png_from_svg(${APP_ICON_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/")
endforeach()
# Product icon with Windows folder (for sizes larger than 20)
foreach(size IN ITEMS 24;32;40;48;64;128;256;512;1024)
generate_sized_png_from_svg(${APP_ICON_WIN_FOLDER_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/")
endforeach()
file(GLOB_RECURSE OWNCLOUD_ICONS_WIN_FOLDER "${APP_SECONDARY_ICONS}/*-${APPLICATION_ICON_NAME}-icon*")
set(APP_ICON_WIN_FOLDER_ICO_NAME "${APPLICATION_ICON_NAME}-win-folder")
set(RC_DEPENDENCIES "${RC_DEPENDENCIES} ${APP_ICON_WIN_FOLDER_ICO_NAME}.ico")
ecm_add_app_icon(APP_ICON_WIN_FOLDER ICONS "${OWNCLOUD_ICONS_WIN_FOLDER}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APP_ICON_WIN_FOLDER_ICO_NAME}" ICON_INDEX 2)
endif()
endif()
# --------------------------------------
if (NOT ${RC_DEPENDENCIES} STREQUAL "")
string(STRIP ${RC_DEPENDENCIES} RC_DEPENDENCIES)
endif()
# generate primary icon from SVG (due to Win .ico vs .rc dependency issues, primary icon must always be generated last)--------------------------------------
if(WIN32)
foreach(size IN ITEMS 16;20;24;32;40;48;64;128;256;512;1024)
generate_sized_png_from_svg(${APP_ICON_SVG} ${size})
endforeach()
else()
foreach(size IN ITEMS 16;24;32;48;64;128;256;512;1024)
generate_sized_png_from_svg(${APP_ICON_SVG} ${size})
endforeach()
endif()
generate_sized_png_from_svg(${APP_ICON_SVG} 16)
generate_sized_png_from_svg(${APP_ICON_SVG} 24)
generate_sized_png_from_svg(${APP_ICON_SVG} 32)
generate_sized_png_from_svg(${APP_ICON_SVG} 48)
generate_sized_png_from_svg(${APP_ICON_SVG} 64)
generate_sized_png_from_svg(${APP_ICON_SVG} 128)
generate_sized_png_from_svg(${APP_ICON_SVG} 256)
generate_sized_png_from_svg(${APP_ICON_SVG} 512)
generate_sized_png_from_svg(${APP_ICON_SVG} 1024)
file(GLOB_RECURSE OWNCLOUD_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-icon*")
if(APPLE)
file(GLOB_RECURSE OWNCLOUD_SIDEBAR_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-sidebar*")
MESSAGE(STATUS "OWNCLOUD_SIDEBAR_ICONS: ${APPLICATION_ICON_NAME}: ${OWNCLOUD_SIDEBAR_ICONS}")
endif()
ecm_add_app_icon(APP_ICON RC_DEPENDENCIES ${RC_DEPENDENCIES} ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}" ICON_INDEX 1)
# --------------------------------------
if(WIN32)
# merge *.rc.in files for Windows (multiple ICON resources must be placed in a single file, otherwise, this won't work de to a bug in Windows compiler https://developercommunity.visualstudio.com/t/visual-studio-2017-prof-1557-cvt1100-duplicate-res/363156)
function(merge_files IN_FILE OUT_FILE)
file(READ ${IN_FILE} CONTENTS)
message("Merging ${IN_FILE} into ${OUT_FILE}")
file(APPEND ${OUT_FILE} "${CONTENTS}")
endfunction()
message("APP_ICON is: ${APP_ICON}")
if(APP_ICON)
get_filename_component(RC_IN_FOLDER ${APP_ICON}} DIRECTORY)
file(GLOB_RECURSE RC_IN_FILES "${RC_IN_FOLDER}/*rc.in")
foreach(rc_in_file IN ITEMS ${RC_IN_FILES})
get_filename_component(rc_in_file_name ${rc_in_file} NAME)
get_filename_component(app_icon_name "${APP_ICON}.in" NAME)
if(NOT "${rc_in_file_name}" STREQUAL "${app_icon_name}")
merge_files(${rc_in_file} "${APP_ICON}.in")
if (DEFINED APPLICATION_FOLDER_ICON_INDEX)
MATH(EXPR APPLICATION_FOLDER_ICON_INDEX "${APPLICATION_FOLDER_ICON_INDEX}+1")
message("APPLICATION_FOLDER_ICON_INDEX is now set to: ${APPLICATION_FOLDER_ICON_INDEX}")
endif()
endif()
endforeach()
endif()
endif()
# --------------------------------------
ecm_add_app_icon(APP_ICON ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}")
if(UNIX AND NOT APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
@@ -433,7 +327,6 @@ add_library(nextcloudCore STATIC ${final_src})
target_link_libraries(nextcloudCore
PUBLIC
Nextcloud::sync
Qt5::Widgets
Qt5::GuiPrivate
Qt5::Svg
@@ -442,10 +335,9 @@ target_link_libraries(nextcloudCore
Qt5::Qml
Qt5::Quick
Qt5::QuickControls2
${synclib_NAME}
)
add_subdirectory(socketapi)
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
target_link_libraries(nextcloudCore PUBLIC Qt5::WebEngineWidgets)
endif()
@@ -461,7 +353,6 @@ target_include_directories(nextcloudCore
PUBLIC
${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
${CMAKE_SOURCE_DIR}/src/3rdparty/kirigami
${CMAKE_SOURCE_DIR}/src/3rdparty/qtsingleapplication
${CMAKE_SOURCE_DIR}/src/3rdparty/kmessagewidget
${CMAKE_CURRENT_BINARY_DIR}
@@ -474,9 +365,9 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
foreach(_file ${_icons})
string(REPLACE "${theme_dir}/colored/" "" _res ${_file})
string(REPLACE "-${APPLICATION_ICON_NAME}-icon.png" "" _res ${_res})
install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}x${_res}/apps)
install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps)
endforeach(_file)
install(FILES ${client_I18N} DESTINATION ${CMAKE_INSTALL_DATADIR}/${APPLICATION_EXECUTABLE}/i18n)
install(FILES ${client_I18N} DESTINATION ${SHAREDIR}/${APPLICATION_EXECUTABLE}/i18n)
else()
file(GLOB_RECURSE VISUAL_ELEMENTS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-w10startmenu*")
install(FILES ${VISUAL_ELEMENTS} DESTINATION bin/visualelements)
@@ -485,23 +376,17 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
endif()
# we may not add MACOSX_BUNDLE here, if not building one
add_executable(nextcloud WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
set_target_properties(nextcloud PROPERTIES
OUTPUT_NAME "${APPLICATION_EXECUTABLE}"
)
add_executable(${APPLICATION_EXECUTABLE} WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
else()
# set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
set(MACOSX_BUNDLE_ICON_FILE "${APPLICATION_ICON_NAME}.icns")
# we must add MACOSX_BUNDLE only if building a bundle
add_executable(nextcloud WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
add_executable(${APPLICATION_EXECUTABLE} WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
if (BUILD_OWNCLOUD_OSX_BUNDLE)
set_target_properties(nextcloud PROPERTIES
set_target_properties(${APPLICATION_EXECUTABLE} PROPERTIES
OUTPUT_NAME "${APPLICATION_NAME}")
else()
set_target_properties(nextcloud PROPERTIES
OUTPUT_NAME "${APPLICATION_EXECUTABLE}")
endif()
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
@@ -521,17 +406,22 @@ endif()
IF(BUILD_UPDATER)
add_library(updater STATIC ${updater_SRCS})
target_link_libraries(updater Nextcloud::sync ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
target_link_libraries(updater ${synclib_NAME} ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(updater PROPERTIES AUTOMOC ON)
target_link_libraries(nextcloudCore PUBLIC updater)
endif()
set_target_properties(nextcloud PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)
target_link_libraries(nextcloud PRIVATE nextcloudCore)
target_link_libraries(${APPLICATION_EXECUTABLE} nextcloudCore)
IF(BUILD_UPDATER)
target_link_libraries(nextcloudCore PUBLIC updater)
endif()
target_link_libraries(nextcloudCore PUBLIC ${OS_SPECIFIC_LINK_LIBRARIES})
if(TARGET PkgConfig::CLOUDPROVIDERS)
message("Building with libcloudproviderssupport")
@@ -577,7 +467,11 @@ if(WITH_CRASHREPORTER)
endif()
endif()
install(TARGETS nextcloud
# application.cpp still uses QDesktopServices::storageLocation
target_compile_definitions(nextcloudCore PRIVATE "QT_DISABLE_DEPRECATED_BEFORE=0")
install(TARGETS ${APPLICATION_EXECUTABLE}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
@@ -604,12 +498,12 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
set(NO_STRIP "")
endif()
add_custom_command(TARGET nextcloud POST_BUILD
add_custom_command(TARGET ${APPLICATION_EXECUTABLE} POST_BUILD
COMMAND "${MACDEPLOYQT_EXECUTABLE}"
"$<TARGET_FILE_DIR:nextcloud>/../.."
"$<TARGET_FILE_DIR:${APPLICATION_EXECUTABLE}>/../.."
-qmldir=${CMAKE_SOURCE_DIR}/src/gui
-always-overwrite
-executable="$<TARGET_FILE_DIR:nextcloud>/${cmd_NAME}"
-executable="$<TARGET_FILE_DIR:${APPLICATION_EXECUTABLE}>/${cmd_NAME}"
${NO_STRIP}
COMMAND "${CMAKE_COMMAND}"
-E rm -rf "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/bearer"
@@ -620,15 +514,13 @@ endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${DATADIR}/applications )
configure_file(owncloud.xml.in ${APPLICATION_EXECUTABLE}.xml)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${DATADIR}/mime/packages )
find_package(SharedMimeInfo)
if(SharedMimeInfo_FOUND)
update_xdg_mimetypes( ${CMAKE_INSTALL_DATADIR}/mime/packages )
update_xdg_mimetypes( ${DATADIR}/mime/packages )
endif(SharedMimeInfo_FOUND)
endif()
configure_file(configgui.h.in ${CMAKE_CURRENT_BINARY_DIR}/configgui.h)

View File

@@ -1,112 +0,0 @@
/*
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
*
* 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.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import com.nextcloud.desktopclient 1.0 as NC
ColumnLayout {
NC.EmojiModel {
id: emojiModel
}
signal chosen(string emoji)
spacing: 0
FontMetrics {
id: metrics
}
ListView {
id: headerLayout
Layout.fillWidth: true
implicitWidth: contentItem.childrenRect.width
implicitHeight: metrics.height * 2
orientation: ListView.Horizontal
model: emojiModel.emojiCategoriesModel
delegate: ItemDelegate {
width: metrics.height * 2
height: headerLayout.height
contentItem: Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: emoji
}
Rectangle {
anchors.bottom: parent.bottom
width: parent.width
height: 2
visible: ListView.isCurrentItem
color: "grey"
}
onClicked: {
emojiModel.setCategory(label)
}
}
}
Rectangle {
height: 1
Layout.fillWidth: true
color: "grey"
}
GridView {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: metrics.height * 8
cellWidth: metrics.height * 2
cellHeight: metrics.height * 2
boundsBehavior: Flickable.DragOverBounds
clip: true
model: emojiModel.model
delegate: ItemDelegate {
width: metrics.height * 2
height: metrics.height * 2
contentItem: Text {
anchors.centerIn: parent
text: modelData === undefined ? "" : modelData.unicode
}
onClicked: {
chosen(modelData.unicode);
emojiModel.emojiUsed(modelData);
}
}
ScrollBar.vertical: ScrollBar {}
}
}

View File

@@ -1,32 +0,0 @@
import QtQuick 2.15
import Style 1.0
Item {
id: errorBox
property var text: ""
property color color: Style.errorBoxTextColor
property color backgroundColor: Style.errorBoxBackgroundColor
property color borderColor: Style.errorBoxBorderColor
implicitHeight: errorMessage.implicitHeight + 2 * 8
Rectangle {
anchors.fill: parent
color: errorBox.backgroundColor
border.color: errorBox.borderColor
}
Text {
id: errorMessage
anchors.fill: parent
anchors.margins: 8
width: parent.width
color: errorBox.color
wrapMode: Text.WordWrap
text: errorBox.text
}
}

View File

@@ -1,200 +0,0 @@
/*
* Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com>
*
* 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.
*/
import QtQuick 2.6
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import com.nextcloud.desktopclient 1.0 as NC
ColumnLayout {
id: rootLayout
spacing: 0
property NC.UserStatusSelectorModel userStatusSelectorModel
FontMetrics {
id: metrics
}
Text {
Layout.topMargin: 16
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 8
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
font.bold: true
text: qsTr("Online status")
}
GridLayout {
Layout.margins: 8
Layout.alignment: Qt.AlignTop
columns: 2
rows: 2
columnSpacing: 8
rowSpacing: 8
Button {
Layout.fillWidth: true
checked: NC.UserStatus.Online == userStatusSelectorModel.onlineStatus
checkable: true
icon.source: userStatusSelectorModel.onlineIcon
icon.color: "transparent"
text: qsTr("Online")
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Online)
implicitWidth: 100
}
Button {
Layout.fillWidth: true
checked: NC.UserStatus.Away == userStatusSelectorModel.onlineStatus
checkable: true
icon.source: userStatusSelectorModel.awayIcon
icon.color: "transparent"
text: qsTr("Away")
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Away)
implicitWidth: 100
}
Button {
Layout.fillWidth: true
checked: NC.UserStatus.DoNotDisturb == userStatusSelectorModel.onlineStatus
checkable: true
icon.source: userStatusSelectorModel.dndIcon
icon.color: "transparent"
text: qsTr("Do not disturb")
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.DoNotDisturb)
implicitWidth: 100
}
Button {
Layout.fillWidth: true
checked: NC.UserStatus.Invisible == userStatusSelectorModel.onlineStatus
checkable: true
icon.source: userStatusSelectorModel.invisibleIcon
icon.color: "transparent"
text: qsTr("Invisible")
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Invisible)
implicitWidth: 100
}
}
Text {
Layout.topMargin: 16
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 8
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
font.bold: true
text: qsTr("Status message")
}
RowLayout {
Layout.topMargin: 8
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 16
Layout.alignment: Qt.AlignTop
Layout.fillWidth: true
Button {
Layout.preferredWidth: userStatusMessageTextField.height // metrics.height * 2
Layout.preferredHeight: userStatusMessageTextField.height // metrics.height * 2
text: userStatusSelectorModel.userStatusEmoji
onClicked: emojiDialog.open()
}
Popup {
id: emojiDialog
padding: 0
margins: 0
anchors.centerIn: Overlay.overlay
EmojiPicker {
id: emojiPicker
onChosen: {
userStatusSelectorModel.userStatusEmoji = emoji
emojiDialog.close()
}
}
}
TextField {
id: userStatusMessageTextField
Layout.fillWidth: true
placeholderText: qsTr("What is your status?")
text: userStatusSelectorModel.userStatusMessage
selectByMouse: true
onEditingFinished: userStatusSelectorModel.setUserStatusMessage(text)
}
}
Repeater {
model: userStatusSelectorModel.predefinedStatusesCount
Button {
id: control
Layout.fillWidth: true
flat: !hovered
hoverEnabled: true
text: userStatusSelectorModel.predefinedStatus(index).icon + " <b>" + userStatusSelectorModel.predefinedStatus(index).message + "</b> - " + userStatusSelectorModel.predefinedStatusClearAt(index)
onClicked: userStatusSelectorModel.setPredefinedStatus(index)
}
}
RowLayout {
Layout.topMargin: 16
Layout.leftMargin: 8
Layout.rightMargin: 8
Layout.bottomMargin: 8
Layout.alignment: Qt.AlignTop
Text {
text: qsTr("Clear status message after")
}
ComboBox {
Layout.fillWidth: true
model: userStatusSelectorModel.clearAtValues
displayText: userStatusSelectorModel.clearAt
onActivated: userStatusSelectorModel.setClearAt(index)
}
}
RowLayout {
Layout.margins: 8
Layout.alignment: Qt.AlignTop
Button {
Layout.fillWidth: true
text: qsTr("Clear status message")
onClicked: userStatusSelectorModel.clearUserStatus()
}
Button {
highlighted: true
Layout.fillWidth: true
text: qsTr("Set status message")
onClicked: userStatusSelectorModel.setUserStatus()
}
}
ErrorBox {
Layout.margins: 8
Layout.fillWidth: true
visible: userStatusSelectorModel.errorMessage != ""
text: "<b>Error:</b> " + userStatusSelectorModel.errorMessage
}
}

View File

@@ -1,27 +0,0 @@
import QtQuick.Window 2.15
import com.nextcloud.desktopclient 1.0 as NC
Window {
id: dialog
property NC.UserStatusSelectorModel model: NC.UserStatusSelectorModel {
onFinished: dialog.close()
}
minimumWidth: view.implicitWidth
minimumHeight: view.implicitHeight
maximumWidth: view.implicitWidth
maximumHeight: view.implicitHeight
width: maximumWidth
height: maximumHeight
visible: true
flags: Qt.Dialog
UserStatusSelector {
id: view
userStatusSelectorModel: model
}
}

View File

@@ -380,8 +380,6 @@ void AccountManager::deleteAccount(AccountState *account)
// Forget E2E keys
account->account()->e2e()->forgetSensitiveData(account->account());
account->account()->deleteAppToken();
emit accountSyncConnectionRemoved(account);
emit accountRemoved(account);
}

View File

@@ -28,7 +28,7 @@ class AccountManager : public QObject
Q_OBJECT
public:
static AccountManager *instance();
~AccountManager() override = default;
~AccountManager() = default;
/**
* Saves the accounts to a given settings file

Some files were not shown because too many files have changed in this diff Show More