1
0
mirror of https://github.com/chylex/Nextcloud-Desktop.git synced 2026-04-04 20:34:17 +02:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Camila San
e0b32c19e4 Bump version to 2.6.0
Signed-off-by: Camila San <hello@camila.codes>
2019-09-27 17:01:24 +02:00
195 changed files with 26973 additions and 37406 deletions

View File

@@ -237,17 +237,13 @@ name: qt-5.12
steps:
- name: build and test
image: nextcloudci/client-5.12:client-5.12-5
image: nextcloudci/client-5.12:client-5.12-2
commands:
# Install QtKeyChain
- /bin/bash -c "
export CC=gcc-7 &&
export CXX=g++-7 &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
source /opt/qt512/bin/qt512-env.sh &&
cd /tmp &&
git clone https://github.com/frankosterfeld/qtkeychain.git &&
cd qtkeychain &&
@@ -261,11 +257,7 @@ steps:
- /bin/bash -c "
export CC=gcc-7 &&
export CXX=g++-7 &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
source /opt/qt512/bin/qt512-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
@@ -286,17 +278,13 @@ name: qt-5.12-clang
steps:
- name: build and test
image: nextcloudci/client-5.12:client-5.12-5
image: nextcloudci/client-5.12:client-5.12-2
commands:
# Install QtKeyChain
- /bin/bash -c "
export CC=clang-6.0 &&
export CXX=clang++-6.0 &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
source /opt/qt512/bin/qt512-env.sh &&
cd /tmp &&
git clone https://github.com/frankosterfeld/qtkeychain.git &&
cd qtkeychain &&
@@ -310,11 +298,7 @@ steps:
- /bin/bash -c "
export CC=clang-6.0 &&
export CXX=clang++-6.0 &&
export QT_BASE_DIR=/opt/qt5.12.5 &&
export QTDIR=\$QT_BASE_DIR &&
export PATH=\$QT_BASE_DIR/bin:\$PATH &&
export LD_LIBRARY_PATH=\$QT_BASE_DIR/lib/x86_64-linux-gnu:\$QT_BASE_DIR/lib:/usr/local/lib:\$LD_LIBRARY_PATH &&
export PKG_CONFIG_PATH=\$QT_BASE_DIR/lib/pkgconfig:\$PKG_CONFIG_PATH &&
source /opt/qt512/bin/qt512-env.sh &&
mkdir build &&
cd build &&
cmake -D NO_SHIBBOLETH=1 -DCMAKE_BUILD_TYPE=Debug -DUNIT_TESTING=1 ../ &&
@@ -335,10 +319,9 @@ name: AppImage
steps:
- name: build
image: nextcloudci/client-5.12:client-5.12-5
image: nextcloudci/client-5.12:client-5.12-2
commands:
- /bin/bash -c "./admin/linux/build-appimage.sh"
- /bin/bash -c "./admin/linux/upload-appimage.sh"
trigger:
branch:
- master
@@ -361,9 +344,10 @@ steps:
from_secret: DEBIAN_SECRET_IV
trigger:
branch:
- stable-2.6
- master
event:
- tag
- pull_request
- push
---
kind: pipeline
name: Documentation

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "src/3rdparty/qtmacgoodies"]
path = src/3rdparty/qtmacgoodies
url = https://github.com/camilasan/qtmacgoodies.git
[submodule "binary"]
path = binary
url = git://github.com/owncloud/owncloud-client-binary.git

View File

@@ -1,204 +0,0 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[cy_GB]=@APPLICATION_ICON_NAME@
Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
GenericName[cy_GB]=Cydweddu Ffolder

View File

