mirror of https://github.com/nextcloud/desktop
commit
810d8f15ee
22
.drone.yml
22
.drone.yml
|
@ -1,19 +1,19 @@
|
|||
---
|
||||
kind: pipeline
|
||||
name: qt-5.15
|
||||
name: drone desktop client
|
||||
|
||||
steps:
|
||||
- name: cmake
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
commands:
|
||||
- cd /drone/build
|
||||
- cmake -G Ninja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DADD_E2E_TESTS=ON -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 ../src
|
||||
- cmake -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt6.6.3 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DADD_E2E_TESTS=ON -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 ../src
|
||||
|
||||
- name: compile
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
|
@ -22,7 +22,7 @@ steps:
|
|||
- ninja
|
||||
|
||||
- name: test
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
|
@ -79,15 +79,15 @@ name: qt-5.15-clang
|
|||
|
||||
steps:
|
||||
- name: cmake
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
commands:
|
||||
- cd /drone/build
|
||||
- cmake -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DADD_E2E_TESTS=ON -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 ../src
|
||||
- cmake -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt6.6.3 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DADD_E2E_TESTS=ON -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 ../src
|
||||
- name: compile
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
|
@ -95,7 +95,7 @@ steps:
|
|||
- cd /drone/build
|
||||
- ninja
|
||||
- name: test
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
|
@ -152,7 +152,7 @@ name: AppImage
|
|||
|
||||
steps:
|
||||
- name: build
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-appimage:client-appimage-10
|
||||
image: ghcr.io/nextcloud/continuous-integration-client-appimage-qt6:client-appimage-6.6.3-2
|
||||
environment:
|
||||
CI_UPLOAD_GIT_TOKEN:
|
||||
from_secret: CI_UPLOAD_GIT_TOKEN
|
||||
|
@ -206,6 +206,6 @@ trigger:
|
|||
- push
|
||||
---
|
||||
kind: signature
|
||||
hmac: 52e9470231175367dbb83f5aa33659332e977546cf1a9db3d942401778f53d68
|
||||
hmac: 418915bcd7a880be3656a8c09aef0f6e7b3721d13f196838f8c5a9de6020f786
|
||||
|
||||
...
|
||||
|
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
build:
|
||||
name: Linux Clang compilation and tests
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
@ -15,7 +15,7 @@ jobs:
|
|||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64
|
||||
cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt6.6.3 -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64
|
||||
ninja
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
build:
|
||||
name: Linux GCC compilation and tests
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
@ -15,7 +15,7 @@ jobs:
|
|||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64
|
||||
cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt6.6.3 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQT_MAJOR_VERSION=6 -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64
|
||||
ninja
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
build:
|
||||
name: SonarCloud analysis
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nextcloud/continuous-integration-client:client-5.15-15
|
||||
container: ghcr.io/nextcloud/continuous-integration-client-qt6:client-6.6.3-2
|
||||
env:
|
||||
SONAR_SERVER_URL: "https://sonarcloud.io"
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
|
@ -25,7 +25,7 @@ jobs:
|
|||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 -DBUILD_COVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/opt/qt6.6.3 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_BUILD_TYPE=Debug -DQUICK_COMPILER=ON -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DQT_MAJOR_VERSION=6 -DCMAKE_CXX_FLAGS=-Werror -DOPENSSL_ROOT_DIR=/usr/local/lib64 -DBUILD_COVERAGE=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} ninja
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
|
|
@ -23,6 +23,9 @@ set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
|||
|
||||
include(${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake)
|
||||
|
||||
set(QT_VERSION_MAJOR "6")
|
||||
set(REQUIRED_QT_VERSION "6.0.0")
|
||||
|
||||
# CfAPI Shell Extensions
|
||||
set( CFAPI_SHELL_EXTENSIONS_LIB_NAME CfApiShellExtensions )
|
||||
|
||||
|
@ -108,7 +111,8 @@ include(GetGitRevisionDescription)
|
|||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
|
||||
add_definitions(
|
||||
-DQT_DISABLE_DEPRECATED_BEFORE=0x000000
|
||||
-DQT_DISABLE_DEPRECATED_BEFORE=0x051200
|
||||
-DQT_DEPRECATED_WARNINGS
|
||||
-DQT_USE_QSTRINGBUILDER
|
||||
-DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output
|
||||
)
|
||||
|
@ -138,7 +142,7 @@ if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE)
|
|||
add_definitions(-DBUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
endif()
|
||||
|
||||
|
||||
find_package(Qt${QT_MAJOR_VERSION} COMPONENTS Core)
|
||||
option(QUICK_COMPILER "Use QtQuick compiler to improve performance" OFF)
|
||||
|
||||
# this option removes Http authentication, keychain, shibboleth etc and is intended for
|
||||
|
|
|
@ -37,3 +37,5 @@ set( MIRALL_VERSION_STRING "${MIRALL_VERSION}${MIRALL_VERSION_SUFFIX}" )
|
|||
if( MIRALL_VERSION_BUILD )
|
||||
set( MIRALL_VERSION_STRING "${MIRALL_VERSION_STRING} (build ${MIRALL_VERSION_BUILD})" )
|
||||
endif( MIRALL_VERSION_BUILD )
|
||||
|
||||
set(QT_MAJOR_VERSION 6)
|
||||
|
|
|
@ -2,17 +2,12 @@
|
|||
|
||||
set -xe
|
||||
|
||||
export APPNAME=${APPNAME:-nextcloud}
|
||||
export APPNAME=${APPNAME:-Nextcloud}
|
||||
export EXECUTABLE_NAME=${EXECUTABLE_NAME:-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/kdeqt5.15
|
||||
|
||||
export QTDIR=$QT_BASE_DIR
|
||||
export PATH=$QT_BASE_DIR/bin:$PATH
|
||||
|
||||
# Set defaults
|
||||
export SUFFIX=${DRONE_PULL_REQUEST:=master}
|
||||
if [ $SUFFIX != "master" ]; then
|
||||
|
@ -29,12 +24,14 @@ mkdir build-client
|
|||
cd build-client
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-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" \
|
||||
-D CMAKE_UNITY_BUILD=ON \
|
||||
-DCMAKE_PREFIX_PATH=/opt/qt6.6.3 \
|
||||
-DOPENSSL_ROOT_DIR=/usr/local/lib64 \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DBUILD_UPDATER=$BUILD_UPDATER \
|
||||
-DMIRALL_VERSION_BUILD=$BUILDNR \
|
||||
-DMIRALL_VERSION_SUFFIX="$VERSION_SUFFIX" \
|
||||
-DCMAKE_UNITY_BUILD=ON \
|
||||
${DESKTOP_CLIENT_ROOT}
|
||||
cmake --build . --target all
|
||||
DESTDIR=/app cmake --install .
|
||||
|
@ -64,48 +61,37 @@ rm -rf etc
|
|||
|
||||
# com.nextcloud.desktopclient.nextcloud.desktop
|
||||
DESKTOP_FILE=$(ls /app/usr/share/applications/*.desktop)
|
||||
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
|
||||
cp ./usr/share/icons/hicolor/512x512/apps/*.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 -P /usr/local/lib*/libssl.so* ./usr/lib/
|
||||
cp -P /usr/local/lib*/libcrypto.so* ./usr/lib/
|
||||
cp -P /usr/local/lib*/libsqlite*.so* ./usr/lib/
|
||||
# Use linuxdeploy to deploy
|
||||
export APPIMAGE_NAME=linuxdeploy-x86_64.AppImage
|
||||
wget -O ${APPIMAGE_NAME} --ca-directory=/etc/ssl/certs -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
||||
chmod a+x ${APPIMAGE_NAME}
|
||||
./${APPIMAGE_NAME} --appimage-extract
|
||||
rm ./${APPIMAGE_NAME}
|
||||
cp -r ./squashfs-root ./linuxdeploy-squashfs-root
|
||||
|
||||
# NSS fun
|
||||
cp -P -r /usr/lib/x86_64-linux-gnu/nss ./usr/lib/
|
||||
export LD_LIBRARY_PATH=/app/usr/lib:/opt/qt6.6.3/lib:/usr/local/lib/x86_64-linux-gnu:/usr/local/lib:/usr/local/lib64
|
||||
./linuxdeploy-squashfs-root/AppRun --desktop-file=${DESKTOP_FILE} --icon-file=usr/share/icons/hicolor/512x512/apps/${APPNAME}.png --executable=usr/bin/${EXECUTABLE_NAME} --appdir=AppDir
|
||||
|
||||
# Use linuxdeployqt to deploy
|
||||
LINUXDEPLOYQT_VERSION="continuous"
|
||||
wget -O linuxdeployqt.AppImage --ca-directory=/etc/ssl/certs -c "https://github.com/probonopd/linuxdeployqt/releases/download/${LINUXDEPLOYQT_VERSION}/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt.AppImage
|
||||
./linuxdeployqt.AppImage --appimage-extract
|
||||
rm ./linuxdeployqt.AppImage
|
||||
cp -r ./squashfs-root ./linuxdeployqt-squashfs-root
|
||||
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib/x86_64-linux-gnu
|
||||
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=${DESKTOP_CLIENT_ROOT}/src/gui
|
||||
# Use linuxdeploy-plugin-qt to deploy qt dependencies
|
||||
export APPIMAGE_NAME=linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
wget -O ${APPIMAGE_NAME} --ca-directory=/etc/ssl/certs -c "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||
chmod a+x ${APPIMAGE_NAME}
|
||||
./${APPIMAGE_NAME} --appimage-extract
|
||||
rm ./${APPIMAGE_NAME}
|
||||
cp -r ./squashfs-root ./linuxdeploy-plugin-qt-squashfs-root
|
||||
|
||||
# Set origin
|
||||
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/lib*sync.so.0
|
||||
export PATH=/opt/qt6.6.3/bin:${PATH}
|
||||
export QML_SOURCES_PATHS=${DESKTOP_CLIENT_ROOT}/src/gui
|
||||
./linuxdeploy-plugin-qt-squashfs-root/AppRun --appdir=AppDir
|
||||
|
||||
# Build AppImage
|
||||
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage -updateinformation="gh-releases-zsync|nextcloud-releases|desktop|latest|Nextcloud-*-x86_64.AppImage.zsync"
|
||||
|
||||
# Workaround issue #103
|
||||
rm -rf ./squashfs-root
|
||||
APPIMAGE=$(ls *.AppImage)
|
||||
"./${APPIMAGE}" --appimage-extract
|
||||
rm "./${APPIMAGE}"
|
||||
rm ./squashfs-root/usr/lib/libglib-2.0.so.0
|
||||
rm ./squashfs-root/usr/lib/libgobject-2.0.so.0
|
||||
PATH=./linuxdeployqt-squashfs-root/usr/bin:$PATH appimagetool -n ./squashfs-root "$APPIMAGE"
|
||||
./linuxdeploy-squashfs-root/AppRun --desktop-file=${DESKTOP_FILE} --icon-file=usr/share/icons/hicolor/512x512/apps/${APPNAME}.png --executable=usr/bin/${EXECUTABLE_NAME} --appdir=AppDir --output appimage
|
||||
|
||||
#move AppImage
|
||||
if [ ! -z "$DRONE_COMMIT" ]
|
||||
then
|
||||
mv *.AppImage ${APPNAME}-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
|
||||
mv *.AppImage ${EXECUTABLE_NAME}-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
|
||||
else
|
||||
mv *.AppImage ${EXECUTABLE_NAME}-${SUFFIX}-x86_64.AppImage
|
||||
fi
|
||||
mv *.AppImage ${DESKTOP_CLIENT_ROOT}/
|
||||
|
|
|
@ -9,7 +9,7 @@ else()
|
|||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
||||
endif()
|
||||
|
||||
find_package(Qt5 5.15 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} 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)
|
||||
|
|
|
@ -25,8 +25,13 @@ macro(libcloudproviders_add_config _sources)
|
|||
endmacro(libcloudproviders_add_config _sources)
|
||||
|
||||
|
||||
find_package(Qt5 5.15 COMPONENTS DBus)
|
||||
IF (Qt5DBus_FOUND)
|
||||
if (Qt6_FOUND)
|
||||
find_package(Qt6 COMPONENTS COMPONENTS DBus)
|
||||
else()
|
||||
set(REQUIRED_QT_VERSION "5.15.0")
|
||||
find_package(Qt5 ${REQUIRED_QT_VERSION} COMPONENTS DBus)
|
||||
endif()
|
||||
IF (Qt5DBus_FOUND OR Qt6DBus_FOUND)
|
||||
STRING(TOLOWER "${APPLICATION_VENDOR}" DBUS_VENDOR)
|
||||
STRING(REGEX REPLACE "[^A-z0-9]" "" DBUS_VENDOR "${DBUS_VENDOR}")
|
||||
STRING(REGEX REPLACE "[^A-z0-9]" "" DBUS_APPLICATION_NAME "${APPLICATION_SHORTNAME}")
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Daniel Molkentin <daniel@molkentin.de>
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TOKENIZER_H
|
||||
#define TOKENIZER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
template <class T, class const_iterator>
|
||||
struct QTokenizerPrivate {
|
||||
using char_type = typename T::value_type;
|
||||
|
||||
struct State {
|
||||
bool inQuote = false;
|
||||
bool inEscape = false;
|
||||
char_type quoteChar = '\0';
|
||||
};
|
||||
|
||||
QTokenizerPrivate(const T& _string, const T& _delims) :
|
||||
string(_string)
|
||||
, begin(string.begin())
|
||||
, end(string.end())
|
||||
, tokenBegin(end)
|
||||
, tokenEnd(begin)
|
||||
, delimiters(_delims)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isDelimiter(char_type c) const {
|
||||
return delimiters.contains(c);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isQuote(char_type c) const {
|
||||
return quotes.contains(c);
|
||||
}
|
||||
|
||||
// Returns true if a delimiter was not hit
|
||||
bool nextChar(State* state, char_type c) {
|
||||
if (state->inQuote) {
|
||||
if (state->inEscape) {
|
||||
state->inEscape = false;
|
||||
} else if (c == '\\') {
|
||||
state->inEscape = true;
|
||||
} else if (c == state->quoteChar) {
|
||||
state->inQuote = false;
|
||||
}
|
||||
} else {
|
||||
if (isDelimiter(c))
|
||||
return false;
|
||||
state->inQuote = isQuote(state->quoteChar = c);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
T string;
|
||||
// ### copies begin and end for performance, premature optimization?
|
||||
const_iterator begin;
|
||||
const_iterator end;
|
||||
const_iterator tokenBegin;
|
||||
const_iterator tokenEnd;
|
||||
T delimiters;
|
||||
T quotes;
|
||||
bool isDelim = false;
|
||||
bool returnDelimiters = false;
|
||||
bool returnQuotes = false;
|
||||
};
|
||||
|
||||
template <class T, class const_iterator = typename T::const_iterator>
|
||||
class QTokenizer {
|
||||
public:
|
||||
using char_type = typename T::value_type;
|
||||
|
||||
/*!
|
||||
\class QTokenizer
|
||||
\inmodule QtNetwork
|
||||
\brief QTokenizer tokenizes Strings on QString, QByteArray,
|
||||
std::string or std::wstring
|
||||
|
||||
Example Usage:
|
||||
|
||||
\code
|
||||
QString str = ...;
|
||||
QByteArrayTokenizer tokenizer(str, "; ");
|
||||
tokenizer.setQuoteCharacters("\"'");
|
||||
tokenizer.setReturnDelimiters(true);
|
||||
while (tokenizer.hasNext()) {
|
||||
QByteArray token = tokenizer.next();
|
||||
bool isDelimiter = tokenizer.isDelimiter();
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
|
||||
\param string The string to tokenize
|
||||
\param delimiters A string containing delimiters
|
||||
|
||||
\sa QStringTokenizer, QByteArrayTokenizer, StringTokenizer, WStringTokenizer
|
||||
*/
|
||||
QTokenizer(const T& string, const T& delimiters)
|
||||
: d(new QTokenizerPrivate<T, const_iterator>(string, delimiters))
|
||||
{ }
|
||||
|
||||
/*!
|
||||
Whether or not to return delimiters as tokens
|
||||
\see setQuoteCharacters
|
||||
*/
|
||||
void setReturnDelimiters(bool enable) { d->returnDelimiters = enable; }
|
||||
|
||||
|
||||
/*!
|
||||
Sets characters that are considered to start and end quotes.
|
||||
|
||||
When between two characters considered a quote, delimiters will
|
||||
be ignored.
|
||||
|
||||
When between quotes, blackslash characters will cause the QTokenizer
|
||||
to skip the next character.
|
||||
|
||||
\param quotes Characters that delimit quotes.
|
||||
*/
|
||||
void setQuoteCharacters(const T& quotes) { d->quotes = quotes; }
|
||||
|
||||
|
||||
/*!
|
||||
Whether or not to return delimiters as tokens
|
||||
\see setQuoteCharacters
|
||||
*/
|
||||
void setReturnQuoteCharacters(bool enable) { d->returnQuotes = enable; }
|
||||
|
||||
|
||||
/*!
|
||||
Retrieve next token.
|
||||
|
||||
Returns true if there are more tokens, false otherwise.
|
||||
|
||||
\sa next()
|
||||
*/
|
||||
bool hasNext()
|
||||
{
|
||||
typename QTokenizerPrivate<T, const_iterator>::State state;
|
||||
d->isDelim = false;
|
||||
for (;;) {
|
||||
d->tokenBegin = d->tokenEnd;
|
||||
if (d->tokenEnd == d->end)
|
||||
return false;
|
||||
d->tokenEnd++;
|
||||
if (d->nextChar(&state, *d->tokenBegin))
|
||||
break;
|
||||
if (d->returnDelimiters) {
|
||||
d->isDelim = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while (d->tokenEnd != d->end && d->nextChar(&state, *d->tokenEnd)) {
|
||||
d->tokenEnd++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Resets the tokenizer to the starting position.
|
||||
*/
|
||||
void reset() {
|
||||
d->tokenEnd = d->begin;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the current token is a delimiter,
|
||||
if one more more delimiting characters have been set.
|
||||
*/
|
||||
[[nodiscard]] bool isDelimiter() const { return d->isDelim; }
|
||||
|
||||
/*!
|
||||
Returns the current token.
|
||||
|
||||
Use \c hasNext() to fetch the next token.
|
||||
*/
|
||||
[[nodiscard]] T next() const {
|
||||
int len = std::distance(d->tokenBegin, d->tokenEnd);
|
||||
const_iterator tmpStart = d->tokenBegin;
|
||||
if (!d->returnQuotes && len > 1 && d->isQuote(*d->tokenBegin)) {
|
||||
tmpStart++;
|
||||
len -= 2;
|
||||
}
|
||||
return T(tmpStart, len);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class QStringTokenizer;
|
||||
QSharedPointer<QTokenizerPrivate<T, const_iterator> > d;
|
||||
};
|
||||
|
||||
class QStringTokenizer : public QTokenizer<QString> {
|
||||
public:
|
||||
QStringTokenizer(const QString &string, const QString &delim) :
|
||||
QTokenizer<QString, QString::const_iterator>(string, delim) {}
|
||||
/**
|
||||
* @brief Like \see next(), but returns a lightweight string reference
|
||||
* @return A reference to the token within the string
|
||||
*/
|
||||
QStringRef stringRef() {
|
||||
// If those differences overflow an int we'd have a veeeeeery long string in memory
|
||||
int begin = std::distance(d->begin, d->tokenBegin);
|
||||
int end = std::distance(d->tokenBegin, d->tokenEnd);
|
||||
if (!d->returnQuotes && d->isQuote(*d->tokenBegin)) {
|
||||
begin++;
|
||||
end -= 2;
|
||||
}
|
||||
return QStringRef(&d->string, begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
using QByteArrayTokenizer = QTokenizer<QByteArray>;
|
||||
using StringTokenizer = QTokenizer<std::string>;
|
||||
using WStringTokenizer = QTokenizer<std::wstring>;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // TOKENIZER_H
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
TEMPLATE = subdirs
|
||||
SUBDIRS = test
|
|
@ -1,8 +0,0 @@
|
|||
TEMPLATE = app
|
||||
QT += testlib
|
||||
CONFIG += testlib
|
||||
TARGET = test
|
||||
INCLUDEPATH += . ..
|
||||
|
||||
# Input
|
||||
SOURCES += tst_qtokenizer.cpp
|
|
@ -1,139 +0,0 @@
|
|||
#include <QtTest>
|
||||
|
||||
#include "qtokenizer.h"
|
||||
|
||||
namespace {
|
||||
const QString simple = QLatin1String("A simple tokenizer test");
|
||||
const QString quoted = QLatin1String("\"Wait for me!\" he shouted");
|
||||
}
|
||||
|
||||
class TestTokenizer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void tokenizeQStringSimple() {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringSimpleRef() {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QVERIFY(tokenizer.stringRef() == QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringQuoted() {
|
||||
const QString multiquote(QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
QStringTokenizer tokenizer(multiquote, " -");
|
||||
tokenizer.setQuoteCharacters("\"");
|
||||
tokenizer.setReturnQuoteCharacters(true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void tokenizeQStringSkipQuotes() {
|
||||
const QString multiquote(QLatin1String("\"'Billy - the Kid' is dead!\""));
|
||||
QStringTokenizer tokenizer(multiquote, " ");
|
||||
tokenizer.setQuoteCharacters("\"");
|
||||
tokenizer.setReturnQuoteCharacters(false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("'Billy - the Kid' is dead!"));
|
||||
QCOMPARE(tokenizer.stringRef().toString(), QLatin1String("'Billy - the Kid' is dead!"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
|
||||
void tokenizeQStringWithDelims() {
|
||||
const QString delims(QLatin1String("I;Insist,On/a-Delimiter"));
|
||||
QStringTokenizer tokenizer(delims, ";,/-");
|
||||
tokenizer.setReturnDelimiters(true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), true);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.isDelimiter(), false);
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
}
|
||||
|
||||
void resetTokenizer() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
QStringTokenizer tokenizer(simple, " ");
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("A"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("simple"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("tokenizer"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), true);
|
||||
QCOMPARE(tokenizer.next(), QLatin1String("test"));
|
||||
|
||||
QCOMPARE(tokenizer.hasNext(), false);
|
||||
|
||||
tokenizer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// ### QByteArray, other types
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(TestTokenizer)
|
||||
|
||||
#include "tst_qtokenizer.moc"
|
||||
|
|
@ -2,71 +2,77 @@ include(ECMEnableSanitizers)
|
|||
|
||||
set(REQUIRED_QT_VERSION "5.15.0")
|
||||
|
||||
find_package(Qt5Core ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt5Core PROPERTIES
|
||||
DESCRIPTION "Qt5 Core component."
|
||||
find_package(Qt${QT_MAJOR_VERSION}Core ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}Core PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} Core component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt5Network ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt5Network PROPERTIES
|
||||
DESCRIPTION "Qt5 Network component."
|
||||
find_package(Qt${QT_MAJOR_VERSION}Network ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}Network PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} Network component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt5Xml ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt5Xml PROPERTIES
|
||||
DESCRIPTION "Qt5 Xml component."
|
||||
find_package(Qt${QT_MAJOR_VERSION}Xml ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}Xml PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} Xml component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt5Concurrent ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt5Concurrent PROPERTIES
|
||||
DESCRIPTION "Qt5 Concurrent component."
|
||||
find_package(Qt${QT_MAJOR_VERSION}Concurrent ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}Concurrent PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} Concurrent component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt5QuickWidgets ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt5QuickWidgets PROPERTIES
|
||||
DESCRIPTION "Qt5 QuickWidgets component."
|
||||
find_package(Qt${QT_MAJOR_VERSION}QuickWidgets ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}QuickWidgets PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} QuickWidgets component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt5WebEngineWidgets ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
find_package(Qt${QT_VERSION_MAJOR}Core5Compat ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
set_package_properties(Qt${QT_VERSION_MAJOR}Core5Compat PROPERTIES
|
||||
DESCRIPTION "Qt${QT_VERSION_MAJOR} Core5Compat component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Qt${QT_MAJOR_VERSION}WebEngineWidgets ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
if(NOT BUILD_WITH_WEBENGINE)
|
||||
set_package_properties(Qt5WebEngineWidgets PROPERTIES
|
||||
DESCRIPTION "Qt5 WebEngineWidgets component."
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}WebEngineWidgets PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} WebEngineWidgets component."
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
else()
|
||||
set_package_properties(Qt5WebEngineWidgets PROPERTIES
|
||||
DESCRIPTION "Qt5 WebEngineWidgets component."
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}WebEngineWidgets PROPERTIES
|
||||
DESCRIPTION "Qt${QT_MAJOR_VERSION} WebEngineWidgets component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(Qt5WebEngine ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
if(NOT BUILD_WITH_WEBENGINE)
|
||||
set_package_properties(Qt5WebEngine PROPERTIES
|
||||
DESCRIPTION "Qt5 WebEngine component."
|
||||
find_package(Qt${QT_VERSION_MAJOR}WebEngineCore ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
if(APPLE)
|
||||
set_package_properties(Qt${QT_VERSION_MAJOR}WebEngineCore PROPERTIES
|
||||
DESCRIPTION "Qt${QT_VERSION_MAJOR} WebEngineCore component."
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
else()
|
||||
set_package_properties(Qt5WebEngine PROPERTIES
|
||||
DESCRIPTION "Qt5 WebEngine component."
|
||||
set_package_properties(Qt${QT_VERSION_MAJOR}WebEngine PROPERTIES
|
||||
DESCRIPTION "Qt${QT_VERSION_MAJOR} WebEngine component."
|
||||
TYPE REQUIRED
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BUILD_WITH_WEBENGINE AND Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||
if(Qt${QT_MAJOR_VERSION}WebEngine_FOUND AND Qt${QT_MAJOR_VERSION}WebEngineWidgets_FOUND)
|
||||
add_compile_definitions(WITH_WEBENGINE=1)
|
||||
endif()
|
||||
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||
message(STATUS "Using Qt ${Qt5Core_VERSION} (${QT_QMAKE_EXECUTABLE})")
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||
message(STATUS "Using Qt ${Qt${QT_MAJOR_VERSION}Core_VERSION} (${QT_QMAKE_EXECUTABLE})")
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5Keychain REQUIRED)
|
||||
find_package(Qt${QT_MAJOR_VERSION}Keychain REQUIRED)
|
||||
endif()
|
||||
|
||||
# TODO: Mingw64 7.3 might also need to be excluded here as it seems to not automatically link libssp
|
||||
|
|
|
@ -10,13 +10,10 @@ add_library(cmdCore STATIC
|
|||
target_link_libraries(cmdCore
|
||||
PUBLIC
|
||||
Nextcloud::sync
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
Qt::Core
|
||||
Qt::Network
|
||||
)
|
||||
|
||||
# Need tokenizer for netrc parser
|
||||
target_include_directories(cmdCore PRIVATE ${CMAKE_SOURCE_DIR}/src/3rdparty/qtokenizer)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE")
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <qtokenizer.h>
|
||||
#include <QStringTokenizer>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
@ -59,33 +58,32 @@ bool NetrcParser::parse()
|
|||
}
|
||||
QString content = netrc.readAll();
|
||||
|
||||
QStringTokenizer tokenizer(content, " \n\t");
|
||||
tokenizer.setQuoteCharacters("\"'");
|
||||
auto tokenizer = QStringTokenizer{content, u" \n\t"};
|
||||
|
||||
LoginPair pair;
|
||||
QString machine;
|
||||
bool isDefault = false;
|
||||
while (tokenizer.hasNext()) {
|
||||
QString key = tokenizer.next();
|
||||
for(auto itToken = tokenizer.cbegin(); itToken != tokenizer.cend(); ++itToken) {
|
||||
const auto key = *itToken;
|
||||
if (key == defaultKeyword) {
|
||||
tryAddEntryAndClear(machine, pair, isDefault);
|
||||
isDefault = true;
|
||||
continue; // don't read a value
|
||||
}
|
||||
|
||||
if (!tokenizer.hasNext()) {
|
||||
if (itToken != tokenizer.cend()) {
|
||||
qDebug() << "error fetching value for" << key;
|
||||
return false;
|
||||
}
|
||||
QString value = tokenizer.next();
|
||||
auto value = *(++itToken);
|
||||
|
||||
if (key == machineKeyword) {
|
||||
tryAddEntryAndClear(machine, pair, isDefault);
|
||||
machine = value;
|
||||
machine = value.toString();
|
||||
} else if (key == loginKeyword) {
|
||||
pair.first = value;
|
||||
pair.first = value.toString();
|
||||
} else if (key == passwordKeyword) {
|
||||
pair.second = value;
|
||||
pair.second = value.toString();
|
||||
} // ignore unsupported tokens
|
||||
}
|
||||
tryAddEntryAndClear(machine, pair, isDefault);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "remotepermissions.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <cstring>
|
||||
|
|
|
@ -209,7 +209,7 @@ qint64 Utility::freeDiskSpace(const QString &path)
|
|||
QString Utility::compactFormatDouble(double value, int prec, const QString &unit)
|
||||
{
|
||||
QLocale locale = QLocale::system();
|
||||
QChar decPoint = locale.decimalPoint();
|
||||
const auto decPoint = locale.decimalPoint();
|
||||
QString str = locale.toString(value, 'f', prec);
|
||||
while (str.endsWith(QLatin1Char('0')) || str.endsWith(decPoint)) {
|
||||
if (str.endsWith(decPoint)) {
|
||||
|
@ -575,7 +575,7 @@ QString Utility::makeConflictFileName(
|
|||
|
||||
bool Utility::isConflictFile(const QString &name)
|
||||
{
|
||||
auto bname = name.midRef(name.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
auto bname = name.mid(name.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
|
||||
if (bname.contains(QStringLiteral("_conflict-"))) {
|
||||
return true;
|
||||
|
@ -676,7 +676,7 @@ QString Utility::makeCaseClashConflictFileName(const QString &filename, const QD
|
|||
|
||||
bool Utility::isCaseClashConflictFile(const QString &name)
|
||||
{
|
||||
const auto bname = name.midRef(name.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
const auto bname = name.mid(name.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
|
||||
return bname.contains(QStringLiteral("(case clash from"));
|
||||
}
|
||||
|
|
|
@ -99,7 +99,6 @@ void Utility::setLaunchOnStartup(const QString &appName, const QString &guiName,
|
|||
const QString executablePath = runningInsideAppImage ? appImagePath : QCoreApplication::applicationFilePath();
|
||||
|
||||
QTextStream ts(&iniFile);
|
||||
ts.setCodec("UTF-8");
|
||||
ts << QLatin1String("[Desktop Entry]\n")
|
||||
<< QLatin1String("Name=") << guiName << QLatin1Char('\n')
|
||||
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer\n")
|
||||
|
|
|
@ -24,14 +24,14 @@ if(NOT BUILD_LIBRARIES_ONLY)
|
|||
${crashreporter_RC_RCC}
|
||||
)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Widgets)
|
||||
|
||||
target_include_directories(${CRASHREPORTER_EXECUTABLE} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES AUTOMOC ON)
|
||||
set_target_properties(${CRASHREPORTER_EXECUTABLE} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY} )
|
||||
target_link_libraries(${CRASHREPORTER_EXECUTABLE}
|
||||
crashreporter-gui
|
||||
Qt5::Core Qt5::Widgets
|
||||
Qt::Core Qt::Widgets
|
||||
)
|
||||
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
|
@ -48,7 +48,7 @@ if(NOT BUILD_LIBRARIES_ONLY)
|
|||
# currently it needs to be done because the code right above needs to be executed no matter
|
||||
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||
get_filename_component(QT_BIN_DIR "${QT_QMAKE_EXECUTABLE}" DIRECTORY)
|
||||
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${QT_BIN_DIR}")
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ generate_export_header(nextcloud_csync
|
|||
target_link_libraries(nextcloud_csync
|
||||
PUBLIC
|
||||
${CSYNC_REQUIRED_LIBRARIES}
|
||||
Qt5::Core Qt5::Concurrent
|
||||
Qt::Core Qt::Concurrent
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <QByteArray>
|
||||
#include <QVariant>
|
||||
|
||||
#include "common/remotepermissions.h"
|
||||
|
||||
namespace OCC {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <QString>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QVariant>
|
||||
|
||||
/** Expands C-like escape sequences (in place)
|
||||
*/
|
||||
|
@ -90,7 +91,7 @@ static const char *win_reserved_words_n[] = { "CLOCK$", "$Recycle.Bin" };
|
|||
* @param file_name filename
|
||||
* @return true if file is reserved, false otherwise
|
||||
*/
|
||||
OCSYNC_EXPORT bool csync_is_windows_reserved_word(const QStringRef &filename)
|
||||
OCSYNC_EXPORT bool csync_is_windows_reserved_word(const QStringView &filename)
|
||||
{
|
||||
size_t len_filename = filename.size();
|
||||
|
||||
|
@ -132,10 +133,10 @@ OCSYNC_EXPORT bool csync_is_windows_reserved_word(const QStringRef &filename)
|
|||
static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QString &path, bool excludeConflictFiles)
|
||||
{
|
||||
/* split up the path */
|
||||
QStringRef bname(&path);
|
||||
QStringView bname(path);
|
||||
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
|
||||
if (lastSlash >= 0) {
|
||||
bname = path.midRef(lastSlash + 1);
|
||||
bname = path.mid(lastSlash + 1);
|
||||
}
|
||||
|
||||
qsizetype blen = bname.size();
|
||||
|
@ -450,10 +451,10 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
|
|||
|
||||
// Check the bname part of the path to see whether the full
|
||||
// regex should be run.
|
||||
QStringRef bnameStr(&path);
|
||||
QStringView bnameStr(path);
|
||||
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
|
||||
if (lastSlash >= 0) {
|
||||
bnameStr = path.midRef(lastSlash + 1);
|
||||
bnameStr = bnameStr.mid(lastSlash + 1);
|
||||
}
|
||||
|
||||
QString basePath(_localPath + path);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
import "./tray"
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
project(gui)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 QuickWidgets Xml Network)
|
||||
find_package(KF5Archive REQUIRED)
|
||||
find_package(KF5GuiAddons)
|
||||
find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 QuickWidgets Xml Network)
|
||||
find_package(KF6Archive REQUIRED)
|
||||
find_package(KF6GuiAddons)
|
||||
|
||||
if(QUICK_COMPILER)
|
||||
find_package(Qt5QuickCompiler)
|
||||
set_package_properties(Qt5QuickCompiler PROPERTIES
|
||||
DESCRIPTION "Compile QML at build time"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET Qt5::GuiPrivate)
|
||||
message(FATAL_ERROR "Could not find GuiPrivate component of Qt5. It might be shipped as a separate package, please check that.")
|
||||
if (NOT TARGET Qt::GuiPrivate)
|
||||
message(FATAL_ERROR "Could not find GuiPrivate component of Qt. It might be shipped as a separate package, please check that.")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
|
@ -55,11 +47,7 @@ set(client_UI_SRCS
|
|||
wizard/welcomepage.ui
|
||||
)
|
||||
|
||||
if(QUICK_COMPILER)
|
||||
qtquick_compiler_add_resources(client_UI_SRCS ../../resources.qrc ${CMAKE_SOURCE_DIR}/theme.qrc)
|
||||
else()
|
||||
qt_add_resources(client_UI_SRCS ../../resources.qrc ${CMAKE_SOURCE_DIR}/theme.qrc)
|
||||
endif()
|
||||
qt_add_resources(client_UI_SRCS ../../resources.qrc ${CMAKE_SOURCE_DIR}/theme.qrc)
|
||||
|
||||
set(client_SRCS
|
||||
accountmanager.h
|
||||
|
@ -261,7 +249,7 @@ set(client_SRCS
|
|||
wizard/linklabel.cpp
|
||||
)
|
||||
|
||||
if (Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||
if (Qt${QT_MAJOR_VERSION}WebEngine_FOUND AND Qt${QT_MAJOR_VERSION}WebEngineWidgets_FOUND)
|
||||
list(APPEND client_SRCS
|
||||
wizard/webviewpage.h
|
||||
wizard/webviewpage.cpp
|
||||
|
@ -332,7 +320,7 @@ IF( APPLE )
|
|||
list(APPEND updater_DEPS ${SPARKLE_LIBRARY})
|
||||
|
||||
# Sparkle.framework is installed from here because macdeployqt's CopyFramework breaks on this bundle
|
||||
# as its logic is tightly tailored around Qt5 frameworks
|
||||
# as its logic is tightly tailored around Qt frameworks
|
||||
install(DIRECTORY "${SPARKLE_LIBRARY}"
|
||||
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks" USE_SOURCE_PERMISSIONS)
|
||||
|
||||
|
@ -377,9 +365,9 @@ else()
|
|||
set_property(SOURCE ../3rdparty/qtlockedfile/qtlockedfile_win.cpp PROPERTY SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
endif()
|
||||
|
||||
find_package(Qt5LinguistTools)
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
qt5_add_translation(client_I18N ${TRANSLATIONS})
|
||||
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} COMPONENTS LinguistTools)
|
||||
if(Qt${QT_MAJOR_VERSION}LinguistTools_FOUND)
|
||||
qt_add_translation(client_I18N ${TRANSLATIONS})
|
||||
endif()
|
||||
|
||||
IF( WIN32 )
|
||||
|
@ -402,8 +390,8 @@ set( final_src
|
|||
${3rdparty_MOC}
|
||||
)
|
||||
|
||||
if(Qt5Keychain_FOUND)
|
||||
list(APPEND libsync_LINK_TARGETS qt5keychain)
|
||||
if(Qt${QT_MAJOR_VERSION}Keychain_FOUND)
|
||||
list(APPEND libsync_LINK_TARGETS Qt6::keychain)
|
||||
endif()
|
||||
|
||||
# add executable icon on windows and osx
|
||||
|
@ -556,22 +544,22 @@ add_library(nextcloudCore STATIC ${final_src})
|
|||
target_link_libraries(nextcloudCore
|
||||
PUBLIC
|
||||
Nextcloud::sync
|
||||
Qt5::Widgets
|
||||
Qt5::GuiPrivate
|
||||
Qt5::Svg
|
||||
Qt5::Network
|
||||
Qt5::Xml
|
||||
Qt5::Qml
|
||||
Qt5::Quick
|
||||
Qt5::QuickControls2
|
||||
Qt5::QuickWidgets
|
||||
KF5::Archive
|
||||
Qt::Widgets
|
||||
Qt::GuiPrivate
|
||||
Qt::Svg
|
||||
Qt::Network
|
||||
Qt::Xml
|
||||
Qt::Qml
|
||||
Qt::Quick
|
||||
Qt::QuickControls2
|
||||
Qt::QuickWidgets
|
||||
KF6::Archive
|
||||
)
|
||||
|
||||
if(KF5GuiAddons_FOUND)
|
||||
if(KF6GuiAddons_FOUND)
|
||||
target_link_libraries(nextcloudCore
|
||||
PUBLIC
|
||||
KF5::GuiAddons
|
||||
KF6::GuiAddons
|
||||
)
|
||||
add_definitions(-DHAVE_KGUIADDONS)
|
||||
endif()
|
||||
|
@ -588,8 +576,8 @@ foreach(FILE IN LISTS client_UI_SRCS)
|
|||
set_property(SOURCE ${FILE} PROPERTY SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
endforeach()
|
||||
|
||||
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::WebEngineWidgets)
|
||||
if(Qt6WebEngine_FOUND AND Qt6WebEngineWidgets_FOUND)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt::WebEngineWidgets)
|
||||
endif()
|
||||
|
||||
set_target_properties(nextcloudCore
|
||||
|
@ -647,7 +635,7 @@ else()
|
|||
|
||||
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
|
||||
install(FILES ${client_I18N} DESTINATION ${QM_DIR})
|
||||
get_target_property(_qmake Qt5::qmake LOCATION)
|
||||
get_target_property(_qmake Qt::qmake LOCATION)
|
||||
execute_process(COMMAND ${_qmake} -query QT_INSTALL_TRANSLATIONS
|
||||
OUTPUT_VARIABLE QT_TRANSLATIONS_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
|
@ -662,7 +650,7 @@ endif()
|
|||
|
||||
IF(BUILD_UPDATER)
|
||||
add_library(updater STATIC ${updater_SRCS})
|
||||
target_link_libraries(updater Nextcloud::sync ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
|
||||
target_link_libraries(updater Nextcloud::sync ${updater_DEPS} Qt::Widgets Qt::Svg Qt::Network Qt::Xml)
|
||||
target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_target_properties(updater PROPERTIES AUTOMOC ON)
|
||||
target_link_libraries(nextcloudCore PUBLIC updater)
|
||||
|
@ -705,20 +693,20 @@ endif()
|
|||
|
||||
## handle DBUS for Fdo notifications
|
||||
if( UNIX AND NOT APPLE )
|
||||
find_package(Qt5 COMPONENTS DBus)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::DBus)
|
||||
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} COMPONENTS DBus)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt::DBus)
|
||||
target_compile_definitions(nextcloudCore PUBLIC "USE_FDO_NOTIFICATIONS")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
find_package(Qt5 COMPONENTS MacExtras)
|
||||
find_package(Qt${QT_MAJOR_VERSION} COMPONENTS MacExtras)
|
||||
|
||||
if (BUILD_FILE_PROVIDER_MODULE)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications -framework FileProvider")
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt::MacExtras "-framework UserNotifications -framework FileProvider")
|
||||
elseif(CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.14)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras "-framework UserNotifications")
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt::MacExtras "-framework UserNotifications")
|
||||
else()
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::MacExtras)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt::MacExtras)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -746,7 +734,7 @@ install(TARGETS nextcloud
|
|||
#
|
||||
# OSX: Run macdeployqt for src/gui and for src/cmd using the -executable option
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||
get_target_property (QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||
get_filename_component(QT_BIN_DIR "${QT_QMAKE_EXECUTABLE}" DIRECTORY)
|
||||
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${QT_BIN_DIR}")
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Window 2.15
|
||||
|
@ -53,36 +54,36 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
UserStatusSelectorButton {
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Online
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.userStatus.Online
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.onlineIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Online")
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Online
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.userStatus.Online
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
||||
}
|
||||
UserStatusSelectorButton {
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Away
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.userStatus.Away
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.awayIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Away")
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Away
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.userStatus.Away
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
||||
|
||||
}
|
||||
UserStatusSelectorButton {
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.DoNotDisturb
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.userStatus.DoNotDisturb
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.dndIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Do not disturb")
|
||||
secondaryText: qsTr("Mute all notifications")
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.DoNotDisturb
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.userStatus.DoNotDisturb
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
||||
|
@ -91,14 +92,14 @@ ColumnLayout {
|
|||
Component.onCompleted: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
|
||||
}
|
||||
UserStatusSelectorButton {
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.UserStatus.Invisible ||
|
||||
userStatusSelectorModel.onlineStatus === NC.UserStatus.Offline
|
||||
checked: userStatusSelectorModel.onlineStatus === NC.userStatus.Invisible ||
|
||||
userStatusSelectorModel.onlineStatus === NC.userStatus.Offline
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.invisibleIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Invisible")
|
||||
secondaryText: qsTr("Appear offline")
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Invisible
|
||||
onClicked: userStatusSelectorModel.onlineStatus = NC.userStatus.Invisible
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
|
||||
|
|
|
@ -244,7 +244,7 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
|
|||
addAction(syncNowAction);
|
||||
|
||||
auto *syncNowWithRemoteDiscovery = new QAction(this);
|
||||
syncNowWithRemoteDiscovery->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6));
|
||||
syncNowWithRemoteDiscovery->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_F6));
|
||||
connect(syncNowWithRemoteDiscovery, &QAction::triggered, this, &AccountSettings::slotScheduleCurrentFolderForceRemoteDiscovery);
|
||||
addAction(syncNowWithRemoteDiscovery);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "accountstate.h"
|
||||
|
||||
#include "accountmanager.h"
|
||||
#include "remotewipe.h"
|
||||
#include "account.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "ocsnavigationappsjob.h"
|
||||
#include "ocsuserstatusconnector.h"
|
||||
#include "pushnotifications.h"
|
||||
#include "networkjobs.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
|
@ -32,6 +34,7 @@
|
|||
#include <QJsonArray>
|
||||
#include <QNetworkRequest>
|
||||
#include <QBuffer>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -44,7 +47,8 @@ AccountState::AccountState(AccountPtr account)
|
|||
, _account(account)
|
||||
, _state(AccountState::Disconnected)
|
||||
, _connectionStatus(ConnectionValidator::Undefined)
|
||||
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
|
||||
, _waitingForNewCredentials(false)
|
||||
, _maintenanceToConnectedDelay(60000 + (QRandomGenerator::global()->generate() % (4 * 60000))) // 1-5min delay
|
||||
, _remoteWipe(new RemoteWipe(_account))
|
||||
, _isDesktopNotificationsAllowed(true)
|
||||
{
|
||||
|
@ -319,7 +323,7 @@ void AccountState::checkConnectivity()
|
|||
|
||||
// If we don't reset the ssl config a second CheckServerJob can produce a
|
||||
// ssl config that does not have a sensible certificate chain.
|
||||
account()->setSslConfiguration(QSslConfiguration());
|
||||
account()->setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
||||
//#endif
|
||||
conValidator->checkServerAndAuth();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QUrlQuery>
|
||||
#include <QVersionNumber>
|
||||
#include <QRandomGenerator>
|
||||
#include <QHttp2Configuration>
|
||||
|
||||
class QSocket;
|
||||
|
||||
|
@ -127,7 +129,7 @@ namespace {
|
|||
#ifdef Q_OS_WIN
|
||||
class WindowsNativeEventFilter : public QAbstractNativeEventFilter {
|
||||
public:
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override {
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override {
|
||||
const auto msg = static_cast<MSG *>(message);
|
||||
if(msg->message == WM_SYSCOLORCHANGE || msg->message == WM_SETTINGCHANGE) {
|
||||
if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
|
||||
|
@ -228,8 +230,6 @@ Application::Application(int &argc, char **argv)
|
|||
{
|
||||
_startedAt.start();
|
||||
|
||||
qsrand(std::random_device()());
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Ensure OpenSSL config file is only loaded from app directory
|
||||
QString opensslConf = QCoreApplication::applicationDirPath() + QString("/openssl.cnf");
|
||||
|
@ -254,7 +254,45 @@ Application::Application(int &argc, char **argv)
|
|||
setApplicationName(_theme->appName());
|
||||
setWindowIcon(_theme->applicationIcon());
|
||||
|
||||
if (ConfigFile().exists()) {
|
||||
if (!ConfigFile().exists()) {
|
||||
// Migrate from version <= 2.4
|
||||
setApplicationName(_theme->appNameGUI());
|
||||
// We need to use the deprecated QDesktopServices::storageLocation because of its Qt4
|
||||
// behavior of adding "data" to the path
|
||||
QString oldDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/data/" + organizationName() + "/" + applicationName();
|
||||
if (oldDir.endsWith('/')) oldDir.chop(1); // macOS 10.11.x does not like trailing slash for rename/move.
|
||||
setApplicationName(_theme->appName());
|
||||
if (QFileInfo(oldDir).isDir()) {
|
||||
auto confDir = ConfigFile().configPath();
|
||||
|
||||
// macOS 10.11.x does not like trailing slash for rename/move.
|
||||
if (confDir.endsWith('/')) {
|
||||
confDir.chop(1);
|
||||
}
|
||||
|
||||
qCInfo(lcApplication) << "Migrating old config from" << oldDir << "to" << confDir;
|
||||
|
||||
if (!QFile::rename(oldDir, confDir)) {
|
||||
qCWarning(lcApplication) << "Failed to move the old config directory to its new location (" << oldDir << "to" << confDir << ")";
|
||||
|
||||
// Try to move the files one by one
|
||||
if (QFileInfo(confDir).isDir() || QDir().mkdir(confDir)) {
|
||||
const QStringList filesList = QDir(oldDir).entryList(QDir::Files);
|
||||
qCInfo(lcApplication) << "Will move the individual files" << filesList;
|
||||
for (const auto &name : filesList) {
|
||||
if (!QFile::rename(oldDir + "/" + name, confDir + "/" + name)) {
|
||||
qCWarning(lcApplication) << "Fallback move of " << name << "also failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifndef Q_OS_WIN
|
||||
// Create a symbolic link so a downgrade of the client would still find the config.
|
||||
QFile::link(confDir, oldDir);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setupConfigFile();
|
||||
}
|
||||
|
||||
|
@ -390,7 +428,7 @@ Application::Application(int &argc, char **argv)
|
|||
QTimer::singleShot(0, this, &Application::slotCheckConnection);
|
||||
|
||||
// Can't use onlineStateChanged because it is always true on modern systems because of many interfaces
|
||||
connect(&_networkConfigurationManager, &QNetworkConfigurationManager::configurationChanged,
|
||||
connect(QNetworkInformation::instance(), &QNetworkInformation::reachabilityChanged,
|
||||
this, &Application::slotSystemOnlineConfigurationChanged);
|
||||
|
||||
#if defined(BUILD_UPDATER)
|
||||
|
@ -492,7 +530,7 @@ void Application::setupConfigFile()
|
|||
QT_WARNING_POP
|
||||
setApplicationName(_theme->appName());
|
||||
|
||||
auto oldDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
auto oldDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
// macOS 10.11.x does not like trailing slash for rename/move.
|
||||
if (oldDir.endsWith('/')) {
|
||||
|
@ -608,9 +646,10 @@ void Application::slotCleanup()
|
|||
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
|
||||
// progress of timing out in some seconds.
|
||||
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
|
||||
void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf)
|
||||
void Application::slotSystemOnlineConfigurationChanged()
|
||||
{
|
||||
if (cnf.state() & QNetworkConfiguration::Active) {
|
||||
if (QNetworkInformation::instance()->reachability() == QNetworkInformation::Reachability::Site ||
|
||||
QNetworkInformation::instance()->reachability() == QNetworkInformation::Reachability::Online) {
|
||||
const auto list = AccountManager::instance()->accounts();
|
||||
for (const auto &accountState : list) {
|
||||
accountState->systemOnlineConfigurationChanged();
|
||||
|
@ -866,16 +905,16 @@ void Application::showHelp()
|
|||
QTextStream stream(&helpText);
|
||||
stream << _theme->appName()
|
||||
<< QLatin1String(" version ")
|
||||
<< _theme->version() << endl;
|
||||
<< _theme->version() << Qt::endl;
|
||||
|
||||
stream << QLatin1String("File synchronisation desktop utility.") << endl
|
||||
<< endl
|
||||
stream << QLatin1String("File synchronisation desktop utility.") << Qt::endl
|
||||
<< Qt::endl
|
||||
<< QLatin1String(optionsC);
|
||||
|
||||
if (_theme->appName() == QLatin1String("ownCloud"))
|
||||
stream << endl
|
||||
<< "For more information, see http://www.owncloud.org" << endl
|
||||
<< endl;
|
||||
stream << Qt::endl
|
||||
<< "For more information, see http://www.owncloud.org" << Qt::endl
|
||||
<< Qt::endl;
|
||||
|
||||
displayHelpText(helpText);
|
||||
}
|
||||
|
@ -980,13 +1019,17 @@ void Application::setupTranslations()
|
|||
if (!qtTranslator->load(qtTrFile, qtTrPath)) {
|
||||
if (!qtTranslator->load(qtTrFile, trPath)) {
|
||||
if (!qtTranslator->load(qtBaseTrFile, qtTrPath)) {
|
||||
qtTranslator->load(qtBaseTrFile, trPath);
|
||||
if (!qtTranslator->load(qtBaseTrFile, trPath)) {
|
||||
qCDebug(lcApplication()) << "impossible to load Qt translation catalog" << qtBaseTrFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const QString qtkeychainTrFile = QLatin1String("qtkeychain_") + lang;
|
||||
if (!qtkeychainTranslator->load(qtkeychainTrFile, qtTrPath)) {
|
||||
qtkeychainTranslator->load(qtkeychainTrFile, trPath);
|
||||
if (!qtkeychainTranslator->load(qtkeychainTrFile, trPath)) {
|
||||
qCDebug(lcApplication()) << "impossible to load QtKeychain translation catalog" << qtkeychainTrFile;
|
||||
}
|
||||
}
|
||||
if (!translator->isEmpty())
|
||||
installTranslator(translator);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
#include <QElapsedTimer>
|
||||
#include <QNetworkConfigurationManager>
|
||||
#include <QNetworkInformation>
|
||||
|
||||
#include "qtsingleapplication.h"
|
||||
|
||||
|
@ -110,7 +110,7 @@ protected slots:
|
|||
void slotCleanup();
|
||||
void slotAccountStateAdded(OCC::AccountState *accountState);
|
||||
void slotAccountStateRemoved(OCC::AccountState *accountState);
|
||||
void slotSystemOnlineConfigurationChanged(QNetworkConfiguration);
|
||||
void slotSystemOnlineConfigurationChanged();
|
||||
void slotGuiIsShowingSettings();
|
||||
|
||||
private:
|
||||
|
@ -152,7 +152,6 @@ private:
|
|||
|
||||
ClientProxy _proxy;
|
||||
|
||||
QNetworkConfigurationManager _networkConfigurationManager;
|
||||
QTimer _checkConnectionTimer;
|
||||
|
||||
QString _overrideServerUrl;
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
#include "creds/httpcredentials.h"
|
||||
#include "creds/keychainchunk.h"
|
||||
#include "accessmanager.h"
|
||||
#include "account.h"
|
||||
#include "configfile.h"
|
||||
#include "theme.h"
|
||||
#ifdef WITH_WEBENGINE
|
||||
#include "wizard/webview.h"
|
||||
#endif // WITH_WEBENGINE
|
||||
#include "webflowcredentialsdialog.h"
|
||||
#include "networkjobs.h"
|
||||
|
||||
#include <QAuthenticator>
|
||||
#include <QNetworkAccessManager>
|
||||
|
@ -12,15 +21,6 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "accessmanager.h"
|
||||
#include "account.h"
|
||||
#include "configfile.h"
|
||||
#include "theme.h"
|
||||
#ifdef WITH_WEBENGINE
|
||||
#include "wizard/webview.h"
|
||||
#endif // WITH_WEBENGINE
|
||||
#include "webflowcredentialsdialog.h"
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
namespace OCC {
|
||||
|
|
|
@ -22,13 +22,13 @@ WebFlowCredentialsDialog::WebFlowCredentialsDialog(Account *account, bool useFlo
|
|||
|
||||
_layout = new QVBoxLayout(this);
|
||||
int spacing = _layout->spacing();
|
||||
int margin = _layout->margin();
|
||||
auto margin = _layout->contentsMargins();
|
||||
_layout->setSpacing(0);
|
||||
_layout->setMargin(0);
|
||||
_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
_containerLayout = new QVBoxLayout(this);
|
||||
_containerLayout->setSpacing(spacing);
|
||||
_containerLayout->setMargin(margin);
|
||||
_containerLayout->setContentsMargins(margin);
|
||||
|
||||
_infoLabel = new QLabel();
|
||||
_infoLabel->setTextFormat(Qt::PlainText);
|
||||
|
|
|
@ -586,7 +586,7 @@ void EditLocallyJob::openFile()
|
|||
// In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl
|
||||
// from a separate thread, or, there will be a freeze. To avoid searching for a specific folder and checking
|
||||
// if the VFS is enabled - we just always call it from a separate thread.
|
||||
QtConcurrent::run([localFilePathUrl, this]() {
|
||||
auto futureResult = QtConcurrent::run([localFilePathUrl, this]() {
|
||||
if (!QDesktopServices::openUrl(localFilePathUrl)) {
|
||||
emit callShowError(tr("Could not open %1").arg(_fileName), tr("Please try again."));
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "editlocallymanager.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
namespace OCC {
|
||||
|
|
|
@ -16,7 +16,7 @@ import QtQuick 2.15
|
|||
import QtQuick.Window 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import com.nextcloud.desktopclient 1.0
|
||||
import Style 1.0
|
||||
|
|
|
@ -16,7 +16,7 @@ import QtQuick 2.15
|
|||
import QtQuick.Window 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import com.nextcloud.desktopclient 1.0
|
||||
import Style 1.0
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace {
|
|||
static const auto placeholderLinkShareId = QStringLiteral("__placeholderLinkShareId__");
|
||||
static const auto internalLinkShareId = QStringLiteral("__internalLinkShareId__");
|
||||
static const auto secureFileDropPlaceholderLinkShareId = QStringLiteral("__secureFileDropPlaceholderLinkShareId__");
|
||||
|
||||
}
|
||||
|
||||
namespace OCC
|
||||
|
@ -1363,7 +1364,7 @@ QString ShareModel::generatePassword()
|
|||
|
||||
for (const auto newChar : unsignedCharArray) {
|
||||
// Ensure byte is within asciiRange
|
||||
const auto byte = (newChar % (asciiRange + 1)) + asciiMin;
|
||||
const auto byte = QChar((newChar % (asciiRange + 1)) + asciiMin);
|
||||
passwd.append(byte);
|
||||
}
|
||||
|
||||
|
|
|
@ -557,17 +557,17 @@ int Folder::slotWipeErrorBlacklist()
|
|||
return _journal.wipeErrorBlacklist();
|
||||
}
|
||||
|
||||
void Folder::slotWatchedPathChanged(const QString &path, ChangeReason reason)
|
||||
void Folder::slotWatchedPathChanged(const QStringView &path, const ChangeReason reason)
|
||||
{
|
||||
if (!path.startsWith(this->path())) {
|
||||
qCDebug(lcFolder) << "Changed path is not contained in folder, ignoring:" << path;
|
||||
return;
|
||||
}
|
||||
|
||||
auto relativePath = path.midRef(this->path().size());
|
||||
auto relativePath = path.mid(this->path().size());
|
||||
|
||||
if (_vfs) {
|
||||
if (pathIsIgnored(path)) {
|
||||
if (pathIsIgnored(path.toString())) {
|
||||
const auto pinState = _vfs->pinState(relativePath.toString());
|
||||
if (!pinState || *pinState != PinState::Excluded) {
|
||||
if (!_vfs->setPinState(relativePath.toString(), PinState::Excluded)) {
|
||||
|
@ -601,7 +601,7 @@ void Folder::slotWatchedPathChanged(const QString &path, ChangeReason reason)
|
|||
// own process. Therefore nothing needs to be done here!
|
||||
#else
|
||||
// Use the path to figure out whether it was our own change
|
||||
if (_engine->wasFileTouched(path)) {
|
||||
if (_engine->wasFileTouched(path.toString())) {
|
||||
qCDebug(lcFolder) << "Changed path was touched by SyncEngine, ignoring:" << path;
|
||||
return;
|
||||
}
|
||||
|
@ -617,7 +617,7 @@ void Folder::slotWatchedPathChanged(const QString &path, ChangeReason reason)
|
|||
// an attribute change (pin state) that caused the notification
|
||||
bool spurious = false;
|
||||
if (record.isValid()
|
||||
&& !FileSystem::fileChanged(path, record._fileSize, record._modtime) && _vfs) {
|
||||
&& !FileSystem::fileChanged(path.toString(), record._fileSize, record._modtime) && _vfs) {
|
||||
spurious = true;
|
||||
|
||||
if (auto pinState = _vfs->pinState(relativePath.toString())) {
|
||||
|
@ -630,7 +630,7 @@ void Folder::slotWatchedPathChanged(const QString &path, ChangeReason reason)
|
|||
} else {
|
||||
spurious = false;
|
||||
}
|
||||
if (spurious && !_vfs->isPlaceHolderInSync(path)) {
|
||||
if (spurious && !_vfs->isPlaceHolderInSync(path.toString())) {
|
||||
spurious = false;
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ void Folder::slotWatchedPathChanged(const QString &path, ChangeReason reason)
|
|||
}
|
||||
warnOnNewExcludedItem(record, relativePath);
|
||||
|
||||
emit watchedFileChangedExternally(path);
|
||||
emit watchedFileChangedExternally(path.toString());
|
||||
|
||||
// Also schedule this folder for a sync, but only after some delay:
|
||||
// The sync will not upload files that were changed too recently.
|
||||
|
@ -1461,7 +1461,7 @@ void Folder::slotFolderConflicts(const QString &folder, const QStringList &confl
|
|||
r.setNumOldConflictItems(conflictPaths.size() - r.numNewConflictItems());
|
||||
}
|
||||
|
||||
void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringRef &path)
|
||||
void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringView &path)
|
||||
{
|
||||
// Never warn for items in the database
|
||||
if (record.isValid())
|
||||
|
@ -1713,8 +1713,8 @@ void Folder::removeLocalE2eFiles()
|
|||
const auto existingBlacklist = _journal.getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||
Q_ASSERT(ok);
|
||||
|
||||
const auto existingBlacklistSet = existingBlacklist.toSet();
|
||||
auto expandedBlacklistSet = existingBlacklist.toSet();
|
||||
const auto existingBlacklistSet = QSet<QString>{existingBlacklist.begin(), existingBlacklist.end()};
|
||||
auto expandedBlacklistSet = QSet<QString>{existingBlacklist.begin(), existingBlacklist.end()};
|
||||
|
||||
for (const auto &path : qAsConst(e2eFoldersToBlacklist)) {
|
||||
expandedBlacklistSet.insert(path);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QUuid>
|
||||
#include <QSet>
|
||||
|
||||
#include <set>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
@ -350,7 +352,7 @@ public slots:
|
|||
* changes. Needs to check whether this change should trigger a new
|
||||
* sync run to be scheduled.
|
||||
*/
|
||||
void slotWatchedPathChanged(const QString &path, OCC::Folder::ChangeReason reason);
|
||||
void slotWatchedPathChanged(const QStringView &path, const OCC::Folder::ChangeReason reason);
|
||||
|
||||
/*
|
||||
* Triggered when lock files were removed
|
||||
|
@ -441,7 +443,7 @@ private slots:
|
|||
void slotFolderConflicts(const QString &folder, const QStringList &conflictPaths);
|
||||
|
||||
/** Warn users if they create a file or folder that is selective-sync excluded */
|
||||
void warnOnNewExcludedItem(const OCC::SyncJournalFileRecord &record, const QStringRef &path);
|
||||
void warnOnNewExcludedItem(const OCC::SyncJournalFileRecord &record, const QStringView &path);
|
||||
|
||||
/** Warn users about an unreliable folder watcher */
|
||||
void slotWatcherUnreliable(const QString &message);
|
||||
|
|
|
@ -1319,7 +1319,7 @@ QStringList FolderMan::findFileInLocalFolders(const QString &relPath, const Acco
|
|||
continue;
|
||||
|
||||
QString path = folder->cleanPath() + '/';
|
||||
path += serverPath.midRef(folder->remotePathTrailingSlash().length());
|
||||
path += serverPath.mid(folder->remotePathTrailingSlash().length());
|
||||
if (QFile::exists(path)) {
|
||||
re.append(path);
|
||||
}
|
||||
|
|
|
@ -72,10 +72,8 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|||
QStyleOptionButton opt;
|
||||
static_cast<QStyleOption &>(opt) = option;
|
||||
opt.text = addFolderText();
|
||||
return QApplication::style()->sizeFromContents(
|
||||
QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text))
|
||||
.expandedTo(QApplication::globalStrut())
|
||||
+ QSize(0, margins);
|
||||
return QApplication::style()->sizeFromContents( QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text)) +
|
||||
QSize(0, margins);
|
||||
}
|
||||
|
||||
if (classif != FolderStatusModel::RootFolder) {
|
||||
|
@ -314,7 +312,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
|||
progressBarOpt.minimum = 0;
|
||||
progressBarOpt.maximum = 100;
|
||||
progressBarOpt.progress = overallPercent;
|
||||
progressBarOpt.orientation = Qt::Horizontal;
|
||||
progressBarOpt.state = QStyle::StateFlag::State_Horizontal;
|
||||
progressBarOpt.rect = QStyle::visualRect(option.direction, option.rect, progressBarRect);
|
||||
#ifdef Q_OS_MACOS
|
||||
backupStyle->drawControl(QStyle::CE_ProgressBar, &progressBarOpt, painter, option.widget);
|
||||
|
@ -322,7 +320,6 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
|||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOpt, painter, option.widget);
|
||||
#endif
|
||||
|
||||
|
||||
// Overall Progress Text
|
||||
QRect overallProgressRect;
|
||||
overallProgressRect.setTop(progressBarRect.bottom() + margin);
|
||||
|
@ -390,7 +387,7 @@ QRect FolderStatusDelegate::optionsButtonRect(QRect within, Qt::LayoutDirection
|
|||
QStyleOptionToolButton opt;
|
||||
int e = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize);
|
||||
opt.rect.setSize(QSize(e,e));
|
||||
QSize size = QApplication::style()->sizeFromContents(QStyle::CT_ToolButton, &opt, opt.rect.size()).expandedTo(QApplication::globalStrut());
|
||||
QSize size = QApplication::style()->sizeFromContents(QStyle::CT_ToolButton, &opt, opt.rect.size());
|
||||
|
||||
int margin = QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
|
||||
QRect r(QPoint(within.right() - size.width() - margin,
|
||||
|
@ -404,7 +401,7 @@ QRect FolderStatusDelegate::addButtonRect(QRect within, Qt::LayoutDirection dire
|
|||
QFontMetrics fm(qApp->font("QPushButton"));
|
||||
QStyleOptionButton opt;
|
||||
opt.text = addFolderText();
|
||||
QSize size = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text)).expandedTo(QApplication::globalStrut());
|
||||
QSize size = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text));
|
||||
QRect r(QPoint(within.left(), within.top() + within.height() / 2 - size.height() / 2), size);
|
||||
return QStyle::visualRect(direction, within, r);
|
||||
}
|
||||
|
|
|
@ -921,12 +921,13 @@ void FolderStatusModel::slotApplySelectiveSync()
|
|||
const auto blackList = createBlackList(folderInfo, oldBlackList);
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
|
||||
auto blackListSet = blackList.toSet();
|
||||
auto oldBlackListSet = oldBlackList.toSet();
|
||||
auto blackListSet = QSet<QString>{blackList.begin(), blackList.end()};
|
||||
auto oldBlackListSet = QSet<QString>{oldBlackList.begin(), oldBlackList.end()};
|
||||
|
||||
// The folders that were undecided or blacklisted and that are now checked should go on the white list.
|
||||
// The user confirmed them already just now.
|
||||
const auto toAddToWhiteList = ((oldBlackListSet + folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok).toSet()) - blackListSet).values();
|
||||
const auto selectiveSyncList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncUndecidedList, &ok);
|
||||
const auto toAddToWhiteList = ((oldBlackListSet + QSet<QString>{selectiveSyncList.begin(), selectiveSyncList.end()}) - blackListSet).values();
|
||||
|
||||
if (!toAddToWhiteList.isEmpty()) {
|
||||
auto whiteList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList, &ok);
|
||||
|
|
|
@ -193,7 +193,7 @@ void FolderWatcher::changeDetected(const QStringList &paths)
|
|||
// - why do we skip the file altogether instead of e.g. reducing the upload frequency?
|
||||
|
||||
// Check if the same path was reported within the last second.
|
||||
const auto pathsSet = paths.toSet();
|
||||
const auto pathsSet = QSet<QString>{paths.begin(), paths.end()};
|
||||
if (pathsSet == _lastPaths && _timer.elapsed() < 1000) {
|
||||
// the same path was reported within the last second. Skip.
|
||||
return;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <QEvent>
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ void GeneralSettings::slotUpdateInfo()
|
|||
if (ocupdater) {
|
||||
connect(ocupdater, &OCUpdater::downloadStateChanged, this, &GeneralSettings::slotUpdateInfo, Qt::UniqueConnection);
|
||||
connect(_ui->restartButton, &QAbstractButton::clicked, ocupdater, &OCUpdater::slotStartInstaller, Qt::UniqueConnection);
|
||||
connect(_ui->restartButton, &QAbstractButton::clicked, qApp, &QApplication::quit, Qt::UniqueConnection);
|
||||
//connect(_ui->restartButton, &QAbstractButton::clicked, qApp, &QApplication::quit, Qt::UniqueConnection);
|
||||
|
||||
QString status = ocupdater->statusString(OCUpdater::UpdateStatusStringFormat::Html);
|
||||
Theme::replaceLinkColorStringBackgroundAware(status);
|
||||
|
|
|
@ -52,19 +52,15 @@ void warnSystray()
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-gpu --no-sandbox");
|
||||
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
SetDllDirectory(L"");
|
||||
qputenv("QML_IMPORT_PATH", (QDir::currentPath() + QStringLiteral("/qml")).toLatin1());
|
||||
#endif
|
||||
|
||||
Q_INIT_RESOURCE(resources);
|
||||
Q_INIT_RESOURCE(theme);
|
||||
|
||||
// OpenSSL 1.1.0: No explicit initialisation or de-initialisation is necessary.
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||
#ifdef Q_OS_MAC
|
||||
Mac::CocoaInitializer cocoaInit; // RIIA
|
||||
#endif
|
||||
|
|
|
@ -62,7 +62,7 @@ NetworkSettings::NetworkSettings(QWidget *parent)
|
|||
|
||||
connect(_ui->typeComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||
&NetworkSettings::saveProxySettings);
|
||||
connect(_ui->proxyButtonGroup, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this,
|
||||
connect(_ui->proxyButtonGroup, &QButtonGroup::buttonClicked, this,
|
||||
&NetworkSettings::saveProxySettings);
|
||||
connect(_ui->hostLineEdit, &QLineEdit::editingFinished, this, &NetworkSettings::saveProxySettings);
|
||||
connect(_ui->userLineEdit, &QLineEdit::editingFinished, this, &NetworkSettings::saveProxySettings);
|
||||
|
|
|
@ -102,7 +102,7 @@ ownCloudGui::ownCloudGui(Application *parent)
|
|||
this, &ownCloudGui::slotShowSettings);
|
||||
|
||||
connect(_tray.data(), &Systray::shutdown,
|
||||
this, &ownCloudGui::slotShutdown);
|
||||
this, &QCoreApplication::quit);
|
||||
|
||||
ProgressDispatcher *pd = ProgressDispatcher::instance();
|
||||
connect(pd, &ProgressDispatcher::progressInfo, this,
|
||||
|
@ -137,8 +137,7 @@ ownCloudGui::ownCloudGui(Application *parent)
|
|||
qmlRegisterUncreatableType<UserStatus>("com.nextcloud.desktopclient", 1, 0, "UserStatus", "Access to Status enum");
|
||||
qmlRegisterUncreatableType<Sharee>("com.nextcloud.desktopclient", 1, 0, "Sharee", "Access to Type enum");
|
||||
|
||||
qRegisterMetaTypeStreamOperators<Emoji>();
|
||||
|
||||
qRegisterMetaType<ActivityListModel *>("ActivityListModel*");
|
||||
qRegisterMetaType<UnifiedSearchResultsListModel *>("UnifiedSearchResultsListModel*");
|
||||
qRegisterMetaType<UserStatus>("UserStatus");
|
||||
qRegisterMetaType<SharePtr>("SharePtr");
|
||||
|
@ -600,13 +599,11 @@ void ownCloudGui::slotShutdown()
|
|||
{
|
||||
// explicitly close windows. This is somewhat of a hack to ensure
|
||||
// that saving the geometries happens ASAP during a OS shutdown
|
||||
|
||||
// those do delete on close
|
||||
if (!_settingsDialog.isNull())
|
||||
_settingsDialog->close();
|
||||
if (!_logBrowser.isNull())
|
||||
_logBrowser->deleteLater();
|
||||
_app->quit();
|
||||
}
|
||||
|
||||
void ownCloudGui::slotToggleLogBrowser()
|
||||
|
|
|
@ -162,7 +162,7 @@ void OwncloudSetupWizard::slotCheckServer(const QString &urlString)
|
|||
|
||||
// And also reset the QSslConfiguration, for the same reason (#6832)
|
||||
// Here the client certificate is added, if any. Later it'll be in HttpCredentials
|
||||
account->setSslConfiguration(QSslConfiguration());
|
||||
account->setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
||||
auto sslConfiguration = account->getOrCreateSslConfig(); // let Account set defaults
|
||||
if (!_ocWizard->_clientSslCertificate.isNull()) {
|
||||
sslConfiguration.setLocalCertificate(_ocWizard->_clientSslCertificate);
|
||||
|
|
|
@ -21,7 +21,11 @@
|
|||
|
||||
#include <QApplication>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <qt6keychain/keychain.h>
|
||||
#else
|
||||
#include <qt5keychain/keychain.h>
|
||||
#endif
|
||||
|
||||
using namespace OCC;
|
||||
using namespace QKeychain;
|
||||
|
|
|
@ -518,7 +518,8 @@ void SelectiveSyncDialog::accept()
|
|||
{
|
||||
if (_folder) {
|
||||
bool ok = false;
|
||||
auto oldBlackListSet = _folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok).toSet();
|
||||
auto oldBlackList = _folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||
auto oldBlackListSet = QSet<QString>{oldBlackList.begin(), oldBlackList.end()};
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
@ -532,7 +533,7 @@ void SelectiveSyncDialog::accept()
|
|||
|
||||
//The part that changed should not be read from the DB on next sync because there might be new folders
|
||||
// (the ones that are no longer in the blacklist)
|
||||
auto blackListSet = blackList.toSet();
|
||||
auto blackListSet = QSet<QString>{blackList.begin(), blackList.end()};
|
||||
auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||
foreach (const auto &it, changes) {
|
||||
_folder->journalDb()->schedulePathForRemoteDiscovery(it);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QQuickView>
|
||||
#include <QActionGroup>
|
||||
|
||||
namespace {
|
||||
const QString TOOLBAR_CSS()
|
||||
|
@ -148,7 +149,7 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
|
|||
addAction(showLogWindow);
|
||||
|
||||
auto *showLogWindow2 = new QAction(this);
|
||||
showLogWindow2->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
|
||||
showLogWindow2->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_L));
|
||||
connect(showLogWindow2, &QAction::triggered, gui, &ownCloudGui::slotToggleLogBrowser);
|
||||
addAction(showLogWindow2);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace OCC {
|
|||
/**
|
||||
* When a share is modified, we need to tell the folders so they can adjust overlay icons
|
||||
*/
|
||||
static void updateFolder(const AccountPtr &account, const QString &path)
|
||||
static void updateFolder(const AccountPtr &account, QStringView path)
|
||||
{
|
||||
foreach (Folder *f, FolderMan::instance()->map()) {
|
||||
if (f->accountState()->account() != account)
|
||||
|
@ -41,7 +41,7 @@ static void updateFolder(const AccountPtr &account, const QString &path)
|
|||
if (path.startsWith(folderPath) && (path == folderPath || folderPath.endsWith('/') || path[folderPath.size()] == '/')) {
|
||||
// Workaround the fact that the server does not invalidate the etags of parent directories
|
||||
// when something is shared.
|
||||
auto relative = path.midRef(f->remotePathTrailingSlash().length());
|
||||
auto relative = path.mid(f->remotePathTrailingSlash().length());
|
||||
f->journalDb()->schedulePathForRemoteDiscovery(relative.toString());
|
||||
|
||||
// Schedule a sync so it can update the remote permission flag and let the socket API
|
||||
|
|
|
@ -300,7 +300,7 @@ SocketApi::SocketApi(QObject *parent)
|
|||
qCDebug(lcSocketApi) << "creating" << info.dir().path() << result;
|
||||
if (result) {
|
||||
QFile::setPermissions(socketPath,
|
||||
QFile::Permissions(QFile::ReadOwner + QFile::WriteOwner + QFile::ExeOwner));
|
||||
QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ void SocketApi::slotReadSocket()
|
|||
const QString line = QString::fromUtf8(socket->readLine().trimmed()).normalized(QString::NormalizationForm_C);
|
||||
qCDebug(lcSocketApi) << "Received SocketAPI message <--" << line << "from" << socket;
|
||||
const int argPos = line.indexOf(QLatin1Char(':'));
|
||||
const QByteArray command = line.midRef(0, argPos).toUtf8().toUpper();
|
||||
const QByteArray command = line.mid(0, argPos).toUtf8().toUpper();
|
||||
const int indexOfMethod = [&] {
|
||||
QByteArray functionWithArguments = QByteArrayLiteral("command_");
|
||||
if (command.startsWith("ASYNC_")) {
|
||||
|
@ -394,7 +394,7 @@ void SocketApi::slotReadSocket()
|
|||
} else {
|
||||
functionWithArguments += command + QByteArrayLiteral("(QString,SocketListener*)");
|
||||
}
|
||||
Q_ASSERT(staticQtMetaObject.normalizedSignature(functionWithArguments) == functionWithArguments);
|
||||
Q_ASSERT(staticMetaObject.normalizedSignature(functionWithArguments) == functionWithArguments);
|
||||
const auto out = staticMetaObject.indexOfMethod(functionWithArguments);
|
||||
if (out == -1) {
|
||||
listener->sendError(QStringLiteral("Function %1 not found").arg(QString::fromUtf8(functionWithArguments)));
|
||||
|
@ -403,7 +403,7 @@ void SocketApi::slotReadSocket()
|
|||
return out;
|
||||
}();
|
||||
|
||||
const auto argument = argPos != -1 ? line.midRef(argPos + 1) : QStringRef();
|
||||
const auto argument = argPos != -1 ? line.mid(argPos + 1) : QStringView();
|
||||
if (command.startsWith("ASYNC_")) {
|
||||
auto arguments = argument.split('|');
|
||||
if (arguments.size() != 2) {
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
class QUrl;
|
||||
class QLocalSocket;
|
||||
class QStringList;
|
||||
class QFileInfo;
|
||||
|
||||
namespace OCC
|
||||
|
|
|
@ -80,12 +80,12 @@ void SyncRunFileLog::start(const QString &folderPath)
|
|||
|
||||
|
||||
if (!exists) {
|
||||
_out << folderPath << endl;
|
||||
_out << folderPath << Qt::endl;
|
||||
// We are creating a new file, add the note.
|
||||
_out << "# timestamp | duration | file | instruction | dir | modtime | etag | "
|
||||
"size | fileId | status | errorString | http result code | "
|
||||
"other size | other modtime | X-Request-ID"
|
||||
<< endl;
|
||||
<< Qt::endl;
|
||||
|
||||
FileSystem::setFileHidden(filename, true);
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ void SyncRunFileLog::start(const QString &folderPath)
|
|||
|
||||
_totalDuration.start();
|
||||
_lapDuration.start();
|
||||
_out << "#=#=#=# Syncrun started " << dateTimeStr(QDateTime::currentDateTimeUtc()) << endl;
|
||||
_out << "#=#=#=# Syncrun started " << dateTimeStr(QDateTime::currentDateTimeUtc()) << Qt::endl;
|
||||
}
|
||||
void SyncRunFileLog::logItem(const SyncFileItem &item)
|
||||
{
|
||||
|
@ -132,21 +132,21 @@ void SyncRunFileLog::logItem(const SyncFileItem &item)
|
|||
_out << QString::number(item._previousModtime) << L;
|
||||
_out << item._requestId << L;
|
||||
|
||||
_out << endl;
|
||||
_out << Qt::endl;
|
||||
}
|
||||
|
||||
void SyncRunFileLog::logLap(const QString &name)
|
||||
{
|
||||
_out << "#=#=#=#=# " << name << " " << dateTimeStr(QDateTime::currentDateTimeUtc())
|
||||
<< " (last step: " << _lapDuration.restart() << " msec"
|
||||
<< ", total: " << _totalDuration.elapsed() << " msec)" << endl;
|
||||
<< ", total: " << _totalDuration.elapsed() << " msec)" << Qt::endl;
|
||||
}
|
||||
|
||||
void SyncRunFileLog::finish()
|
||||
{
|
||||
_out << "#=#=#=# Syncrun finished " << dateTimeStr(QDateTime::currentDateTimeUtc())
|
||||
<< " (last step: " << _lapDuration.elapsed() << " msec"
|
||||
<< ", total: " << _totalDuration.elapsed() << " msec)" << endl;
|
||||
<< ", total: " << _totalDuration.elapsed() << " msec)" << Qt::endl;
|
||||
_file->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,8 @@ void Systray::create()
|
|||
if (_trayEngine) {
|
||||
if (!AccountManager::instance()->accounts().isEmpty()) {
|
||||
_trayEngine->rootContext()->setContextProperty("activityModel", UserModel::instance()->currentActivityModel());
|
||||
} else {
|
||||
_trayEngine->rootContext()->setContextProperty("activityModel", &_fakeActivityModel);
|
||||
}
|
||||
|
||||
QQmlComponent trayWindowComponent(trayEngine(), QStringLiteral("qrc:/qml/src/gui/tray/Window.qml"));
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#ifndef SYSTRAY_H
|
||||
#define SYSTRAY_H
|
||||
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include "accountmanager.h"
|
||||
#include "tray/usermodel.h"
|
||||
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QQmlNetworkAccessManagerFactory>
|
||||
#include <QStringListModel>
|
||||
|
||||
class QScreen;
|
||||
class QQmlApplicationEngine;
|
||||
|
@ -189,6 +189,8 @@ private:
|
|||
QSet<qlonglong> _callsAlreadyNotified;
|
||||
QPointer<QObject> _editFileLocallyLoadingDialog;
|
||||
QVector<QQuickWindow*> _fileDetailDialogs;
|
||||
|
||||
QStringListModel _fakeActivityModel;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -2,8 +2,8 @@ import QtQml 2.15
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Style 1.0
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import com.nextcloud.desktopclient 1.0
|
||||
|
||||
RowLayout {
|
||||
|
|
|
@ -20,7 +20,7 @@ import com.nextcloud.desktopclient 1.0
|
|||
import QtQuick.Layouts 1.2
|
||||
import QtMultimedia 5.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
|
|
|
@ -18,7 +18,7 @@ import QtQuick 2.15
|
|||
import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
// Custom qml modules are in /theme (and included by resources.qrc)
|
||||
import Style 1.0
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.0
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Style 1.0
|
||||
|
||||
HeaderButton {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import QtQml 2.15
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Style 1.0
|
||||
|
||||
import com.nextcloud.desktopclient 1.0
|
||||
|
|
|
@ -16,7 +16,7 @@ import QtQml 2.15
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import QtQml 2.15
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Style 1.0
|
||||
|
||||
RowLayout {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import QtQml 2.15
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import QtQml 2.15
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import QtQuick 2.15
|
|||
import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Qt.labs.platform 1.1 as NativeDialogs
|
||||
|
||||
import "../"
|
||||
|
@ -485,7 +485,7 @@ ApplicationWindow {
|
|||
Layout.leftMargin: Style.trayHorizontalMargin
|
||||
verticalAlignment: Qt.AlignCenter
|
||||
cache: false
|
||||
source: UserModel.currentUser.avatar != "" ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"
|
||||
source: (UserModel.currentUser && UserModel.currentUser.avatar !== "") ? UserModel.currentUser.avatar : "image://avatars/fallbackWhite"
|
||||
Layout.preferredHeight: Style.accountAvatarSize
|
||||
Layout.preferredWidth: Style.accountAvatarSize
|
||||
|
||||
|
@ -494,7 +494,7 @@ ApplicationWindow {
|
|||
|
||||
Rectangle {
|
||||
id: currentAccountStatusIndicatorBackground
|
||||
visible: UserModel.currentUser.isConnected
|
||||
visible: UserModel.currentUser && UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
width: Style.accountAvatarStateIndicatorSize + + Style.trayFolderStatusIndicatorSizeOffset
|
||||
height: width
|
||||
|
@ -506,7 +506,7 @@ ApplicationWindow {
|
|||
|
||||
Rectangle {
|
||||
id: currentAccountStatusIndicatorMouseHover
|
||||
visible: UserModel.currentUser.isConnected
|
||||
visible: UserModel.currentUser && UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
width: Style.accountAvatarStateIndicatorSize + + Style.trayFolderStatusIndicatorSizeOffset
|
||||
height: width
|
||||
|
@ -519,9 +519,9 @@ ApplicationWindow {
|
|||
|
||||
Image {
|
||||
id: currentAccountStatusIndicator
|
||||
visible: UserModel.currentUser.isConnected
|
||||
visible: UserModel.currentUser && UserModel.currentUser.isConnected
|
||||
&& UserModel.currentUser.serverHasUserStatus
|
||||
source: UserModel.currentUser.statusIcon
|
||||
source: UserModel.currentUser ? UserModel.currentUser.statusIcon : ""
|
||||
cache: false
|
||||
x: currentAccountStatusIndicatorBackground.x + 1
|
||||
y: currentAccountStatusIndicatorBackground.y + 1
|
||||
|
@ -545,7 +545,7 @@ ApplicationWindow {
|
|||
id: currentAccountUser
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.name
|
||||
text: UserModel.currentUser ? UserModel.currentUser.name : ""
|
||||
elide: Text.ElideRight
|
||||
color: Style.currentUserHeaderTextColor
|
||||
|
||||
|
@ -557,7 +557,7 @@ ApplicationWindow {
|
|||
id: currentAccountServer
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.server
|
||||
text: UserModel.currentUser ? UserModel.currentUser.server : ""
|
||||
elide: Text.ElideRight
|
||||
color: Style.currentUserHeaderTextColor
|
||||
visible: UserModel.numUsers() > 1
|
||||
|
@ -565,26 +565,26 @@ ApplicationWindow {
|
|||
|
||||
RowLayout {
|
||||
id: currentUserStatus
|
||||
visible: UserModel.currentUser.isConnected &&
|
||||
visible: UserModel.currentUser && UserModel.currentUser.isConnected &&
|
||||
UserModel.currentUser.serverHasUserStatus
|
||||
spacing: Style.accountLabelsSpacing
|
||||
width: parent.width
|
||||
|
||||
EnforcedPlainTextLabel {
|
||||
id: emoji
|
||||
visible: UserModel.currentUser.statusEmoji !== ""
|
||||
visible: UserModel.currentUser && UserModel.currentUser.statusEmoji !== ""
|
||||
width: Style.userStatusEmojiSize
|
||||
text: UserModel.currentUser.statusEmoji
|
||||
text: UserModel.currentUser ? UserModel.currentUser.statusEmoji : ""
|
||||
}
|
||||
EnforcedPlainTextLabel {
|
||||
id: message
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
visible: UserModel.currentUser.statusMessage !== ""
|
||||
visible: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""
|
||||
width: Style.currentAccountLabelWidth
|
||||
text: UserModel.currentUser.statusMessage !== ""
|
||||
text: UserModel.currentUser && UserModel.currentUser.statusMessage !== ""
|
||||
? UserModel.currentUser.statusMessage
|
||||
: UserModel.currentUser.server
|
||||
: UserModel.currentUser ? UserModel.currentUser.server : ""
|
||||
elide: Text.ElideRight
|
||||
color: Style.currentUserHeaderTextColor
|
||||
font.pixelSize: Style.subLinePixelSize
|
||||
|
@ -639,7 +639,7 @@ ApplicationWindow {
|
|||
HeaderButton {
|
||||
id: trayWindowTalkButton
|
||||
|
||||
visible: UserModel.currentUser.serverHasTalk
|
||||
visible: UserModel.currentUser && UserModel.currentUser.serverHasTalk
|
||||
icon.source: "qrc:///client/theme/white/talk-app.svg"
|
||||
icon.color: Style.currentUserHeaderTextColor
|
||||
onClicked: UserModel.openCurrentAccountTalk()
|
||||
|
@ -753,6 +753,18 @@ ApplicationWindow {
|
|||
isSearchInProgress: UserModel.currentUser.unifiedSearchResultsListModel.isSearchInProgress
|
||||
onTextEdited: { UserModel.currentUser.unifiedSearchResultsListModel.searchTerm = trayWindowUnifiedSearchInputContainer.text }
|
||||
onClearText: { UserModel.currentUser.unifiedSearchResultsListModel.searchTerm = "" }
|
||||
|
||||
Rectangle {
|
||||
id: bottomUnifiedSearchInputSeparator
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
height: 1
|
||||
color: Style.menuBorder
|
||||
visible: trayWindowMainItem.isUnifiedSearchActive
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBox {
|
||||
|
@ -860,6 +872,16 @@ ApplicationWindow {
|
|||
anchors.top: trayWindowUnifiedSearchInputContainer.bottom
|
||||
anchors.left: trayWindowMainItem.left
|
||||
anchors.right: trayWindowMainItem.right
|
||||
|
||||
Rectangle {
|
||||
id: syncStatusSeparator
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 1
|
||||
|
||||
height: 1
|
||||
color: Style.menuBorder
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
@ -939,7 +961,7 @@ ApplicationWindow {
|
|||
}
|
||||
Connections {
|
||||
target: activityModel
|
||||
onInteractiveActivityReceived: {
|
||||
function onInteractiveActivityReceived() {
|
||||
if (!activityList.atYBeginning) {
|
||||
newActivitiesButtonLoader.active = true;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "talkreply.h"
|
||||
|
||||
#include "accountstate.h"
|
||||
#include "networkjobs.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
|
|
@ -89,7 +89,7 @@ UpdateInfo UpdateInfo::parseString(const QString &xml, bool *ok)
|
|||
QDomDocument doc;
|
||||
if (!doc.setContent(xml, false, &errorMsg, &errorLine, &errorCol)) {
|
||||
qCWarning(lcUpdater).noquote().nospace() << errorMsg << " at " << errorLine << "," << errorCol
|
||||
<< "\n" << xml.splitRef("\n").value(errorLine-1) << "\n"
|
||||
<< "\n" << xml.split("\n").value(errorLine-1) << "\n"
|
||||
<< QString(" ").repeated(errorCol - 1) << "^\n"
|
||||
<< "->" << xml << "<-";
|
||||
if (ok)
|
||||
|
|
|
@ -27,7 +27,7 @@ void LinkLabel::setUrl(const QUrl &url)
|
|||
this->url = url;
|
||||
}
|
||||
|
||||
void LinkLabel::enterEvent(QEvent * /*event*/)
|
||||
void LinkLabel::enterEvent(QEnterEvent * /*event*/)
|
||||
{
|
||||
setFontUnderline(true);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
|
|
|
@ -31,7 +31,7 @@ signals:
|
|||
void clicked();
|
||||
|
||||
protected:
|
||||
void enterEvent(QEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ void PostfixLineEdit::setPostfix(const QString &postfix)
|
|||
_postfix = postfix;
|
||||
QFontMetricsF fm(font());
|
||||
QMargins tm = textMargins();
|
||||
tm.setRight(tm.right() + qRound(fm.width(_postfix)) + verticalMargin);
|
||||
tm.setRight(tm.right() + qRound(fm.horizontalAdvance(_postfix)) + verticalMargin);
|
||||
setTextMargins(tm);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ void PostfixLineEdit::paintEvent(QPaintEvent *pe)
|
|||
//
|
||||
p.setPen(palette().color(QPalette::Disabled, QPalette::Text));
|
||||
QFontMetricsF fm(font());
|
||||
int start = rect().right() - qRound(fm.width(_postfix));
|
||||
int start = rect().right() - qRound(fm.horizontalAdvance(_postfix));
|
||||
QStyleOptionFrame panel;
|
||||
initStyleOption(&panel);
|
||||
QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
|
||||
|
|
|
@ -86,7 +86,7 @@ WebView::WebView(QWidget *parent)
|
|||
const QString userAgent(Utility::userAgentString());
|
||||
_profile->setHttpUserAgent(userAgent);
|
||||
QWebEngineProfile::defaultProfile()->setHttpUserAgent(userAgent);
|
||||
_profile->setRequestInterceptor(_interceptor);
|
||||
_profile->setUrlRequestInterceptor(_interceptor);
|
||||
_profile->installUrlSchemeHandler("nc", _schemeHandler);
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,7 +26,7 @@ WebViewPage::WebViewPage(QWidget *parent)
|
|||
_webView = new WebView(this);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(_webView, 1);
|
||||
setLayout(layout);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
project(libsync)
|
||||
find_package(KF5Archive REQUIRED)
|
||||
find_package(KF6Archive REQUIRED)
|
||||
include(DefinePlatformDefaults)
|
||||
|
||||
set(CMAKE_AUTOMOC TRUE)
|
||||
|
@ -195,7 +195,7 @@ IF (NOT APPLE)
|
|||
)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS WebSockets Xml Sql)
|
||||
find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS WebSockets Xml Sql)
|
||||
|
||||
add_library(nextcloudsync SHARED ${libsync_SRCS})
|
||||
add_library(Nextcloud::sync ALIAS nextcloudsync)
|
||||
|
@ -206,12 +206,13 @@ target_link_libraries(nextcloudsync
|
|||
OpenSSL::Crypto
|
||||
OpenSSL::SSL
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
Qt5::WebSockets
|
||||
Qt5::Xml
|
||||
Qt5::Sql
|
||||
KF5::Archive
|
||||
Qt::Core
|
||||
Qt::Network
|
||||
Qt::WebSockets
|
||||
Qt::Xml
|
||||
Qt::Sql
|
||||
KF6::Archive
|
||||
Qt::Core5Compat
|
||||
)
|
||||
|
||||
target_compile_features(nextcloudsync
|
||||
|
@ -221,11 +222,9 @@ target_compile_features(nextcloudsync
|
|||
|
||||
target_compile_definitions(nextcloudsync PRIVATE OPENSSL_SUPPRESS_DEPRECATED)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Gui Widgets Svg)
|
||||
target_link_libraries(nextcloudsync PUBLIC Qt5::Gui Qt5::Widgets Qt5::Svg)
|
||||
|
||||
if (NOT TOKEN_AUTH_ONLY)
|
||||
target_link_libraries(nextcloudsync PUBLIC qt5keychain)
|
||||
find_package(Qt${QT_MAJOR_VERSION} COMPONENTS REQUIRED Widgets Svg)
|
||||
target_link_libraries(nextcloudsync PUBLIC Qt::Widgets Qt::Svg Qt${QT_MAJOR_VERSION}Keychain::Qt${QT_MAJOR_VERSION}Keychain)
|
||||
endif()
|
||||
|
||||
if(Inotify_FOUND)
|
||||
|
|
|
@ -408,7 +408,7 @@ QString extractErrorMessage(const QByteArray &errorResponse)
|
|||
{
|
||||
QXmlStreamReader reader(errorResponse);
|
||||
reader.readNextStartElement();
|
||||
if (reader.name() != "error") {
|
||||
if (reader.name() != QStringLiteral("error")) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include "accountfwd.h"
|
||||
#include "common/asserts.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
|
@ -23,8 +27,6 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
#include "accountfwd.h"
|
||||
#include "common/asserts.h"
|
||||
|
||||
class QUrl;
|
||||
|
||||
|
|
|
@ -20,7 +20,11 @@
|
|||
#include <QSslConfiguration>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkCookieJar>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QNetworkConfiguration>
|
||||
#else
|
||||
#include <QNetworkInformation>
|
||||
#endif
|
||||
#include <QUuid>
|
||||
|
||||
#include "cookiejar.h"
|
||||
|
@ -42,8 +46,8 @@ AccessManager::AccessManager(QObject *parent)
|
|||
setProxy(proxy);
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_LINUX
|
||||
// Attempt to workaround for https://github.com/owncloud/client/issues/3969
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_OS_LINUX)
|
||||
// Atempt to workaround for https://github.com/owncloud/client/issues/3969
|
||||
setConfiguration(QNetworkConfiguration());
|
||||
#endif
|
||||
setCookieJar(new CookieJar);
|
||||
|
|
|
@ -52,7 +52,13 @@
|
|||
#include <QHttpMultiPart>
|
||||
|
||||
#include <qsslconfiguration.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <qt6keychain/keychain.h>
|
||||
#else
|
||||
#include <qt5keychain/keychain.h>
|
||||
#endif
|
||||
|
||||
#include "creds/abstractcredentials.h"
|
||||
|
||||
using namespace QKeychain;
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#ifndef SERVERCONNECTION_H
|
||||
#define SERVERCONNECTION_H
|
||||
|
||||
#include "capabilities.h"
|
||||
#include "clientsideencryption.h"
|
||||
#include "clientstatusreporting.h"
|
||||
#include "common/utility.h"
|
||||
#include "syncfileitem.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QUrl>
|
||||
#include <QNetworkCookie>
|
||||
|
@ -26,17 +32,13 @@
|
|||
#include <QSslCipher>
|
||||
#include <QSslError>
|
||||
#include <QSharedPointer>
|
||||
#include <QHttpMultiPart>
|
||||
#include <QTimer>
|
||||
|
||||
#ifndef TOKEN_AUTH_ONLY
|
||||
#include <QPixmap>
|
||||
#endif
|
||||
|
||||
#include "capabilities.h"
|
||||
#include "clientsideencryption.h"
|
||||
#include "clientstatusreporting.h"
|
||||
#include "common/utility.h"
|
||||
#include "syncfileitem.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QSettings;
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#include <common/checksums.h>
|
||||
#include "wordlist.h"
|
||||
|
||||
#include <qt5keychain/keychain.h>
|
||||
#include <qt6keychain/keychain.h>
|
||||
|
||||
#include <KCompressionDevice>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLoggingCategory>
|
||||
|
@ -37,8 +39,6 @@
|
|||
#include <QJsonArray>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include <KCompressionDevice>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
@ -1195,7 +1195,7 @@ void ClientSideEncryption::getUsersPublicKeyFromServer(const AccountPtr &account
|
|||
const auto job = new JsonApiJob(account, e2eeBaseUrl(account) + QStringLiteral("public-key"), this);
|
||||
connect(job, &JsonApiJob::jsonReceived, [this, account, userIds](const QJsonDocument &doc, int retCode) {
|
||||
if (retCode == 200) {
|
||||
QHash<QString, QSslCertificate> results;
|
||||
QHash<QString, NextcloudSslCertificate> results;
|
||||
const auto publicKeys = doc.object()[QStringLiteral("ocs")].toObject()[QStringLiteral("data")].toObject()[QStringLiteral("public-keys")].toObject();
|
||||
for (const auto &userId : publicKeys.keys()) {
|
||||
if (userIds.contains(userId)) {
|
||||
|
@ -2302,4 +2302,57 @@ bool EncryptionHelper::StreamingDecryptor::isFinished() const
|
|||
{
|
||||
return _isFinished;
|
||||
}
|
||||
|
||||
NextcloudSslCertificate::NextcloudSslCertificate() = default;
|
||||
|
||||
NextcloudSslCertificate::NextcloudSslCertificate(const NextcloudSslCertificate &other) = default;
|
||||
|
||||
NextcloudSslCertificate::NextcloudSslCertificate(const QSslCertificate &certificate)
|
||||
: _certificate(certificate)
|
||||
{
|
||||
}
|
||||
|
||||
NextcloudSslCertificate::NextcloudSslCertificate(QSslCertificate &&certificate)
|
||||
: _certificate(std::move(certificate))
|
||||
{
|
||||
}
|
||||
|
||||
OCC::NextcloudSslCertificate::operator QSslCertificate()
|
||||
{
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
QSslCertificate &NextcloudSslCertificate::get()
|
||||
{
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
const QSslCertificate &NextcloudSslCertificate::get() const
|
||||
{
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
NextcloudSslCertificate &NextcloudSslCertificate::operator=(const NextcloudSslCertificate &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
_certificate = other._certificate;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NextcloudSslCertificate &NextcloudSslCertificate::operator=(NextcloudSslCertificate &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
_certificate = std::move(other._certificate);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
OCC::NextcloudSslCertificate::operator QSslCertificate() const
|
||||
{
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef CLIENTSIDEENCRYPTION_H
|
||||
#define CLIENTSIDEENCRYPTION_H
|
||||
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include "clientsideencryptionprimitives.h"
|
||||
#include "accountfwd.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
@ -12,12 +15,10 @@
|
|||
#include <QFile>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "accountfwd.h"
|
||||
#include "networkjobs.h"
|
||||
|
||||
namespace QKeychain {
|
||||
class Job;
|
||||
class WritePasswordJob;
|
||||
|
@ -124,6 +125,27 @@ private:
|
|||
};
|
||||
}
|
||||
|
||||
class OWNCLOUDSYNC_EXPORT NextcloudSslCertificate
|
||||
{
|
||||
public:
|
||||
NextcloudSslCertificate();
|
||||
NextcloudSslCertificate(const NextcloudSslCertificate &other);
|
||||
NextcloudSslCertificate(const QSslCertificate &certificate);
|
||||
NextcloudSslCertificate(QSslCertificate &&certificate);
|
||||
|
||||
operator QSslCertificate();
|
||||
operator QSslCertificate() const;
|
||||
|
||||
QSslCertificate& get();
|
||||
const QSslCertificate &get() const;
|
||||
|
||||
NextcloudSslCertificate &operator=(const NextcloudSslCertificate &other);
|
||||
NextcloudSslCertificate &operator=(NextcloudSslCertificate &&other);
|
||||
|
||||
private:
|
||||
QSslCertificate _certificate;
|
||||
};
|
||||
|
||||
class OWNCLOUDSYNC_EXPORT ClientSideEncryption : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -143,7 +165,7 @@ signals:
|
|||
void mnemonicDeleted();
|
||||
void publicKeyDeleted();
|
||||
void certificateFetchedFromKeychain(QSslCertificate certificate);
|
||||
void certificatesFetchedFromServer(const QHash<QString, QSslCertificate> &results);
|
||||
void certificatesFetchedFromServer(const QHash<QString, OCC::NextcloudSslCertificate> &results);
|
||||
void certificateWriteComplete(const QSslCertificate &certificate);
|
||||
|
||||
public:
|
||||
|
@ -153,9 +175,9 @@ public:
|
|||
public slots:
|
||||
void initialize(const OCC::AccountPtr &account);
|
||||
void forgetSensitiveData(const OCC::AccountPtr &account);
|
||||
void getUsersPublicKeyFromServer(const AccountPtr &account, const QStringList &userIds);
|
||||
void getUsersPublicKeyFromServer(const OCC::AccountPtr &account, const QStringList &userIds);
|
||||
void fetchCertificateFromKeyChain(const OCC::AccountPtr &account, const QString &userId);
|
||||
void writeCertificate(const AccountPtr &account, const QString &userId, const QSslCertificate &certificate);
|
||||
void writeCertificate(const OCC::AccountPtr &account, const QString &userId, const QSslCertificate &certificate);
|
||||
|
||||
private slots:
|
||||
void generateKeyPair(const OCC::AccountPtr &account);
|
||||
|
|
|
@ -22,7 +22,11 @@
|
|||
#include <QJsonDocument>
|
||||
#include <QBuffer>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <qt6keychain/keychain.h>
|
||||
#else
|
||||
#include <qt5keychain/keychain.h>
|
||||
#endif
|
||||
|
||||
#include "account.h"
|
||||
#include "accessmanager.h"
|
||||
|
|
|
@ -17,7 +17,13 @@
|
|||
#define KEYCHAINCHUNK_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <qt6keychain/keychain.h>
|
||||
#else
|
||||
#include <qt5keychain/keychain.h>
|
||||
#endif
|
||||
|
||||
#include "accountfwd.h"
|
||||
|
||||
// We don't support insecure fallback
|
||||
|
|
|
@ -452,13 +452,15 @@ void ProcessDirectoryJob::checkAndUpdateSelectiveSyncListsForE2eeFolders(const Q
|
|||
|
||||
const auto pathWithTrailingSpace = Utility::trailingSlashPath(path);
|
||||
|
||||
auto blackListSet = _discoveryData->_statedb->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok).toSet();
|
||||
const auto blackListList = _discoveryData->_statedb->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||
auto blackListSet = QSet<QString>{blackListList.begin(), blackListList.end()};
|
||||
blackListSet.insert(pathWithTrailingSpace);
|
||||
auto blackList = blackListSet.values();
|
||||
blackList.sort();
|
||||
_discoveryData->_statedb->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
|
||||
auto toRemoveFromBlacklistSet = _discoveryData->_statedb->getSelectiveSyncList(SyncJournalDb::SelectiveSyncE2eFoldersToRemoveFromBlacklist, &ok).toSet();
|
||||
const auto toRemoveFromBlacklistList = _discoveryData->_statedb->getSelectiveSyncList(SyncJournalDb::SelectiveSyncE2eFoldersToRemoveFromBlacklist, &ok);
|
||||
auto toRemoveFromBlacklistSet = QSet<QString>{toRemoveFromBlacklistList.begin(), toRemoveFromBlacklistList.end()};
|
||||
toRemoveFromBlacklistSet.insert(pathWithTrailingSpace);
|
||||
// record it into a separate list to automatically remove from blacklist once the e2EE gets set up
|
||||
auto toRemoveFromBlacklist = toRemoveFromBlacklistSet.values();
|
||||
|
|
|
@ -467,7 +467,9 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemotePer
|
|||
if (property == QLatin1String("resourcetype")) {
|
||||
result.isDirectory = value.contains(QLatin1String("collection"));
|
||||
} else if (property == QLatin1String("getlastmodified")) {
|
||||
value.replace("GMT", "+0000");
|
||||
const auto date = QDateTime::fromString(value, Qt::RFC2822Date);
|
||||
qCInfo(lcDiscovery()) << value << date << date.isValid() << QDateTime::currentDateTime().toString(Qt::RFC2822Date);
|
||||
Q_ASSERT(date.isValid());
|
||||
result.modtime = 0;
|
||||
if (date.toSecsSinceEpoch() > 0) {
|
||||
|
|
|
@ -14,13 +14,18 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "owncloudlib.h"
|
||||
|
||||
#include "account.h"
|
||||
#include "rootencryptedfolderinfo.h"
|
||||
#include "common/syncjournaldb.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QSslCertificate>
|
||||
#include <QString>
|
||||
#include <QPointer>
|
||||
|
||||
namespace OCC {
|
||||
class FolderMetadata;
|
||||
|
|
|
@ -599,7 +599,7 @@ QByteArray FolderMetadata::encryptedMetadata()
|
|||
|
||||
QJsonObject files, folders;
|
||||
for (auto it = _files.constBegin(), end = _files.constEnd(); it != end; ++it) {
|
||||
const auto file = convertFileToJsonObject(it);
|
||||
const auto file = convertFileToJsonObject(&(*it));
|
||||
if (file.isEmpty()) {
|
||||
qCDebug(lcCseMetadata) << "Metadata generation failed for file" << it->encryptedFilename;
|
||||
return {};
|
||||
|
|
|
@ -111,7 +111,7 @@ void Logger::postGuiMessage(const QString &title, const QString &message)
|
|||
bool Logger::isLoggingToFile() const
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
return _logstream;
|
||||
return !_logstream.isNull();
|
||||
}
|
||||
|
||||
void Logger::doLog(QtMsgType type, const QMessageLogContext &ctx, const QString &message)
|
||||
|
@ -359,7 +359,6 @@ void Logger::setLogFileNoLock(const QString &name)
|
|||
}
|
||||
|
||||
_logstream.reset(new QTextStream(&_logFile));
|
||||
_logstream->setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
}
|
||||
|
||||
void Logger::enterNextLogFile()
|
||||
|
|
|
@ -280,21 +280,21 @@ bool LsColXMLParser::parse(const QByteArray &xml, QHash<QString, ExtraFolderInfo
|
|||
// End elements with DAV:
|
||||
if (type == QXmlStreamReader::EndElement) {
|
||||
if (reader.namespaceUri() == QLatin1String("DAV:")) {
|
||||
if (reader.name() == "response") {
|
||||
if (reader.name() == QStringLiteral("response")) {
|
||||
if (currentHref.endsWith('/')) {
|
||||
currentHref.chop(1);
|
||||
}
|
||||
emit directoryListingIterated(currentHref, currentHttp200Properties);
|
||||
currentHref.clear();
|
||||
currentHttp200Properties.clear();
|
||||
} else if (reader.name() == "propstat") {
|
||||
} else if (reader.name() == QStringLiteral("propstat")) {
|
||||
insidePropstat = false;
|
||||
if (currentPropsHaveHttp200) {
|
||||
currentHttp200Properties = QMap<QString, QString>(currentTmpProperties);
|
||||
}
|
||||
currentTmpProperties.clear();
|
||||
currentPropsHaveHttp200 = false;
|
||||
} else if (reader.name() == "prop") {
|
||||
} else if (reader.name() == QStringLiteral("prop")) {
|
||||
insideProp = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
#ifndef NETWORKJOBS_H
|
||||
#define NETWORKJOBS_H
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
#include "abstractnetworkjob.h"
|
||||
|
||||
#include "common/result.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QUrlQuery>
|
||||
|
||||
class QUrl;
|
||||
class QUrlQuery;
|
||||
class QJsonObject;
|
||||
class QJsonDocument;
|
||||
class QDomDocument;
|
||||
|
|
|
@ -514,24 +514,22 @@ void OwncloudPropagator::start(SyncFileItemVector &&items)
|
|||
|
||||
const auto regex = syncOptions().fileRegex();
|
||||
if (regex.isValid()) {
|
||||
QSet<QStringRef> names;
|
||||
QSet<QStringView> names;
|
||||
for (auto &i : items) {
|
||||
if (regex.match(i->_file).hasMatch()) {
|
||||
int index = -1;
|
||||
QStringRef ref;
|
||||
QStringView ref;
|
||||
do {
|
||||
ref = i->_file.midRef(0, index);
|
||||
ref = i->_file.mid(0, index);
|
||||
names.insert(ref);
|
||||
index = ref.lastIndexOf(QLatin1Char('/'));
|
||||
} while (index > 0);
|
||||
}
|
||||
}
|
||||
items.erase(std::remove_if(items.begin(),
|
||||
items.end(),
|
||||
[&names](auto i) {
|
||||
return !names.contains(QStringRef{&i->_file});
|
||||
}),
|
||||
items.end());
|
||||
items.erase(std::remove_if(items.begin(), items.end(), [&names](auto i) {
|
||||
return !names.contains(QStringView { i->_file });
|
||||
}),
|
||||
items.end());
|
||||
}
|
||||
|
||||
QStringList files;
|
||||
|
|
|
@ -887,8 +887,7 @@ void PropagateDownloadFile::slotGetFinished()
|
|||
// of the compressed data. See QTBUG-73364.
|
||||
const auto contentEncoding = job->reply()->rawHeader("content-encoding").toLower();
|
||||
if ((contentEncoding == "gzip" || contentEncoding == "deflate")
|
||||
&& (job->reply()->attribute(QNetworkRequest::Http2WasUsedAttribute).toBool()
|
||||
|| job->reply()->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool())) {
|
||||
&& job->reply()->attribute(QNetworkRequest::Http2WasUsedAttribute).toBool()) {
|
||||
bodySize = 0;
|
||||
hasSizeHeader = false;
|
||||
}
|
||||
|
@ -1218,10 +1217,10 @@ void PropagateDownloadFile::downloadFinished()
|
|||
}
|
||||
|
||||
if (_item->_locked == SyncFileItem::LockStatus::LockedItem && (_item->_lockOwnerType != SyncFileItem::LockOwnerType::UserLock || _item->_lockOwnerId != propagator()->account()->davUser())) {
|
||||
qCDebug(lcPropagateDownload()) << _tmpFile << "file is locked: making it read only";
|
||||
qCDebug(lcPropagateDownload()) << _tmpFile.fileName() << "file is locked: making it read only";
|
||||
FileSystem::setFileReadOnly(_tmpFile.fileName(), true);
|
||||
} else {
|
||||
qCDebug(lcPropagateDownload()) << _tmpFile << "file is not locked: making it"
|
||||
qCDebug(lcPropagateDownload()) << _tmpFile.fileName() << "file is not locked: making it"
|
||||
<< ((!_item->_remotePerm.isNull() && !_item->_remotePerm.hasPermission(RemotePermissions::CanWrite)) ? "read only"
|
||||
: "read write");
|
||||
FileSystem::setFileReadOnlyWeak(_tmpFile.fileName(), (!_item->_remotePerm.isNull() && !_item->_remotePerm.hasPermission(RemotePermissions::CanWrite)));
|
||||
|
|
|
@ -719,13 +719,14 @@ void PropagateUploadFileCommon::commonErrorHandling(AbstractNetworkJob *job)
|
|||
void PropagateUploadFileCommon::adjustLastJobTimeout(AbstractNetworkJob *job, qint64 fileSize)
|
||||
{
|
||||
constexpr double threeMinutes = 3.0 * 60 * 1000;
|
||||
constexpr qint64 thirtyMinutes = 30 * 60 * 1000;
|
||||
|
||||
job->setTimeout(qBound(
|
||||
job->timeoutMsec(),
|
||||
// Calculate 3 minutes for each gigabyte of data
|
||||
qRound64(threeMinutes * fileSize / 1e9),
|
||||
qMin(thirtyMinutes - 1, qRound64(threeMinutes * fileSize / 1e9)),
|
||||
job->timeoutMsec(),
|
||||
// Maximum of 30 minutes
|
||||
static_cast<qint64>(30 * 60 * 1000)));
|
||||
thirtyMinutes));
|
||||
}
|
||||
|
||||
void PropagateUploadFileCommon::slotJobDestroyed(QObject *job)
|
||||
|
|
|
@ -929,15 +929,40 @@ void Theme::connectToPaletteSignal()
|
|||
}
|
||||
}
|
||||
|
||||
QPalette Theme::systemPalette()
|
||||
QVariantMap Theme::systemPalette()
|
||||
{
|
||||
connectToPaletteSignal();
|
||||
#if defined(Q_OS_WIN)
|
||||
auto systemPalette = QGuiApplication::palette();
|
||||
if(darkMode()) {
|
||||
return reserveDarkPalette;
|
||||
systemPalette = reserveDarkPalette;
|
||||
}
|
||||
#else
|
||||
const auto systemPalette = QGuiApplication::palette();
|
||||
#endif
|
||||
return QGuiApplication::palette();
|
||||
|
||||
return QVariantMap {
|
||||
{ QStringLiteral("base"), systemPalette.base().color() },
|
||||
{ QStringLiteral("alternateBase"), systemPalette.alternateBase().color() },
|
||||
{ QStringLiteral("text"), systemPalette.text().color() },
|
||||
{ QStringLiteral("toolTipBase"), systemPalette.toolTipBase().color() },
|
||||
{ QStringLiteral("toolTipText"), systemPalette.toolTipText().color() },
|
||||
{ QStringLiteral("brightText"), systemPalette.brightText().color() },
|
||||
{ QStringLiteral("buttonText"), systemPalette.buttonText().color() },
|
||||
{ QStringLiteral("button"), systemPalette.button().color() },
|
||||
{ QStringLiteral("highlightedText"), systemPalette.highlightedText().color() },
|
||||
{ QStringLiteral("placeholderText"), systemPalette.placeholderText().color() },
|
||||
{ QStringLiteral("windowText"), systemPalette.windowText().color() },
|
||||
{ QStringLiteral("window"), systemPalette.window().color() },
|
||||
{ QStringLiteral("dark"), systemPalette.dark().color() },
|
||||
{ QStringLiteral("highlight"), systemPalette.highlight().color() },
|
||||
{ QStringLiteral("light"), systemPalette.light().color() },
|
||||
{ QStringLiteral("link"), systemPalette.link().color() },
|
||||
{ QStringLiteral("midlight"), systemPalette.midlight().color() },
|
||||
{ QStringLiteral("mid"), systemPalette.mid().color() },
|
||||
{ QStringLiteral("linkVisited"), systemPalette.linkVisited().color() },
|
||||
{ QStringLiteral("shadow"), systemPalette.shadow().color() },
|
||||
};
|
||||
}
|
||||
|
||||
bool Theme::darkMode()
|
||||
|
|
|
@ -67,7 +67,7 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject
|
|||
|
||||
Q_PROPERTY(QColor defaultColor READ defaultColor CONSTANT)
|
||||
|
||||
Q_PROPERTY(QPalette systemPalette READ systemPalette NOTIFY systemPaletteChanged)
|
||||
Q_PROPERTY(QVariantMap systemPalette READ systemPalette NOTIFY systemPaletteChanged)
|
||||
Q_PROPERTY(bool darkMode READ darkMode NOTIFY darkModeChanged)
|
||||
public:
|
||||
enum CustomMediaType {
|
||||
|
@ -593,7 +593,7 @@ public:
|
|||
|
||||
static constexpr const char *themePrefix = ":/client/theme/";
|
||||
|
||||
QPalette systemPalette();
|
||||
QVariantMap systemPalette();
|
||||
bool darkMode();
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -299,11 +299,11 @@ void UpdateE2eeFolderUsersMetadataJob::slotCertificateFetchedFromKeychain(const
|
|||
emit certificateReady();
|
||||
}
|
||||
|
||||
void UpdateE2eeFolderUsersMetadataJob::slotCertificatesFetchedFromServer(const QHash<QString, QSslCertificate> &results)
|
||||
void UpdateE2eeFolderUsersMetadataJob::slotCertificatesFetchedFromServer(const QHash<QString, NextcloudSslCertificate> &results)
|
||||
{
|
||||
const auto certificate = results.isEmpty() ? QSslCertificate{} : results.value(_folderUserId);
|
||||
const auto certificate = results.isEmpty() ? NextcloudSslCertificate{} : results.value(_folderUserId);
|
||||
_folderUserCertificate = certificate;
|
||||
if (certificate.isNull()) {
|
||||
if (certificate.get().isNull()) {
|
||||
emit certificateReady();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -55,14 +55,14 @@ public:
|
|||
|
||||
public slots:
|
||||
void start(const bool keepLock = false);
|
||||
void setUserData(const UserData &userData);
|
||||
void setUserData(const UpdateE2eeFolderUsersMetadataJob::UserData &userData);
|
||||
|
||||
void setFolderToken(const QByteArray &folderToken);
|
||||
void setMetadataKeyForEncryption(const QByteArray &metadataKey);
|
||||
void setMetadataKeyForDecryption(const QByteArray &metadataKey);
|
||||
void setKeyChecksums(const QSet<QByteArray> &keyChecksums);
|
||||
|
||||
void setSubJobSyncItems(const QHash<QString, SyncFileItemPtr> &subJobSyncItems);
|
||||
void setSubJobSyncItems(const QHash<QString, OCC::SyncFileItemPtr> &subJobSyncItems);
|
||||
|
||||
private:
|
||||
void scheduleSubJobs();
|
||||
|
@ -78,7 +78,7 @@ private slots:
|
|||
void slotFolderUnlocked(const QByteArray &folderId, int httpStatus);
|
||||
|
||||
void slotUpdateMetadataFinished(int code, const QString &message = {});
|
||||
void slotCertificatesFetchedFromServer(const QHash<QString, QSslCertificate> &results);
|
||||
void slotCertificatesFetchedFromServer(const QHash<QString, OCC::NextcloudSslCertificate> &results);
|
||||
void slotCertificateFetchedFromKeychain(const QSslCertificate &certificate);
|
||||
|
||||
private: signals:
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
#include <QUuid>
|
||||
|
||||
#include <sddl.h>
|
||||
#include <ntstatus.h>
|
||||
#include <cfapi.h>
|
||||
#include <comdef.h>
|
||||
#include <ntstatus.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
@ -269,7 +269,7 @@ void CALLBACK cfApiFetchDataCallback(const CF_CALLBACK_INFO *callbackInfo, const
|
|||
|
||||
int hydrationJobResult = OCC::HydrationJob::Status::Error;
|
||||
const auto invokeFinalizeResult = QMetaObject::invokeMethod(
|
||||
vfs, [=] { vfs->finalizeHydrationJob(requestId); }, Qt::BlockingQueuedConnection,
|
||||
vfs, [&hydrationJobResult, vfs, requestId] { return vfs->finalizeHydrationJob(requestId); }, Qt::BlockingQueuedConnection,
|
||||
&hydrationJobResult);
|
||||
if (!invokeFinalizeResult) {
|
||||
qCritical(lcCfApiWrapper) << "Failed to finalize hydration job for" << path << requestId;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue