Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d3270dd25 | ||
|
|
680ab37542 | ||
|
|
b59ec4a0bf | ||
|
|
9f74f8521e | ||
|
|
e9a9455872 | ||
|
|
4584e8fa01 | ||
|
|
39831da3be | ||
|
|
33e71a248c | ||
|
|
44970c84f0 | ||
|
|
0f81d41935 | ||
|
|
c264a6025f | ||
|
|
e0ead91e51 | ||
|
|
c63421ceaf | ||
|
|
4ecd861aec | ||
|
|
6b2d6abbed | ||
|
|
f751c951cf | ||
|
|
68cb6a4d4e | ||
|
|
c207231dd1 | ||
|
|
c82b07a3f7 | ||
|
|
3ec9b62c10 | ||
|
|
3d9f2a2d8c | ||
|
|
52cf1b1db3 | ||
|
|
ac96c05a1d | ||
|
|
d9b53527d2 | ||
|
|
fc101f01ca | ||
|
|
f6487b65a6 | ||
|
|
78612ae03b | ||
|
|
80017d9eb0 | ||
|
|
7887e31447 | ||
|
|
ae319a1b17 | ||
|
|
90e89a7f94 | ||
|
|
840c5dcaa6 | ||
|
|
71133a3ab3 | ||
|
|
cfa4ac994f | ||
|
|
5de9fb3cd4 | ||
|
|
0d9a6987eb | ||
|
|
229bd8a745 | ||
|
|
2ded349f9c | ||
|
|
b27eb606ed | ||
|
|
412be77929 | ||
|
|
8d1aa2f38c | ||
|
|
8233131897 | ||
|
|
e7e1114237 | ||
|
|
25b7f8f1f9 | ||
|
|
d23264f254 | ||
|
|
c5099f9134 | ||
|
|
5295340649 | ||
|
|
0be98b1610 | ||
|
|
12557272f7 | ||
|
|
c666592142 | ||
|
|
bf865f930d | ||
|
|
9e932c9af9 | ||
|
|
dcc0fa9f9d | ||
|
|
26dfa3983f | ||
|
|
ed99ffaeec | ||
|
|
adf8f4bdb2 | ||
|
|
524eeac107 | ||
|
|
45830fbf0d | ||
|
|
ac0cf09335 | ||
|
|
5c77aacfe9 | ||
|
|
cc2548bcc7 | ||
|
|
63aaa8419d | ||
|
|
6db2028725 | ||
|
|
8dcc0a3cbe | ||
|
|
fee7801f98 | ||
|
|
735179047d | ||
|
|
1badf7955a | ||
|
|
5dd18690a0 | ||
|
|
c4b188caee | ||
|
|
5dccbbf343 | ||
|
|
5ec5e2f03c | ||
|
|
62ec748f57 | ||
|
|
d515337e36 | ||
|
|
8237f0085b | ||
|
|
7841de3bee | ||
|
|
2c3cef1c27 | ||
|
|
2d54bc4d17 | ||
|
|
664ab345fa | ||
|
|
2eee656dec | ||
|
|
28c135c26f | ||
|
|
01fdd229ab | ||
|
|
c1fefa3251 | ||
|
|
dcbb7847d0 | ||
|
|
0ee03468c6 | ||
|
|
ef7e29a0d8 | ||
|
|
c19d489852 | ||
|
|
3e56ebcfff | ||
|
|
189ada15fd | ||
|
|
50453d9d7e | ||
|
|
2740fea577 | ||
|
|
02a95b6f57 | ||
|
|
3aeeeb56ff | ||
|
|
9e6750f3d2 | ||
|
|
ff38f1cffc | ||
|
|
58f34bd0c6 | ||
|
|
44f89224b3 | ||
|
|
cf8b2c98c7 | ||
|
|
35b55d7221 | ||
|
|
9492defbe2 | ||
|
|
8fbc25a0d7 | ||
|
|
c05136ce50 | ||
|
|
60542aec87 | ||
|
|
6155b24c60 | ||
|
|
3b75cddefb | ||
|
|
75307b70c2 | ||
|
|
23591f385e | ||
|
|
82d8c363c5 | ||
|
|
b05d2d791e | ||
|
|
4df0ddcbd5 | ||
|
|
26ca566428 | ||
|
|
21caff6dd5 | ||
|
|
5d3cd92631 | ||
|
|
aa8521c70f | ||
|
|
1865bc6881 | ||
|
|
cd934ba80c | ||
|
|
5202df4407 | ||
|
|
99bcf30f77 | ||
|
|
56e8561e64 | ||
|
|
05fef8e463 | ||
|
|
6f5c61e442 | ||
|
|
1e28185ee9 | ||
|
|
4d7f72e3a1 | ||
|
|
6a414d5fb3 | ||
|
|
694c6e7214 | ||
|
|
e0e4e9778b | ||
|
|
7baa66b83e | ||
|
|
301bb2024e | ||
|
|
f7fce0100b | ||
|
|
af894485b4 | ||
|
|
2fb609fa98 | ||
|
|
c4627c3c04 | ||
|
|
5f0e8b8268 | ||
|
|
99c6bee64b | ||
|
|
853bfed89a | ||
|
|
86dc3fefc8 | ||
|
|
ea800b638d | ||
|
|
a2e69d8574 | ||
|
|
0178b322f9 |
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
32
.drone.yml
@@ -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 -DQUICK_COMPILER=ON -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 -DQUICK_COMPILER=ON -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:
|
||||
|
||||
31
.github/workflows/command-rebase.yml
vendored
@@ -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 }}
|
||||
|
||||
50
.github/workflows/sonarcloud.yml
vendored
@@ -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
@@ -184,7 +184,6 @@ compile_commands.json
|
||||
convert.exe
|
||||
.dir-locals.el
|
||||
*-icon.png
|
||||
*-icon-win-folder.png
|
||||
*-sidebar.png
|
||||
*-w10startmenu.png
|
||||
theme.qrc
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -22,6 +22,5 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[ko]=@APPLICATION_ICON_NAME@
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크탑
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
cmake_policy(SET CMP0071 NEW) # Enable use of QtQuick compiler/generated code
|
||||
|
||||
project(client)
|
||||
|
||||
@@ -43,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
|
||||
@@ -78,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)
|
||||
@@ -97,18 +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()
|
||||
|
||||
|
||||
option(QUICK_COMPILER "Use QtQuick compiler to improve performance" OFF)
|
||||
#####
|
||||
|
||||
# this option removes Http authentication, keychain, shibboleth etc and is intended for
|
||||
# external authentication mechanisms
|
||||
@@ -123,8 +131,11 @@ if(NO_MSG_HANDLER)
|
||||
add_definitions(-DNO_MSG_HANDLER=1)
|
||||
endif()
|
||||
|
||||
# this option builds the updater
|
||||
option(BUILD_UPDATER "BUILD_UPDATER" OFF)
|
||||
if(BUILD_UPDATER)
|
||||
message("Compiling with updater")
|
||||
add_definitions(-DBUILD_UPDATER=1)
|
||||
else()
|
||||
message("Compiling without updater")
|
||||
endif()
|
||||
@@ -183,7 +194,6 @@ if(BUILD_CLIENT)
|
||||
pkg_check_modules(CLOUDPROVIDERS cloudproviders IMPORTED_TARGET)
|
||||
|
||||
if(CLOUDPROVIDERS_FOUND)
|
||||
pkg_check_modules(DBUS-1 REQUIRED dbus-1 IMPORTED_TARGET)
|
||||
pkg_check_modules(GIO REQUIRED gio-2.0 IMPORTED_TARGET)
|
||||
pkg_check_modules(GLIB2 REQUIRED glib-2.0 IMPORTED_TARGET)
|
||||
endif()
|
||||
|
||||
@@ -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}")
|
||||
@@ -30,13 +28,10 @@ option( WITH_CRASHREPORTER "Build crashreporter" OFF )
|
||||
#set( CRASHREPORTER_ICON ":/owncloud-icon.png" )
|
||||
|
||||
## Updater options
|
||||
option( BUILD_UPDATER "Build updater" ON )
|
||||
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")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set( MIRALL_VERSION_MAJOR 3 )
|
||||
set( MIRALL_VERSION_MINOR 4 )
|
||||
set( MIRALL_VERSION_PATCH 50 )
|
||||
set( MIRALL_VERSION_MINOR 3 )
|
||||
set( MIRALL_VERSION_PATCH 6 )
|
||||
set( MIRALL_VERSION_YEAR 2021 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
40
admin/linux/count_compiler_warnings.py
Executable 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)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 :)")
|
||||
@@ -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/)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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%
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()
|
||||
|
||||
253
cmake/modules/GNUInstallDirs.cmake
Normal 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()
|
||||
@@ -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()
|
||||
|
||||
@@ -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@
|
||||
|
||||
@@ -42,6 +38,4 @@
|
||||
|
||||
#cmakedefine01 GUI_TESTING
|
||||
|
||||
#cmakedefine BUILD_UPDATER "@BUILD_UPDATER@"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@ result, the Nextcloud Client runs on Linux, Windows, and MacOS.
|
||||
The Synchronization Process
|
||||
---------------------------
|
||||
|
||||
The process of synchronization keeps files in two separate repositories the
|
||||
The process of synchronization keeps files in two separate repositories the
|
||||
same. When synchronized:
|
||||
|
||||
- If a file is added to one repository it is copied to the other synchronized repository.
|
||||
@@ -93,7 +93,7 @@ traverses the file tree and compares the modification time of each file with an
|
||||
expected value stored in its database. If the value is not the same, the client
|
||||
determines that the file has been modified in the local repository.
|
||||
|
||||
.. note:: On the local side, the modification time is a good attribute to use for
|
||||
.. note:: On the local side, the modification time is a good attribute to use for
|
||||
detecting changes, because
|
||||
the value does not depend on time shifts and such.
|
||||
|
||||
@@ -122,7 +122,7 @@ Conflict files are always created on the client and never on the server.
|
||||
|
||||
In ownCloud 10.0 we implemented a checksum feature which checks the file integrity on upload and download by computing a checksum after the file transfer finishes.
|
||||
The client queries the server capabilities after login to decide which checksum algorithm to use.
|
||||
Currently, SHA1 is hard-coded in the official server release and can't be changed by the end-user.
|
||||
Currently, SHA1 is hard-coded in the official server release and can't be changed by the end-user.
|
||||
Note that the server additionally also supports MD5 and Adler-32, but the desktop client will always use the checksum algorithm announced in the capabilities:
|
||||
|
||||
::
|
||||
@@ -202,14 +202,14 @@ Conflict files are always created on the client and never on the server.
|
||||
Upload
|
||||
~~~~~~
|
||||
|
||||
A checksum is calculated with the previously negotiated algorithm by the client and sent along with the file in an HTTP Header.
|
||||
A checksum is calculated with the previously negotiated algorithm by the client and sent along with the file in an HTTP Header.
|
||||
```OC-Checksum: [algorithm]:[checksum]```
|
||||
|
||||
.. image:: ./images/checksums/client-activity.png
|
||||
|
||||
During file upload, the server computes SHA1, MD5, and Adler-32 checksums and compares one of them to the checksum supplied by the client.
|
||||
During file upload, the server computes SHA1, MD5, and Adler-32 checksums and compares one of them to the checksum supplied by the client.
|
||||
|
||||
On mismatch, the server returns HTTP Status code 400 (Bad Request) thus signaling the client that the upload failed.
|
||||
On mismatch, the server returns HTTP Status code 400 (Bad Request) thus signaling the client that the upload failed.
|
||||
The server then discards the upload, and the client blacklists the file:
|
||||
|
||||
.. image:: ./images/checksums/testing-checksums.png
|
||||
@@ -223,29 +223,29 @@ Conflict files are always created on the client and never on the server.
|
||||
client.</s:message>
|
||||
</d:error>
|
||||
|
||||
The client retries the upload using exponential back-off.
|
||||
The client retries the upload using exponential back-off.
|
||||
On success (matching checksum) the computed checksums are stored by the server in ``oc_filecache`` alongside the file.
|
||||
|
||||
Chunked Upload
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Mostly same as above.
|
||||
The checksum of the full file is sent with every chunk of the file.
|
||||
Mostly same as above.
|
||||
The checksum of the full file is sent with every chunk of the file.
|
||||
But the server only compares the checksum after receiving the checksum sent with the last chunk.
|
||||
|
||||
Download
|
||||
~~~~~~~~
|
||||
|
||||
The server sends the checksum in an HTTP header with the file. (same format as above).
|
||||
If no checksum is found in ``oc_filecache`` (freshly mounted external storage) it is computed and stored in ``oc_filecache`` on the first download.
|
||||
The checksum is then provided on all subsequent downloads but not on the first.
|
||||
If no checksum is found in ``oc_filecache`` (freshly mounted external storage) it is computed and stored in ``oc_filecache`` on the first download.
|
||||
The checksum is then provided on all subsequent downloads but not on the first.
|
||||
|
||||
.. _ignored-files-label:
|
||||
|
||||
Ignored Files
|
||||
-------------
|
||||
|
||||
The Nextcloud Client supports the ability to exclude or ignore certain files from the synchronization process.
|
||||
The Nextcloud Client supports the ability to exclude or ignore certain files from the synchronization process.
|
||||
Some system wide file patterns that are used to exclude or ignore files are included with the client by default and the Nextcloud Client provides the ability to add custom patterns.
|
||||
|
||||
By default, the Nextcloud Client ignores the following files:
|
||||
@@ -262,18 +262,18 @@ By default, the Nextcloud Client ignores the following files:
|
||||
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
|
||||
a line in the exclude file starts with the character ``]`` directly followed by
|
||||
the file pattern), files matching the pattern are considered *fleeting meta
|
||||
data*.
|
||||
data*.
|
||||
|
||||
These files are ignored and *removed* by the client if found in the
|
||||
synchronized folder.
|
||||
synchronized folder.
|
||||
This is suitable for meta files created by some applications that have no sustainable meaning.
|
||||
|
||||
If a pattern ends with the forward slash (``/``) character, only directories are matched.
|
||||
If a pattern ends with the forward slash (``/``) character, only directories are matched.
|
||||
The pattern is only applied for directory components of filenames selected using the checkbox.
|
||||
|
||||
To match filenames against the exclude patterns, the UNIX standard C library
|
||||
function ``fnmatch`` is used.
|
||||
This process checks the filename against the specified pattern using standard shell wildcard pattern matching.
|
||||
function ``fnmatch`` is used.
|
||||
This process checks the filename against the specified pattern using standard shell wildcard pattern matching.
|
||||
For more information, please refer to `The opengroup website
|
||||
<http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01>`_.
|
||||
|
||||
@@ -369,7 +369,7 @@ is renamed or moved.
|
||||
Example:
|
||||
|
||||
<oc:id>00000020oc5cfy6qqizm</oc:id>
|
||||
|
||||
|
||||
End-to-end Encryption
|
||||
---------------------
|
||||
|
||||
@@ -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
|
||||
@@ -440,3 +433,13 @@ Files that must be removed from the local storage only, need to be dehydrated vi
|
||||
|
||||
.. note::
|
||||
* End-to-end Encryption works with Virtual Files (VFS) but only on a per-folder level. Folders with E2EE can be made available offline in their entirety, but the individual files in them can not be retrieved on demand. This is mainly due to two technical reasons. First, the Windows VFS API is not designed for handling encrypted files. Second, while the VFS is designed to deal mostly with large files, E2EE is mostly recommended for use with small files as encrypting and decrypting large files puts large demands on the computer infrastructure.
|
||||
|
||||
|
||||
User Status
|
||||
-----------
|
||||
|
||||
Starting from 3.2.0, user status is displayed in the Nextcloud desktop client's tray window. The icon and a text message are displayed as long as those are set in the user's account menu in the Web UI (server's website). At the moment, setting the status from the desktop client is not available.
|
||||
The status is updated almost immediately after it is set in the Web UI. Default user status is always "Online" if no other status is available from the server-side.
|
||||
|
||||
.. image:: images/status_feature_example.png
|
||||
:alt: User Status feature in the tray window
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.50'
|
||||
release = '3.3.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -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. |
|
||||
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 45 KiB |
@@ -8,9 +8,7 @@ There are clients for Linux, macOs, and Microsoft Windows.
|
||||
|
||||
The currently supported server releases are the latest three stable versions
|
||||
at time of publication. It means that the |version| release series is supporting
|
||||
stable server major versions.
|
||||
See https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule for
|
||||
supported major versions.
|
||||
server major version 20, 21 and 22.
|
||||
|
||||
Installation on Mac OS X and Windows is the same as for any software
|
||||
application: download the program and then double-click it to launch the
|
||||
@@ -33,7 +31,7 @@ download page.
|
||||
System Requirements
|
||||
----------------------------------
|
||||
|
||||
- Windows 8.1+
|
||||
- Windows 10+
|
||||
- macOS 10.12+ (64-bit only)
|
||||
- Linux
|
||||
- FreeBSD
|
||||
|
||||
@@ -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
|
||||
-------------------------
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
===========
|
||||
Visual Tour
|
||||
===========
|
||||
|
||||
@@ -12,7 +11,23 @@ as an icon in the system tray (Windows, KDE), status bar
|
||||
(macOS), or notification area (Ubuntu).
|
||||
|
||||
.. image:: images/icon.png
|
||||
:alt: desktop client icon
|
||||
|
||||
Main dialog
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. index:: activity, recent changes, sync activity, main dialog, adding account, account, add account, remove account
|
||||
|
||||
The main dialog, which can be invoked from the tray icon in the
|
||||
taskbar, will show files information about the activities of the sync
|
||||
client and Nextcloud. If there are any synchronization issues, they
|
||||
will show up here. The dialog also gives information about other
|
||||
activities or notifications like Talk mentions or file changes. It
|
||||
does also show the status of the user.
|
||||
|
||||
.. image:: images/main_dialog.png
|
||||
|
||||
When clicking on the avatar a menu opens where it is possible to add a
|
||||
new account or removing an existing account.
|
||||
|
||||
Menu
|
||||
----
|
||||
@@ -30,9 +45,8 @@ A right click on the icon provides the following menu:
|
||||
.. NOTE::
|
||||
This menu is not available on macOS.
|
||||
|
||||
|
||||
Settings
|
||||
~~~~~~~~
|
||||
--------
|
||||
|
||||
Account Settings
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -204,98 +218,3 @@ while syncing for a three times. These are listed in the activity view.
|
||||
There also is a button to retry the sync for another three times.
|
||||
|
||||
For more detailed information see :ref:`ignored-files-label`.
|
||||
|
||||
Main dialog
|
||||
-----------
|
||||
|
||||
.. index:: activity, recent changes, sync activity, main dialog, adding account, account, add account, remove account, sync state, user status, unified search, share dialog
|
||||
|
||||
Sync State
|
||||
~~~~~~~~~~
|
||||
|
||||
The main dialog, which can be invoked from the tray icon in the
|
||||
taskbar, will show files information about the activities of the sync
|
||||
client and Nextcloud.
|
||||
|
||||
|
||||
.. image:: images/sync-state-paused.png
|
||||
:alt: sync state paused
|
||||
|
||||
.. image:: images/sync-state-syncing.png
|
||||
:alt: sync state syncing
|
||||
|
||||
.. image:: images/sync-state-synced.png
|
||||
:alt: sync state synced
|
||||
|
||||
|
||||
If there are any synchronization issues, they will show up here:
|
||||
|
||||
.. image:: images/sync-state-warnings.png
|
||||
:alt: sync state warnings
|
||||
|
||||
For more information on how to solve these issues see :doc:`troubleshooting`.
|
||||
|
||||
When clicking on the avatar a menu opens where it is
|
||||
possible to add a new account or removing an existing account.
|
||||
|
||||
.. image:: images/user-account-options.png
|
||||
:alt: user account options
|
||||
|
||||
|
||||
User Status
|
||||
~~~~~~~~~~~
|
||||
|
||||
User status is displayed in the Nextcloud desktop client's tray window.
|
||||
Default user status is always "Online" if no other status is available from the server-side.
|
||||
|
||||
.. image:: images/status_feature_example.png
|
||||
:alt: User Status feature in the tray window
|
||||
|
||||
When clicking on ``Set status`` you can edit the emoji, message and the timer to clear your user status:
|
||||
|
||||
.. image:: images/set-user-status.png
|
||||
:alt: set user status menu option
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/set-user-status-menu.png
|
||||
:alt: changing the user status
|
||||
|
||||
Activities list
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The dialog also gives information about other activities or
|
||||
notifications like Talk mentions or file changes.
|
||||
It does also show the status of the user.
|
||||
|
||||
.. image:: images/main_dialog.png
|
||||
:alt: main dialog activities list
|
||||
|
||||
Unified search
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
With the unified search you can find everything you have in your server - files,
|
||||
Talk messages, calendar appointments:
|
||||
|
||||
.. image:: images/unified-search-files.png
|
||||
:alt: unified search files search result
|
||||
|
||||
.. image:: images/unified-search-talk.png
|
||||
:alt: unified search Talk conversations search result
|
||||
|
||||
.. image:: images/unified-search-events.png
|
||||
:alt: unified search calendar appointments search result
|
||||
|
||||
|
||||
Share dialog: Talk options and View Profile
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can now share a file directly in a conversation in Talk and view the sharee user profile:
|
||||
|
||||
.. image:: images/open-share-dialog.png
|
||||
:alt: open share dialog option
|
||||
|
||||
|
|
||||
|
||||
.. image:: images/share-dialog-view-profile.png
|
||||
:alt: shared dialog sharing options
|
||||
@@ -1,32 +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>
|
||||
<file>src/gui/tray/CustomButton.qml</file>
|
||||
<file>src/gui/tray/CustomTextButton.qml</file>
|
||||
<file>src/gui/tray/ActivityItemContextMenu.qml</file>
|
||||
<file>src/gui/tray/ActivityItemActions.qml</file>
|
||||
<file>src/gui/tray/ActivityItemContent.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class RemotePathChecker {
|
||||
class __declspec(dllexport) RemotePathChecker {
|
||||
public:
|
||||
enum FileState {
|
||||
// Order synced with NCOverlay
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
280
src/3rdparty/kirigami/wheelhandler.cpp
vendored
@@ -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"
|
||||
213
src/3rdparty/kirigami/wheelhandler.h
vendored
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
2
src/3rdparty/libcrashreporter-qt
vendored
2
src/3rdparty/qtlockedfile/qtlockedfile.h
vendored
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
QtLockedFile();
|
||||
QtLockedFile(const QString &name);
|
||||
~QtLockedFile() override;
|
||||
~QtLockedFile();
|
||||
|
||||
bool lock(LockMode mode, bool block = true);
|
||||
bool unlock();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
@@ -321,6 +320,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;
|
||||
@@ -483,7 +484,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 +502,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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -337,7 +334,7 @@ ComputeChecksum *ValidateChecksumHeader::prepareStart(const QByteArray &checksum
|
||||
|
||||
if (!parseChecksumHeader(checksumHeader, &_expectedChecksumType, &_expectedChecksum)) {
|
||||
qCWarning(lcChecksums) << "Checksum header malformed:" << checksumHeader;
|
||||
emit validationFailed(tr("The checksum header is malformed."), _calculatedChecksumType, _calculatedChecksum, ChecksumHeaderMalformed);
|
||||
emit validationFailed(tr("The checksum header is malformed."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -360,30 +357,15 @@ void ValidateChecksumHeader::start(std::unique_ptr<QIODevice> device, const QByt
|
||||
calculator->start(std::move(device));
|
||||
}
|
||||
|
||||
QByteArray ValidateChecksumHeader::calculatedChecksumType() const
|
||||
{
|
||||
return _calculatedChecksumType;
|
||||
}
|
||||
|
||||
QByteArray ValidateChecksumHeader::calculatedChecksum() const
|
||||
{
|
||||
return _calculatedChecksum;
|
||||
}
|
||||
|
||||
void ValidateChecksumHeader::slotChecksumCalculated(const QByteArray &checksumType,
|
||||
const QByteArray &checksum)
|
||||
{
|
||||
_calculatedChecksumType = checksumType;
|
||||
_calculatedChecksum = checksum;
|
||||
|
||||
if (checksumType != _expectedChecksumType) {
|
||||
emit validationFailed(tr("The checksum header contained an unknown checksum type \"%1\"").arg(QString::fromLatin1(_expectedChecksumType)),
|
||||
_calculatedChecksumType, _calculatedChecksum, ChecksumTypeUnknown);
|
||||
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)),
|
||||
_calculatedChecksumType, _calculatedChecksum, ChecksumMismatch);
|
||||
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);
|
||||
|
||||
@@ -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.
|
||||
@@ -140,14 +140,6 @@ class OCSYNC_EXPORT ValidateChecksumHeader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum FailureReason {
|
||||
Success,
|
||||
ChecksumHeaderMalformed,
|
||||
ChecksumTypeUnknown,
|
||||
ChecksumMismatch,
|
||||
};
|
||||
Q_ENUM(FailureReason)
|
||||
|
||||
explicit ValidateChecksumHeader(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
@@ -169,13 +161,9 @@ public:
|
||||
*/
|
||||
void start(std::unique_ptr<QIODevice> device, const QByteArray &checksumHeader);
|
||||
|
||||
QByteArray calculatedChecksumType() const;
|
||||
QByteArray calculatedChecksum() const;
|
||||
|
||||
signals:
|
||||
void validated(const QByteArray &checksumType, const QByteArray &checksum);
|
||||
void validationFailed(const QString &errMsg, const QByteArray &calculatedChecksumType,
|
||||
const QByteArray &calculatedChecksum, const ValidateChecksumHeader::FailureReason reason);
|
||||
void validationFailed(const QString &errMsg);
|
||||
|
||||
private slots:
|
||||
void slotChecksumCalculated(const QByteArray &checksumType, const QByteArray &checksum);
|
||||
@@ -185,9 +173,6 @@ private:
|
||||
|
||||
QByteArray _expectedChecksumType;
|
||||
QByteArray _expectedChecksum;
|
||||
|
||||
QByteArray _calculatedChecksumType;
|
||||
QByteArray _calculatedChecksum;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -77,7 +77,7 @@ enum class PinState {
|
||||
*/
|
||||
Unspecified = 3,
|
||||
};
|
||||
Q_ENUM_NS(PinState)
|
||||
Q_ENUM_NS(PinState);
|
||||
|
||||
/** A user-facing version of PinState.
|
||||
*
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
/**
|
||||
|
||||