@@ -201,4 +201,4 @@ X-GNOME-Autostart-Delay=3
Icon[ro]=@APPLICATION_ICON_NAME@
Name[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
GenericName[ro]=Sincronizare director
GenericName[ro]=Sincronizare dosare

View File

@@ -201,4 +201,4 @@ X-GNOME-Autostart-Delay=3
Icon[sk_SK]=@APPLICATION_ICON_NAME@
Name[sk_SK]=@APPLICATION_NAME@ synchronizačný klient pre PC
Comment[sk_SK]=@APPLICATION_NAME@ synchronizačný klient pre PC
GenericName[sk_SK]=Synchronizácia priečinkov
GenericName[sk_SK]=Synchnonizácia priečinkov

View File

@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
# Translations
Icon[sl]=@APPLICATION_ICON_NAME@
Name[sl]=@APPLICATION_NAME@ program za usklajevanje
Comment[sl]=@APPLICATION_NAME@ program za usklajevanje
Name[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
Comment[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
GenericName[sl]=Usklajevanje map

View File

@@ -1,204 +0,0 @@
[Desktop Entry]
Categories=Utility;X-SuSE-SyncUtility;
Type=Application
Exec=@APPLICATION_EXECUTABLE@
Name=@APPLICATION_NAME@ desktop sync client
Comment=@APPLICATION_NAME@ desktop synchronization client
GenericName=Folder Sync
Icon=@APPLICATION_ICON_NAME@
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
X-GNOME-Autostart-Delay=3
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
# Translations
Icon[sw]=@APPLICATION_ICON_NAME@
Name[sw]=Teja ya @APPLICATION_NAME@ ya kufanana faili kwa seva na faili ziko hapa
Comment[sw]=Teja ya @APPLICATION_NAME@ ya kufanana faili kwa seva na faili ziko hapa
GenericName[sw]=Fanana Kabrasha

View File

@@ -203,16 +203,8 @@ if( WIN32 )
add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
add_definitions( -DNOMINMAX )
# Get APIs from from Vista onwards.
add_definitions( -D_WIN32_WINNT=0x0601 )
add_definitions( -DWINVER=0x0601 )
if( MSVC )
# Use automatic overload for suitable CRT safe-functions
# See https://docs.microsoft.com/de-de/cpp/c-runtime-library/security-features-in-the-crt?view=vs-2019
add_definitions( -D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1 )
# Also: Disable compiler warnings because we don't use Windows CRT safe-functions explicitly and don't intend to
# as this is a pure cross-platform source the only alternative would be a ton of ifdefs with calls to the _s version
add_definitions( -D_CRT_SECURE_NO_WARNINGS )
endif( MSVC )
add_definitions( -D_WIN32_WINNT=0x0600)
add_definitions( -DWINVER=0x0600)
endif( WIN32 )
if (APPLE)

View File

@@ -1,6 +1,6 @@
set( MIRALL_VERSION_MAJOR 2 )
set( MIRALL_VERSION_MINOR 6 )
set( MIRALL_VERSION_PATCH 2 )
set( MIRALL_VERSION_PATCH 0 )
set( MIRALL_VERSION_YEAR 2019 )
set( MIRALL_SOVERSION 0 )

View File

@@ -14,7 +14,6 @@ RUN apt-get update -q && DEBIAN_FRONTEND=noninteractive apt-get install -q -y --
libsqlite3-dev \
libssl-dev \
libcmocka-dev \
libcloudproviders-dev \
qt5-default \
qttools5-dev-tools \
libqt5webkit5-dev \

View File

@@ -6,7 +6,7 @@ mkdir /app
mkdir /build
#Set Qt-5.12
export QT_BASE_DIR=/opt/qt5.12.5
export QT_BASE_DIR=/opt/qt512
export QTDIR=$QT_BASE_DIR
export PATH=$QT_BASE_DIR/bin:$PATH
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
@@ -66,8 +66,7 @@ rm -rf ./usr/share/nemo-python/
mv ./etc/Nextcloud/sync-exclude.lst ./usr/bin/
rm -rf ./etc
DESKTOP_FILE=/app/usr/share/applications/${LINUX_APPLICATION_ID}.desktop
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' usr/share/applications/nextcloud.desktop # Bug in desktop file?
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
@@ -88,12 +87,17 @@ chmod a+x linuxdeployqt*.AppImage
rm ./linuxdeployqt-continuous-x86_64.AppImage
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/app/usr/lib/
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs
./squashfs-root/AppRun /app/usr/share/applications/nextcloud.desktop -bundle-non-qt-libs
# Set origin
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/libnextcloudsync.so.0
# Build AppImage
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage
./squashfs-root/AppRun /app/usr/share/applications/nextcloud.desktop -appimage
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
curl --upload-file $(readlink -f ./Nextcloud*.AppImage) https://transfer.sh/Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
echo
echo "Get the AppImage at the link above!"

View File

@@ -7,10 +7,9 @@ Build-Depends: cmake,
cdbs,
dh-python,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
libkf5kio-dev,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5svg5-dev,

View File

@@ -1,48 +0,0 @@
nextcloud-client (2.3.3-1.0~oldstable1) oldstable; urgency=medium
* Debian build support for the forked client.
-- István Váradi <ivaradi@varadiistvan.hu> Mon, 6 Nov 2017 20:20:04 +0100
nextcloud-client (2.3.1-1.0) oldstable; urgency=medium
* New upstream version
-- István Váradi <ivaradi@varadiistvan.hu> Thu, 23 Mar 2017 19:07:36 +0100
nextcloud-client (2.3.0-1.0) oldstable; urgency=medium
* New upstream version
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 21 Mar 2017 19:34:13 +0100
nextcloud-client (2.2.4-1.4) oldstable; urgency=medium
* The locale-specific icon names are correct too
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 7 Feb 2017 19:55:40 +0100
nextcloud-client (2.2.4-1.3) oldstable; urgency=medium
* Caja syncstate plugin is built.
* The syncstate plugin has application-specific name
-- István Váradi <ivaradi@varadiistvan.hu> Fri, 27 Jan 2017 19:34:18 +0100
nextcloud-client (2.2.4-1.2) oldstable; urgency=medium
* Fixed appname in the Nemo syncstate extension.
-- István Váradi <ivaradi@varadiistvan.hu> Thu, 19 Jan 2017 16:46:50 +0100
nextcloud-client (2.2.4-1.1) oldstable; urgency=medium
* Added Nautilus and Nemo syncstate extensions.
-- István Váradi <ivaradi@varadiistvan.hu> Tue, 17 Jan 2017 19:55:32 +0100
nextcloud-client (2.2.4-1.0) oldstable; urgency=medium
* Initial release.
-- István Váradi <ivaradi@varadiistvan.hu> Wed, 14 Dec 2016 20:07:46 +0100

View File

@@ -1,84 +0,0 @@
Source: nextcloud-client
Section: contrib/devel
Priority: optional
Maintainer: István Váradi <ivaradi@varadiistvan.hu>
Build-Depends: cmake,
debhelper,
cdbs,
dh-python,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
kio-dev,
libcmocka-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5webkit5-dev,
libqt5svg5-dev,
libsqlite3-dev,
libssl-dev (>= 1.1.0),
zlib1g-dev,
optipng,
pkg-kde-tools,
python-sphinx | python3-sphinx,
python3-all,
qt5keychain-dev,
qtwebengine5-dev,
qtdeclarative5-dev,
qttools5-dev,
qttools5-dev-tools,
xvfb
Standards-Version: 3.9.8
Homepage: https://github.com/nextcloud/client_theming
#Vcs-Git: git://anonscm.debian.org/collab-maint/nextcloud-client.git
#Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nextcloud-client.git
Package: nextcloud-client
Architecture: any
Depends: libnextcloudsync0 (=${binary:Version}), ${shlibs:Depends}, ${misc:Depends}, nextcloud-client-l10n
Recommends: libgnome-keyring0
Description: Nextcloud desktop sync client
Use the desktop client to keep your files synchronized
between your Nextcloud server and your desktop. Select
one or more directories on your local machine and always
have access to your latest files wherever you are.
Package: libnextcloudsync0
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Nextcloud sync library
Used by the Nextcloud desktop client as the synchronization engine.
Package: libnextcloudsync-dev
Architecture: any
Section: contrib/libdevel
Depends: libnextcloudsync0 (=${binary:Version}), ${misc:Depends}
Description: Nextcloud sync library development files
The headers and development library for the Nextcloud sync library.
Package: nextcloud-client-l10n
Architecture: all
Depends: ${misc:Depends}
Description: Nextcloud client internatialization files
The translation files.
Package: nextcloud-client-nautilus
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-nautilus, nautilus, ${misc:Depends}
Description: Nautilus plugin for Nextcloud
This package contains a Nautilus plugin to display
synchronization status icons for Nextcloud files.
Package: nextcloud-client-nemo
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-nemo, nemo, ${misc:Depends}
Description: Nemo plugin for Nextcloud
This package contains a Nemo plugin to display
synchronization status icons for Nextcloud files.
Package: nextcloud-client-caja
Architecture: all
Depends: nextcloud-client (>=${binary:Version}), libnextcloudsync0, python-caja, caja, ${misc:Depends}
Description: Caja plugin for Nextcloud
This package contains a Caja plugin to display
synchronization status icons for Nextcloud files.

View File

@@ -9,10 +9,7 @@ Build-Depends: cmake,
extra-cmake-modules (>= 5.16),
kdelibs5-dev,
kio-dev,
libavcodec58,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5webkit5-dev,

View File

@@ -10,8 +10,6 @@ Build-Depends: cmake,
kdelibs5-dev,
libkf5kio-dev,
libcmocka-dev,
libcloudproviders-dev,
libdbus-1-dev,
libhttp-dav-perl,
libinotify-dev [kfreebsd-any],
libqt5svg5-dev,

View File

@@ -51,7 +51,7 @@ if ! wget http://ppa.launchpad.net/${repo}/ubuntu/pool/main/n/nextcloud-client/n
origsourceopt="-sa"
fi
for distribution in xenial bionic disco eoan stable oldstable; do
for distribution in xenial bionic disco eoan stable; do
rm -rf nextcloud-client_${basever}
cp -a ${DRONE_WORKSPACE} nextcloud-client_${basever}
@@ -98,46 +98,26 @@ if test "${pull_request}" = "master"; then
PPA=$PPA_BETA
OBS_PROJECT=$OBS_PROJECT_BETA
fi
OBS_SUBDIR="${OBS_PROJECT}/${OBS_PACKAGE}"
if test -f ~/.has_ppa_keys; then
for changes in nextcloud-client_*~+([a-z])1_source.changes; do
case "${changes}" in
*oldstable1*)
;;
*)
dput $PPA $changes > /dev/null
;;
esac
dput $PPA $changes > /dev/null
done
for distribution in stable oldstable; do
if test "${distribution}" = "oldstable"; then
pkgsuffix=".${distribution}"
pkgvertag="~${distribution}1"
else
pkgsuffix=""
pkgvertag=""
fi
mkdir osc
cd osc
osc co ${OBS_PROJECT} ${OBS_PACKAGE}
if test "$(ls ${OBS_SUBDIR})"; then
osc delete ${OBS_SUBDIR}/*
fi
cp ../nextcloud-client*.orig.tar.* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9].dsc ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9].debian.tar* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]_source.changes ${OBS_SUBDIR}/
osc add ${OBS_SUBDIR}/*
package="${OBS_PACKAGE}${pkgsuffix}"
OBS_SUBDIR="${OBS_PROJECT}/${package}"
mkdir -p osc
pushd osc
osc co ${OBS_PROJECT} ${package}
if test "$(ls ${OBS_SUBDIR})"; then
osc delete ${OBS_SUBDIR}/*
fi
cp ../nextcloud-client*.orig.tar.* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}.dsc ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}.debian.tar* ${OBS_SUBDIR}/
cp ../nextcloud-client_*[0-9.][0-9]${pkgvertag}_source.changes ${OBS_SUBDIR}/
osc add ${OBS_SUBDIR}/*
cd ${OBS_SUBDIR}
osc commit -m "Travis update"
popd
done
cd ${OBS_SUBDIR}
osc commit -m "Travis update"
fi
fi

View File

@@ -1,21 +0,0 @@
#! /bin/bash
set -xe
cd /build
# Upload AppImage
APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
BASENAME=$(basename ${APPIMAGE})
if curl --max-time 900 --upload-file ${APPIMAGE} https://transfer.sh/${BASENAME}
then
echo
echo "Get the AppImage at the link above!"
else
echo
echo "Upload failed, however this is an optional step."
fi
# Don't let the Drone build fail
exit 0

View File

@@ -49,7 +49,7 @@ fi
if [ ! -z "$identity" ]; then
echo "Will try to sign the installer"
pushd $install_path
productsign --timestamp --sign "$identity" "$installer_file" "$installer_file.new"
productsign --sign "$identity" "$installer_file" "$installer_file.new"
mv "$installer_file".new "$installer_file"
popd
else

View File

@@ -32,12 +32,11 @@ FRAMEWORK_SEARCH_PATH=[
os.path.join(os.environ['HOME'], 'Library/Frameworks')
]
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Qt-5.12.5/lib', '.']
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Qt-5.6.2/lib', '.']
QT_PLUGINS = [
'sqldrivers/libqsqlite.dylib',
'platforms/libqcocoa.dylib',
'styles/libqmacstyle.dylib',
'imageformats/libqgif.dylib',
'imageformats/libqico.dylib',
'imageformats/libqjpeg.dylib',
@@ -47,7 +46,7 @@ QT_PLUGINS = [
QT_PLUGINS_SEARCH_PATH=[
# os.path.join(os.environ['QTDIR'], 'plugins'),
# '/usr/local/Cellar/qt/5.2.1/plugins',
'/usr/local/Qt-5.12.5/plugins',
'/usr/local/Qt-5.6.2/plugins',
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

2
binary

Submodule binary updated: 09f12de312...3425fab2c6

View File

@@ -27,7 +27,7 @@
<key>CFBundleShortVersionString</key>
<string>@MIRALL_VERSION_STRING@</string>
<key>NSHumanReadableCopyright</key>
<string>(C) 2014-2019 @APPLICATION_VENDOR@</string>
<string>(C) 2014-2018 @APPLICATION_VENDOR@</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>SUShowReleaseNotes</key>

View File

@@ -3,11 +3,7 @@
# For details see the accompanying COPYING* file.
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Use this only for Clang
if (CMAKE_CXX_COMPILER MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
# Fix sqlite compilation on macOS
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")

View File

@@ -467,7 +467,6 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";

View File

@@ -35,11 +35,11 @@ public:
QString contextMenuTitle() const
{
return _strings.value("CONTEXT_MENU_TITLE", "Nextcloud");
return _strings.value("CONTEXT_MENU_TITLE", "ownCloud");
}
QString shareActionTitle() const
{
return _strings.value("SHARE_MENU_TITLE", "Share");
return _strings.value("SHARE_MENU_TITLE", "Share...");
}
QString copyPrivateLinkTitle() const { return _strings["COPY_PRIVATE_LINK_MENU_TITLE"]; }

View File

@@ -89,7 +89,7 @@ IFACEMETHODIMP OCContextMenu::Initialize(
HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
if (hDrop) {
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
for (UINT i = 0; i < nFiles; ++i) {
for (int i = 0; i < nFiles; ++i) {
// Get the path of the file.
wchar_t buffer[MAX_PATH];

View File

@@ -5,8 +5,6 @@
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#include <SDKDDKVer.h>

View File

@@ -13,10 +13,8 @@
*/
#define WIN32_LEAN_AND_MEAN
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#include "CommunicationSocket.h"
#include "RegistryUtil.h"

View File

@@ -1,9 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
// Note: Here was a #define for windows target version
// e.g. WINVER / _WIN32_WINNT, see https://devblogs.microsoft.com/oldnewthing/20070411-00/?p=27283
// Unnecessary because we define both in desktop/CMakeLists.txt
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#include <windows.h>

1
src/3rdparty/qtmacgoodies vendored Submodule

View File

@@ -29,17 +29,12 @@ if(NOT MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2")
endif()
# Calling Qt's qCWarning(category, ...) with no params for "..." is a GNU
# extension (C++11 §16.3/4 forbids them). Silence clang's warnings.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
endif()
if(WIN32)
# Enable DEP & ASLR
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /nxcompat /dynamicbase")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /nxcompat /dynamicbase")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
elseif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")

View File

@@ -11,50 +11,43 @@
// For overloading macros by argument count
// See stackoverflow.com/questions/16683146/can-macros-be-overloaded-by-number-of-arguments
// Bugfix 08/09/2019: Broken arg expansion led to always collapsing to 1 arg (XXXX_1 overload result)
// See also: https://stackoverflow.com/questions/9183993/msvc-variadic-macro-expansion
#define OC_ASSERT_GLUE(x, y) x y
#define OC_ASSERT_CAT(A, B) A##B
#define OC_ASSERT_SELECT(NAME, NUM) OC_ASSERT_CAT(NAME##_, NUM)
#define OC_ASSERT_GET_COUNT(_1, _2, _3, COUNT, ...) COUNT
#define OC_ASSERT_EXPAND_ARGS(args) OC_ASSERT_GET_COUNT args
#define OC_ASSERT_VA_SIZE(...) OC_ASSERT_EXPAND_ARGS((__VA_ARGS__, 3, 2, 1, 0))
#define OC_ASSERT_VA_SIZE(...) OC_ASSERT_GET_COUNT(__VA_ARGS__, 3, 2, 1, 0)
#define OC_ASSERT_SELECT2(NAME, COUNT) NAME##COUNT
#define OC_ASSERT_SELECT1(NAME, COUNT) OC_ASSERT_SELECT2(NAME, COUNT)
#define OC_ASSERT_SELECT(NAME, COUNT) OC_ASSERT_SELECT1(NAME, COUNT)
#define OC_ASSERT_OVERLOAD(NAME, ...) OC_ASSERT_GLUE(OC_ASSERT_SELECT(NAME, OC_ASSERT_VA_SIZE(__VA_ARGS__)), \
(__VA_ARGS__))
#define OC_ASSERT_OVERLOAD(NAME, ...) OC_ASSERT_SELECT(NAME, OC_ASSERT_VA_SIZE(__VA_ARGS__)) \
(__VA_ARGS__)
// Default assert: If the condition is false in debug builds, terminate.
//
// Prints a message on failure, even in release builds.
#define ASSERT1(cond) \
#define ASSERT(...) OC_ASSERT_OVERLOAD(ASSERT, __VA_ARGS__)
#define ASSERT_1(cond) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else { \
}
#define ASSERT2(cond, message) \
#define ASSERT_2(cond, message) \
if (!(cond)) { \
OC_ASSERT_MSG("ASSERT: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else { \
}
#define ASSERT(...) OC_ASSERT_OVERLOAD(ASSERT, __VA_ARGS__)
// Enforce condition to be true, even in release builds.
//
// Prints 'message' and aborts execution if 'cond' is false.
#define ENFORCE1(cond) \
#define ENFORCE(...) OC_ASSERT_OVERLOAD(ENFORCE, __VA_ARGS__)
#define ENFORCE_1(cond) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d", #cond, __FILE__, __LINE__); \
} else { \
}
#define ENFORCE2(cond, message) \
#define ENFORCE_2(cond, message) \
if (!(cond)) { \
qFatal("ENFORCE: \"%s\" in file %s, line %d with message: %s", #cond, __FILE__, __LINE__, message); \
} else { \
}
#define ENFORCE(...) OC_ASSERT_OVERLOAD(ENFORCE, __VA_ARGS__)
// An assert that is only present in debug builds: typically used for
// asserts that are too expensive for release mode.

View File

@@ -207,10 +207,7 @@ static inline uint64_t c_jhash64(const uint8_t *k, uint64_t length, uint64_t int
/* handle the last 23 bytes */
c += length;
switch(len) {
// pragma only for GCC (and clang continues to pretend to be it by defining __GNUC__)
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
case 23: c+=((uint64_t)k[22]<<56);
case 22: c+=((uint64_t)k[21]<<48);
case 21: c+=((uint64_t)k[20]<<40);

View File

@@ -281,8 +281,8 @@ int SqlQuery::prepare(const QByteArray &sql, bool allow_failure)
*/
static bool startsWithInsensitive(const QByteArray &a, const char *b)
{
size_t len = strlen(b);
return a.size() >= len && qstrnicmp(a.constData(), b, Utility::convertSizeToUint(len)) == 0;
int len = strlen(b);
return a.size() >= len && qstrnicmp(a.constData(), b, len) == 0;
}
bool SqlQuery::isSelect()

View File

@@ -103,7 +103,6 @@ public:
: _chunk(0)
, _transferid(0)
, _size(0)
, _modtime(0)
, _errorCount(0)
, _valid(false)
{

View File

@@ -396,26 +396,6 @@ void Utility::crash()
*a = 1;
}
// Use this functions to retrieve uint/int (often required by Qt and WIN32) from size_t
// without compiler warnings about possible truncation
uint Utility::convertSizeToUint(size_t &convertVar)
{
if( convertVar > UINT_MAX ) {
//throw std::bad_cast();
convertVar = UINT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<uint>(convertVar);
}
uint Utility::convertSizeToInt(size_t &convertVar)
{
if( convertVar > INT_MAX ) {
//throw std::bad_cast();
convertVar = INT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<int>(convertVar);
}
// read the output of the owncloud --version command from the owncloud
// version that is on disk. This works for most versions of the client,
// because clients that do not yet know the --version flag return the

View File

@@ -55,12 +55,6 @@ namespace Utility {
OCSYNC_EXPORT QByteArray userAgentString();
OCSYNC_EXPORT bool hasLaunchOnStartup(const QString &appName);
OCSYNC_EXPORT void setLaunchOnStartup(const QString &appName, const QString &guiName, bool launch);
OCSYNC_EXPORT uint convertSizeToUint(size_t &convertVar);
OCSYNC_EXPORT uint convertSizeToInt(size_t &convertVar);
#ifdef Q_OS_WIN
OCSYNC_EXPORT DWORD convertSizeToDWORD(size_t &convertVar);
#endif
/**
* Return the amount of free space available.

View File

@@ -90,13 +90,32 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
// TODO: Right now only detection on toggle/startup, not when windows theme is switched while nextcloud is running
static inline bool hasDarkSystray_private()
{
if(Utility::registryGetKeyValue( HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
"SystemUsesLightTheme" ) == 1) {
return false;
}
else {
return true;
bool hasDarkSystray = true;
// Open registry key first, continue only on success (may be legitimately absent in earlier windows versions)
HKEY hKey;
LONG lRes = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey);
// classical windows function - preserve buff size for DWORD, call ExW version, store regkey value in nResult
if (lRes == ERROR_SUCCESS) {
DWORD dwBufferSize(sizeof(DWORD));
DWORD nResult(0);
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw
LONG nError = ::RegQueryValueExW(hKey,
L"SystemUsesLightTheme",
NULL,
NULL,
reinterpret_cast<LPBYTE>(&nResult),
&dwBufferSize);
// if RegQuery returned no error and light theme was found, change systray return value
if (nError == ERROR_SUCCESS && nResult == 1)
hasDarkSystray = false;
return hasDarkSystray;
} else {
// fallback to true if regkey could not be determined
return hasDarkSystray;
}
}
@@ -264,13 +283,4 @@ bool Utility::registryWalkSubKeys(HKEY hRootKey, const QString &subKey, const st
return retCode != ERROR_NO_MORE_ITEMS;
}
DWORD Utility::convertSizeToDWORD(size_t &convertVar)
{
if( convertVar > UINT_MAX ) {
//throw std::bad_cast();
convertVar = UINT_MAX; // intentionally default to wrong value here to not crash: exception handling TBD
}
return static_cast<DWORD>(convertVar);
}
} // namespace OCC

View File

@@ -73,7 +73,7 @@ static void csync_exclude_expand_escapes(QByteArray &input)
line[o++] = line[i];
}
}
input.resize(OCC::Utility::convertSizeToUint(o));
input.resize(o);
}
// See http://support.microsoft.com/kb/74496 and
@@ -288,11 +288,7 @@ void ExcludedFiles::addManualExclude(const QByteArray &expr)
void ExcludedFiles::addManualExclude(const QByteArray &expr, const QByteArray &basePath)
{
#if defined(Q_OS_WIN)
Q_ASSERT(basePath.size() >= 2 && basePath.at(1) == ':');
#else
Q_ASSERT(basePath.startsWith('/'));
#endif
Q_ASSERT(basePath.endsWith('/'));
auto key = basePath;
@@ -326,11 +322,7 @@ bool ExcludedFiles::loadExcludeFile(const QByteArray & basePath, const QString &
csync_exclude_expand_escapes(line);
_allExcludes[basePath].append(line);
}
// nothing to prepare if the user decided to not exclude anything
if(_allExcludes.size())
prepare(basePath);
prepare(basePath);
return true;
}
@@ -346,8 +338,8 @@ bool ExcludedFiles::reloadExcludeFiles()
_fullRegexDir.clear();
bool success = true;
for (const auto& basePath : _excludeFiles.keys()) {
for (const auto& file : _excludeFiles.value(basePath)) {
for (auto basePath : _excludeFiles.keys()) {
for (auto file : _excludeFiles.value(basePath)) {
success = loadExcludeFile(basePath, file);
}
}

View File

@@ -724,8 +724,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
if (ctx->current == LOCAL_REPLICA) {
ASSERT(dirent->path.startsWith(ctx->local.uri)); // path is relative to uri
// "len + 1" to include the slash in-between.
size_t uriLength = strlen(ctx->local.uri);
dirent->path = dirent->path.mid(OCC::Utility::convertSizeToInt(uriLength) + 1);
dirent->path = dirent->path.mid(strlen(ctx->local.uri) + 1);
}
previous_fs = ctx->current_fs;

View File

@@ -38,7 +38,6 @@
#include "c_alloc.h"
#include "c_string.h"
#include "common/filesystembase.h"
#include "common/utility.h"
/* Convert a locale String to UTF8 */
QByteArray c_utf8_from_locale(const mbchar_t *wstr)
@@ -53,10 +52,10 @@ QByteArray c_utf8_from_locale(const mbchar_t *wstr)
size_t len;
len = wcslen(wstr);
/* Call once to get the required size. */
size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, OCC::Utility::convertSizeToInt(len), NULL, 0, NULL, NULL);
size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
if (size_needed > 0) {
dst.resize(size_needed);
WideCharToMultiByte(CP_UTF8, 0, wstr, OCC::Utility::convertSizeToInt(len), dst.data(), size_needed, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, wstr, len, dst.data(), size_needed, NULL, NULL);
}
return dst;
#else
@@ -96,7 +95,7 @@ mbchar_t* c_utf8_string_to_locale(const char *str)
int size_needed;
len = strlen(str);
size_needed = MultiByteToWideChar(CP_UTF8, 0, str, OCC::Utility::convertSizeToInt(len), NULL, 0);
size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
if (size_needed > 0) {
int size_char = (size_needed + 1) * sizeof(mbchar_t);
dst = (mbchar_t*)c_malloc(size_char);
@@ -115,8 +114,7 @@ mbchar_t* c_utf8_string_to_locale(const char *str)
return NULL;
} else {
#ifdef _WIN32
size_t strLength = strlen(str);
QByteArray unc_str = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(str, OCC::Utility::convertSizeToInt(strLength)));
QByteArray unc_str = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(str, strlen(str)));
mbchar_t *dst = c_utf8_string_to_locale(unc_str);
return dst;
#else

View File

@@ -57,7 +57,7 @@ csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
handle = (dhandle_t*)c_malloc(sizeof(dhandle_t));
// the file wildcard has to be attached
size_t len_name = strlen(name);
int len_name = strlen(name);
if( len_name ) {
char *h = NULL;

View File

@@ -104,7 +104,6 @@ set(client_SRCS
guiutility.cpp
elidedlabel.cpp
iconjob.cpp
remotewipe.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
@@ -145,6 +144,8 @@ set(updater_SRCS
IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
list(APPEND client_SRCS settingsdialogmac.cpp)
list(REMOVE_ITEM client_SRCS settingsdialog.cpp)
list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm)
@@ -174,6 +175,14 @@ set(3rdparty_SRC
../3rdparty/kmessagewidget/kmessagewidget.cpp
)
if (APPLE)
list(APPEND 3rdparty_SRC
../3rdparty/qtmacgoodies/src/macpreferenceswindow.mm
../3rdparty/qtmacgoodies/src/macstandardicon.mm
../3rdparty/qtmacgoodies/src/macwindow.mm
)
endif()
if(NOT WIN32)
list(APPEND 3rdparty_SRC ../3rdparty/qtlockedfile/qtlockedfile_unix.cpp)
else()
@@ -329,6 +338,7 @@ ENDIF()
target_include_directories(${APPLICATION_EXECUTABLE} PRIVATE
${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
${CMAKE_SOURCE_DIR}/src/3rdparty/qtmacgoodies/src
${CMAKE_SOURCE_DIR}/src/3rdparty/qtsingleapplication
${CMAKE_SOURCE_DIR}/src/3rdparty/kmessagewidget
${CMAKE_CURRENT_BINARY_DIR}

View File

@@ -368,7 +368,6 @@ void AccountManager::shutdown()
_accounts.clear();
foreach (const auto &acc, accountsCopy) {
emit accountRemoved(acc.data());
emit removeAccountFolders(acc.data());
}
}

View File

@@ -70,6 +70,7 @@ public:
*/
void deleteAccount(AccountState *account);
/**
* Creates an account and sets up some basic handlers.
* Does *not* add the account to the account manager just yet.
@@ -103,7 +104,6 @@ public slots:
Q_SIGNALS:
void accountAdded(AccountState *account);
void accountRemoved(AccountState *account);
void removeAccountFolders(AccountState *account);
private:
AccountManager() {}

View File

@@ -57,6 +57,10 @@
#include "account.h"
#ifdef Q_OS_MAC
#include "settingsdialogmac.h"
#endif
namespace OCC {
Q_LOGGING_CATEGORY(lcAccountSettings, "nextcloud.gui.account.settings", QtInfoMsg)
@@ -143,8 +147,6 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
createAccountToolbox();
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &AccountSettings::slotAccountAdded);
connect(this, &AccountSettings::removeAccountFolders,
AccountManager::instance(), &AccountManager::removeAccountFolders);
connect(ui->_folderList, &QWidget::customContextMenuRequested,
this, &AccountSettings::slotCustomContextMenuRequested);
connect(ui->_folderList, &QAbstractItemView::clicked,
@@ -202,8 +204,6 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
} else {
ui->encryptionMessage->hide();
}
customizeStyle();
}
@@ -278,7 +278,16 @@ void AccountSettings::slotOpenAccountWizard()
if (qgetenv("QT_QPA_PLATFORMTHEME") == "appmenu-qt5" || QSystemTrayIcon::isSystemTrayAvailable()) {
topLevelWidget()->close();
}
#ifdef Q_OS_MAC
qCDebug(lcAccountSettings) << parent() << topLevelWidget();
SettingsDialogMac *sd = qobject_cast<SettingsDialogMac *>(topLevelWidget());
if (sd) {
sd->showActivityPage();
} else {
qFatal("nope");
}
#endif
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), nullptr);
}
@@ -325,9 +334,9 @@ void AccountSettings::slotEncryptionFlagError(const QByteArray& fileId, int http
void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, const QByteArray &token)
{
accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
FolderMetadata emptyMetadata(accountsState()->account());
FolderMetadata emptyMetadata(accountsState()->account());
auto encryptedMetadata = emptyMetadata.encryptedMetadata();
if (encryptedMetadata.isEmpty()) {
//TODO: Mark the folder as unencrypted as the metadata generation failed.
@@ -339,36 +348,36 @@ void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, con
return;
}
auto storeMetadataJob = new StoreMetaDataApiJob(accountsState()->account(), fileId, emptyMetadata.encryptedMetadata());
connect(storeMetadataJob, &StoreMetaDataApiJob::success,
this, &AccountSettings::slotUploadMetadataSuccess);
connect(storeMetadataJob, &StoreMetaDataApiJob::error,
this, &AccountSettings::slotUpdateMetadataError);
connect(storeMetadataJob, &StoreMetaDataApiJob::success,
this, &AccountSettings::slotUploadMetadataSuccess);
connect(storeMetadataJob, &StoreMetaDataApiJob::error,
this, &AccountSettings::slotUpdateMetadataError);
storeMetadataJob->start();
storeMetadataJob->start();
}
void AccountSettings::slotUploadMetadataSuccess(const QByteArray& folderId)
{
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
}
void AccountSettings::slotUpdateMetadataError(const QByteArray& folderId, int httpReturnCode)
{
Q_UNUSED(httpReturnCode);
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
connect(unlockJob, &UnlockEncryptFolderApiJob::success,
this, &AccountSettings::slotUnlockFolderSuccess);
connect(unlockJob, &UnlockEncryptFolderApiJob::error,
this, &AccountSettings::slotUnlockFolderError);
unlockJob->start();
}
void AccountSettings::slotLockForEncryptionError(const QByteArray& fileId, int httpErrorCode)
@@ -735,7 +744,7 @@ void AccountSettings::slotFolderWizardAccepted()
qCInfo(lcAccountSettings) << "Creating folder" << definition.localPath;
if (!dir.mkpath(".")) {
QMessageBox::warning(this, tr("Folder creation failed"),
tr("<p>Could not create local folder <i>%1</i>.</p>")
tr("<p>Could not create local folder <i>%1</i>.")
.arg(QDir::toNativeSeparators(definition.localPath)));
return;
}
@@ -836,16 +845,13 @@ void AccountSettings::showConnectionLabel(const QString &message, QStringList er
"border-width: 1px; border-style: solid; border-color: #aaaaaa;"
"border-radius:5px;");
if (errors.isEmpty()) {
QString msg = message;
Theme::replaceLinkColorStringBackgroundAware(msg);
ui->connectLabel->setText(msg);
ui->connectLabel->setText(message);
ui->connectLabel->setToolTip(QString());
ui->connectLabel->setStyleSheet(QString());
} else {
errors.prepend(message);
QString msg = errors.join(QLatin1String("\n"));
const QString msg = errors.join(QLatin1String("\n"));
qCDebug(lcAccountSettings) << msg;
Theme::replaceLinkColorStringBackgroundAware(msg, QColor("#bb4d4d"));
ui->connectLabel->setText(msg);
ui->connectLabel->setToolTip(QString());
ui->connectLabel->setStyleSheet(errStyle);
@@ -1024,7 +1030,7 @@ void AccountSettings::slotAccountStateChanged()
"<a href='%1'>Click here</a> to re-open the browser.")
.arg(url.toString(QUrl::FullyEncoded)));
} else {
showConnectionLabel(tr("Connecting to %1").arg(serverWithUser));
showConnectionLabel(tr("Connecting to %1...").arg(serverWithUser));
}
} else {
showConnectionLabel(tr("No connection to %1 at %2.")
@@ -1246,18 +1252,6 @@ bool AccountSettings::event(QEvent *e)
return QWidget::event(e);
}
void AccountSettings::slotStyleChanged()
{
customizeStyle();
}
void AccountSettings::customizeStyle()
{
QString msg = ui->connectLabel->text();
Theme::replaceLinkColorStringBackgroundAware(msg);
ui->connectLabel->setText(msg);
}
} // namespace OCC
#include "accountsettings.moc"

View File

@@ -63,13 +63,11 @@ signals:
void openFolderAlias(const QString &);
void showIssuesList(AccountState *account);
void requesetMnemonic();
void removeAccountFolders(AccountState *account);
public slots:
void slotOpenOC();
void slotUpdateQuota(qint64, qint64);
void slotAccountStateChanged();
void slotStyleChanged();
AccountState *accountsState() { return _accountState; }
@@ -130,7 +128,6 @@ private:
bool event(QEvent *) override;
void createAccountToolbox();
void openIgnoredFilesDialog(const QString & absFolderPath);
void customizeStyle();
/// Returns the alias of the selected folder, empty string if none
QString selectedFolderAlias() const;

View File

@@ -187,7 +187,7 @@
<item row="0" column="2">
<widget class="QToolButton" name="_accountToolbox">
<property name="text">
<string notr="true">...</string>
<string>...</string>
</property>
</widget>
</item>

View File

@@ -14,7 +14,6 @@
#include "accountstate.h"
#include "accountmanager.h"
#include "remotewipe.h"
#include "account.h"
#include "creds/abstractcredentials.h"
#include "creds/httpcredentials.h"
@@ -25,11 +24,6 @@
#include <QTimer>
#include <qfontmetrics.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkRequest>
#include <QBuffer>
namespace OCC {
Q_LOGGING_CATEGORY(lcAccountState, "nextcloud.gui.account.state", QtInfoMsg)
@@ -42,12 +36,11 @@ AccountState::AccountState(AccountPtr account)
, _waitingForNewCredentials(false)
, _notificationsEtagResponseHeader("*")
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
, _remoteWipe(new RemoteWipe(_account))
{
qRegisterMetaType<AccountState *>("AccountState*");
connect(account.data(), &Account::invalidCredentials,
this, &AccountState::slotHandleRemoteWipeCheck);
this, &AccountState::slotInvalidCredentials);
connect(account.data(), &Account::credentialsFetched,
this, &AccountState::slotCredentialsFetched);
connect(account.data(), &Account::credentialsAsked,
@@ -310,7 +303,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
break;
case ConnectionValidator::CredentialsWrong:
case ConnectionValidator::CredentialsNotReady:
handleInvalidCredentials();
slotInvalidCredentials();
break;
case ConnectionValidator::SslError:
setState(SignedOut);
@@ -329,20 +322,7 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
}
}
void AccountState::slotHandleRemoteWipeCheck()
{
// make sure it changes account state and icons
signOutByUi();
qCInfo(lcAccountState) << "Invalid credentials for" << _account->url().toString()
<< "checking for remote wipe request";
_waitingForNewCredentials = false;
setState(SignedOut);
}
void AccountState::handleInvalidCredentials()
void AccountState::slotInvalidCredentials()
{
if (isSignedOut() || _waitingForNewCredentials)
return;
@@ -363,7 +343,6 @@ void AccountState::handleInvalidCredentials()
account()->credentials()->askFromUser();
}
void AccountState::slotCredentialsFetched(AbstractCredentials *)
{
// Make a connection attempt, no matter whether the credentials are

View File

@@ -29,7 +29,6 @@ namespace OCC {
class AccountState;
class Account;
class RemoteWipe;
typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
@@ -151,9 +150,6 @@ public:
*/
void setNavigationAppsEtagResponseHeader(const QByteArray &value);
///Asks for user credentials
void handleInvalidCredentials();
public slots:
/// Triggers a ping to the server to update state and
/// connection status and errors.
@@ -168,11 +164,7 @@ signals:
protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
/// When client gets a 401 or 403 checks if server requested remote wipe
/// before asking for user credentials again
void slotHandleRemoteWipeCheck();
void slotInvalidCredentials();
void slotCredentialsFetched(AbstractCredentials *creds);
void slotCredentialsAsked(AbstractCredentials *creds);
@@ -198,13 +190,6 @@ private:
* Milliseconds for which to delay reconnection after 503/maintenance.
*/
int _maintenanceToConnectedDelay;
/**
* Connects remote wipe check with the account
* the log out triggers the check (loads app password -> create request)
*/
RemoteWipe *_remoteWipe;
};
}

View File

@@ -21,7 +21,7 @@ namespace OCC {
bool operator<(const Activity &rhs, const Activity &lhs)
{
return rhs._dateTime > lhs._dateTime;
return rhs._dateTime.toMSecsSinceEpoch() > lhs._dateTime.toMSecsSinceEpoch();
}
bool operator==(const Activity &rhs, const Activity &lhs)

View File

@@ -26,8 +26,6 @@
#include <QPainter>
#include <QApplication>
#define HASQT5_11 (QT_VERSION >= QT_VERSION_CHECK(5,11,0))
namespace OCC {
int ActivityItemDelegate::_iconHeight = 0;
@@ -108,11 +106,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
// subject text rect
QRect actionTextBox = actionIconRect;
#if (HASQT5_11)
int actionTextBoxWidth = fm.horizontalAdvance(actionText);
#else
int actionTextBoxWidth = fm.width(actionText);
#endif
actionTextBox.setTop(option.rect.top() + margin + offset/2);
actionTextBox.setHeight(fm.height());
actionTextBox.setLeft(actionIconRect.right() + margin);
@@ -120,11 +114,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
// message text rect
QRect messageTextBox = actionTextBox;
#if (HASQT5_11)
int messageTextWidth = fm.horizontalAdvance(messageText);
#else
int messageTextWidth = fm.width(messageText);
#endif
int messageTextTop = option.rect.top() + fm.height() + margin;
if(actionText.isEmpty()) messageTextTop = option.rect.top() + margin + offset/2;
messageTextBox.setTop(messageTextTop);
@@ -139,11 +129,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
// time box rect
QRect timeBox = messageTextBox;
QString timeStr = tr("%1").arg(timeText);
#if (HASQT5_11)
int timeTextWidth = fm.horizontalAdvance(timeStr);
#else
int timeTextWidth = fm.width(timeStr);
#endif
int timeTop = option.rect.top() + fm.height() + fm.height() + margin + offset/2;
if(messageText.isEmpty() || actionText.isEmpty())
timeTop = option.rect.top() + fm.height() + margin;
@@ -194,11 +180,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
if(objectType == _remote_share) primaryButton.text = tr("Accept");
if(objectType == _call) primaryButton.text = tr("Join");
#if (HASQT5_11)
primaryButton.rect.setLeft(left - margin * 2 - fm.horizontalAdvance(primaryButton.text));
#else
primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
#endif
// save info to be able to filter mouse clicks
_buttonHeight = buttonSize;
@@ -214,12 +196,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
// Primary button will be 'open browser'
primaryButton.text = tr("Open Browser");
#if (HASQT5_11)
primaryButton.rect.setLeft(left - margin * 2 - fm.horizontalAdvance(primaryButton.text));
#else
primaryButton.rect.setLeft(left - margin * 2 - fm.width(primaryButton.text));
#endif
// save info to be able to filter mouse clicks
_buttonHeight = buttonSize;

View File

@@ -64,12 +64,20 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
case ActivityItemDelegate::PathRole:
if(!a._file.isEmpty()){
auto folder = FolderMan::instance()->folder(a._folder);
list = FolderMan::instance()->findFileInLocalFolders(folder->remotePath(), ast->account());
QString relPath(a._file);
if(folder) relPath.prepend(folder->remotePath());
list = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());
if (list.count() > 0) {
return QVariant(list.at(0));
}
// File does not exist anymore? Let's try to open its path
list = FolderMan::instance()->findFileInLocalFolders(QFileInfo(relPath).path(), ast->account());
if (list.count() > 0) {
return QVariant(list.at(0));
}
}
return QVariant();
break;
case ActivityItemDelegate::ActionsLinksRole:{
QList<QVariant> customList;
foreach (ActivityLink customItem, a._links) {
@@ -78,6 +86,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
customList << customVariant;
}
return customList;
break;
}
case ActivityItemDelegate::ActionIconRole:
if(a._type == Activity::NotificationType){
@@ -220,29 +229,6 @@ void ActivityListModel::addErrorToActivityList(Activity activity) {
combineActivityLists();
}
void ActivityListModel::addIgnoredFileToList(Activity newActivity) {
qCInfo(lcActivity) << "First checking for duplicates then add file to the notification list of ignored files: " << newActivity._file;
bool duplicate = false;
if(_listOfIgnoredFiles.size() == 0){
_notificationIgnoredFiles = newActivity;
_notificationIgnoredFiles._subject = tr("Files from the ignore list as well as symbolic links are not synced. This includes:");
_listOfIgnoredFiles.append(newActivity);
return;
}
foreach(Activity activity, _listOfIgnoredFiles){
if(activity._file == newActivity._file){
duplicate = true;
break;
}
}
if(!duplicate){
_notificationIgnoredFiles._message.append(", " + newActivity._file);
}
}
void ActivityListModel::addNotificationToActivityList(Activity activity) {
qCInfo(lcActivity) << "Notification successfully added to the notification list: " << activity._subject;
_notificationLists.prepend(activity);
@@ -290,31 +276,22 @@ void ActivityListModel::removeActivityFromActivityList(Activity activity) {
}
}
void ActivityListModel::combineActivityLists()
{
ActivityList resultList;
if(_notificationErrorsLists.count() > 0) {
std::sort(_notificationErrorsLists.begin(), _notificationErrorsLists.end());
resultList.append(_notificationErrorsLists);
}
if(_listOfIgnoredFiles.size() > 0)
resultList.append(_notificationIgnoredFiles);
std::sort(_notificationErrorsLists.begin(), _notificationErrorsLists.end());
resultList.append(_notificationErrorsLists);
if(_notificationLists.count() > 0) {
std::sort(_notificationLists.begin(), _notificationLists.end());
resultList.append(_notificationLists);
}
std::sort(_notificationLists.begin(), _notificationLists.end());
resultList.append(_notificationLists);
if(_syncFileItemLists.count() > 0) {
std::sort(_syncFileItemLists.begin(), _syncFileItemLists.end());
resultList.append(_syncFileItemLists);
}
std::sort(_syncFileItemLists.begin(), _syncFileItemLists.end());
resultList.append(_syncFileItemLists);
if(_activityLists.count() > 0) {
std::sort(_activityLists.begin(), _activityLists.end());
resultList.append(_activityLists);
}
std::sort(_activityLists.begin(), _activityLists.end());
resultList.append(_activityLists);
beginResetModel();
_finalList.clear();

View File

@@ -51,7 +51,6 @@ public:
void addNotificationToActivityList(Activity activity);
void clearNotifications();
void addErrorToActivityList(Activity activity);
void addIgnoredFileToList(Activity newActivity);
void addSyncFileItemToActivityList(Activity activity);
void removeActivityFromActivityList(int row);
void removeActivityFromActivityList(Activity activity);
@@ -74,8 +73,6 @@ private:
ActivityList _activityLists;
ActivityList _syncFileItemLists;
ActivityList _notificationLists;
ActivityList _listOfIgnoredFiles;
Activity _notificationIgnoredFiles;
ActivityList _notificationErrorsLists;
ActivityList _finalList;
AccountState *_accountState;

View File

@@ -127,12 +127,11 @@ void ActivityWidget::slotProgressInfo(const QString &folder, const ProgressInfo
}
if(activity._status == SyncFileItem::FileIgnored && !QFileInfo(f->path() + activity._file).exists()) {
if(activity._status == SyncFileItem::FileIgnored && !QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
}
if(!QFileInfo(f->path() + activity._file).exists()){
_model->removeActivityFromActivityList(activity);
continue;
@@ -192,12 +191,8 @@ void ActivityWidget::slotItemCompleted(const QString &folder, const SyncFileItem
qCWarning(lcActivity) << "Item " << item->_file << " retrieved resulted in error " << item->_errorString;
activity._subject = item->_errorString;
if(item->_status == SyncFileItem::Status::FileIgnored) {
_model->addIgnoredFileToList(activity);
} else {
// add 'protocol error' to activity list
_model->addErrorToActivityList(activity);
}
// add 'protocol error' to activity list
_model->addErrorToActivityList(activity);
}
}
}

View File

@@ -108,7 +108,6 @@ Application::Application(int &argc, char **argv)
, _userTriggeredConnect(false)
, _debugMode(false)
, _backgroundMode(false)
, _isQuitting(false)
{
_startedAt.start();
@@ -265,8 +264,6 @@ Application::~Application()
}
// Remove the account from the account manager so it can be deleted.
disconnect(AccountManager::instance(), &AccountManager::accountRemoved,
this, &Application::slotAccountStateRemoved);
AccountManager::instance()->shutdown();
}
@@ -286,7 +283,7 @@ void Application::slotAccountStateRemoved(AccountState *accountState)
}
// if there is no more account, show the wizard.
if (!_isQuitting && AccountManager::instance()->accounts().isEmpty()) {
if (AccountManager::instance()->accounts().isEmpty()) {
// allow to add a new account if there is non any more. Always think
// about single account theming!
OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int)));
@@ -309,8 +306,6 @@ void Application::slotAccountStateAdded(AccountState *accountState)
void Application::slotCleanup()
{
_isQuitting = true;
AccountManager::instance()->save();
FolderMan::instance()->unloadAndDeleteAllFolders();

View File

@@ -114,7 +114,6 @@ private:
bool _userTriggeredConnect;
bool _debugMode;
bool _backgroundMode;
bool _isQuitting;
ClientProxy _proxy;

View File

@@ -52,11 +52,7 @@ void Flow2Auth::openBrowser()
// Step 1: Initiate a login, do an anonymous POST request
QUrl url = Utility::concatUrlPath(_account->url().toString(), QLatin1String("/index.php/login/v2"));
// add 'Content-Length: 0' header (see https://github.com/nextcloud/desktop/issues/1473)
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentLengthHeader, "0");
auto job = _account->sendRequest("POST", url, req);
auto job = _account->sendRequest("POST", url);
job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec()));
QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) {

View File

@@ -147,31 +147,25 @@ void WebFlowCredentials::fetchFromKeychain() {
}
void WebFlowCredentials::askFromUser() {
// Determine if the old flow has to be used (GS for now)
// Do a DetermineAuthTypeJob to make sure that the server is still using Flow2
DetermineAuthTypeJob *job = new DetermineAuthTypeJob(_account->sharedFromThis(), this);
connect(job, &DetermineAuthTypeJob::authType, [this](DetermineAuthTypeJob::AuthType type) {
// LoginFlowV2 > WebViewFlow > OAuth > Shib > Basic
bool useFlow2 = (type != DetermineAuthTypeJob::WebViewFlow);
// LoginFlowV2 > WebViewFlow > OAuth > Shib > Basic
bool useFlow2 = (_account->serverVersionInt() >= Account::makeServerVersion(16, 0, 0));
_askDialog = new WebFlowCredentialsDialog(_account, useFlow2);
_askDialog = new WebFlowCredentialsDialog(_account, useFlow2);
if (!useFlow2) {
QUrl url = _account->url();
QString path = url.path() + "/index.php/login/flow";
url.setPath(path);
_askDialog->setUrl(url);
}
if (!useFlow2) {
QUrl url = _account->url();
QString path = url.path() + "/index.php/login/flow";
url.setPath(path);
_askDialog->setUrl(url);
}
QString msg = tr("You have been logged out of %1 as user %2. Please login again")
.arg(_account->displayName(), _user);
_askDialog->setInfo(msg);
QString msg = tr("You have been logged out of %1 as user %2. Please login again")
.arg(_account->displayName(), _user);
_askDialog->setInfo(msg);
_askDialog->show();
_askDialog->show();
connect(_askDialog, &WebFlowCredentialsDialog::urlCatched, this, &WebFlowCredentials::slotAskFromUserCredentialsProvided);
});
job->start();
connect(_askDialog, &WebFlowCredentialsDialog::urlCatched, this, &WebFlowCredentials::slotAskFromUserCredentialsProvided);
qCDebug(lcWebFlowCredentials()) << "User needs to reauth!";
}
@@ -246,68 +240,15 @@ void WebFlowCredentials::slotWriteClientCertPEMJobDone()
{
// write ssl key if there is one
if (!_clientSslKey.isNull()) {
// Windows workaround: Split the private key into chunks of 2048 bytes,
// to allow 4k (4096 bit) keys to be saved (obey Windows's limits)
_clientSslKeyChunkBufferPEM = _clientSslKey.toPem();
_clientSslKeyChunkCount = 0;
writeSingleClientKeyChunkPEM(nullptr);
} else {
// no key, just write credentials
slotWriteClientKeyPEMJobDone();
}
}
void WebFlowCredentials::writeSingleClientKeyChunkPEM(QKeychain::Job *incomingJob)
{
// errors?
if (incomingJob) {
WritePasswordJob *writeJob = static_cast<WritePasswordJob *>(incomingJob);
if (writeJob->error() != NoError) {
qCWarning(lcWebFlowCredentials) << "Error while writing client CA key chunk" << writeJob->errorString();
_clientSslKeyChunkBufferPEM.clear();
}
}
// write a key chunk if there is any in the buffer
if (!_clientSslKeyChunkBufferPEM.isEmpty()) {
#if defined(Q_OS_WIN)
// Windows workaround: Split the private key into chunks of 2048 bytes,
// to allow 4k (4096 bit) keys to be saved (obey Windows's limits)
auto chunk = _clientSslKeyChunkBufferPEM.left(_clientSslKeyChunkSize);
_clientSslKeyChunkBufferPEM = _clientSslKeyChunkBufferPEM.right(_clientSslKeyChunkBufferPEM.size() - chunk.size());
#else
// write full key in one slot on non-Windows, as usual
auto chunk = _clientSslKeyChunkBufferPEM;
_clientSslKeyChunkBufferPEM.clear();
#endif
auto index = (_clientSslKeyChunkCount++);
// keep the limit
if (_clientSslKeyChunkCount > _clientSslKeyMaxChunks) {
qCWarning(lcWebFlowCredentials) << "Maximum client key chunk count exceeded while writing slot" << QString::number(index) << "cutting off after" << QString::number(_clientSslKeyMaxChunks) << "chunks";
_clientSslKeyChunkBufferPEM.clear();
slotWriteClientKeyPEMJobDone();
return;
}
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, &Job::finished, this, &WebFlowCredentials::writeSingleClientKeyChunkPEM);
// only add the key's (sub)"index" after the first element, to stay compatible with older versions and non-Windows
job->setKey(keychainKey(_account->url().toString(), _user + clientKeyPEMC + (index > 0 ? (QString(".") + QString::number(index)) : QString()), _account->id()));
job->setBinaryData(chunk);
connect(job, &Job::finished, this, &WebFlowCredentials::slotWriteClientKeyPEMJobDone);
job->setKey(keychainKey(_account->url().toString(), _user + clientKeyPEMC, _account->id()));
job->setBinaryData(_clientSslKey.toPem());
job->start();
chunk.clear();
} else {
// no key, just write credentials
slotWriteClientKeyPEMJobDone();
}
}
@@ -323,7 +264,7 @@ void WebFlowCredentials::writeSingleClientCaCertPEM()
// keep the limit
if (index > (_clientSslCaCertificatesMaxCount - 1)) {
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while writing slot" << QString::number(index) << "cutting off after" << QString::number(_clientSslCaCertificatesMaxCount) << "certs";
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while writing slot" << QString::number(index) << "), cutting off after " << QString::number(_clientSslCaCertificatesMaxCount) << "certs";
_clientSslCaCertificatesWriteQueue.clear();
@@ -417,8 +358,6 @@ void WebFlowCredentials::forgetSensitiveData() {
fetchUser();
_account->deleteAppPassword();
const QString kck = keychainKey(_account->url().toString(), _user, _account->id());
if (kck.isEmpty()) {
qCDebug(lcWebFlowCredentials()) << "InvalidateToken: User is empty, bailing out!";
@@ -432,7 +371,14 @@ void WebFlowCredentials::forgetSensitiveData() {
invalidateToken();
deleteKeychainEntries();
/* IMPORTANT
/* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
* Disabled as long as selecting another cert is not supported by the UI.
*
* Being able to specify a new certificate is important anyway: expiry etc.
*/
//deleteKeychainEntries();
}
void WebFlowCredentials::setAccount(Account *account) {
@@ -470,9 +416,6 @@ void WebFlowCredentials::slotFinished(QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NoError) {
_credentialsValid = true;
/// Used later for remote wipe
_account->writeAppPasswordOnce(_password);
}
}
@@ -518,9 +461,6 @@ void WebFlowCredentials::slotReadClientCertPEMJobDone(QKeychain::Job *incomingJo
}
// Load key too
_clientSslKeyChunkCount = 0;
_clientSslKeyChunkBufferPEM.clear();
const QString kck = keychainKey(
_account->url().toString(),
_user + clientKeyPEMC,
@@ -536,58 +476,23 @@ void WebFlowCredentials::slotReadClientCertPEMJobDone(QKeychain::Job *incomingJo
void WebFlowCredentials::slotReadClientKeyPEMJobDone(QKeychain::Job *incomingJob)
{
// Errors or next key chunk?
// Store key in memory
ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(incomingJob);
if (readJob) {
if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
_clientSslKeyChunkBufferPEM.append(readJob->binaryData());
_clientSslKeyChunkCount++;
#if defined(Q_OS_WIN)
// try to fetch next chunk
if (_clientSslKeyChunkCount < _clientSslKeyMaxChunks) {
const QString kck = keychainKey(
_account->url().toString(),
_user + clientKeyPEMC + QString(".") + QString::number(_clientSslKeyChunkCount),
_keychainMigration ? QString() : _account->id());
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadClientKeyPEMJobDone);
job->start();
return;
} else {
qCWarning(lcWebFlowCredentials) << "Maximum client key chunk count reached, ignoring after" << _clientSslKeyMaxChunks;
}
#endif
} else {
if (readJob->error() != QKeychain::Error::EntryNotFound ||
((readJob->error() == QKeychain::Error::EntryNotFound) && _clientSslKeyChunkCount == 0)) {
qCWarning(lcWebFlowCredentials) << "Unable to read client key chunk slot" << QString::number(_clientSslKeyChunkCount) << readJob->errorString();
}
}
}
// Store key in memory
if (_clientSslKeyChunkBufferPEM.size() > 0) {
QByteArray clientKeyPEM = readJob->binaryData();
// FIXME Unfortunately Qt has a bug and we can't just use QSsl::Opaque to let it
// load whatever we have. So we try until it works.
_clientSslKey = QSslKey(_clientSslKeyChunkBufferPEM, QSsl::Rsa);
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Rsa);
if (_clientSslKey.isNull()) {
_clientSslKey = QSslKey(_clientSslKeyChunkBufferPEM, QSsl::Dsa);
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Dsa);
}
if (_clientSslKey.isNull()) {
_clientSslKey = QSslKey(_clientSslKeyChunkBufferPEM, QSsl::Ec);
_clientSslKey = QSslKey(clientKeyPEM, QSsl::Ec);
}
if (_clientSslKey.isNull()) {
qCWarning(lcWebFlowCredentials) << "Could not load SSL key into Qt!";
}
// clear key chunk buffer, but don't set _clientSslKeyChunkCount to zero because we need it for deleteKeychainEntries
_clientSslKeyChunkBufferPEM.clear();
}
// Start fetching client CA certs
@@ -612,7 +517,7 @@ void WebFlowCredentials::readSingleClientCaCertPEM()
connect(job, &Job::finished, this, &WebFlowCredentials::slotReadClientCaCertsPEMJobDone);
job->start();
} else {
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while reading, ignoring after" << _clientSslCaCertificatesMaxCount;
qCWarning(lcWebFlowCredentials) << "Maximum client CA cert count exceeded while reading, ignoring after " << _clientSslCaCertificatesMaxCount;
slotReadClientCaCertsPEMJobDone(nullptr);
}
@@ -634,8 +539,8 @@ void WebFlowCredentials::slotReadClientCaCertsPEMJobDone(QKeychain::Job *incomin
return;
} else {
if (readJob->error() != QKeychain::Error::EntryNotFound ||
((readJob->error() == QKeychain::Error::EntryNotFound) && _clientSslCaCertificates.count() == 0)) {
qCWarning(lcWebFlowCredentials) << "Unable to read client CA cert slot" << QString::number(_clientSslCaCertificates.count()) << readJob->errorString();
(readJob->error() == QKeychain::Error::EntryNotFound) && _clientSslCaCertificates.count() == 0) {
qCWarning(lcWebFlowCredentials) << "Unable to read client CA cert slot " << QString::number(_clientSslCaCertificates.count()) << readJob->errorString();
}
}
}
@@ -691,7 +596,7 @@ void WebFlowCredentials::deleteKeychainEntries(bool oldKeychainEntries) {
auto startDeleteJob = [this, oldKeychainEntries](QString user) {
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setInsecureFallback(true);
job->setKey(keychainKey(_account->url().toString(),
user,
oldKeychainEntries ? QString() : _account->id()));
@@ -699,34 +604,12 @@ void WebFlowCredentials::deleteKeychainEntries(bool oldKeychainEntries) {
};
startDeleteJob(_user);
startDeleteJob(_user + clientKeyPEMC);
startDeleteJob(_user + clientCertificatePEMC);
/* IMPORTANT - remove later - FIXME MS@2019-12-07 -->
* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
* Disabled as long as selecting another cert is not supported by the UI.
*
* Being able to specify a new certificate is important anyway: expiry etc.
*
* We introduce this dirty hack here, to allow deleting them upon Remote Wipe.
*/
if(_account->isRemoteWipeRequested_HACK()) {
// <-- FIXME MS@2019-12-07
startDeleteJob(_user + clientKeyPEMC);
startDeleteJob(_user + clientCertificatePEMC);
for (auto i = 0; i < _clientSslCaCertificates.count(); i++) {
startDeleteJob(_user + clientCaCertificatePEMC + QString::number(i));
}
#if defined(Q_OS_WIN)
// also delete key sub-chunks (Windows workaround)
for (auto i = 1; i < _clientSslKeyChunkCount; i++) {
startDeleteJob(_user + clientKeyPEMC + QString(".") + QString::number(i));
}
#endif
// FIXME MS@2019-12-07 -->
for (auto i = 0; i < _clientSslCaCertificates.count(); i++) {
startDeleteJob(_user + clientCaCertificatePEMC + QString::number(i));
}
// <-- FIXME MS@2019-12-07
}
}

View File

@@ -83,7 +83,7 @@ private:
void writeSingleClientCaCertPEM();
/*
* Since we're limited by Windows limits, we just create our own
* Since we're limited by Windows limits we just create our own
* limit to avoid evil things happening by endless recursion
*
* Better than storing the count and relying on maybe-hacked values
@@ -91,19 +91,6 @@ private:
static constexpr int _clientSslCaCertificatesMaxCount = 10;
QQueue<QSslCertificate> _clientSslCaCertificatesWriteQueue;
/*
* Workaround: ...and this time only on Windows:
*
* Split the private key into chunks of 2048 bytes,
* to allow 4k (4096 bit) keys to be saved (see limits above)
*/
void writeSingleClientKeyChunkPEM(QKeychain::Job *incomingJob);
static constexpr int _clientSslKeyChunkSize = 2048;
static constexpr int _clientSslKeyMaxChunks = 10;
int _clientSslKeyChunkCount = 0;
QByteArray _clientSslKeyChunkBufferPEM;
protected:
/** Reads data from keychain locations
*

View File

@@ -417,13 +417,6 @@ void Folder::createGuiLog(const QString &filename, LogStatus status, int count,
text = tr("%1 could not be synced due to an error. See the log for details.").arg(file);
}
break;
case LogStatusFileLocked:
if (count > 1) {
text = tr("%1 and %n other file(s) are currently locked.", "", count -1).arg(file);
} else {
text = tr("%1 is currently locked.").arg(file);
}
break;
}
if (!text.isEmpty()) {
@@ -902,19 +895,13 @@ void Folder::slotItemCompleted(const SyncFileItemPtr &item)
}
// add new directories or remove gone away dirs to the watcher
if (_folderWatcher && item->isDirectory()) {
switch (item->_instruction) {
case CSYNC_INSTRUCTION_NEW:
_folderWatcher->addPath(path() + item->_file);
break;
case CSYNC_INSTRUCTION_REMOVE:
_folderWatcher->removePath(path() + item->_file);
break;
case CSYNC_INSTRUCTION_RENAME:
_folderWatcher->removePath(path() + item->_file);
_folderWatcher->addPath(path() + item->destination());
break;
}
if (item->isDirectory() && item->_instruction == CSYNC_INSTRUCTION_NEW) {
if (_folderWatcher)
_folderWatcher->addPath(path() + item->_file);
}
if (item->isDirectory() && item->_instruction == CSYNC_INSTRUCTION_REMOVE) {
if (_folderWatcher)
_folderWatcher->removePath(path() + item->_file);
}
// Success and failure of sync items adjust what the next sync is
@@ -1085,7 +1072,7 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel
if (!cfgFile.promptDeleteFiles())
return;
QString msg = dir == SyncFileItem::Down ? tr("All files in the sync folder '%1' were deleted on the server.\n"
QString msg = dir == SyncFileItem::Down ? tr("All files in the sync folder '%1' folder were deleted on the server.\n"
"These deletes will be synchronized to your local sync folder, making such files "
"unavailable unless you have a right to restore. \n"
"If you decide to restore the files, they will be re-synced with the server if you have rights to do so.\n"

View File

@@ -75,7 +75,7 @@ FolderMan::FolderMan(QObject *parent)
this, &FolderMan::slotScheduleFolderByTime);
_timeScheduler.start();
connect(AccountManager::instance(), &AccountManager::removeAccountFolders,
connect(AccountManager::instance(), &AccountManager::accountRemoved,
this, &FolderMan::slotRemoveFoldersForAccount);
connect(_lockWatcher.data(), &LockWatcher::fileUnlocked,
@@ -443,7 +443,7 @@ void FolderMan::slotFolderSyncPaused(Folder *f, bool paused)
void FolderMan::slotFolderCanSyncChanged()
{
Folder *f = qobject_cast<Folder *>(sender());
ASSERT(f);
ASSERT(f);
if (f->canSync()) {
_socketApi->slotRegisterPath(f->alias());
} else {
@@ -562,7 +562,7 @@ void FolderMan::slotEtagJobDestroyed(QObject * /*o*/)
void FolderMan::slotRunOneEtagJob()
{
if (_currentEtagJob.isNull()) {
Folder *folder = nullptr;
Folder *folder;
foreach (Folder *f, _folderMap) {
if (f->etagJob()) {
// Caveat: always grabs the first folder with a job, but we think this is Ok for now and avoids us having a seperate queue.
@@ -1084,73 +1084,6 @@ bool FolderMan::startFromScratch(const QString &localFolder)
return true;
}
void FolderMan::slotWipeFolderForAccount(AccountState *accountState)
{
QVarLengthArray<Folder *, 16> foldersToRemove;
Folder::MapIterator i(_folderMap);
while (i.hasNext()) {
i.next();
Folder *folder = i.value();
if (folder->accountState() == accountState) {
foldersToRemove.append(folder);
}
}
bool success = false;
foreach (const auto &f, foldersToRemove) {
if (!f) {
qCCritical(lcFolderMan) << "Can not remove null folder";
return;
}
qCInfo(lcFolderMan) << "Removing " << f->alias();
const bool currentlyRunning = (_currentSyncFolder == f);
if (currentlyRunning) {
// abort the sync now
terminateSyncProcess();
}
if (_scheduledFolders.removeAll(f) > 0) {
emit scheduleQueueChanged();
}
// wipe database
f->wipe();
// wipe data
QDir userFolder(f->path());
if (userFolder.exists()) {
success = userFolder.removeRecursively();
if (!success) {
qCWarning(lcFolderMan) << "Failed to remove existing folder " << f->path();
} else {
qCInfo(lcFolderMan) << "wipe: Removed file " << f->path();
}
} else {
success = true;
qCWarning(lcFolderMan) << "folder does not exist, can not remove.";
}
f->setSyncPaused(true);
// remove the folder configuration
f->removeFromSettings();
unloadFolder(f);
if (currentlyRunning) {
delete f;
}
_navigationPaneHelper.scheduleUpdateCloudStorageRegistry();
}
emit folderListChanged(_folderMap);
emit wipeDone(accountState, success);
}
void FolderMan::setDirtyProxy()
{
foreach (Folder *f, _folderMap.values()) {

View File

@@ -207,11 +207,6 @@ signals:
*/
void folderListChanged(const Folder::Map &);
/**
* Emitted once slotRemoveFoldersForAccount is done wiping
*/
void wipeDone(AccountState *account, bool success);
public slots:
/**
@@ -236,9 +231,6 @@ public slots:
// slot to schedule an ETag job (from Folder only)
void slotScheduleETagJob(const QString &alias, RequestEtagJob *job);
/** Wipe folder */
void slotWipeFolderForAccount(AccountState *accountState);
private slots:
void slotFolderSyncPaused(Folder *, bool paused);
void slotFolderCanSyncChanged();

View File

@@ -168,7 +168,6 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QString itemString = qvariant_cast<QString>(index.data(SyncProgressItemString));
int warningCount = qvariant_cast<int>(index.data(WarningCount));
bool syncOngoing = qvariant_cast<bool>(index.data(SyncRunning));
QDateTime syncDate = qvariant_cast<QDateTime>(index.data(SyncDate));
bool syncEnabled = qvariant_cast<bool>(index.data(FolderAccountConnected));
QRect iconRect = option.rect;
@@ -253,7 +252,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
if (!showProgess) {
painter->setFont(subFont);
QString elidedRemotePathText = subFm.elidedText(
tr("Synchronized with local folder (%1)").arg(syncDate.toTimeSpec(Qt::LocalTime).toString(Qt::SystemLocaleShortDate)),
tr("Synchronized with local folder"),
Qt::ElideRight, remotePathRect.width());
painter->drawText(QStyle::visualRect(option.direction, option.rect, remotePathRect),
textAlign, elidedRemotePathText);

View File

@@ -44,7 +44,6 @@ public:
SyncProgressItemString,
WarningCount,
SyncRunning,
SyncDate,
AddButton // 1 = enabled; 2 = disabled
};

View File

@@ -186,7 +186,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
return QVariant(tr("Error while loading the list of folders from the server.")
+ QString("\n") + x->_lastErrorString);
} else {
return tr("Fetching folder list from server");
return tr("Fetching folder list from server...");
}
break;
default:
@@ -218,8 +218,6 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
return f->syncResult().errorStrings();
case FolderStatusDelegate::SyncRunning:
return f->syncResult().status() == SyncResult::SyncRunning;
case FolderStatusDelegate::SyncDate:
return f->syncResult().syncTime();
case FolderStatusDelegate::HeaderRole:
return f->shortGuiRemotePathOrAppName();
case FolderStatusDelegate::FolderAliasRole:
@@ -1099,15 +1097,15 @@ void FolderStatusModel::slotFolderSyncStateChange(Folder *f)
}
QString message;
if (pos <= 0) {
message = tr("Waiting");
message = tr("Waiting...");
} else {
message = tr("Waiting for %n other folder(s)", "", pos);
message = tr("Waiting for %n other folder(s)...", "", pos);
}
pi = SubFolderInfo::Progress();
pi._overallSyncString = message;
} else if (state == SyncResult::SyncPrepare) {
pi = SubFolderInfo::Progress();
pi._overallSyncString = tr("Preparing to sync");
pi._overallSyncString = tr("Preparing to sync...");
} else if (state == SyncResult::Problem || state == SyncResult::Success) {
// Reset the progress info after a sync.
pi = SubFolderInfo::Progress();

View File

@@ -19,8 +19,6 @@
#include "folderwatcher.h"
#include "folderwatcher_win.h"
#include "common/utility.h"
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
@@ -54,7 +52,7 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
// QVarLengthArray ensures the stack-buffer is aligned like double and qint64.
QVarLengthArray<char, 4096 * 10> fileNotifyBuffer;
fileNotifyBuffer.resize(OCC::Utility::convertSizeToInt(fileNotifyBufferSize));
fileNotifyBuffer.resize(fileNotifyBufferSize);
const size_t fileNameBufferSize = 4096;
TCHAR fileNameBuffer[fileNameBufferSize];
@@ -68,7 +66,7 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
DWORD dwBytesReturned = 0;
SecureZeroMemory(pFileNotifyBuffer, fileNotifyBufferSize);
if (!ReadDirectoryChangesW(_directory, (LPVOID)pFileNotifyBuffer,
OCC::Utility::convertSizeToDWORD(fileNotifyBufferSize), true,
fileNotifyBufferSize, true,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwBytesReturned,
&overlapped,
@@ -115,7 +113,7 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
FILE_NOTIFY_INFORMATION *curEntry = pFileNotifyBuffer;
forever {
size_t len = curEntry->FileNameLength / 2;
QString file = _path + "\\" + QString::fromWCharArray(curEntry->FileName, OCC::Utility::convertSizeToInt(len));
QString file = _path + "\\" + QString::fromWCharArray(curEntry->FileName, len);
// Unless the file was removed or renamed, get its full long name
// TODO: We could still try expanding the path in the tricky cases...
@@ -124,7 +122,7 @@ void WatcherThread::watchChanges(size_t fileNotifyBufferSize,
&& curEntry->Action != FILE_ACTION_RENAMED_OLD_NAME) {
size_t longNameSize = GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), fileNameBuffer, fileNameBufferSize);
if (longNameSize > 0) {
longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(fileNameBuffer), OCC::Utility::convertSizeToInt(longNameSize));
longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(fileNameBuffer), longNameSize);
} else {
qCWarning(lcFolderWatcher) << "Error converting file name to full length, keeping original name.";
}

View File

@@ -107,7 +107,7 @@
<enum>QFrame::Plain</enum>
</property>
<property name="text">
<string notr="true">TextLabel</string>
<string>TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@@ -26,7 +26,6 @@
#include "updater/updater.h"
#include "updater/ocupdater.h"
#include "ignorelisteditor.h"
#include "common/utility.h"
#include "config.h"
@@ -36,12 +35,6 @@
#include <QDir>
#include <QScopedValueRollback>
#define QTLEGACY (QT_VERSION < QT_VERSION_CHECK(5,9,0))
#if !(QTLEGACY)
#include <QOperatingSystemVersion>
#endif
namespace OCC {
GeneralSettings::GeneralSettings(QWidget *parent)
@@ -57,13 +50,6 @@ GeneralSettings::GeneralSettings(QWidget *parent)
connect(_ui->showInExplorerNavigationPaneCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotShowInExplorerNavigationPane);
// Rename 'Explorer' appropriately on non-Windows
#ifdef Q_OS_MAC
QString txt = _ui->showInExplorerNavigationPaneCheckBox->text();
txt.replace(QString::fromLatin1("Explorer"), QString::fromLatin1("Finder"));
_ui->showInExplorerNavigationPaneCheckBox->setText(txt);
#endif
_ui->autostartCheckBox->setChecked(Utility::hasLaunchOnStartup(Theme::instance()->appName()));
connect(_ui->autostartCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::slotToggleLaunchOnStartup);
@@ -77,8 +63,7 @@ GeneralSettings::GeneralSettings(QWidget *parent)
connect(_ui->legalNoticeButton, &QPushButton::clicked, this, &GeneralSettings::slotShowLegalNotice);
loadMiscSettings();
// updater info now set in: customizeStyle
//slotUpdateInfo();
slotUpdateInfo();
// misc
connect(_ui->monoIconsCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
@@ -94,13 +79,9 @@ GeneralSettings::GeneralSettings(QWidget *parent)
// Hide on non-Windows, or WindowsVersion < 10.
// The condition should match the default value of ConfigFile::showInExplorerNavigationPane.
#ifdef Q_OS_WIN
#if QTLEGACY
if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS10)
#else
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows10)
#endif
_ui->showInExplorerNavigationPaneCheckBox->setVisible(false);
if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS10)
#endif
_ui->showInExplorerNavigationPaneCheckBox->setVisible(false);
/* Set the left contents margin of the layout to zero to make the checkboxes
* align properly vertically , fixes bug #3758
@@ -117,8 +98,6 @@ GeneralSettings::GeneralSettings(QWidget *parent)
// accountAdded means the wizard was finished and the wizard might change some options.
connect(AccountManager::instance(), &AccountManager::accountAdded, this, &GeneralSettings::loadMiscSettings);
customizeStyle();
}
GeneralSettings::~GeneralSettings()
@@ -159,11 +138,7 @@ void GeneralSettings::slotUpdateInfo()
connect(updater, &OCUpdater::downloadStateChanged, this, &GeneralSettings::slotUpdateInfo, Qt::UniqueConnection);
connect(_ui->restartButton, &QAbstractButton::clicked, updater, &OCUpdater::slotStartInstaller, Qt::UniqueConnection);
connect(_ui->restartButton, &QAbstractButton::clicked, qApp, &QApplication::quit, Qt::UniqueConnection);
QString status = updater->statusString();
Theme::replaceLinkColorStringBackgroundAware(status);
_ui->updateStateLabel->setText(status);
_ui->updateStateLabel->setText(updater->statusString());
_ui->restartButton->setVisible(updater->downloadState() == OCUpdater::DownloadComplete);
} else {
// can't have those infos from sparkle currently
@@ -225,20 +200,4 @@ void GeneralSettings::slotShowLegalNotice()
delete notice;
}
void GeneralSettings::slotStyleChanged()
{
customizeStyle();
}
void GeneralSettings::customizeStyle()
{
// setup about section
QString about = Theme::instance()->about();
Theme::replaceLinkColorStringBackgroundAware(about);
_ui->aboutLabel->setText(about);
// updater info
slotUpdateInfo();
}
} // namespace OCC

View File

@@ -39,9 +39,6 @@ public:
~GeneralSettings();
QSize sizeHint() const override;
public slots:
void slotStyleChanged();
private slots:
void saveMiscSettings();
void slotToggleLaunchOnStartup(bool);
@@ -53,8 +50,6 @@ private slots:
void slotShowLegalNotice();
private:
void customizeStyle();
Ui::GeneralSettings *_ui;
QPointer<IgnoreListEditor> _ignoreEditor;
QPointer<SyncLogDialog> _syncLogDialog;

View File

@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string notr="true">IgnoreListTableWidget</string>
<string>IgnoreListTableWidget</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" rowspan="4">

View File

@@ -24,7 +24,7 @@ LegalNotice::LegalNotice(QDialog *parent)
{
_ui->setupUi(this);
QString notice = tr("<p>Copyright 2017-2019 Nextcloud GmbH<br />"
QString notice = tr("<p>Copyright 2017-2018 Nextcloud GmbH<br />"
"Copyright 2012-2018 ownCloud GmbH</p>");
notice += tr("<p>Licensed under the GNU General Public License (GPL) Version 2.0 or any later version.</p>");

View File

@@ -55,7 +55,7 @@
</size>
</property>
<property name="text">
<string notr="true">Label</string>
<string>Label</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>563</width>
<height>444</height>
<width>542</width>
<height>396</height>
</rect>
</property>
<property name="windowTitle">
@@ -228,7 +228,7 @@
<bool>false</bool>
</property>
<property name="maximum">
<number>999999</number>
<number>9999</number>
</property>
<property name="value">
<number>80</number>
@@ -307,7 +307,7 @@
<number>1</number>
</property>
<property name="maximum">
<number>999999</number>
<number>9999</number>
</property>
<property name="value">
<number>10</number>

View File

@@ -22,12 +22,6 @@
#include <QDesktopServices>
#include <QApplication>
#define QTLEGACY (QT_VERSION < QT_VERSION_CHECK(5,9,0))
#if !(QTLEGACY)
#include <QOperatingSystemVersion>
#endif
namespace OCC {
// according to the QStandardDir impl from Qt5
@@ -95,14 +89,10 @@ void showInFileManager(const QString &localPath)
{
if (Utility::isWindows()) {
#ifdef Q_OS_WIN
#if QTLEGACY
if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS10)
#else
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows7)
#endif
return;
if (QSysInfo::windowsVersion() <= QSysInfo::WV_2003) {
return;
}
#endif
QString explorer = "explorer.exe "; // FIXME: we trust it's in PATH
QFileInfo fi(localPath);

View File

@@ -20,7 +20,12 @@
#include "progressdispatcher.h"
#include "owncloudsetupwizard.h"
#include "sharedialog.h"
#if defined(Q_OS_MAC)
#include "settingsdialogmac.h"
#include "macwindow.h" // qtmacgoodies
#else
#include "settingsdialog.h"
#endif
#include "logger.h"
#include "logbrowser.h"
#include "account.h"
@@ -57,7 +62,11 @@ const char propertyAccountC[] = "oc_account";
ownCloudGui::ownCloudGui(Application *parent)
: QObject(parent)
, _tray(nullptr)
#if defined(Q_OS_MAC)
, _settingsDialog(new SettingsDialogMac(this))
#else
, _settingsDialog(new SettingsDialog(this))
#endif
, _logBrowser(nullptr)
#ifdef WITH_LIBCLOUDPROVIDERS
, _bus(QDBusConnection::sessionBus())
@@ -412,7 +421,7 @@ void ownCloudGui::addAccountContextMenu(AccountStatePtr accountState, QMenu *men
}
if (accountState->isSignedOut()) {
QAction *signin = menu->addAction(tr("Log in"));
QAction *signin = menu->addAction(tr("Log in..."));
signin->setProperty(propertyAccountC, QVariant::fromValue(accountState));
connect(signin, &QAction::triggered, this, &ownCloudGui::slotLogin);
} else {
@@ -666,12 +675,6 @@ void ownCloudGui::updateContextMenu()
_contextMenu->addSeparator();
if (_navLinksMenu) {
_contextMenu->addMenu(_navLinksMenu);
}
_contextMenu->addSeparator();
if (accountList.isEmpty()) {
_contextMenu->addAction(_actionNewAccountWizard);
}
@@ -685,7 +688,6 @@ void ownCloudGui::updateContextMenu()
}
_contextMenu->addSeparator();
if (atLeastOnePaused) {
QString text;
if (accountList.count() > 1) {
@@ -775,11 +777,9 @@ void ownCloudGui::setupActions()
{
_actionStatus = new QAction(tr("Unknown status"), this);
_actionStatus->setEnabled(false);
_navLinksMenu = new QMenu(tr("Apps"));
_navLinksMenu->setEnabled(false);
_actionSettings = new QAction(tr("Settings …"), this);
_actionNewAccountWizard = new QAction(tr("New account …"), this);
_actionRecent = new QAction(tr("View more activity …"), this);
_actionSettings = new QAction(tr("Settings..."), this);
_actionNewAccountWizard = new QAction(tr("New account..."), this);
_actionRecent = new QAction(tr("View more activity..."), this);
_actionRecent->setEnabled(true);
QObject::connect(_actionRecent, &QAction::triggered, this, &ownCloudGui::slotShowSyncProtocol);
@@ -818,11 +818,8 @@ void ownCloudGui::fetchNavigationApps(AccountStatePtr account){
void ownCloudGui::buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu){
auto navLinks = _navApps.value(account);
_navLinksMenu->clear();
_navLinksMenu->setEnabled(navLinks.size() > 0);
if(navLinks.size() > 0){
// when there is only one account add the nav links above the settings
QAction *actionBefore = _actionSettings;
@@ -841,13 +838,17 @@ void ownCloudGui::buildNavigationAppsMenu(AccountStatePtr account, QMenu *accoun
}
// Create submenu with links
QMenu *navLinksMenu = new QMenu(tr("Apps"));
accountMenu->insertSeparator(actionBefore);
accountMenu->insertMenu(actionBefore, navLinksMenu);
foreach (const QJsonValue &value, navLinks) {
auto navLink = value.toObject();
QAction *action = new QAction(navLink.value("name").toString(), this);
QUrl href(navLink.value("href").toString());
connect(action, &QAction::triggered, this, [href] { QDesktopServices::openUrl(href); });
_navLinksMenu->addAction(action);
navLinksMenu->addAction(action);
}
accountMenu->insertSeparator(actionBefore);
}
}
@@ -934,7 +935,7 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &
quint64 totalFileCount = qMax(progress.totalFiles(), currentFile);
QString msg;
if (progress.trustEta()) {
msg = tr("Syncing %1 of %2 (%3 left)")
msg = tr("Syncing %1 of %2 (%3 left)")
.arg(currentFile)
.arg(totalFileCount)
.arg(Utility::durationToDescriptiveString2(progress.totalProgress().estimatedEta));
@@ -1068,7 +1069,12 @@ void ownCloudGui::slotShowGuiMessage(const QString &title, const QString &messag
void ownCloudGui::slotShowSettings()
{
if (_settingsDialog.isNull()) {
_settingsDialog = new SettingsDialog(this);
_settingsDialog =
#if defined(Q_OS_MAC)
new SettingsDialogMac(this);
#else
new SettingsDialog(this);
#endif
_settingsDialog->setAttribute(Qt::WA_DeleteOnClose, true);
_settingsDialog->show();
}
@@ -1129,6 +1135,10 @@ void ownCloudGui::raiseDialog(QWidget *raiseWidget)
raiseWidget->raise();
raiseWidget->activateWindow();
#if defined(Q_OS_MAC)
// viel hilft viel ;-)
MacWindow::bringToFront(raiseWidget);
#endif
#if defined(Q_OS_X11)
WId wid = widget->winId();
NETWM::init();

View File

@@ -34,6 +34,7 @@ namespace OCC {
class Folder;
class SettingsDialog;
class SettingsDialogMac;
class ShareDialog;
class Application;
class LogBrowser;
@@ -130,7 +131,11 @@ private:
void buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu);
QPointer<Systray> _tray;
#if defined(Q_OS_MAC)
QPointer<SettingsDialogMac> _settingsDialog;
#else
QPointer<SettingsDialog> _settingsDialog;
#endif
QPointer<LogBrowser> _logBrowser;
// tray's menu
QScopedPointer<QMenu> _contextMenu;
@@ -163,7 +168,6 @@ private:
QAction *_actionQuit;
QAction *_actionCrash;
QMenu *_navLinksMenu;
QMap<AccountStatePtr, QJsonArray> _navApps;
QList<QAction *> _recentItemsActions;

View File

@@ -331,7 +331,7 @@ void OwncloudSetupWizard::slotConnectToOCUrl(const QString &url)
AbstractCredentials *creds = _ocWizard->getCredentials();
_ocWizard->account()->setCredentials(creds);
_ocWizard->setField(QLatin1String("OCUrl"), url);
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2")
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2...")
.arg(Theme::instance()->appNameGUI())
.arg(url));
@@ -452,7 +452,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString &localFo
tr("Local sync folder %1 already exists, setting it up for sync.<br/><br/>")
.arg(Utility::escape(localFolder)));
} else {
QString res = tr("Creating local sync folder %1").arg(localFolder);
QString res = tr("Creating local sync folder %1...").arg(localFolder);
if (fi.mkpath(localFolder)) {
FileSystem::setFolderMinimumPermissions(localFolder);
Utility::setupFavLink(localFolder);
@@ -466,41 +466,7 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString &localFo
_ocWizard->appendToConfigurationLog(res);
}
if (nextStep) {
/*
* BEGIN - Sanitize URL paths to eliminate double-slashes
*
* Purpose: Don't rely on unsafe paths, be extra careful.
*
* Example: https://cloud.example.com/remote.php/webdav//
*
*/
qCInfo(lcWizard) << "Sanitize got URL path:" << QString(_ocWizard->account()->url().toString() + '/' + _ocWizard->account()->davPath() + remoteFolder);
QString newDavPath = _ocWizard->account()->davPath(),
newRemoteFolder = remoteFolder;
while (newDavPath.startsWith('/')) {
newDavPath.remove(0, 1);
}
while (newDavPath.endsWith('/')) {
newDavPath.chop(1);
}
while (newRemoteFolder.startsWith('/')) {
newRemoteFolder.remove(0, 1);
}
while (newRemoteFolder.endsWith('/')) {
newRemoteFolder.chop(1);
}
QString newUrlPath = newDavPath + '/' + newRemoteFolder;
qCInfo(lcWizard) << "Sanitized to URL path:" << _ocWizard->account()->url().toString() + '/' + newUrlPath;
/*
* END - Sanitize URL paths to eliminate double-slashes
*/
EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), newUrlPath, this);
EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), _ocWizard->account()->davPath() + remoteFolder, this);
connect(job, &EntityExistsJob::exists, this, &OwncloudSetupWizard::slotRemoteFolderExists);
job->start();
} else {

View File

@@ -71,7 +71,7 @@
<item row="2" column="1">
<widget class="QLabel" name="proxyAddress">
<property name="text">
<string notr="true">TextLabel</string>
<string>TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>

View File

@@ -1,173 +0,0 @@
/*
* Copyright (C) by Camila Ayres <hello@camila.codes>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "remotewipe.h"
#include "folderman.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkRequest>
#include <QBuffer>
namespace OCC {
Q_LOGGING_CATEGORY(lcRemoteWipe, "nextcloud.gui.remotewipe", QtInfoMsg)
RemoteWipe::RemoteWipe(AccountPtr account, QObject *parent)
: _account(account),
_appPassword(QString()),
_accountRemoved(false),
_networkManager(nullptr),
_networkReplyCheck(nullptr),
_networkReplySuccess(nullptr)
{
QObject::connect(AccountManager::instance(), &AccountManager::accountRemoved,
this, [=](AccountState *) {
_accountRemoved = true;
});
QObject::connect(this, &RemoteWipe::authorized, FolderMan::instance(),
&FolderMan::slotWipeFolderForAccount);
QObject::connect(FolderMan::instance(), &FolderMan::wipeDone, this,
&RemoteWipe::notifyServerSuccessJob);
QObject::connect(_account.data(), &Account::appPasswordRetrieved, this,
&RemoteWipe::startCheckJobWithAppPassword);
}
void RemoteWipe::startCheckJobWithAppPassword(QString pwd){
if(pwd.isEmpty())
return;
_appPassword = pwd;
QUrl requestUrl = Utility::concatUrlPath(_account->url().toString(),
QLatin1String("/index.php/core/wipe/check"));
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
request.setUrl(requestUrl);
request.setSslConfiguration(_account->getOrCreateSslConfig());
auto requestBody = new QBuffer;
QUrlQuery arguments(QString("token=%1").arg(_appPassword));
requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1());
_networkReplyCheck = _networkManager.post(request, requestBody);
QObject::connect(&_networkManager, SIGNAL(sslErrors(QNetworkReply *, QList<QSslError>)),
_account.data(), SLOT(slotHandleSslErrors(QNetworkReply *, QList<QSslError>)));
QObject::connect(_networkReplyCheck, &QNetworkReply::finished, this,
&RemoteWipe::checkJobSlot);
}
void RemoteWipe::checkJobSlot()
{
auto jsonData = _networkReplyCheck->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
bool wipe = false;
//check for errors
if (_networkReplyCheck->error() != QNetworkReply::NoError ||
jsonParseError.error != QJsonParseError::NoError) {
QString errorReason;
QString errorFromJson = json["error"].toString();
if (!errorFromJson.isEmpty()) {
qCWarning(lcRemoteWipe) << QString("Error returned from the server: <em>%1<em>")
.arg(errorFromJson.toHtmlEscaped());
} else if (_networkReplyCheck->error() != QNetworkReply::NoError) {
qCWarning(lcRemoteWipe) << QString("There was an error accessing the 'token' endpoint: <br><em>%1</em>")
.arg(_networkReplyCheck->errorString().toHtmlEscaped());
} else if (jsonParseError.error != QJsonParseError::NoError) {
qCWarning(lcRemoteWipe) << QString("Could not parse the JSON returned from the server: <br><em>%1</em>")
.arg(jsonParseError.errorString());
} else {
qCWarning(lcRemoteWipe) << QString("The reply from the server did not contain all expected fields");
}
// check for wipe request
} else if(!json.value("wipe").isUndefined()){
wipe = json["wipe"].toBool();
}
auto manager = AccountManager::instance();
auto accountState = manager->account(_account->displayName()).data();
if(wipe){
/* IMPORTANT - remove later - FIXME MS@2019-12-07 -->
* TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
*
* Disabled as long as selecting another cert is not supported by the UI.
*
* Being able to specify a new certificate is important anyway: expiry etc.
*
* We introduce this dirty hack here, to allow deleting them upon Remote Wipe.
*/
_account->setRemoteWipeRequested_HACK();
// <-- FIXME MS@2019-12-07
// delete account
manager->deleteAccount(accountState);
manager->save();
// delete data
emit authorized(accountState);
} else {
// ask user for his credentials again
accountState->handleInvalidCredentials();
}
_networkReplyCheck->deleteLater();
}
void RemoteWipe::notifyServerSuccessJob(AccountState *accountState, bool dataWiped){
if(_accountRemoved && dataWiped && _account == accountState->account()){
QUrl requestUrl = Utility::concatUrlPath(_account->url().toString(),
QLatin1String("/index.php/core/wipe/success"));
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
request.setUrl(requestUrl);
request.setSslConfiguration(_account->getOrCreateSslConfig());
auto requestBody = new QBuffer;
QUrlQuery arguments(QString("token=%1").arg(_appPassword));
requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1());
_networkReplySuccess = _networkManager.post(request, requestBody);
QObject::connect(_networkReplySuccess, &QNetworkReply::finished, this,
&RemoteWipe::notifyServerSuccessJobSlot);
}
}
void RemoteWipe::notifyServerSuccessJobSlot()
{
auto jsonData = _networkReplySuccess->readAll();
QJsonParseError jsonParseError;
QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
if (_networkReplySuccess->error() != QNetworkReply::NoError ||
jsonParseError.error != QJsonParseError::NoError) {
QString errorReason;
QString errorFromJson = json["error"].toString();
if (!errorFromJson.isEmpty()) {
qCWarning(lcRemoteWipe) << QString("Error returned from the server: <em>%1</em>")
.arg(errorFromJson.toHtmlEscaped());
} else if (_networkReplySuccess->error() != QNetworkReply::NoError) {
qCWarning(lcRemoteWipe) << QString("There was an error accessing the 'success' endpoint: <br><em>%1</em>")
.arg(_networkReplySuccess->errorString().toHtmlEscaped());
} else if (jsonParseError.error != QJsonParseError::NoError) {
qCWarning(lcRemoteWipe) << QString("Could not parse the JSON returned from the server: <br><em>%1</em>")
.arg(jsonParseError.errorString());
} else {
qCWarning(lcRemoteWipe) << QString("The reply from the server did not contain all expected fields.");
}
}
_networkReplySuccess->deleteLater();
}
}

