Merge pull request #4584 from nextcloud/feature/qt6

Migrate to Qt 6
This commit is contained in:
Matthieu Gallien 2024-04-26 09:05:38 +02:00 committed by GitHub
commit 810d8f15ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
119 changed files with 642 additions and 836 deletions

View File

@ -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
...

View File

@ -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: |

View File

@ -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: |

View File

@ -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: |

View File

@ -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

View File

@ -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)

View File

@ -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}/

View File

@ -9,7 +9,7 @@ else()
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
endif()
find_package(Qt5 5.15 COMPONENTS Core REQUIRED)
find_package(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)

View File

@ -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}")

View File

@ -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

View File

@ -1,2 +0,0 @@
TEMPLATE = subdirs
SUBDIRS = test

View File

@ -1,8 +0,0 @@
TEMPLATE = app
QT += testlib
CONFIG += testlib
TARGET = test
INCLUDEPATH += . ..
# Input
SOURCES += tst_qtokenizer.cpp

View File

@ -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"

View File

@ -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

View File

@ -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")

View File

@ -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);

View File

@ -18,6 +18,7 @@
#include "remotepermissions.h"
#include <QVariant>
#include <QLoggingCategory>
#include <cstring>

View File

@ -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"));
}

View File

@ -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")

View File

@ -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}")

View File

@ -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)

View File

@ -43,6 +43,8 @@
#include <functional>
#include <memory>
#include <QByteArray>
#include <QVariant>
#include "common/remotepermissions.h"
namespace OCC {

View File

@ -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);

View File

@ -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"

View File

@ -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}")

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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."));
}

View File

@ -15,6 +15,7 @@
#include "editlocallymanager.h"
#include <QUrl>
#include <QUrlQuery>
#include <QLoggingCategory>
namespace OCC {

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -38,6 +38,7 @@
#include <QEvent>
#include <QCheckBox>
#include <QMessageBox>
#include <QStandardPaths>
#include <cstdlib>

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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()

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -25,7 +25,6 @@
class QUrl;
class QLocalSocket;
class QStringList;
class QFileInfo;
namespace OCC

View File

@ -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();
}
}

View File

@ -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"));

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -1,5 +1,7 @@
#include "talkreply.h"
#include "accountstate.h"
#include "networkjobs.h"
#include <QJsonDocument>
#include <QJsonObject>

View File

@ -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)

View File

@ -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);

View File

@ -31,7 +31,7 @@ signals:
void clicked();
protected:
void enterEvent(QEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;

View File

@ -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);

View File

@ -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);
/*

View File

@ -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);

View File

@ -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)

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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();

View File

@ -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) {

View File

@ -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;

View File

@ -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 {};

View File

@ -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()

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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)));

View File

@ -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)

View File

@ -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()

View File

@ -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:

View File

@ -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;
}

View File

@ -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:

View File

@ -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