View File

@@ -1,61 +0,0 @@
#ifndef REMOTEWIPE_H
#define REMOTEWIPE_H
#include "accountmanager.h"
#include <QNetworkAccessManager>
class QJsonDocument;
class TestRemoteWipe;
namespace OCC {
class RemoteWipe : public QObject
{
Q_OBJECT
public:
explicit RemoteWipe(AccountPtr account, QObject *parent = nullptr);
signals:
/**
* Notify if wipe was requested
*/
void authorized(AccountState*);
/**
* Notify if user only needs to login again
*/
void askUserCredentials();
public slots:
/**
* Once receives a 401 or 403 status response it will do a fetch to
* <server>/index.php/core/wipe/check
*/
void startCheckJobWithAppPassword(QString);
private slots:
/**
* If wipe is requested, delete account and data, if not continue by asking
* the user to login again
*/
void checkJobSlot();
/**
* Once the client has wiped all the required data a POST to
* <server>/index.php/core/wipe/success
*/
void notifyServerSuccessJob(AccountState *accountState, bool);
void notifyServerSuccessJobSlot();
private:
AccountPtr _account;
QString _appPassword;
bool _accountRemoved;
QNetworkAccessManager _networkManager;
QNetworkReply *_networkReplyCheck;
QNetworkReply *_networkReplySuccess;
friend class ::TestRemoteWipe;
};
}
#endif // REMOTEWIPE_H

View File

@@ -70,7 +70,7 @@ SelectiveSyncWidget::SelectiveSyncWidget(AccountPtr account, QWidget *parent)
, _inserting(false)
, _folderTree(new QTreeWidget(this))
{
_loading = new QLabel(tr("Loading "), _folderTree);
_loading = new QLabel(tr("Loading ..."), _folderTree);
auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);

View File

@@ -48,7 +48,7 @@ const char TOOLBAR_CSS[] =
"QToolBar QToolBarExtension { padding:0; } "
"QToolBar QToolButton:checked { background: %3; color: %4; }";
static const float buttonSizeRatio = 1.618f; // golden ratio
static const float buttonSizeRatio = 1.618; // golden ratio
}
@@ -56,6 +56,10 @@ namespace OCC {
#include "settingsdialogcommon.cpp"
//
// Whenever you change something here check both settingsdialog.cpp and settingsdialogmac.cpp !
//
SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
: QDialog(parent)
, _ui(new Ui::SettingsDialog)
@@ -104,9 +108,6 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
GeneralSettings *generalSettings = new GeneralSettings;
_ui->stack->addWidget(generalSettings);
// Connect styleChanged events to our widgets, so they can adapt (Dark-/Light-Mode switching)
connect(this, &SettingsDialog::styleChanged, generalSettings, &GeneralSettings::slotStyleChanged);
QAction *networkAction = createColorAwareAction(QLatin1String(":/client/resources/network.png"), tr("Network"));
_actionGroup->addAction(networkAction);
_toolBar->addAction(networkAction);
@@ -159,9 +160,6 @@ void SettingsDialog::changeEvent(QEvent *e)
case QEvent::PaletteChange:
case QEvent::ThemeChange:
customizeStyle();
// Notify the other widgets (Dark-/Light-Mode switching)
emit styleChanged();
break;
default:
break;
@@ -254,9 +252,6 @@ void SettingsDialog::accountAdded(AccountState *s)
_actionGroupWidgets.insert(accountAction, accountSettings);
_actionForAccount.insert(s->account().data(), accountAction);
accountAction->trigger();
// Connect styleChanged event, to adapt (Dark-/Light-Mode switching)
connect(this, &SettingsDialog::styleChanged, accountSettings, &AccountSettings::slotStyleChanged);
connect(accountSettings, &AccountSettings::folderChanged, _gui, &ownCloudGui::slotFoldersChanged);
connect(accountSettings, &AccountSettings::openFolderAlias,
@@ -349,13 +344,13 @@ void SettingsDialog::accountRemoved(AccountState *s)
void SettingsDialog::customizeStyle()
{
QString highlightColor(palette().highlight().color().name());
QString highlightTextColor(palette().highlightedText().color().name());
QString altBase(palette().alternateBase().color().name());
QString dark(palette().dark().color().name());
QString background(palette().base().color().name());
_toolBar->setStyleSheet(QString::fromLatin1(TOOLBAR_CSS).arg(background, dark, highlightColor, highlightTextColor));
_toolBar->setStyleSheet(QString::fromLatin1(TOOLBAR_CSS).arg(background, dark, highlightColor, altBase));
Q_FOREACH (QAction *a, _actionGroup->actions()) {
QIcon icon = Theme::createColorAwareIcon(a->property("iconPath").toString(), palette());
QIcon icon = createColorAwareIcon(a->property("iconPath").toString());
a->setIcon(icon);
QToolButton *btn = qobject_cast<QToolButton *>(_toolBar->widgetForAction(a));
if (btn)
@@ -363,6 +358,34 @@ void SettingsDialog::customizeStyle()
}
}
static bool isDarkColor(const QColor &color)
{
// account for different sensitivity of the human eye to certain colors
double treshold = 1.0 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255.0;
return treshold > 0.5;
}
QIcon SettingsDialog::createColorAwareIcon(const QString &name)
{
QPalette pal = palette();
QImage img(name);
QImage inverted(img);
inverted.invertPixels(QImage::InvertRgb);
QIcon icon;
if (isDarkColor(pal.color(QPalette::Base))) {
icon.addPixmap(QPixmap::fromImage(inverted));
} else {
icon.addPixmap(QPixmap::fromImage(img));
}
if (isDarkColor(pal.color(QPalette::HighlightedText))) {
icon.addPixmap(QPixmap::fromImage(img), QIcon::Normal, QIcon::On);
} else {
icon.addPixmap(QPixmap::fromImage(inverted), QIcon::Normal, QIcon::On);
}
return icon;
}
class ToolButtonAction : public QWidgetAction
{
public:
@@ -403,7 +426,7 @@ QAction *SettingsDialog::createActionWithIcon(const QIcon &icon, const QString &
QAction *SettingsDialog::createColorAwareAction(const QString &iconPath, const QString &text)
{
// all buttons must have the same size in order to keep a good layout
QIcon coloredIcon = Theme::createColorAwareIcon(iconPath, palette());
QIcon coloredIcon = createColorAwareIcon(iconPath);
return createActionWithIcon(coloredIcon, text, iconPath);
}

View File

@@ -63,9 +63,6 @@ public slots:
void slotAccountAvatarChanged();
void slotAccountDisplayNameChanged();
signals:
void styleChanged();
protected:
void reject() override;
void accept() override;
@@ -79,6 +76,7 @@ private:
void customizeStyle();
void activityAdded(AccountState *);
QIcon createColorAwareIcon(const QString &name);
QAction *createColorAwareAction(const QString &iconName, const QString &fileName);
QAction *createActionWithIcon(const QIcon &icon, const QString &text, const QString &iconPath = QString());

View File

@@ -2,7 +2,7 @@ namespace SettingsDialogCommon
{
/** display name with two lines that is displayed in the settings
* If width is bigger than 0, the string will be elided so it does not exceed that width
* If width is bigger than 0, the string will be ellided so it does not exceed that width
*/
QString shortDisplayNameForSettings(Account* account, int width)
{

View File

@@ -0,0 +1,239 @@
/*
* Copyright (C) by Denis Dzyubenko
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "settingsdialogmac.h"
#include "macstandardicon.h"
#include "folderman.h"
#include "theme.h"
#include "generalsettings.h"
#include "networksettings.h"
#include "accountsettings.h"
#include "accountstate.h"
#include "creds/abstractcredentials.h"
#include "configfile.h"
#include "progressdispatcher.h"
#include "owncloudgui.h"
#include "activitywidget.h"
#include "accountmanager.h"
#include <QLabel>
#include <QStandardItemModel>
#include <QPushButton>
#include <QSettings>
#include <QPainter>
#include <QPainterPath>
namespace OCC {
#include "settingsdialogcommon.cpp"
// Duplicate in settingsdialog.cpp
static QIcon circleMask(const QImage &avatar)
{
int dim = avatar.width();
QPixmap fixedImage(dim, dim);
fixedImage.fill(Qt::transparent);
QPainter imgPainter(&fixedImage);
QPainterPath clip;
clip.addEllipse(0, 0, dim, dim);
imgPainter.setClipPath(clip);
imgPainter.drawImage(0, 0, avatar);
imgPainter.end();
return QIcon(fixedImage);
}
//
// Whenever you change something here check both settingsdialog.cpp and settingsdialogmac.cpp !
//
SettingsDialogMac::SettingsDialogMac(ownCloudGui *gui, QWidget *parent)
: MacPreferencesWindow(parent)
, _gui(gui)
{
// do not show minimize button. There is no use, and restoring the
// dialog from minimize is broken in MacPreferencesWindow
setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint);
// Emulate dialog behavior: Escape means close
QAction *closeDialogAction = new QAction(this);
closeDialogAction->setShortcut(QKeySequence(Qt::Key_Escape));
connect(closeDialogAction, &QAction::triggered, this, &SettingsDialogMac::close);
addAction(closeDialogAction);
// People perceive this as a Window, so also make Ctrl+W work
QAction *closeWindowAction = new QAction(this);
closeWindowAction->setShortcut(QKeySequence("Ctrl+W"));
connect(closeWindowAction, &QAction::triggered, this, &SettingsDialogMac::close);
addAction(closeWindowAction);
// People perceive this as a Window, so also make Ctrl+H work
QAction *hideWindowAction = new QAction(this);
hideWindowAction->setShortcut(QKeySequence("Ctrl+H"));
connect(hideWindowAction, &QAction::triggered, this, &SettingsDialogMac::hide);
addAction(hideWindowAction);
setObjectName("SettingsMac"); // required as group for saveGeometry call
setWindowTitle(tr("%1").arg(Theme::instance()->appNameGUI()));
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &SettingsDialogMac::accountAdded);
connect(AccountManager::instance(), &AccountManager::accountRemoved,
this, &SettingsDialogMac::accountRemoved);
_actionsIdx = -1;
foreach (auto ai, AccountManager::instance()->accounts()) {
accountAdded(ai.data());
}
QIcon generalIcon = MacStandardIcon::icon(MacStandardIcon::PreferencesGeneral);
GeneralSettings *generalSettings = new GeneralSettings;
addPreferencesPanel(generalIcon, tr("General"), generalSettings);
QIcon networkIcon = MacStandardIcon::icon(MacStandardIcon::Network);
NetworkSettings *networkSettings = new NetworkSettings;
addPreferencesPanel(networkIcon, tr("Network"), networkSettings);
QAction *showLogWindow = new QAction(this);
showLogWindow->setShortcut(QKeySequence("F12"));
connect(showLogWindow, &QAction::triggered, gui, &ownCloudGui::slotToggleLogBrowser);
addAction(showLogWindow);
ConfigFile cfg;
cfg.restoreGeometry(this);
}
void SettingsDialogMac::closeEvent(QCloseEvent *event)
{
ConfigFile cfg;
cfg.saveGeometry(this);
MacPreferencesWindow::closeEvent(event);
}
void SettingsDialogMac::showActivityPage()
{
// Count backwards (0-based) from the last panel (multiple accounts can be on the left)
setCurrentPanelIndex(preferencePanelCount() - 1 - 2);
}
void SettingsDialogMac::accountAdded(AccountState *s)
{
QIcon accountIcon = MacStandardIcon::icon(MacStandardIcon::UserAccounts);
auto accountSettings = new AccountSettings(s, this);
QString displayName = Theme::instance()->multiAccount() ? SettingsDialogCommon::shortDisplayNameForSettings(s->account().data(), 0) : tr("Account");
// this adds the panel - nothing to add here just to fix the order
insertPreferencesPanel(++_actionsIdx, accountIcon, displayName, accountSettings);
connect(accountSettings, &AccountSettings::folderChanged, _gui, &ownCloudGui::slotFoldersChanged);
connect(accountSettings, &AccountSettings::openFolderAlias, _gui, &ownCloudGui::slotFolderOpenAction);
connect(s->account().data(), &Account::accountChangedAvatar, this, &SettingsDialogMac::slotAccountAvatarChanged);
connect(s->account().data(), &Account::accountChangedDisplayName, this, &SettingsDialogMac::slotAccountDisplayNameChanged);
// Refresh immediatly when getting online
connect(s, &AccountState::isConnectedChanged, this, &SettingsDialogMac::slotRefreshActivityAccountStateSender);
// Add activity panel
QIcon activityIcon(QLatin1String(":/client/resources/activity.png"));
_activitySettings[s] = new ActivitySettings(s, this);
insertPreferencesPanel(++_actionsIdx, activityIcon, tr("Activity"), _activitySettings[s]);
connect(_activitySettings[s], SIGNAL(guiLog(QString, QString)), _gui,
SLOT(slotShowOptionalTrayMessage(QString, QString)));
// if this is not the first account, add separator 2 positions before int the toolbar
if(AccountManager::instance()->accounts().first().data() != s &&
AccountManager::instance()->accounts().size() >= 1){
_separators[s] = insertSeparator(_actionsIdx - 1);
++_actionsIdx; //we have one more item in the toolbar
}
ConfigFile cfg;
_activitySettings[s]->setNotificationRefreshInterval(cfg.notificationRefreshInterval());
slotRefreshActivity(s);
setCurrentPanelIndex(0);
}
void SettingsDialogMac::accountRemoved(AccountState *s)
{
auto list = findChildren<AccountSettings *>(QString());
foreach (auto p, list) {
if (p->accountsState() == s) {
removePreferencesPanel(p);
// remove settings panel
if(_activitySettings.contains(s))
removePreferencesPanel(_activitySettings[s]);
// remove separator if there is any
if(_separators.contains(s)){
removeSeparator(_separators[s]);
_separators.remove(s);
}
}
}
}
void SettingsDialogMac::slotRefreshActivityAccountStateSender()
{
slotRefreshActivity(qobject_cast<AccountState*>(sender()));
}
void SettingsDialogMac::slotRefreshActivity(AccountState *accountState)
{
if (accountState) {
_activitySettings[accountState]->slotRefresh();
}
}
void SettingsDialogMac::slotAccountAvatarChanged()
{
Account *account = static_cast<Account *>(sender());
auto list = findChildren<AccountSettings *>(QString());
foreach (auto p, list) {
if (p->accountsState()->account() == account) {
int idx = indexForPanel(p);
QImage pix = account->avatar();
if (!pix.isNull()) {
setPreferencesPanelIcon(idx, circleMask(pix));
}
}
}
}
void SettingsDialogMac::slotAccountDisplayNameChanged()
{
Account *account = static_cast<Account *>(sender());
auto list = findChildren<AccountSettings *>(QString());
foreach (auto p, list) {
if (p->accountsState()->account() == account) {
int idx = indexForPanel(p);
QString displayName = account->displayName();
if (!displayName.isNull()) {
displayName = Theme::instance()->multiAccount()
? SettingsDialogCommon::shortDisplayNameForSettings(account, 0)
: tr("Account");
setPreferencesPanelTitle(idx, displayName);
}
}
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) by Denis Dzyubenko
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef SETTINGSDIALOGMAC_H
#define SETTINGSDIALOGMAC_H
#include "progressdispatcher.h"
#include "macpreferenceswindow.h"
#include "owncloudgui.h"
class QStandardItemModel;
class QListWidgetItem;
namespace OCC {
class AccountSettings;
class Application;
class FolderMan;
class ownCloudGui;
class Folder;
class AccountState;
class ActivitySettings;
/**
* @brief The SettingsDialogMac class
* @ingroup gui
*/
class SettingsDialogMac : public MacPreferencesWindow
{
Q_OBJECT
public:
explicit SettingsDialogMac(ownCloudGui *gui, QWidget *parent = 0);
public slots:
void showActivityPage();
void slotRefreshActivity(AccountState *accountState);
void slotRefreshActivityAccountStateSender();
private slots:
void accountAdded(AccountState *);
void accountRemoved(AccountState *);
void slotAccountAvatarChanged();
void slotAccountDisplayNameChanged();
private:
void closeEvent(QCloseEvent *event);
QAction *_actionBefore;
int _actionsIdx;
QMap<AccountState *, QAction *> _separators;
QMap<AccountState *, ActivitySettings *> _activitySettings;
ownCloudGui *_gui;
int _protocolIdx;
};
}
#endif // SETTINGSDIALOGMAC_H
;

View File

@@ -156,9 +156,6 @@ void ShareDialog::addLinkShareWidget(const QSharedPointer<LinkShare> &linkShare)
connect(_linkWidgetList.at(index), &ShareLinkWidget::deleteLinkShare, this, &ShareDialog::slotDeleteShare);
//connect(_linkWidgetList.at(index), &ShareLinkWidget::resizeRequested, this, &ShareDialog::slotAdjustScrollWidgetSize);
// Connect styleChanged events to our widget, so it can adapt (Dark-/Light-Mode switching)
connect(this, &ShareDialog::styleChanged, _linkWidgetList.at(index), &ShareLinkWidget::slotStyleChanged);
_ui->verticalLayout->insertWidget(_linkWidgetList.size()+1, _linkWidgetList.at(index));
_linkWidgetList.at(index)->setupUiOptions();
}
@@ -285,10 +282,6 @@ void ShareDialog::showSharingUi()
if (userGroupSharing) {
_userGroupWidget = new ShareUserGroupWidget(_accountState->account(), _sharePath, _localPath, _maxSharingPermissions, _privateLinkUrl, this);
// Connect styleChanged events to our widget, so it can adapt (Dark-/Light-Mode switching)
connect(this, &ShareDialog::styleChanged, _userGroupWidget, &ShareUserGroupWidget::slotStyleChanged);
_ui->verticalLayout->insertWidget(1, _userGroupWidget);
_userGroupWidget->getShares();
}
@@ -342,21 +335,4 @@ void ShareDialog::slotAccountStateChanged(int state)
}
}
}
void ShareDialog::changeEvent(QEvent *e)
{
switch (e->type()) {
case QEvent::StyleChange:
case QEvent::PaletteChange:
case QEvent::ThemeChange:
// Notify the other widgets (Dark-/Light-Mode switching)
emit styleChanged();
break;
default:
break;
}
QDialog::changeEvent(e);
}
}

View File

@@ -68,10 +68,6 @@ private slots:
signals:
void toggleAnimation(bool);
void styleChanged();
protected:
void changeEvent(QEvent *) override;
private:
void showSharingUi();

View File

@@ -89,7 +89,7 @@
</size>
</property>
<property name="text">
<string notr="true">share label</string>
<string>share label</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
@@ -120,7 +120,7 @@
</size>
</property>
<property name="text">
<string notr="true">Icon</string>
<string>Icon</string>
</property>
</widget>
</item>
@@ -151,8 +151,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>367</width>
<height>85</height>
<width>352</width>
<height>68</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scrollAreaVerticalLayout"/>

View File

@@ -19,7 +19,6 @@
#include "capabilities.h"
#include "guiutility.h"
#include "sharemanager.h"
#include "theme.h"
#include "QProgressIndicator.h"
#include <QBuffer>
@@ -241,8 +240,6 @@ void ShareLinkWidget::setupUiOptions(){
//TO DO
//startAnimation(0, height());
customizeStyle();
}
void ShareLinkWidget::slotCopyLinkShare(bool clicked){
@@ -280,7 +277,6 @@ void ShareLinkWidget::slotCreatePassword()
void ShareLinkWidget::slotCreateShareLink(bool clicked)
{
Q_UNUSED(clicked);
slotToggleAnimation(true);
emit createLinkShare();
}
@@ -492,30 +488,4 @@ void ShareLinkWidget::displayError(const QString &errMsg)
_ui->errorLabel->setText(errMsg);
_ui->errorLabel->show();
}
void ShareLinkWidget::slotStyleChanged()
{
customizeStyle();
}
void ShareLinkWidget::customizeStyle()
{
_unshareLinkAction->setIcon(Theme::createColorAwareIcon(":/client/resources/delete.png"));
_addAnotherLinkAction->setIcon(Theme::createColorAwareIcon(":/client/resources/add.png"));
_ui->enableShareLink->setIcon(Theme::createColorAwareIcon(":/client/resources/copy.svg"));
// only on master, not in stable-2.6 yet
// _ui->shareLinkIconLabel->setPixmap(Theme::createColorAwarePixmap(":/client/resources/public.svg"));
_ui->createShareButton->setIcon(Theme::createColorAwareIcon(":/client/resources/public.svg"));
_ui->shareLinkToolButton->setIcon(Theme::createColorAwareIcon(":/client/resources/more.svg"));
// only on master, not in stable-2.6 yet
// _ui->confirmNote->setIcon(Theme::createColorAwareIcon(":/client/resources/confirm.svg"));
_ui->confirmPassword->setIcon(Theme::createColorAwareIcon(":/client/resources/confirm.svg"));
_ui->confirmExpirationDate->setIcon(Theme::createColorAwareIcon(":/client/resources/confirm.svg"));
}
}

View File

@@ -65,7 +65,6 @@ public slots:
void slotToggleAnimation(bool start);
void slotServerError(int code, const QString &message);
void slotCreateShareRequiresPassword(const QString &message);
void slotStyleChanged();
private slots:
void slotCreateShareLink(bool clicked);
@@ -108,8 +107,6 @@ private:
void startAnimation(const int start, const int end);
void customizeStyle();
Ui::ShareLinkWidget *_ui;
AccountPtr _account;
QString _sharePath;

View File

@@ -109,7 +109,7 @@
</palette>
</property>
<property name="text">
<string notr="true">TextLabel</string>
<string>TextLabel</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>

View File

@@ -26,7 +26,6 @@
#include "thumbnailjob.h"
#include "sharee.h"
#include "sharemanager.h"
#include "theme.h"
#include "QProgressIndicator.h"
#include <QBuffer>
@@ -113,8 +112,6 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
//_ui->shareeHorizontalLayout->addWidget(&_pi_sharee);
_parentScrollArea = parentWidget()->findChild<QScrollArea*>("scrollArea");
customizeStyle();
}
ShareUserGroupWidget::~ShareUserGroupWidget()
@@ -214,10 +211,6 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
connect(s, &ShareUserLine::resizeRequested, this, &ShareUserGroupWidget::slotAdjustScrollWidgetSize);
connect(s, &ShareUserLine::visualDeletionDone, this, &ShareUserGroupWidget::getShares);
s->setBackgroundRole(layout->count() % 2 == 0 ? QPalette::Base : QPalette::AlternateBase);
// Connect styleChanged events to our widget, so it can adapt (Dark-/Light-Mode switching)
connect(this, &ShareUserGroupWidget::styleChanged, s, &ShareUserLine::slotStyleChanged);
layout->addWidget(s);
x++;
@@ -262,8 +255,7 @@ void ShareUserGroupWidget::slotPrivateLinkShare()
auto menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
// this icon is not handled by slotStyleChanged() -> customizeStyle but we can live with that
menu->addAction(Theme::createColorAwareIcon(":/client/resources/copy.svg"),
menu->addAction(QIcon(":/client/resources/copy.svg"),
tr("Copy link"),
this, SLOT(slotPrivateLinkCopy()));
@@ -366,19 +358,6 @@ void ShareUserGroupWidget::slotPrivateLinkEmail()
this);
}
void ShareUserGroupWidget::slotStyleChanged()
{
customizeStyle();
// Notify the other widgets (ShareUserLine in this case, Dark-/Light-Mode switching)
emit styleChanged();
}
void ShareUserGroupWidget::customizeStyle()
{
_ui->confirmShare->setIcon(Theme::createColorAwareIcon(":/client/resources/confirm.svg"));
}
ShareUserLine::ShareUserLine(QSharedPointer<Share> share,
SharePermissions maxSharingPermissions,
bool isFile,
@@ -444,9 +423,8 @@ ShareUserLine::ShareUserLine(QSharedPointer<Share> share,
_ui->permissionToolButton->setMenu(menu);
_ui->permissionToolButton->setPopupMode(QToolButton::InstantPopup);
// icon now set in: customizeStyle
/*QIcon icon(QLatin1String(":/client/resources/more.svg"));
_ui->permissionToolButton->setIcon(icon);*/
QIcon icon(QLatin1String(":/client/resources/more.svg"));
_ui->permissionToolButton->setIcon(icon);
// Set the permissions checkboxes
displayPermissions();
@@ -473,8 +451,6 @@ ShareUserLine::ShareUserLine(QSharedPointer<Share> share,
}
loadAvatar();
customizeStyle();
}
void ShareUserLine::loadAvatar()
@@ -669,18 +645,4 @@ void ShareUserLine::displayPermissions()
_permissionDelete->setChecked(perm & SharePermissionDelete);
}
}
void ShareUserLine::slotStyleChanged()
{
customizeStyle();
}
void ShareUserLine::customizeStyle()
{
_ui->permissionToolButton->setIcon(Theme::createColorAwareIcon(":/client/resources/more.svg"));
QIcon deleteicon = QIcon::fromTheme(QLatin1String("user-trash"),Theme::createColorAwareIcon(QLatin1String(":/client/resources/delete.png")));
_deleteShareButton->setIcon(deleteicon);
}
}

View File

@@ -64,11 +64,9 @@ public:
signals:
void togglePublicLinkShare(bool);
void styleChanged();
public slots:
void getShares();
void slotStyleChanged();
private slots:
void slotSharesFetched(const QList<QSharedPointer<Share>> &shares);
@@ -90,8 +88,6 @@ private slots:
void slotPrivateLinkEmail();
private:
void customizeStyle();
Ui::ShareUserGroupWidget *_ui;
QScrollArea *_parentScrollArea;
AccountPtr _account;
@@ -131,9 +127,6 @@ signals:
void visualDeletionDone();
void resizeRequested();
public slots:
void slotStyleChanged();
private slots:
void on_deleteShareButton_clicked();
void slotPermissionsChanged();
@@ -148,7 +141,6 @@ private slots:
private:
void displayPermissions();
void loadAvatar();
void customizeStyle();
Ui::ShareUserLine *_ui;
QSharedPointer<Share> _share;

View File

@@ -623,12 +623,12 @@ void SocketApi::command_GET_STRINGS(const QString &argument, SocketListener *lis
{
static std::array<std::pair<const char *, QString>, 5> strings { {
{ "SHARE_MENU_TITLE", tr("Share options") },
{ "CONTEXT_MENU_TITLE", tr("Share via %1").arg(Theme::instance()->appNameGUI())},
{ "CONTEXT_MENU_TITLE", tr("Share via ") + Theme::instance()->appNameGUI()},
{ "COPY_PRIVATE_LINK_MENU_TITLE", tr("Copy private link to clipboard") },
{ "EMAIL_PRIVATE_LINK_MENU_TITLE", tr("Send private link by email") },
{ "EMAIL_PRIVATE_LINK_MENU_TITLE", tr("Send private link by email...") },
} };
listener->sendMessage(QString("GET_STRINGS:BEGIN"));
for (const auto& key_value : strings) {
for (auto key_value : strings) {
if (argument.isEmpty() || argument == QLatin1String(key_value.first)) {
listener->sendMessage(QString("STRING:%1:%2").arg(key_value.first, key_value.second));
}
@@ -673,7 +673,7 @@ void SocketApi::sendSharingContextMenuOptions(const FileData &fileData, SocketLi
// Disabled: only providing email option for private links would look odd,
// and the copy option is more general.
//listener->sendMessage(QLatin1String("MENU_ITEM:EMAIL_PRIVATE_LINK") + flagString + tr("Send private link by email"));
//listener->sendMessage(QLatin1String("MENU_ITEM:EMAIL_PRIVATE_LINK") + flagString + tr("Send private link by email..."));
}
SocketApi::FileData SocketApi::FileData::get(const QString &localFile)

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