mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-09 15:13:06 +02:00
Compare commits
250 Commits
v2.5.0-bet
...
v2.5.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dae188ed9 | ||
|
|
2b760cd63b | ||
|
|
54b490c8d1 | ||
|
|
1e6b0b8924 | ||
|
|
ef15534c64 | ||
|
|
ea806a1287 | ||
|
|
b904d79d8f | ||
|
|
0c535872cb | ||
|
|
15553df34e | ||
|
|
028979d752 | ||
|
|
1e1d116052 | ||
|
|
045bba0161 | ||
|
|
b44408a91b | ||
|
|
af8a2819be | ||
|
|
17d05a2ad4 | ||
|
|
0f767ed995 | ||
|
|
e6f1d7632a | ||
|
|
40c36a9ed3 | ||
|
|
67714d33db | ||
|
|
e01cb108e1 | ||
|
|
3e634dad70 | ||
|
|
c2d947ee02 | ||
|
|
28fe702e8e | ||
|
|
baf4d5f9fc | ||
|
|
188a1a6e24 | ||
|
|
899fca12ba | ||
|
|
0f1395fdf0 | ||
|
|
c9f720b68d | ||
|
|
b30a8528bd | ||
|
|
bb4c180c89 | ||
|
|
a23dd9dfb3 | ||
|
|
3b5d8f0277 | ||
|
|
feb9a69703 | ||
|
|
fd2293b067 | ||
|
|
5cfdc71ca5 | ||
|
|
d3ee6ed9c5 | ||
|
|
08879c0f14 | ||
|
|
b7d0e5672a | ||
|
|
a39d4777fd | ||
|
|
cb4450864e | ||
|
|
ef3aeb65cc | ||
|
|
aca75ee982 | ||
|
|
326c872ba7 | ||
|
|
dd39887f2b | ||
|
|
8df9746005 | ||
|
|
668c53a0af | ||
|
|
30032f9c0c | ||
|
|
f2bc5c0482 | ||
|
|
1d3d261e38 | ||
|
|
c40793257d | ||
|
|
85b9f94a36 | ||
|
|
8688fabee3 | ||
|
|
e88b81c6c9 | ||
|
|
2344db8937 | ||
|
|
58302e9fc0 | ||
|
|
f48aabf344 | ||
|
|
8acc5573ff | ||
|
|
6224f6a1fa | ||
|
|
44bc637237 | ||
|
|
99d4f81892 | ||
|
|
98bedf1031 | ||
|
|
ef8e029cbf | ||
|
|
eb31e9205c | ||
|
|
c8204f1725 | ||
|
|
174f99728f | ||
|
|
dcdf6d966d | ||
|
|
3e79ebed60 | ||
|
|
5237a2c3e2 | ||
|
|
6e0d636989 | ||
|
|
d246c1e8b9 | ||
|
|
96541d8ab8 | ||
|
|
091c4fd9b0 | ||
|
|
8098566140 | ||
|
|
21dc97b809 | ||
|
|
23883b2b60 | ||
|
|
0f9b8daa57 | ||
|
|
cddb9aa8ba | ||
|
|
24606c0105 | ||
|
|
3384f7e28b | ||
|
|
6b7328bb87 | ||
|
|
f3529e3dd7 | ||
|
|
305952e32e | ||
|
|
c37186cc56 | ||
|
|
4e866123c5 | ||
|
|
35c0c9c0b1 | ||
|
|
d3bc9fbdf3 | ||
|
|
0cf2970134 | ||
|
|
206f081505 | ||
|
|
1c8307f264 | ||
|
|
2d65091f27 | ||
|
|
a492ab8294 | ||
|
|
3da6f45ba9 | ||
|
|
856d40fd99 | ||
|
|
846075704e | ||
|
|
156308c72e | ||
|
|
c99a35a8a5 | ||
|
|
f937fdd624 | ||
|
|
1f8c3074a6 | ||
|
|
11673005db | ||
|
|
df24a25829 | ||
|
|
2dc7ff7332 | ||
|
|
7ace48d5de | ||
|
|
56ccff4ee8 | ||
|
|
9d9f96a685 | ||
|
|
052c37acda | ||
|
|
fd2e88e13b | ||
|
|
4bd3829f78 | ||
|
|
28b399ec2b | ||
|
|
4bb936f876 | ||
|
|
6805d91033 | ||
|
|
8da2b9dbf8 | ||
|
|
45ff3385c7 | ||
|
|
53cc6a1611 | ||
|
|
4e3b408c50 | ||
|
|
bfc8154e68 | ||
|
|
620908523e | ||
|
|
8a996ba9a9 | ||
|
|
74d8f32f37 | ||
|
|
a5e329a1c5 | ||
|
|
3fe44f0d25 | ||
|
|
e207c91228 | ||
|
|
cdf922f51d | ||
|
|
45ffc0ae09 | ||
|
|
e214234001 | ||
|
|
54e58b51ab | ||
|
|
debe37308f | ||
|
|
7c096d08aa | ||
|
|
ac631d008c | ||
|
|
f1cad3443b | ||
|
|
cacde7a3aa | ||
|
|
b533c3582e | ||
|
|
69f18f6b7d | ||
|
|
de80f7d6ca | ||
|
|
38ec3b8972 | ||
|
|
52d40235b6 | ||
|
|
0ee662bb0e | ||
|
|
5733e90b09 | ||
|
|
95d2c64c1b | ||
|
|
b71c753a94 | ||
|
|
bd88ddfa07 | ||
|
|
373c6cd631 | ||
|
|
a464ad2c71 | ||
|
|
f3dd97f29c | ||
|
|
6587955668 | ||
|
|
9013036685 | ||
|
|
ebd632f582 | ||
|
|
ce22007b16 | ||
|
|
6a1043cef0 | ||
|
|
82f3b4c91f | ||
|
|
d0b6a611f2 | ||
|
|
714a4090a7 | ||
|
|
63d7e54ef3 | ||
|
|
a2f4917daf | ||
|
|
a09f1d14ba | ||
|
|
96c37b1fac | ||
|
|
4bd2545dad | ||
|
|
f4dfdf5889 | ||
|
|
08e4ba3363 | ||
|
|
3b2c6d2202 | ||
|
|
4f83bba829 | ||
|
|
109947ba3f | ||
|
|
5b228d1afd | ||
|
|
90d3917481 | ||
|
|
d9cc362258 | ||
|
|
0a5f890bf9 | ||
|
|
b873311bc5 | ||
|
|
eaa4e77626 | ||
|
|
7a7799407d | ||
|
|
a4e23e7655 | ||
|
|
56ea525499 | ||
|
|
e84bdd59c7 | ||
|
|
b5f484aaf5 | ||
|
|
3ec4fc6145 | ||
|
|
264b77c634 | ||
|
|
23d64dd3ac | ||
|
|
b3e4ec9454 | ||
|
|
39c6196487 | ||
|
|
986cf448a9 | ||
|
|
67f793a49e | ||
|
|
d202942a2c | ||
|
|
d338c130af | ||
|
|
283c4b13a1 | ||
|
|
7019f03e46 | ||
|
|
40007537ea | ||
|
|
6122a47241 | ||
|
|
ce3339a00f | ||
|
|
14df7a3273 | ||
|
|
9330d2b178 | ||
|
|
87dd198b52 | ||
|
|
a68c95522d | ||
|
|
cba0627a9c | ||
|
|
cb69944b5c | ||
|
|
f80517d719 | ||
|
|
13cfd80093 | ||
|
|
17ac41377e | ||
|
|
0b8459ca14 | ||
|
|
537fac70bf | ||
|
|
cf150caa2b | ||
|
|
23d276021e | ||
|
|
599f6f0228 | ||
|
|
bddc573c54 | ||
|
|
1a73d3323a | ||
|
|
2bfb99f174 | ||
|
|
f4a704164f | ||
|
|
e730f95a71 | ||
|
|
9f1f99f4db | ||
|
|
d236c3c011 | ||
|
|
73ccccb8a7 | ||
|
|
7ab2a9bfcb | ||
|
|
b19abe9c86 | ||
|
|
44026763b8 | ||
|
|
617cd6dfdb | ||
|
|
3a489b73f9 | ||
|
|
07013783ea | ||
|
|
7c77864396 | ||
|
|
3b8dde601d | ||
|
|
d9f79215a7 | ||
|
|
309b0b6382 | ||
|
|
9d021d004d | ||
|
|
452f64221e | ||
|
|
72419a1149 | ||
|
|
ab5c4749c1 | ||
|
|
5cdf8a2997 | ||
|
|
bfd8897f22 | ||
|
|
8c19be7213 | ||
|
|
4a47d1c8ef | ||
|
|
e3d7c9f1ea | ||
|
|
fbd8438072 | ||
|
|
efc2f0eded | ||
|
|
3e839b2e44 | ||
|
|
678e2c873e | ||
|
|
121c0d8433 | ||
|
|
881c7f804f | ||
|
|
2e55702258 | ||
|
|
964470fc11 | ||
|
|
c4d01b6aea | ||
|
|
0f80ecbb39 | ||
|
|
bf35821bc0 | ||
|
|
d896edeee8 | ||
|
|
328f82297a | ||
|
|
cafdcf77cb | ||
|
|
ed705ba98c | ||
|
|
2844c925eb | ||
|
|
ea8676ad2c | ||
|
|
028da61824 | ||
|
|
16337bf656 | ||
|
|
d8bf20310b | ||
|
|
cdd84dce6e | ||
|
|
797b40237e | ||
|
|
09f83f4fa9 |
12
.drone.yml
12
.drone.yml
@@ -14,7 +14,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
@@ -42,7 +42,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
@@ -70,7 +70,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
@@ -100,7 +100,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
@@ -132,7 +132,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
@@ -165,7 +165,7 @@ pipeline:
|
||||
cd /tmp &&
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git &&
|
||||
cd qtkeychain &&
|
||||
git checkout v0.8.0 &&
|
||||
git checkout v0.9.1 &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake ../ &&
|
||||
|
||||
64
.github/issue_template.md
vendored
Normal file
64
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<!---
|
||||
Please try to only report a bug if it happens with the latest version
|
||||
The latest version can be seen by checking https://download.nextcloud.com/desktop/
|
||||
For support try our forums: https://help.nextcloud.com
|
||||
--->
|
||||
|
||||
|
||||
### Expected behaviour
|
||||
Tell us what should happen
|
||||
|
||||
### Actual behaviour
|
||||
Tell us what happens instead
|
||||
|
||||
### Steps to reproduce
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### Client configuration
|
||||
Client version:
|
||||
|
||||
Operating system:
|
||||
|
||||
OS language:
|
||||
|
||||
Qt version used by client package (Linux only, see also Settings dialog):
|
||||
|
||||
Client package (From Nextcloud or distro) (Linux only):
|
||||
|
||||
Installation path of client:
|
||||
|
||||
|
||||
### Server configuration
|
||||
<!---
|
||||
Optional section. It depends on the issue.
|
||||
--->
|
||||
|
||||
Operating system:
|
||||
|
||||
Web server:
|
||||
|
||||
Database:
|
||||
|
||||
PHP version:
|
||||
|
||||
Nextcloud version:
|
||||
|
||||
Storage backend (external storage):
|
||||
|
||||
### Logs
|
||||
|
||||
Please use Gist (https://gist.github.com/) or a similar code paster for longer
|
||||
logs.
|
||||
|
||||
```Template for output < 10 lines```
|
||||
|
||||
1. Client logfile: Output of `nextcloud --logwindow` or `nextcloud --logfile log.txt`
|
||||
(On Windows using `cmd.exe`, you might need to first `cd` into the Nextcloud directory)
|
||||
(See also https://docs.nextcloud.com/desktop/2.3/troubleshooting.html#log-files)
|
||||
|
||||
2. Web server error log:
|
||||
|
||||
3. Server logfile: nextcloud log (data/nextcloud.log):
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -164,3 +164,10 @@ UpgradeLog*.htm
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
#cmake temporary stuff
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
CPackConfig.cmake
|
||||
CPackOptions.cmake
|
||||
CPackSourceConfig.cmake
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[ca]=@APPLICATION_NAME@ client de sincronització d'escriptori
|
||||
Icon[ca]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ca]=@APPLICATION_ICON_NAME@
|
||||
Name[ca]=@APPLICATION_NAME@ client de sincro d'escriptori
|
||||
GenericName[ca]=Directori de sincronització
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -198,7 +198,7 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[cs_CZ]=@APPLICATION_NAME@ desktopový synchronizační klient
|
||||
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ desktopový synchronizační klient
|
||||
Comment[cs_CZ]=@APPLICATION_NAME@ synchronizační klient pro desktop
|
||||
Icon[cs_CZ]=@NAZEV_IKONY_APLIKACE@
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ synchronizační klient pro desktop
|
||||
GenericName[cs_CZ]=Synchronizace složek
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -198,7 +198,7 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
|
||||
Icon[de]=@APPLICATION_EXECUTABLE@
|
||||
Name[de]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
|
||||
GenericName[de]=Synchronisationsordner
|
||||
Comment[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
|
||||
Icon[de_DE]=@APPLICATION_ICON_NAME@
|
||||
Name[de_DE]=@APPLICATION_NAME@ Client zur Desktop-Synchronisation
|
||||
GenericName[de_DE]=Synchronisationsordner
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||
Icon[en_GB]=@APPLICATION_EXECUTABLE@
|
||||
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
|
||||
GenericName[en_GB]=Folder Sync
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_CL]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_CL]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_CL]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_CL]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_CO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_CO]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_CO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_CO]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_CR]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_CR]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_CR]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_CR]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_DO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_DO]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_DO]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_DO]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_EC]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_EC]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_EC]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_EC]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_GT]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_GT]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_GT]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_GT]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_MX]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_MX]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_MX]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_MX]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es_SV]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
Icon[es_SV]=@APPLICATION_EXECUTABLE@
|
||||
Name[es_SV]=@APPLICATION_NAME@ Cliente de sincronización de escritorio
|
||||
GenericName[es_SV]=Sincronización de carpeta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[es]=Cliente de sincronización de escritorio @APPLICATION_NAME@
|
||||
Icon[es]=@APPLICATION_EXECUTABLE@
|
||||
Icon[es]=@APPLICATION_ICON_NAME@
|
||||
Name[es]=Cliente de sincronización de escritorio @APPLICATION_NAME@
|
||||
GenericName[es]=Sincronización de carpetas
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -198,7 +198,7 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
Comment[fr]=Client desktop de synchronisation @APPLICATION_NAME@
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[fr]=Client de synchronisation @APPLICATION_NAME@ desktop
|
||||
Icon[fr]=@APPLICATION_ICON_NAME@
|
||||
Name[fr]=Client desktop de synchronisation @APPLICATION_NAME@
|
||||
GenericName[fr]=Synchronisation du dossier
|
||||
|
||||
204
.tx/nextcloud.client-desktop/gl_translation
Normal file
204
.tx/nextcloud.client-desktop/gl_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
|
||||
Icon[gl]=@APPLICATION_ICON_NAME@
|
||||
Name[gl]=@APPLICATION_NAME@ cliente de sincr escritorio
|
||||
GenericName[gl]=Sincr. de cartafol
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[he]=@APPLICATION_NAME@ לקוח סנכרון לשולחן העבודה
|
||||
Icon[he]=@APPLICATION_EXECUTABLE@
|
||||
Name[he]=@APPLICATION_NAME@ לקוח סנכרון לשולחן העבודה
|
||||
GenericName[he]=סנכרון תיקיות
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
|
||||
204
.tx/nextcloud.client-desktop/hu_translation
Normal file
204
.tx/nextcloud.client-desktop/hu_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[hu_HU]=@APPLICATION_NAME@ deszktop szinkronizációs kliens
|
||||
Icon[hu_HU]=@APPLICATION_ICON_NAME@
|
||||
Name[hu_HU]=@APPLICATION_NAME@ deszktop szinkronizációs kliens
|
||||
GenericName[hu_HU]=Mappa szinkronizáció
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[is]=@APPLICATION_NAME@ forrit til samstillingar við tölvu
|
||||
Icon[is]=@APPLICATION_EXECUTABLE@
|
||||
Icon[is]=@APPLICATION_ICON_NAME@
|
||||
Name[is]=@APPLICATION_NAME@ forrit til samstillingar við tölvu
|
||||
GenericName[is]=Samstilling á möppum
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[it]=Client di sincronizzazione desktop di @APPLICATION_NAME@
|
||||
Icon[it]=@APPLICATION_EXECUTABLE@
|
||||
Icon[it]=@APPLICATION_ICON_NAME@
|
||||
Name[it]=Client di sincronizzazione desktop di @APPLICATION_NAME@
|
||||
GenericName[it]=Sincronizzazione cartelle
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
|
||||
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
GenericName[ja_JP]=フォルダーを同期する
|
||||
|
||||
204
.tx/nextcloud.client-desktop/lt_LT_translation
Normal file
204
.tx/nextcloud.client-desktop/lt_LT_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo kliento programa
|
||||
Icon[lt_LT]=@APPLICATION_ICON_NAME@
|
||||
Name[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo kliento programa
|
||||
GenericName[lt_LT]=Aplankų sinchronizavimas
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[lv]=@APPLICATION_NAME@ darbavirsmas sinhronizešanas klients
|
||||
Icon[lv]=@APPLICATION_EXECUTABLE@
|
||||
Icon[lv]=@APPLICATION_ICON_NAME@
|
||||
Name[lv]=@APPLICATION_NAME@ darbavirsmas sinhronizešanas klients
|
||||
GenericName[lv]=Mapju Sinhronizēšana
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[nb_NO]=@APPLICATION_NAME@ klient for synkroinisering
|
||||
Icon[nb_NO]=@APPLICATION_EXECUTABLE@
|
||||
Name[nb_NO]=@APPLICATION_NAME@ klient for synkroinisering
|
||||
GenericName[nb_NO]=Mappe synkroinisering
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[nl]=@APPLICATION_NAME@ desktopsynchronisatieclient
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[nl]=@APPLICATION_ICON_NAME@
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
GenericName[nl]=Map synchronisatie
|
||||
|
||||
204
.tx/nextcloud.client-desktop/pl_translation
Normal file
204
.tx/nextcloud.client-desktop/pl_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[pl]=@APPLICATION_NAME@ desktopowy klient synchronizacji
|
||||
Icon[pl]=@APPLICATION_ICON_NAME@
|
||||
Name[pl]=@APPLICATION_NAME@ desktopowy klient synchronizacji
|
||||
GenericName[pl]=Katalog synchronizacji
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização desktop
|
||||
Icon[pt_BR]=@APPLICATION_EXECUTABLE@
|
||||
Icon[pt_BR]=@APPLICATION_ICON_NAME@
|
||||
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização desktop
|
||||
GenericName[pt_BR]=Sincronizar Pasta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização da Área de Trabalho
|
||||
Icon[pt_PT]=@APPLICATION_EXECUTABLE@
|
||||
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização da Área de Trabalho
|
||||
GenericName[pt_PT]=Sincronização de Pasta
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК
|
||||
Icon[ru]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ru]=@APPLICATION_ICON_NAME@
|
||||
Name[ru]=@APPLICATION_NAME@ клиент для ПК
|
||||
GenericName[ru]=Синхронизация папок
|
||||
|
||||
204
.tx/nextcloud.client-desktop/sk_translation
Normal file
204
.tx/nextcloud.client-desktop/sk_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[sk_SK]=@APPLICATION_NAME@ Synchronizačný klient pre PC
|
||||
Icon[sk_SK]=@APPLICATION_ICON_NAME@
|
||||
Name[sk_SK]=@APPLICATION_NAME@ Synchronizačný klient pre PC
|
||||
GenericName[sk_SK]=Synchnonizácia priečinka
|
||||
204
.tx/nextcloud.client-desktop/sl_translation
Normal file
204
.tx/nextcloud.client-desktop/sl_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
|
||||
Icon[sl]=@APPLICATION_ICON_NAME@
|
||||
Name[sl]=@APPLICATION_NAME@ odjemalec za usklajevanje
|
||||
GenericName[sl]=Usklajevanje map
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[sr]=@APPLICATION_NAME@ десктоп клијент за синхронизацију
|
||||
Icon[sr]=@APPLICATION_EXECUTABLE@
|
||||
Icon[sr]=@APPLICATION_ICON_NAME@
|
||||
Name[sr]=@APPLICATION_NAME@ десктоп клијент за синхронизацију
|
||||
GenericName[sr]=Синхронизација фасцикли
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,6 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi
|
||||
Icon[tr]=@APPLICATION_EXECUTABLE@
|
||||
Icon[tr]=@APPLICATION_ICON_NAME@
|
||||
Name[tr]=@APPLICATION_NAME@ masaüstü eşiteme istemcisi
|
||||
GenericName[tr]=Klasör Eşitleme
|
||||
|
||||
204
.tx/nextcloud.client-desktop/zh_CN_translation
Normal file
204
.tx/nextcloud.client-desktop/zh_CN_translation
Normal file
@@ -0,0 +1,204 @@
|
||||
[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
|
||||
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
Icon[zh_CN]=@APPLICATION_ICON_NAME@
|
||||
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
GenericName[zh_CN]=文件夹同步
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -199,6 +199,5 @@ X-GNOME-Autostart-Delay=3
|
||||
|
||||
# Translations
|
||||
Comment[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
Icon[zh_TW]=@APPLICATION_EXECUTABLE@
|
||||
Name[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
GenericName[zh_TW]=資料夾同步
|
||||
|
||||
@@ -19,7 +19,7 @@ if(APPLE)
|
||||
set( CPACK_GENERATOR "DragNDrop" )
|
||||
set( CPACK_SOURCE_GENERATOR "")
|
||||
set( CPACK_PACKAGE_FILE_NAME ${APPLICATION_SHORTNAME}-${CPACK_PACKAGE_VERSION} )
|
||||
set( CPACK_PACKAGE_ICON ${CMAKE_BINARY_DIR}/src/gui/ownCloud.icns)
|
||||
set( CPACK_PACKAGE_ICON ${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns)
|
||||
|
||||
set( CPACK_DMG_DS_STORE "${CMAKE_SOURCE_DIR}/admin/osx/DS_Store.in")
|
||||
# set( CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/admin/osx/DMGBackground.png" )
|
||||
|
||||
18
README.md
18
README.md
@@ -17,30 +17,36 @@ with your computer.
|
||||
|
||||
##### Clone the repo and create build directory
|
||||
```
|
||||
$ git clone git@github.com:nextcloud/desktop.git
|
||||
$ git clone https://github.com/nextcloud/desktop.git
|
||||
$ cd desktop
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
```
|
||||
##### Compile and install
|
||||
|
||||
For development reasons it is better to install the client on user space
|
||||
instead on the global system. For example you could use in the next
|
||||
instructions `path-to-install-folder/` as `~/.local/` in a linux system. If
|
||||
you want to install system wide you could use `/usr/local` or `/opt/nextcloud/`.
|
||||
|
||||
##### Linux
|
||||
|
||||
```
|
||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1
|
||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1 -DQTKEYCHAIN_LIBRARY=/path-to-qt5keychain-folder/lib64/libqt5keychain.so -DQTKEYCHAIN_INCLUDE_DIR=/path-to-qt5keychain-folder/include/qt5keychain/ -DOPENSSL_ROOT_DIR=/path-to-openssl-folder/ -DOPENSSL_INCLUDE_DIR=path-to-openssl-folder/include -DOPENSSL_LIBRARIES=path-to-openssl-folder/lib
|
||||
$ make install
|
||||
```
|
||||
|
||||
##### Windows
|
||||
|
||||
```
|
||||
$ cmake -G "Visual Studio 15 2017 Win64" .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1
|
||||
$ cmake -G "Visual Studio 15 2017 Win64" .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1 -DPng2Ico_EXECUTABLE=/path-to-install-png2ico/png2ico.exe -DQTKEYCHAIN_LIBRARY=/path-to-qt5keychain-folder/lib/qt5keychain.lib -DQTKEYCHAIN_INCLUDE_DIR=/path-to-qt5keychain-folder/include/qt5keychain/ -DOPENSSL_ROOT_DIR=/path-to-openssl-folder/ -DOPENSSL_INCLUDE_DIR=path-to-openssl-folder/include -DOPENSSL_LIBRARIES=path-to-openssl-folder/lib
|
||||
$ cmake --build . --config Debug --target install
|
||||
```
|
||||
|
||||
##### Mac OS
|
||||
|
||||
```
|
||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1
|
||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=path-to-install-folder/ -DCMAKE_BUILD_TYPE=Debug -DNO_SHIBBOLETH=1 -DQTKEYCHAIN_LIBRARY=/path-to-qt5keychain-folder/lib/libqt5keychain.dylib -DQTKEYCHAIN_INCLUDE_DIR=/path-to-qt5keychain-folder/include/qt5keychain/ -DOPENSSL_ROOT_DIR=/path-to-openssl-folder/ -DOPENSSL_INCLUDE_DIR=path-to-openssl-folder/include -DOPENSSL_LIBRARIES=path-to-openssl-folder/lib
|
||||
$ make install
|
||||
```
|
||||
|
||||
@@ -69,6 +75,8 @@ of your report being lost. :boom:
|
||||
|
||||
- If you created a patch :heart_eyes:, please submit a [Pull
|
||||
Request](https://github.com/nextcloud/client/pulls).
|
||||
- How to create a pull request? This guide will help you get started: [Opening a pull request](https://opensource.guide/how-to-contribute/#opening-a-pull-request) :heart:
|
||||
|
||||
|
||||
## :satellite: Contact us
|
||||
|
||||
@@ -99,5 +107,3 @@ https://github.com/nextcloud/desktop.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ if [ $SUFFIX != "master" ]; then
|
||||
SUFFIX="PR-$SUFFIX"
|
||||
fi
|
||||
|
||||
#QtKeyChain 0.8.0
|
||||
#QtKeyChain 0.9.1
|
||||
cd /build
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git
|
||||
cd qtkeychain
|
||||
git checkout v0.8.0
|
||||
git checkout v0.9.1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -D CMAKE_INSTALL_PREFIX=/usr ../
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
--- nextcloud-client-2.4.0.orig/src/gui/wizard/owncloudoauthcredspage.cpp
|
||||
+++ nextcloud-client-2.4.0/src/gui/wizard/owncloudoauthcredspage.cpp
|
||||
@@ -53,10 +53,8 @@ OwncloudOAuthCredsPage::OwncloudOAuthCredsPage()
|
||||
_ui.openLinkButton->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
QObject::connect(_ui.openLinkButton, &QWidget::customContextMenuRequested, [this](const QPoint &pos) {
|
||||
auto menu = new QMenu(_ui.openLinkButton);
|
||||
- menu->addAction(tr("Copy link to clipboard"), this, [this] {
|
||||
- if (_asyncAuth)
|
||||
- QApplication::clipboard()->setText(_asyncAuth->authorisationLink().toString(QUrl::FullyEncoded));
|
||||
- });
|
||||
+ auto action = menu->addAction(tr("Copy link to clipboard"));
|
||||
+ connect(action, &QAction::triggered, this, &OwncloudOAuthCredsPage::copyLinkToClipboard);
|
||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
menu->popup(_ui.openLinkButton->mapToGlobal(pos));
|
||||
});
|
||||
@@ -131,4 +129,11 @@ bool OwncloudOAuthCredsPage::isComplete() const
|
||||
return false; /* We can never go forward manually */
|
||||
}
|
||||
|
||||
+void OwncloudOAuthCredsPage::copyLinkToClipboard()
|
||||
+{
|
||||
+ if (_asyncAuth)
|
||||
+ QApplication::clipboard()->setText(_asyncAuth->authorisationLink().toString(QUrl::FullyEncoded));
|
||||
+}
|
||||
+
|
||||
+
|
||||
} // namespace OCC
|
||||
--- nextcloud-client-2.4.0.orig/src/gui/wizard/owncloudoauthcredspage.h
|
||||
+++ nextcloud-client-2.4.0/src/gui/wizard/owncloudoauthcredspage.h
|
||||
@@ -57,6 +57,10 @@ public:
|
||||
QString _refreshToken;
|
||||
QScopedPointer<OAuth> _asyncAuth;
|
||||
Ui_OwncloudOAuthCredsPage _ui;
|
||||
+
|
||||
+protected slots:
|
||||
+ void copyLinkToClipboard();
|
||||
+
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
@@ -45,6 +45,9 @@ macro (KDE4_ADD_APP_ICON appsources pattern)
|
||||
if (fn MATCHES ".*128.*" )
|
||||
list (APPEND _icons ${it})
|
||||
endif (fn MATCHES ".*128.*")
|
||||
if (fn MATCHES ".*256.*" )
|
||||
list (APPEND _icons ${it})
|
||||
endif (fn MATCHES ".*256.*")
|
||||
endforeach (it)
|
||||
if (_icons)
|
||||
add_custom_command(OUTPUT ${_outfilename}.ico ${_outfilename}.rc
|
||||
|
||||
@@ -168,7 +168,8 @@ function(ecm_add_app_icon appsources)
|
||||
${icons_at_32px}
|
||||
${icons_at_48px}
|
||||
${icons_at_64px}
|
||||
${icons_at_128px})
|
||||
${icons_at_128px}
|
||||
${icons_at_256px})
|
||||
if (NOT windows_icons)
|
||||
message(AUTHOR_WARNING "No icons suitable for use on Windows provided")
|
||||
endif()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@APPLICATION_EXECUTABLE@</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>ownCloud.icns</string>
|
||||
<string>@APPLICATION_ICON_NAME@.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@APPLICATION_REV_DOMAIN@</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
||||
19
doc/faq.rst
19
doc/faq.rst
@@ -21,6 +21,25 @@ When a deeply nested directory is excluded from synchronization it will be
|
||||
listed with other ignored files and directories in the "Not synced" tab of
|
||||
the "Activity" pane.
|
||||
|
||||
There Was A Warning About Changes In Synchronized Folders Not Being Tracked Reliably.
|
||||
-------------------------------------------------------------------------------------
|
||||
|
||||
On linux when the synchronized folder contains very many subfolders the
|
||||
operating system may not allow for enough inotify watches to monitor the
|
||||
changes in all of them.
|
||||
|
||||
In this case the client will not be able to immediately start the
|
||||
synchronization process when a file in one of the unmonitored folders changes.
|
||||
Instead, the client will show the warning and manually scan folders for changes
|
||||
in a regular interval (two hours by default).
|
||||
|
||||
This problem can be solved by setting the fs.inotify.max_user_watches
|
||||
sysctl to a higher value. This can usually be done either temporarily::
|
||||
|
||||
echo 524288 > /proc/sys/fs/inotify/max_user_watches
|
||||
|
||||
or permanently by adjusting ``/etc/sysctl.conf``.
|
||||
|
||||
I Want To Move My Local Sync Folder
|
||||
-----------------------------------
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ The other options are:
|
||||
``--logflush``
|
||||
Clears (flushes) the log file after each write action.
|
||||
|
||||
``--logdebug``
|
||||
Also output debug-level messages in the log (equivalent to setting the env var QT_LOGGING_RULES="qt.*=true;*.debug=true").
|
||||
)
|
||||
|
||||
``--confdir`` `<dirname>`
|
||||
Uses the specified configuration directory.
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Exec=@APPLICATION_EXECUTABLE@
|
||||
Name=@APPLICATION_NAME@ desktop sync client
|
||||
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||
GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Icon=@APPLICATION_ICON_NAME@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
# Translations
|
||||
@@ -198,185 +198,185 @@ X-GNOME-Autostart-Delay=3
|
||||
Comment[oc]=@APPLICATION_NAME@ sincronizacion del client
|
||||
GenericName[oc]=Dorsièr de Sincronizacion
|
||||
Name[oc]=@APPLICATION_NAME@ sincronizacion del client
|
||||
Icon[oc]=@APPLICATION_EXECUTABLE@
|
||||
Icon[oc]=@APPLICATION_ICON_NAME@
|
||||
Comment[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
GenericName[ar]=مزامنة المجلد
|
||||
Name[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
Icon[ar]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ar]=@APPLICATION_ICON_NAME@
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
|
||||
GenericName[bg_BG]=Синхронизиране на папката
|
||||
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
|
||||
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
|
||||
Icon[bg_BG]=@APPLICATION_ICON_NAME@
|
||||
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
GenericName[ca]=Sincronització de carpetes
|
||||
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
Icon[ca]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ca]=@APPLICATION_ICON_NAME@
|
||||
Comment[da]=@APPLICATION_NAME@ skrivebordsklient til synkronisering
|
||||
GenericName[da]=Mappesynkronisering
|
||||
Name[da]=@APPLICATION_NAME@ skrivebordsklient til synk
|
||||
Icon[da]=@APPLICATION_EXECUTABLE@
|
||||
Icon[da]=@APPLICATION_ICON_NAME@
|
||||
Comment[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de]=Ordner-Synchronisation
|
||||
Name[de]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de]=@APPLICATION_EXECUTABLE@
|
||||
Icon[de]=@APPLICATION_ICON_NAME@
|
||||
Comment[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
GenericName[ja_JP]=フォルダー同期
|
||||
Name[ja_JP]=@APPLICATION_NAME@ デスクトップ同期クライアント
|
||||
Icon[ja_JP]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ja_JP]=@APPLICATION_ICON_NAME@
|
||||
Comment[el]=@ΟΝΟΜΑ_ΕΦΑΡΜΟΓΗΣ@ συγχρονισμός επιφάνειας εργασίας πελάτη
|
||||
GenericName[el]=Συγχρονισμός φακέλου
|
||||
Name[el]=@ΟΝΟΜΑ_ΕΦΑΡΜΟΓΗΣ@ συγχρονισμός επιφάνειας εργασίας πελάτη
|
||||
Icon[el]=@APPLICATION_EXECUTABLE@
|
||||
Icon[el]=@APPLICATION_ICON_NAME@
|
||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||
GenericName[en_GB]=Folder Sync
|
||||
Name[en_GB]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[en_GB]=@APPLICATION_EXECUTABLE@
|
||||
Icon[en_GB]=@APPLICATION_ICON_NAME@
|
||||
Comment[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
GenericName[es]=Sincronización de carpeta
|
||||
Name[es]=@APPLICATION_NAME@ cliente de sincronización de escritorio
|
||||
Icon[es]=@APPLICATION_EXECUTABLE@
|
||||
Icon[es]=@APPLICATION_ICON_NAME@
|
||||
Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de_DE]=Ordner-Synchronisation
|
||||
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de_DE]=@APPLICATION_EXECUTABLE@
|
||||
Icon[de_DE]=@APPLICATION_ICON_NAME@
|
||||
Comment[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
|
||||
GenericName[eu]=Karpetaren sinkronizazioa
|
||||
Name[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
|
||||
Icon[eu]=@APPLICATION_EXECUTABLE@
|
||||
Icon[eu]=@APPLICATION_ICON_NAME@
|
||||
GenericName[fa]=همسان سازی پوشهها
|
||||
Name[fa]=@APPLICATION_EXECUTABLE@ نسخهی همسان سازی مشتری
|
||||
Icon[fa]=@APPLICATION_EXECUTABLE@
|
||||
Icon[fa]=@APPLICATION_ICON_NAME@
|
||||
Comment[fr]=Synchronisez vos dossiers avec un serveur @APPLICATION_NAME@
|
||||
GenericName[fr]=Synchronisation de dossier
|
||||
Name[fr]=Client de synchronisation @APPLICATION_NAME@
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
Icon[fr]=@APPLICATION_ICON_NAME@
|
||||
Comment[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
|
||||
GenericName[gl]=Sincronizar Cartafol
|
||||
Name[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
|
||||
Icon[gl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[gl]=@APPLICATION_ICON_NAME@
|
||||
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
|
||||
GenericName[he]=סנכון תיקייה
|
||||
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
|
||||
Icon[he]=@APPLICATION_EXECUTABLE@
|
||||
Icon[he]=@APPLICATION_ICON_NAME@
|
||||
Comment[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
|
||||
GenericName[ia]=Synchronisar Dossier
|
||||
Name[ia]=@APPLICATION_NAME@ cliente de synchronisation pro scriptorio
|
||||
Icon[ia]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ia]=@APPLICATION_ICON_NAME@
|
||||
Comment[id]=Klien sinkronisasi desktop @APPLICATION_NAME@
|
||||
GenericName[id]=Folder Sync
|
||||
Name[id]=Klien sync desktop @APPLICATION_NAME@
|
||||
Icon[id]=@APPLICATION_EXECUTABLE@
|
||||
Icon[id]=@APPLICATION_ICON_NAME@
|
||||
Comment[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
GenericName[is]=Samstilling möppu
|
||||
Name[is]=@APPLICATION_NAME@ skjáborðsforrit samstillingar
|
||||
Icon[is]=@APPLICATION_EXECUTABLE@
|
||||
Icon[is]=@APPLICATION_ICON_NAME@
|
||||
Comment[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
GenericName[it]=Sincronizzazione cartella
|
||||
Name[it]=Client di sincronizzazione del desktop di @APPLICATION_NAME@
|
||||
Icon[it]=@APPLICATION_EXECUTABLE@
|
||||
Icon[it]=@APPLICATION_ICON_NAME@
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
Icon[ko]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ko]=@APPLICATION_ICON_NAME@
|
||||
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
|
||||
GenericName[hu_HU]=Könyvtár szinkronizálás
|
||||
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
|
||||
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
|
||||
Icon[hu_HU]=@APPLICATION_ICON_NAME@
|
||||
Comment[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
|
||||
GenericName[af_ZA]=Vouersinchronisering
|
||||
Name[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
|
||||
Icon[af_ZA]=@APPLICATION_EXECUTABLE@
|
||||
Icon[af_ZA]=@APPLICATION_ICON_NAME@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
Icon[nl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[nl]=@APPLICATION_ICON_NAME@
|
||||
Comment[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
|
||||
GenericName[et_EE]=Kaustade sünkroonimine
|
||||
Name[et_EE]=@APPLICATION_NAME@ sünkroonimise klient töölauale
|
||||
Icon[et_EE]=@APPLICATION_EXECUTABLE@
|
||||
Icon[et_EE]=@APPLICATION_ICON_NAME@
|
||||
Comment[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
|
||||
GenericName[pl]=Folder Synchronizacji
|
||||
Name[pl]=@APPLICATION_NAME@ klient synchronizacji dla komputerów stacjonarnych
|
||||
Icon[pl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[pl]=@APPLICATION_ICON_NAME@
|
||||
Comment[pt_BR]=@APPLICATION_NAME@ cliente de sincronização do computador
|
||||
GenericName[pt_BR]=Sincronização de Pasta
|
||||
Name[pt_BR]=@APPLICATION_NAME@ cliente de sincronização de desktop
|
||||
Icon[pt_BR]=@APPLICATION_EXECUTABLE@
|
||||
Icon[pt_BR]=@APPLICATION_ICON_NAME@
|
||||
Comment[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
GenericName[cs_CZ]=Synchronizace adresáře
|
||||
Name[cs_CZ]=@APPLICATION_NAME@ počítačový synchronizační klient
|
||||
Icon[cs_CZ]=@APPLICATION_EXECUTABLE@
|
||||
Icon[cs_CZ]=@APPLICATION_ICON_NAME@
|
||||
Comment[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
|
||||
GenericName[ru]=Синхронизация каталогов
|
||||
Name[ru]=Настольный клиент синхронизации @APPLICATION_NAME@
|
||||
Icon[ru]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ru]=@APPLICATION_ICON_NAME@
|
||||
Comment[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
GenericName[sl]=Usklajevanje map
|
||||
Name[sl]=@APPLICATION_NAME@ ‒ Program za usklajevanje datotek z namizjem
|
||||
Icon[sl]=@APPLICATION_EXECUTABLE@
|
||||
Icon[sl]=@APPLICATION_ICON_NAME@
|
||||
Comment[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
GenericName[sq]=Njëkohësim Dosjesh
|
||||
Name[sq]=Klient njëkohësimesh @APPLICATION_NAME@ për desktop
|
||||
Icon[sq]=@APPLICATION_EXECUTABLE@
|
||||
Icon[sq]=@APPLICATION_ICON_NAME@
|
||||
Comment[fi_FI]=@APPLICATION_NAME@ työpöytäsynkronointisovellus
|
||||
GenericName[fi_FI]=Kansion synkronointi
|
||||
Name[fi_FI]=@APPLICATION_NAME@ työpöytäsynkronointisovellus
|
||||
Icon[fi_FI]=@APPLICATION_EXECUTABLE@
|
||||
Icon[fi_FI]=@APPLICATION_ICON_NAME@
|
||||
Comment[sv]=@APPLICATION_NAME@ desktop synkroniseringsklient
|
||||
GenericName[sv]=Mappsynk
|
||||
Name[sv]=@APPLICATION_NAME@ desktop synk-klient
|
||||
Icon[sv]=@APPLICATION_EXECUTABLE@
|
||||
Icon[sv]=@APPLICATION_ICON_NAME@
|
||||
Comment[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi
|
||||
GenericName[tr]=Dosya Eşitleme
|
||||
Name[tr]=@APPLICATION_NAME@ masaüstü eşitleme istemcisi
|
||||
Icon[tr]=@APPLICATION_EXECUTABLE@
|
||||
Icon[tr]=@APPLICATION_ICON_NAME@
|
||||
Comment[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
GenericName[uk]=Синхронізація теки
|
||||
Name[uk]=Настільний клієнт синхронізації @APPLICATION_NAME@
|
||||
Icon[uk]=@APPLICATION_EXECUTABLE@
|
||||
Icon[uk]=@APPLICATION_ICON_NAME@
|
||||
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
GenericName[ro]=Sincronizare director
|
||||
Name[ro]=@APPLICATION_NAME@ client de sincronizare pe desktop
|
||||
Icon[ro]=@APPLICATION_EXECUTABLE@
|
||||
Icon[ro]=@APPLICATION_ICON_NAME@
|
||||
Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
GenericName[zh_CN]=文件夹同步
|
||||
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
Icon[zh_CN]=@APPLICATION_EXECUTABLE@
|
||||
Icon[zh_CN]=@APPLICATION_ICON_NAME@
|
||||
Comment[zh_HK]=桌面版同步客户端
|
||||
Comment[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
GenericName[zh_TW]=資料夾同步
|
||||
Name[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
Icon[zh_TW]=@APPLICATION_EXECUTABLE@
|
||||
Icon[zh_TW]=@APPLICATION_ICON_NAME@
|
||||
Comment[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
|
||||
GenericName[es_AR]=Sincronización de directorio
|
||||
Name[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
|
||||
Icon[es_AR]=@APPLICATION_EXECUTABLE@
|
||||
Icon[es_AR]=@APPLICATION_ICON_NAME@
|
||||
Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo programa
|
||||
GenericName[lt_LT]=Katalogo sinchnorizacija
|
||||
Name[lt_LT]=@APPLICATION_NAME@ darbalaukio programa
|
||||
Icon[lt_LT]=@APPLICATION_EXECUTABLE@
|
||||
Icon[lt_LT]=@APPLICATION_ICON_NAME@
|
||||
Comment[th_TH]=@APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
GenericName[th_TH]=ประสานข้อมูลโฟลเดอร์
|
||||
Name[th_TH]= @APPLICATION_NAME@ ไคลเอนต์ประสานข้อมูลเดสก์ท็อป
|
||||
Icon[th_TH]=@APPLICATION_EXECUTABLE@
|
||||
Icon[th_TH]=@APPLICATION_ICON_NAME@
|
||||
Comment[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
|
||||
GenericName[es_MX]=Sincronización de Carpetas
|
||||
Name[es_MX]=Cliente de escritorio para sincronziación de @APPLICATION_NAME@
|
||||
Icon[es_MX]=@APPLICATION_EXECUTABLE@
|
||||
Icon[es_MX]=@APPLICATION_ICON_NAME@
|
||||
Comment[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
|
||||
GenericName[nb_NO]=Mappesynkronisering
|
||||
Name[nb_NO]=@APPLICATION_NAME@ skrivebordssynkroniseringsklient
|
||||
Icon[nb_NO]=@APPLICATION_EXECUTABLE@
|
||||
Icon[nb_NO]=@APPLICATION_ICON_NAME@
|
||||
Comment[nn_NO]=@APPLICATION_NAME@ klient for å synkronisera frå skrivebord
|
||||
GenericName[nn_NO]=Mappe synkronisering
|
||||
Name[nn_NO]=@APPLICATION_NAME@ klient for å synkronisera frå skrivebord
|
||||
Icon[nn_NO]=@APPLICATION_EXECUTABLE@
|
||||
Icon[nn_NO]=@APPLICATION_ICON_NAME@
|
||||
Comment[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
GenericName[pt_PT]=Sincronizar Pasta
|
||||
Name[pt_PT]=@APPLICATION_NAME@ - Cliente de Sincronização para PC
|
||||
Icon[pt_PT]=@APPLICATION_EXECUTABLE@
|
||||
Icon[km]=@APPLICATION_EXECUTABLE@
|
||||
Icon[pt_PT]=@APPLICATION_ICON_NAME@
|
||||
Icon[km]=@APPLICATION_ICON_NAME@
|
||||
Comment[lb]=@APPLICATION_NAME@ Desktop Synchronisatioun Client
|
||||
GenericName[lb]=Dossier Dync
|
||||
Name[lb]=@APPLICATION_NAME@ Desktop Sync Client
|
||||
Icon[lb]=@APPLICATION_EXECUTABLE@
|
||||
Icon[lb]=@APPLICATION_ICON_NAME@
|
||||
|
||||
@@ -63,7 +63,7 @@ class SocketConnect(GObject.GObject):
|
||||
self._watch_id = 0
|
||||
self._sock = None
|
||||
self._listeners = [self._update_registered_paths, self._get_version]
|
||||
self._remainder = ''.encode()
|
||||
self._remainder = ''.encode() if python3 else ''
|
||||
self.protocolVersion = '1.0'
|
||||
self.nautilusVFSFile_table = {} # not needed in this object actually but shared
|
||||
# all over the other objects.
|
||||
@@ -82,7 +82,7 @@ class SocketConnect(GObject.GObject):
|
||||
# print("Server command: " + cmd)
|
||||
if self.connected:
|
||||
try:
|
||||
self._sock.send(cmd.encode())
|
||||
self._sock.send(cmd.encode() if python3 else cmd)
|
||||
except:
|
||||
print("Sending failed.")
|
||||
self.reconnect()
|
||||
@@ -134,7 +134,8 @@ class SocketConnect(GObject.GObject):
|
||||
return []
|
||||
data = self._remainder[:end]
|
||||
self._remainder = self._remainder[end+1:]
|
||||
return data.decode().split('\n')
|
||||
data = data.decode() if python3 else data
|
||||
return data.split('\n')
|
||||
|
||||
# Notify is the raw answer from the socket
|
||||
def _handle_notify(self, source, condition):
|
||||
@@ -233,7 +234,7 @@ class MenuExtension(GObject.GObject, Nautilus.MenuProvider):
|
||||
def ask_for_menu_items(self, files):
|
||||
record_separator = '\x1e'
|
||||
filesstring = record_separator.join(files)
|
||||
socketConnect.sendCommand('GET_MENU_ITEMS:{}\n'.format(filesstring))
|
||||
socketConnect.sendCommand(u'GET_MENU_ITEMS:{}\n'.format(filesstring))
|
||||
|
||||
done = False
|
||||
start = time.time()
|
||||
|
||||
2
src/3rdparty/qtmacgoodies
vendored
2
src/3rdparty/qtmacgoodies
vendored
Submodule src/3rdparty/qtmacgoodies updated: 4ffbff5d5f...ebc7ec6f68
8853
src/3rdparty/sqlite3/sqlite3.c
vendored
8853
src/3rdparty/sqlite3/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
275
src/3rdparty/sqlite3/sqlite3.h
vendored
275
src/3rdparty/sqlite3/sqlite3.h
vendored
@@ -123,9 +123,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.23.1"
|
||||
#define SQLITE_VERSION_NUMBER 3023001
|
||||
#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b"
|
||||
#define SQLITE_VERSION "3.24.0"
|
||||
#define SQLITE_VERSION_NUMBER 3024000
|
||||
#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@@ -504,6 +504,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
@@ -511,6 +512,7 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
@@ -1930,6 +1932,22 @@ struct sqlite3_mem_methods {
|
||||
** I/O required to support statement rollback.
|
||||
** The default value for this setting is controlled by the
|
||||
** [SQLITE_STMTJRNL_SPILL] compile-time option.
|
||||
**
|
||||
** [[SQLITE_CONFIG_SORTERREF_SIZE]]
|
||||
** <dt>SQLITE_CONFIG_SORTERREF_SIZE
|
||||
** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter
|
||||
** of type (int) - the new value of the sorter-reference size threshold.
|
||||
** Usually, when SQLite uses an external sort to order records according
|
||||
** to an ORDER BY clause, all fields required by the caller are present in the
|
||||
** sorted records. However, if SQLite determines based on the declared type
|
||||
** of a table column that its values are likely to be very large - larger
|
||||
** than the configured sorter-reference size threshold - then a reference
|
||||
** is stored in each sorted record and the required column values loaded
|
||||
** from the database as records are returned in sorted order. The default
|
||||
** value for this option is to never use this optimization. Specifying a
|
||||
** negative value for this option restores the default behaviour.
|
||||
** This option is only available if SQLite is compiled with the
|
||||
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@@ -1959,6 +1977,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
|
||||
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
|
||||
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
||||
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@@ -2095,6 +2114,21 @@ struct sqlite3_mem_methods {
|
||||
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
|
||||
** it is not disabled, 1 if it is.
|
||||
** </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
|
||||
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
|
||||
** [VACUUM] in order to reset a database back to an empty database
|
||||
** with no schema and no content. The following process works even for
|
||||
** a badly corrupted database file:
|
||||
** <ol>
|
||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
|
||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
||||
** </ol>
|
||||
** Because resetting a database is destructive and irreversible, the
|
||||
** process requires the use of this obscure API and multiple steps to help
|
||||
** ensure that it does not happen by accident.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
@@ -2106,7 +2140,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
|
||||
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */
|
||||
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@@ -5492,6 +5527,41 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory;
|
||||
*/
|
||||
SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Win32 Specific Interface
|
||||
**
|
||||
** These interfaces are available only on Windows. The
|
||||
** [sqlite3_win32_set_directory] interface is used to set the value associated
|
||||
** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to
|
||||
** zValue, depending on the value of the type parameter. The zValue parameter
|
||||
** should be NULL to cause the previous value to be freed via [sqlite3_free];
|
||||
** a non-NULL value will be copied into memory obtained from [sqlite3_malloc]
|
||||
** prior to being used. The [sqlite3_win32_set_directory] interface returns
|
||||
** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported,
|
||||
** or [SQLITE_NOMEM] if memory could not be allocated. The value of the
|
||||
** [sqlite3_data_directory] variable is intended to act as a replacement for
|
||||
** the current directory on the sub-platforms of Win32 where that concept is
|
||||
** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and
|
||||
** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the
|
||||
** sqlite3_win32_set_directory interface except the string parameter must be
|
||||
** UTF-8 or UTF-16, respectively.
|
||||
*/
|
||||
SQLITE_API int sqlite3_win32_set_directory(
|
||||
unsigned long type, /* Identifier for directory being set or reset */
|
||||
void *zValue /* New value for directory being set or reset */
|
||||
);
|
||||
SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
|
||||
SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Win32 Directory Types
|
||||
**
|
||||
** These macros are only available on Windows. They define the allowed values
|
||||
** for the type argument to the [sqlite3_win32_set_directory] interface.
|
||||
*/
|
||||
#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1
|
||||
#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test For Auto-Commit Mode
|
||||
** KEYWORDS: {autocommit mode}
|
||||
@@ -6224,6 +6294,10 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Scan Flags
|
||||
**
|
||||
** Virtual table implementations are allowed to set the
|
||||
** [sqlite3_index_info].idxFlags field to some combination of
|
||||
** these bits.
|
||||
*/
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
||||
|
||||
@@ -6999,7 +7073,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ALWAYS 13
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
@@ -7013,6 +7087,189 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
||||
#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
**
|
||||
** These routines provide access to the set of SQL language keywords
|
||||
** recognized by SQLite. Applications can uses these routines to determine
|
||||
** whether or not a specific identifier needs to be escaped (for example,
|
||||
** by enclosing in double-quotes) so as not to confuse the parser.
|
||||
**
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
|
||||
** or L are NULL or invalid pointers then calls to
|
||||
** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
|
||||
**
|
||||
** The sqlite3_keyword_check(Z,L) interface checks to see whether or not
|
||||
** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero
|
||||
** if it is and zero if not.
|
||||
**
|
||||
** The parser used by SQLite is forgiving. It is often possible to use
|
||||
** a keyword as an identifier as long as such use does not result in a
|
||||
** parsing ambiguity. For example, the statement
|
||||
** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and
|
||||
** creates a new table named "BEGIN" with three columns named
|
||||
** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid
|
||||
** using keywords as identifiers. Common techniques used to avoid keyword
|
||||
** name collisions include:
|
||||
** <ul>
|
||||
** <li> Put all identifier names inside double-quotes. This is the official
|
||||
** SQL way to escape identifier names.
|
||||
** <li> Put identifier names inside [...]. This is not standard SQL,
|
||||
** but it is what SQL Server does and so lots of programmers use this
|
||||
** technique.
|
||||
** <li> Begin every identifier with the letter "Z" as no SQL keywords start
|
||||
** with "Z".
|
||||
** <li> Include a digit somewhere in every identifier name.
|
||||
** </ul>
|
||||
**
|
||||
** Note that the number of keywords understood by SQLite can depend on
|
||||
** compile-time options. For example, "VACUUM" is not a keyword if
|
||||
** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also,
|
||||
** new keywords may be added to future releases of SQLite.
|
||||
*/
|
||||
SQLITE_API int sqlite3_keyword_count(void);
|
||||
SQLITE_API int sqlite3_keyword_name(int,const char**,int*);
|
||||
SQLITE_API int sqlite3_keyword_check(const char*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Dynamic String Object
|
||||
** KEYWORDS: {dynamic string}
|
||||
**
|
||||
** An instance of the sqlite3_str object contains a dynamically-sized
|
||||
** string under construction.
|
||||
**
|
||||
** The lifecycle of an sqlite3_str object is as follows:
|
||||
** <ol>
|
||||
** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
|
||||
** <li> ^Text is appended to the sqlite3_str object using various
|
||||
** methods, such as [sqlite3_str_appendf()].
|
||||
** <li> ^The sqlite3_str object is destroyed and the string it created
|
||||
** is returned using the [sqlite3_str_finish()] interface.
|
||||
** </ol>
|
||||
*/
|
||||
typedef struct sqlite3_str sqlite3_str;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create A New Dynamic String Object
|
||||
** CONSTRUCTOR: sqlite3_str
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface allocates and initializes
|
||||
** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
|
||||
** [sqlite3_str_new()] must be freed by a subsequent call to
|
||||
** [sqlite3_str_finish(X)].
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
|
||||
** valid [sqlite3_str] object, though in the event of an out-of-memory
|
||||
** error the returned object might be a special singleton that will
|
||||
** silently reject new text, always return SQLITE_NOMEM from
|
||||
** [sqlite3_str_errcode()], always return 0 for
|
||||
** [sqlite3_str_length()], and always return NULL from
|
||||
** [sqlite3_str_finish(X)]. It is always safe to use the value
|
||||
** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
|
||||
** to any of the other [sqlite3_str] methods.
|
||||
**
|
||||
** The D parameter to [sqlite3_str_new(D)] may be NULL. If the
|
||||
** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum
|
||||
** length of the string contained in the [sqlite3_str] object will be
|
||||
** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead
|
||||
** of [SQLITE_MAX_LENGTH].
|
||||
*/
|
||||
SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finalize A Dynamic String
|
||||
** DESTRUCTOR: sqlite3_str
|
||||
**
|
||||
** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X
|
||||
** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()]
|
||||
** that contains the constructed string. The calling application should
|
||||
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
|
||||
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
|
||||
** errors were encountered during construction of the string. ^The
|
||||
** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
|
||||
** string in [sqlite3_str] object X is zero bytes long.
|
||||
*/
|
||||
SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add Content To A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
**
|
||||
** These interfaces add content to an sqlite3_str object previously obtained
|
||||
** from [sqlite3_str_new()].
|
||||
**
|
||||
** ^The [sqlite3_str_appendf(X,F,...)] and
|
||||
** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
|
||||
** functionality of SQLite to append formatted text onto the end of
|
||||
** [sqlite3_str] object X.
|
||||
**
|
||||
** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S
|
||||
** onto the end of the [sqlite3_str] object X. N must be non-negative.
|
||||
** S must contain at least N non-zero bytes of content. To append a
|
||||
** zero-terminated string in its entirety, use the [sqlite3_str_appendall()]
|
||||
** method instead.
|
||||
**
|
||||
** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of
|
||||
** zero-terminated string S onto the end of [sqlite3_str] object X.
|
||||
**
|
||||
** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the
|
||||
** single-byte character C onto the end of [sqlite3_str] object X.
|
||||
** ^This method can be used, for example, to add whitespace indentation.
|
||||
**
|
||||
** ^The [sqlite3_str_reset(X)] method resets the string under construction
|
||||
** inside [sqlite3_str] object X back to zero bytes in length.
|
||||
**
|
||||
** These methods do not return a result code. ^If an error occurs, that fact
|
||||
** is recorded in the [sqlite3_str] object and can be recovered by a
|
||||
** subsequent call to [sqlite3_str_errcode(X)].
|
||||
*/
|
||||
SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
|
||||
SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
|
||||
SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
|
||||
SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
|
||||
SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
|
||||
SQLITE_API void sqlite3_str_reset(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Of A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
**
|
||||
** These interfaces return the current status of an [sqlite3_str] object.
|
||||
**
|
||||
** ^If any prior errors have occurred while constructing the dynamic string
|
||||
** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return
|
||||
** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns
|
||||
** [SQLITE_NOMEM] following any out-of-memory error, or
|
||||
** [SQLITE_TOOBIG] if the size of the dynamic string exceeds
|
||||
** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors.
|
||||
**
|
||||
** ^The [sqlite3_str_length(X)] method returns the current length, in bytes,
|
||||
** of the dynamic string under construction in [sqlite3_str] object X.
|
||||
** ^The length returned by [sqlite3_str_length(X)] does not include the
|
||||
** zero-termination byte.
|
||||
**
|
||||
** ^The [sqlite3_str_value(X)] method returns a pointer to the current
|
||||
** content of the dynamic string under construction in X. The value
|
||||
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
|
||||
** and might be freed or altered by any subsequent method on the same
|
||||
** [sqlite3_str] object. Applications must not used the pointer returned
|
||||
** [sqlite3_str_value(X)] after any subsequent method call on the same
|
||||
** object. ^Applications may change the content of the string returned
|
||||
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
|
||||
** outside the range of 0 to [sqlite3_str_length(X)] and do not read or
|
||||
** write any byte after any subsequent sqlite3_str method call.
|
||||
*/
|
||||
SQLITE_API int sqlite3_str_errcode(sqlite3_str*);
|
||||
SQLITE_API int sqlite3_str_length(sqlite3_str*);
|
||||
SQLITE_API char *sqlite3_str_value(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
**
|
||||
@@ -8282,11 +8539,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** method of a [virtual table], then it returns true if and only if the
|
||||
** column is being fetched as part of an UPDATE operation during which the
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a lighter-weight value to return that the corresponding [xUpdate] method
|
||||
** understands as a "no-change" value.
|
||||
** a return value that is less expensive to compute and that the corresponding
|
||||
** [xUpdate] method understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
** the column is not changed by the UPDATE statement, they the xColumn
|
||||
** the column is not changed by the UPDATE statement, then the xColumn
|
||||
** method can optionally return without setting a result, without calling
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
@@ -8781,7 +9038,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
|
||||
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
|
||||
** values of D and S.
|
||||
** The size of the database is written into *P even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
||||
** of the database exists.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
|
||||
@@ -319,7 +319,7 @@ int main(int argc, char **argv)
|
||||
options.trustSSL = false;
|
||||
options.useNetrc = false;
|
||||
options.interactive = true;
|
||||
options.ignoreHiddenFiles = true;
|
||||
options.ignoreHiddenFiles = false; // Default is to sync hidden files
|
||||
options.nonShib = false;
|
||||
options.restartTimes = 3;
|
||||
options.uplimit = 0;
|
||||
|
||||
@@ -272,10 +272,12 @@ bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qi
|
||||
int fd = _open_osfhandle((intptr_t)fileHandle, _O_RDONLY);
|
||||
if (fd == -1) {
|
||||
error = "could not make fd from handle";
|
||||
CloseHandle(fileHandle);
|
||||
return false;
|
||||
}
|
||||
if (!file->open(fd, QIODevice::ReadOnly, QFile::AutoCloseHandle)) {
|
||||
error = file->errorString();
|
||||
_close(fd); // implicitly closes fileHandle
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -602,7 +602,7 @@ void SyncJournalDb::close()
|
||||
commitTransaction();
|
||||
|
||||
_db.close();
|
||||
_avoidReadFromDbOnNextSyncFilter.clear();
|
||||
clearEtagStorageFilter();
|
||||
_metadataTableIsEmpty = false;
|
||||
}
|
||||
|
||||
@@ -824,10 +824,10 @@ bool SyncJournalDb::setFileRecord(const SyncJournalFileRecord &_record)
|
||||
SyncJournalFileRecord record = _record;
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (!_avoidReadFromDbOnNextSyncFilter.isEmpty()) {
|
||||
if (!_etagStorageFilter.isEmpty()) {
|
||||
// If we are a directory that should not be read from db next time, don't write the etag
|
||||
QByteArray prefix = record._path + "/";
|
||||
foreach (const QByteArray &it, _avoidReadFromDbOnNextSyncFilter) {
|
||||
foreach (const QByteArray &it, _etagStorageFilter) {
|
||||
if (it.startsWith(prefix)) {
|
||||
qCInfo(lcDb) << "Filtered writing the etag of" << prefix << "because it is a prefix of" << it;
|
||||
record._etag = "_invalid_";
|
||||
@@ -1816,7 +1816,12 @@ void SyncJournalDb::avoidReadFromDbOnNextSync(const QByteArray &fileName)
|
||||
// Prevent future overwrite of the etags of this folder and all
|
||||
// parent folders for this sync
|
||||
argument.append('/');
|
||||
_avoidReadFromDbOnNextSyncFilter.append(argument);
|
||||
_etagStorageFilter.append(argument);
|
||||
}
|
||||
|
||||
void SyncJournalDb::clearEtagStorageFilter()
|
||||
{
|
||||
_etagStorageFilter.clear();
|
||||
}
|
||||
|
||||
void SyncJournalDb::forceRemoteDiscoveryNextSync()
|
||||
|
||||
@@ -178,10 +178,18 @@ public:
|
||||
* Since folders in the selective sync list will not be rediscovered (csync_ftw,
|
||||
* _csync_detect_update skip them), the _invalid_ marker will stay. And any
|
||||
* child items in the db will be ignored when reading a remote tree from the database.
|
||||
*
|
||||
* Any setFileRecord() call to affected directories before the next sync run will be
|
||||
* adjusted to retain the invalid etag via _etagStorageFilter.
|
||||
*/
|
||||
void avoidReadFromDbOnNextSync(const QString &fileName) { avoidReadFromDbOnNextSync(fileName.toUtf8()); }
|
||||
void avoidReadFromDbOnNextSync(const QByteArray &fileName);
|
||||
|
||||
/**
|
||||
* Wipe _etagStorageFilter. Also done implicitly on close().
|
||||
*/
|
||||
void clearEtagStorageFilter();
|
||||
|
||||
/**
|
||||
* Ensures full remote discovery happens on the next sync.
|
||||
*
|
||||
@@ -295,13 +303,20 @@ private:
|
||||
SqlQuery _setConflictRecordQuery;
|
||||
SqlQuery _deleteConflictRecordQuery;
|
||||
|
||||
/* This is the list of paths we called avoidReadFromDbOnNextSync on.
|
||||
* It means that they should not be written to the DB in any case since doing
|
||||
* that would write the etag and would void the purpose of avoidReadFromDbOnNextSync
|
||||
/* Storing etags to these folders, or their parent folders, is filtered out.
|
||||
*
|
||||
* When avoidReadFromDbOnNextSync() is called some etags to _invalid_ in the
|
||||
* database. If this is done during a sync run, a later propagation job might
|
||||
* undo that by writing the correct etag to the database instead. This filter
|
||||
* will prevent this write and instead guarantee the _invalid_ etag stays in
|
||||
* place.
|
||||
*
|
||||
* The list is cleared on close() (end of sync run) and explicitly with
|
||||
* clearEtagStorageFilter() (start of sync run).
|
||||
*
|
||||
* The contained paths have a trailing /.
|
||||
*/
|
||||
QList<QByteArray> _avoidReadFromDbOnNextSyncFilter;
|
||||
QList<QByteArray> _etagStorageFilter;
|
||||
|
||||
/** The journal mode to use for the db.
|
||||
*
|
||||
|
||||
@@ -166,7 +166,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
/* First, check that the file is NOT in our tree (another file with the same name was added) */
|
||||
if (our_tree->findFile(basePath)) {
|
||||
other = nullptr;
|
||||
qCDebug(lcReconcile, "Origin found in our tree : %s", basePath.constData());
|
||||
qCInfo(lcReconcile, "Origin found in our tree : %s", basePath.constData());
|
||||
} else {
|
||||
/* Find the potential rename source file in the other tree.
|
||||
* If the renamed file could not be found in the opposite tree, that is because it
|
||||
@@ -174,7 +174,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
* The journal is cleaned up later after propagation.
|
||||
*/
|
||||
other = other_tree->findFile(basePath);
|
||||
qCDebug(lcReconcile, "Rename origin in other tree (%s) %s",
|
||||
qCInfo(lcReconcile, "Rename origin in other tree (%s) %s",
|
||||
basePath.constData(), other ? "found" : "not found");
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
// Some other EVAL_RENAME already claimed other.
|
||||
// We do nothing: maybe a different candidate for
|
||||
// other is found as well?
|
||||
qCDebug(lcReconcile, "Other has already been renamed to %s",
|
||||
qCInfo(lcReconcile, "Other has already been renamed to %s",
|
||||
other->rename_path.constData());
|
||||
} else if (cur->type == ItemTypeDirectory
|
||||
// The local replica is reconciled first, so the remote tree would
|
||||
@@ -197,13 +197,17 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
|| other->instruction == CSYNC_INSTRUCTION_NONE
|
||||
|| other->instruction == CSYNC_INSTRUCTION_UPDATE_METADATA
|
||||
|| other->instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
qCDebug(lcReconcile, "Switching %s to RENAME to %s",
|
||||
qCInfo(lcReconcile, "Switching %s to RENAME to %s",
|
||||
other->path.constData(), cur->path.constData());
|
||||
other->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
other->rename_path = cur->path;
|
||||
if( !cur->file_id.isEmpty() ) {
|
||||
other->file_id = cur->file_id;
|
||||
}
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
// Keep the local mtime.
|
||||
other->modtime = cur->modtime;
|
||||
}
|
||||
other->inode = cur->inode;
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
// We have consumed 'other': exit this loop to not consume another one.
|
||||
@@ -217,7 +221,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
// Local: The remote reconcile will be able to deal with this.
|
||||
// Remote: The local replica has already dealt with this.
|
||||
// See the EVAL_RENAME case when other was found directly.
|
||||
qCDebug(lcReconcile, "File in a renamed directory, other side's instruction: %d",
|
||||
qCInfo(lcReconcile, "File in a renamed directory, other side's instruction: %d",
|
||||
other->instruction);
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else {
|
||||
@@ -225,7 +229,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
// and the instruction in the local tree is NEW while cur has EVAL_RENAME
|
||||
// due to a remote move of the same file. In these scenarios we just
|
||||
// want the instruction to stay NEW.
|
||||
qCDebug(lcReconcile, "Other already has instruction %d",
|
||||
qCInfo(lcReconcile, "Other already has instruction %d",
|
||||
other->instruction);
|
||||
}
|
||||
};
|
||||
@@ -233,7 +237,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
/* use the old name to find the "other" node */
|
||||
OCC::SyncJournalFileRecord base;
|
||||
qCDebug(lcReconcile, "Finding rename origin through inode %" PRIu64 "",
|
||||
qCInfo(lcReconcile, "Finding rename origin through inode %" PRIu64 "",
|
||||
cur->inode);
|
||||
ctx->statedb->getFileRecordByInode(cur->inode, &base);
|
||||
renameCandidateProcessing(base._path);
|
||||
@@ -246,7 +250,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
// line.
|
||||
auto basePath = csync_rename_adjust_full_path_source(ctx, cur->path);
|
||||
if (basePath != cur->path) {
|
||||
qCDebug(lcReconcile, "Trying rename origin by csync_rename mapping %s",
|
||||
qCInfo(lcReconcile, "Trying rename origin by csync_rename mapping %s",
|
||||
basePath.constData());
|
||||
// We go through getFileRecordsByFileId to ensure the basePath
|
||||
// computed in this way also has the expected fileid.
|
||||
@@ -259,7 +263,7 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
|
||||
|
||||
// Also feed all the other files with the same fileid if necessary
|
||||
if (!processedRename) {
|
||||
qCDebug(lcReconcile, "Finding rename origin through file ID %s",
|
||||
qCInfo(lcReconcile, "Finding rename origin through file ID %s",
|
||||
cur->file_id.constData());
|
||||
ctx->statedb->getFileRecordsByFileId(cur->file_id,
|
||||
[&](const OCC::SyncJournalFileRecord &base) { renameCandidateProcessing(base._path); });
|
||||
|
||||
@@ -125,12 +125,12 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
* This code should probably be in csync_exclude, but it does not have the fs parameter.
|
||||
* Keep it here for now */
|
||||
if (ctx->ignore_hidden_files && (fs->is_hidden)) {
|
||||
qCDebug(lcUpdate, "file excluded because it is a hidden file: %s", fs->path.constData());
|
||||
qCInfo(lcUpdate, "file excluded because it is a hidden file: %s", fs->path.constData());
|
||||
excluded = CSYNC_FILE_EXCLUDE_HIDDEN;
|
||||
}
|
||||
} else {
|
||||
/* File is ignored because it's matched by a user- or system exclude pattern. */
|
||||
qCDebug(lcUpdate, "%s excluded (%d)", fs->path.constData(), excluded);
|
||||
qCInfo(lcUpdate, "%s excluded (%d)", fs->path.constData(), excluded);
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
|
||||
return 1;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
*/
|
||||
QTextEncoder encoder(localCodec, QTextCodec::ConvertInvalidToNull);
|
||||
if (encoder.fromUnicode(QString::fromUtf8(fs->path)).contains('\0')) {
|
||||
qCDebug(lcUpdate, "cannot encode %s to local encoding %d",
|
||||
qCInfo(lcUpdate, "cannot encode %s to local encoding %d",
|
||||
fs->path.constData(), localCodec->mibEnum());
|
||||
excluded = CSYNC_FILE_EXCLUDE_CANNOT_ENCODE;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
|
||||
if (fs->type == ItemTypeFile ) {
|
||||
if (fs->modtime == 0) {
|
||||
qCDebug(lcUpdate, "file: %s - mtime is zero!", fs->path.constData());
|
||||
qCInfo(lcUpdate, "file: %s - mtime is zero!", fs->path.constData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
checksumIdentical = fs->checksumHeader == base._checksumHeader;
|
||||
}
|
||||
if (checksumIdentical) {
|
||||
qCDebug(lcUpdate, "NOTE: Checksums are identical, file did not actually change: %s", fs->path.constData());
|
||||
qCInfo(lcUpdate, "NOTE: Checksums are identical, file did not actually change: %s", fs->path.constData());
|
||||
fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
goto out;
|
||||
}
|
||||
@@ -269,7 +269,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
* The metadata comparison ensure that we fetch all the file id or permission when
|
||||
* upgrading owncloud
|
||||
*/
|
||||
qCDebug(lcUpdate, "Reading from database: %s", fs->path.constData());
|
||||
qCInfo(lcUpdate, "Reading from database: %s", fs->path.constData());
|
||||
ctx->remote.read_from_db = true;
|
||||
}
|
||||
/* If it was remembered in the db that the remote dir has ignored files, store
|
||||
@@ -280,7 +280,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
}
|
||||
if (metadata_differ) {
|
||||
/* file id or permissions has changed. Which means we need to update them in the DB. */
|
||||
qCDebug(lcUpdate, "Need to update metadata for: %s", fs->path.constData());
|
||||
qCInfo(lcUpdate, "Need to update metadata for: %s", fs->path.constData());
|
||||
fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else {
|
||||
fs->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
@@ -288,7 +288,7 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
} else {
|
||||
/* check if it's a file and has been renamed */
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
qCDebug(lcUpdate, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
qCInfo(lcUpdate, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
|
||||
OCC::SyncJournalFileRecord base;
|
||||
if(!ctx->statedb->getFileRecordByInode(fs->inode, &base)) {
|
||||
@@ -315,13 +315,13 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
_rel_to_abs(ctx, fs->path), base._checksumHeader,
|
||||
ctx->callbacks.checksum_userdata);
|
||||
if (!fs->checksumHeader.isEmpty()) {
|
||||
qCDebug(lcUpdate, "checking checksum of potential rename %s %s <-> %s", fs->path.constData(), fs->checksumHeader.constData(), base._checksumHeader.constData());
|
||||
qCInfo(lcUpdate, "checking checksum of potential rename %s %s <-> %s", fs->path.constData(), fs->checksumHeader.constData(), base._checksumHeader.constData());
|
||||
isRename = fs->checksumHeader == base._checksumHeader;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRename) {
|
||||
qCDebug(lcUpdate, "pot rename detected based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
qCInfo(lcUpdate, "pot rename detected based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
/* inode found so the file has been renamed */
|
||||
fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
|
||||
if (fs->type == ItemTypeDirectory) {
|
||||
@@ -331,6 +331,8 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
goto out;
|
||||
|
||||
} else {
|
||||
qCInfo(lcUpdate, "Checking for rename based on fileid %s", fs->file_id.constData());
|
||||
|
||||
/* Remote Replica Rename check */
|
||||
fs->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
|
||||
@@ -376,7 +378,8 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(lcUpdate, "remote rename detected based on fileid %s --> %s", qPrintable(base._path), qPrintable(fs->path.constData()));
|
||||
qCInfo(lcUpdate, "remote rename detected based on fileid %s --> %s", base._path.constData(), fs->path.constData());
|
||||
|
||||
fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
|
||||
done = true;
|
||||
};
|
||||
@@ -484,11 +487,11 @@ int csync_walker(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> fs) {
|
||||
}
|
||||
break;
|
||||
case ItemTypeSoftLink:
|
||||
qCDebug(lcUpdate, "symlink: %s - not supported", fs->path.constData());
|
||||
qCInfo(lcUpdate, "symlink: %s - not supported", fs->path.constData());
|
||||
break;
|
||||
default:
|
||||
qCInfo(lcUpdate, "item: %s - item type %d not iterated", fs->path.constData(), fs->type);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = _csync_detect_update(ctx, std::move(fs));
|
||||
@@ -511,7 +514,7 @@ static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
|
||||
* their correct etags again and we don't run into this case.
|
||||
*/
|
||||
if (rec._etag == "_invalid_") {
|
||||
qCDebug(lcUpdate, "%s selective sync excluded", rec._path.constData());
|
||||
qCInfo(lcUpdate, "%s selective sync excluded", rec._path.constData());
|
||||
skipbase = rec._path;
|
||||
skipbase += '/';
|
||||
return;
|
||||
@@ -663,7 +666,21 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((dirent = csync_vio_readdir(ctx, dh))) {
|
||||
while (true) {
|
||||
// Get the next item in the directory
|
||||
errno = 0;
|
||||
dirent = csync_vio_readdir(ctx, dh);
|
||||
if (!dirent) {
|
||||
if (errno != 0) {
|
||||
// Note: Windows vio converts any error into EACCES
|
||||
qCWarning(lcUpdate, "readdir failed for file in %s - errno %d", uri, errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Normal case: End of items in directory
|
||||
break;
|
||||
}
|
||||
|
||||
/* Conversion error */
|
||||
if (dirent->path.isEmpty() && !dirent->original_path.isEmpty()) {
|
||||
ctx->status_code = CSYNC_STATUS_INVALID_CHARACTERS;
|
||||
@@ -757,7 +774,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
}
|
||||
|
||||
csync_vio_closedir(ctx, dh);
|
||||
qCDebug(lcUpdate, " <= Closing walk for %s with read_from_db %d", uri, read_from_db);
|
||||
qCInfo(lcUpdate, " <= Closing walk for %s with read_from_db %d", uri, read_from_db);
|
||||
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
// might be error, check!
|
||||
int dwError = GetLastError();
|
||||
if (dwError != ERROR_NO_MORE_FILES) {
|
||||
qCWarning(lcCSyncVIOLocal, "FindNextFile error %d", dwError);
|
||||
errno = EACCES; // no more files is fine. Otherwise EACCESS
|
||||
}
|
||||
return nullptr;
|
||||
@@ -181,7 +182,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
}
|
||||
} else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
) {
|
||||
file_stat->type = ItemTypeSkip;
|
||||
} else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
file_stat->type = ItemTypeDirectory;
|
||||
|
||||
@@ -53,6 +53,7 @@ set(client_SRCS
|
||||
folderman.cpp
|
||||
folderstatusmodel.cpp
|
||||
folderstatusdelegate.cpp
|
||||
folderstatusview.cpp
|
||||
folderwatcher.cpp
|
||||
folderwizard.cpp
|
||||
generalsettings.cpp
|
||||
@@ -116,6 +117,7 @@ set(client_SRCS
|
||||
wizard/owncloudwizardresultpage.cpp
|
||||
wizard/webviewpage.cpp
|
||||
wizard/webview.cpp
|
||||
wizard/slideshow.cpp
|
||||
)
|
||||
|
||||
IF(NOT NO_SHIBBOLETH)
|
||||
@@ -272,7 +274,7 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
add_executable( ${APPLICATION_EXECUTABLE} WIN32 main.cpp ${final_src})
|
||||
else()
|
||||
# set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
|
||||
set(MACOSX_BUNDLE_ICON_FILE "ownCloud.icns")
|
||||
set(MACOSX_BUNDLE_ICON_FILE "${APPLICATION_ICON_NAME}.icns")
|
||||
|
||||
# we must add MACOSX_BUNDLE only if building a bundle
|
||||
add_executable( ${APPLICATION_EXECUTABLE} WIN32 MACOSX_BUNDLE main.cpp ${final_src})
|
||||
|
||||
@@ -52,7 +52,7 @@ AccountManager *AccountManager::instance()
|
||||
bool AccountManager::restore()
|
||||
{
|
||||
auto settings = ConfigFile::settingsWithGroup(QLatin1String(accountsC));
|
||||
if (settings->status() != QSettings::NoError) {
|
||||
if (settings->status() != QSettings::NoError || !settings->isWritable()) {
|
||||
qCWarning(lcAccountManager) << "Could not read settings from" << settings->fileName()
|
||||
<< settings->status();
|
||||
return false;
|
||||
@@ -253,6 +253,20 @@ AccountPtr AccountManager::loadAccountHelper(QSettings &settings)
|
||||
acc->setUrl(urlConfig.toUrl());
|
||||
}
|
||||
|
||||
// Migrate to webflow
|
||||
if (authType == QLatin1String("http")) {
|
||||
authType = "webflow";
|
||||
settings.setValue(QLatin1String(authTypeC), authType);
|
||||
|
||||
foreach(QString key, settings.childKeys()) {
|
||||
if (!key.startsWith("http_"))
|
||||
continue;
|
||||
auto newkey = QString::fromLatin1("webflow_").append(key.mid(5));
|
||||
settings.setValue(newkey, settings.value((key)));
|
||||
settings.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
qCInfo(lcAccountManager) << "Account for" << acc->url() << "using auth type" << authType;
|
||||
|
||||
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
|
||||
|
||||
@@ -680,7 +680,7 @@ void AccountSettings::slotFolderWizardAccepted()
|
||||
|
||||
/* take the value from the definition of already existing folders. All folders have
|
||||
* the same setting so far.
|
||||
* The default is to not sync hidden files
|
||||
* The default is to sync hidden files
|
||||
*/
|
||||
definition.ignoreHiddenFiles = folderMan->ignoreHiddenFiles();
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTreeView" name="_folderList">
|
||||
<widget class="OCC::FolderStatusView" name="_folderList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -275,6 +275,11 @@
|
||||
<extends>QToolButton</extends>
|
||||
<header>sslbutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>OCC::FolderStatusView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>folderstatusview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -335,10 +335,10 @@ void AccountState::slotInvalidCredentials()
|
||||
|
||||
if (account()->credentials()->ready()) {
|
||||
account()->credentials()->invalidateToken();
|
||||
if (auto creds = qobject_cast<HttpCredentials *>(account()->credentials())) {
|
||||
if (creds->refreshAccessToken())
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (auto creds = qobject_cast<HttpCredentials *>(account()->credentials())) {
|
||||
if (creds->refreshAccessToken())
|
||||
return;
|
||||
}
|
||||
account()->credentials()->askFromUser();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,6 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||
return type;
|
||||
break;
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
case ActivityItemDelegate::ActionTextRole:
|
||||
return a._subject;
|
||||
break;
|
||||
|
||||
@@ -81,6 +81,18 @@
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListView" name="_activityList">
|
||||
<property name="sizePolicy">
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace {
|
||||
" --logexpire <hours> : removes logs older than <hours> hours.\n"
|
||||
" (to be used with --logdir)\n"
|
||||
" --logflush : flush the log file after every write.\n"
|
||||
" --logdebug : also output debug-level messages in the log (equivalent to setting the env var QT_LOGGING_RULES=\"qt.*=true;*.debug=true\").\n"
|
||||
" --logdebug : also output debug-level messages in the log.\n"
|
||||
" --confdir <dirname> : Use the given configuration folder.\n";
|
||||
|
||||
QString applicationTrPath()
|
||||
@@ -125,7 +125,8 @@ Application::Application(int &argc, char **argv)
|
||||
setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
|
||||
auto confDir = ConfigFile().configPath();
|
||||
if (!QFileInfo(confDir).exists()) {
|
||||
if (confDir.endsWith('/')) confDir.chop(1); // macOS 10.11.x does not like trailing slash for rename/move.
|
||||
if (!QFileInfo(confDir).isDir()) {
|
||||
// Migrate from version <= 2.4
|
||||
setApplicationName(_theme->appNameGUI());
|
||||
#ifndef QT_WARNING_DISABLE_DEPRECATED // Was added in Qt 5.9
|
||||
@@ -136,6 +137,7 @@ Application::Application(int &argc, char **argv)
|
||||
// We need to use the deprecated QDesktopServices::storageLocation because of its Qt4
|
||||
// behavior of adding "data" to the path
|
||||
QString oldDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
|
||||
if (oldDir.endsWith('/')) oldDir.chop(1); // macOS 10.11.x does not like trailing slash for rename/move.
|
||||
QT_WARNING_POP
|
||||
setApplicationName(_theme->appName());
|
||||
if (QFileInfo(oldDir).isDir()) {
|
||||
@@ -202,9 +204,8 @@ Application::Application(int &argc, char **argv)
|
||||
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
|
||||
connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
|
||||
|
||||
FolderMan::instance()->setupFolders();
|
||||
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
|
||||
|
||||
// Setting up the gui class will allow tray notifications for the
|
||||
// setup that follows, like folder setup
|
||||
_gui = new ownCloudGui(this);
|
||||
if (_showLogWindow) {
|
||||
_gui->slotToggleLogBrowser(); // _showLogWindow is set in parseOptions.
|
||||
@@ -213,6 +214,9 @@ Application::Application(int &argc, char **argv)
|
||||
_gui->setupCloudProviders();
|
||||
#endif
|
||||
|
||||
FolderMan::instance()->setupFolders();
|
||||
_proxy.setupQtProxyFromConfig(); // folders have to be defined first, than we set up the Qt proxy.
|
||||
|
||||
// Enable word wrapping of QInputDialog (#4197)
|
||||
setStyleSheet("QInputDialog QLabel { qproperty-wordWrap:1; }");
|
||||
|
||||
|
||||
@@ -150,7 +150,6 @@ void OAuth::start()
|
||||
});
|
||||
}
|
||||
});
|
||||
QTimer::singleShot(5 * 60 * 1000, this, [this] { result(Error); });
|
||||
}
|
||||
|
||||
QUrl OAuth::authorisationLink() const
|
||||
|
||||
@@ -24,9 +24,39 @@ namespace OCC {
|
||||
|
||||
Q_LOGGING_CATEGORY(lcWebFlowCredentials, "sync.credentials.webflow", QtInfoMsg)
|
||||
|
||||
class WebFlowCredentialsAccessManager : public AccessManager
|
||||
{
|
||||
public:
|
||||
WebFlowCredentialsAccessManager(const WebFlowCredentials *cred, QObject *parent = nullptr)
|
||||
: AccessManager(parent)
|
||||
, _cred(cred)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) Q_DECL_OVERRIDE
|
||||
{
|
||||
QNetworkRequest req(request);
|
||||
if (!req.attribute(HttpCredentials::DontAddCredentialsAttribute).toBool()) {
|
||||
if (_cred && !_cred->password().isEmpty()) {
|
||||
QByteArray credHash = QByteArray(_cred->user().toUtf8() + ":" + _cred->password().toUtf8()).toBase64();
|
||||
req.setRawHeader("Authorization", "Basic " + credHash);
|
||||
}
|
||||
}
|
||||
|
||||
return AccessManager::createRequest(op, req, outgoingData);
|
||||
}
|
||||
|
||||
private:
|
||||
// The credentials object dies along with the account, while the QNAM might
|
||||
// outlive both.
|
||||
QPointer<const WebFlowCredentials> _cred;
|
||||
};
|
||||
|
||||
WebFlowCredentials::WebFlowCredentials()
|
||||
: _ready(false),
|
||||
_credentialsValid(false)
|
||||
: _ready(false)
|
||||
, _credentialsValid(false)
|
||||
, _keychainMigration(false)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -38,6 +68,7 @@ WebFlowCredentials::WebFlowCredentials(const QString &user, const QString &passw
|
||||
, _clientSslCertificate(certificate)
|
||||
, _ready(true)
|
||||
, _credentialsValid(true)
|
||||
, _keychainMigration(false)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -56,7 +87,7 @@ QString WebFlowCredentials::password() const {
|
||||
|
||||
QNetworkAccessManager *WebFlowCredentials::createQNAM() const {
|
||||
qCInfo(lcWebFlowCredentials()) << "Get QNAM";
|
||||
AccessManager *qnam = new AccessManager();
|
||||
AccessManager *qnam = new WebFlowCredentialsAccessManager(this);
|
||||
|
||||
connect(qnam, &AccessManager::authenticationRequired, this, &WebFlowCredentials::slotAuthentication);
|
||||
connect(qnam, &AccessManager::finished, this, &WebFlowCredentials::slotFinished);
|
||||
@@ -231,7 +262,7 @@ void WebFlowCredentials::fetchFromKeychainHelper() {
|
||||
const QString kck = keychainKey(
|
||||
_account->url().toString(),
|
||||
_user,
|
||||
_account->id());
|
||||
_keychainMigration ? QString() : _account->id());
|
||||
|
||||
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
|
||||
job->setInsecureFallback(false);
|
||||
@@ -244,6 +275,13 @@ void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) {
|
||||
QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob *>(incomingJob);
|
||||
QKeychain::Error error = job->error();
|
||||
|
||||
// If we could not find the entry try the old entries
|
||||
if (!_keychainMigration && error == QKeychain::EntryNotFound) {
|
||||
_keychainMigration = true;
|
||||
fetchFromKeychainHelper();
|
||||
return;
|
||||
}
|
||||
|
||||
if (error == QKeychain::NoError) {
|
||||
_password = job->textData();
|
||||
_ready = true;
|
||||
@@ -251,8 +289,22 @@ void WebFlowCredentials::slotReadPasswordJobDone(Job *incomingJob) {
|
||||
} else {
|
||||
_ready = false;
|
||||
}
|
||||
|
||||
emit fetched();
|
||||
|
||||
// If keychain data was read from legacy location, wipe these entries and store new ones
|
||||
if (_keychainMigration && _ready) {
|
||||
_keychainMigration = false;
|
||||
persist();
|
||||
deleteOldKeychainEntries();
|
||||
qCWarning(lcWebFlowCredentials) << "Migrated old keychain entries";
|
||||
}
|
||||
}
|
||||
|
||||
void WebFlowCredentials::deleteOldKeychainEntries() {
|
||||
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
|
||||
job->setInsecureFallback(false);
|
||||
job->setKey(keychainKey(_account->url().toString(), _user, QString()));
|
||||
job->start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,14 +52,8 @@ private slots:
|
||||
void slotAskFromUserCredentialsProvided(const QString &user, const QString &pass, const QString &host);
|
||||
|
||||
private:
|
||||
/** Reads data from keychain locations
|
||||
*
|
||||
* Goes through
|
||||
* slotReadClientCertPEMJobDone to
|
||||
* slotReadClientCertPEMJobDone to
|
||||
* slotReadJobDone
|
||||
*/
|
||||
void fetchFromKeychainHelper();
|
||||
void deleteOldKeychainEntries();
|
||||
|
||||
QString fetchUser();
|
||||
|
||||
@@ -70,6 +64,7 @@ private:
|
||||
|
||||
bool _ready;
|
||||
bool _credentialsValid;
|
||||
bool _keychainMigration;
|
||||
|
||||
WebFlowCredentialsDialog *_askDialog;
|
||||
};
|
||||
|
||||
@@ -645,9 +645,13 @@ void Folder::startSync(const QStringList &pathList)
|
||||
}
|
||||
return interval;
|
||||
}();
|
||||
if (_folderWatcher && _folderWatcher->isReliable() && _timeSinceLastFullLocalDiscovery.isValid()
|
||||
&& (fullLocalDiscoveryInterval.count() < 0
|
||||
|| _timeSinceLastFullLocalDiscovery.hasExpired(fullLocalDiscoveryInterval.count()))) {
|
||||
bool hasDoneFullLocalDiscovery = _timeSinceLastFullLocalDiscovery.isValid();
|
||||
bool periodicFullLocalDiscoveryNow =
|
||||
fullLocalDiscoveryInterval.count() >= 0 // negative means we don't require periodic full runs
|
||||
&& _timeSinceLastFullLocalDiscovery.hasExpired(fullLocalDiscoveryInterval.count());
|
||||
if (_folderWatcher && _folderWatcher->isReliable()
|
||||
&& hasDoneFullLocalDiscovery
|
||||
&& !periodicFullLocalDiscoveryNow) {
|
||||
qCInfo(lcFolder) << "Allowing local discovery to read from the database";
|
||||
_engine->setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, _localDiscoveryPaths);
|
||||
|
||||
@@ -1015,6 +1019,20 @@ void Folder::warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QS
|
||||
Logger::instance()->postOptionalGuiLog(Theme::instance()->appNameGUI(), message);
|
||||
}
|
||||
|
||||
void Folder::slotWatcherUnreliable(const QString &message)
|
||||
{
|
||||
qCWarning(lcFolder) << "Folder watcher for" << path() << "became unreliable:" << message;
|
||||
auto fullMessage =
|
||||
tr("Changes in synchronized folders could not be tracked reliably.\n"
|
||||
"\n"
|
||||
"This means that the synchronization client might not upload local changes "
|
||||
"immediately and will instead only scan for local changes and upload them "
|
||||
"occasionally (every two hours by default).\n"
|
||||
"\n"
|
||||
"%1").arg(message);
|
||||
Logger::instance()->postGuiLog(Theme::instance()->appNameGUI(), fullMessage);
|
||||
}
|
||||
|
||||
void Folder::scheduleThisFolderSoon()
|
||||
{
|
||||
if (!_scheduleSelfTimer.isActive()) {
|
||||
@@ -1034,11 +1052,14 @@ void Folder::registerFolderWatcher()
|
||||
if (!QDir(path()).exists())
|
||||
return;
|
||||
|
||||
_folderWatcher.reset(new FolderWatcher(path(), this));
|
||||
_folderWatcher.reset(new FolderWatcher(this));
|
||||
connect(_folderWatcher.data(), &FolderWatcher::pathChanged,
|
||||
this, &Folder::slotWatchedPathChanged);
|
||||
connect(_folderWatcher.data(), &FolderWatcher::lostChanges,
|
||||
this, &Folder::slotNextSyncFullLocalDiscovery);
|
||||
connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable,
|
||||
this, &Folder::slotWatcherUnreliable);
|
||||
_folderWatcher->init(path());
|
||||
}
|
||||
|
||||
void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, bool *cancel)
|
||||
|
||||
@@ -49,7 +49,7 @@ class FolderDefinition
|
||||
public:
|
||||
FolderDefinition()
|
||||
: paused(false)
|
||||
, ignoreHiddenFiles(true)
|
||||
, ignoreHiddenFiles(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -325,6 +325,9 @@ private slots:
|
||||
/** Warn users if they create a file or folder that is selective-sync excluded */
|
||||
void warnOnNewExcludedItem(const SyncJournalFileRecord &record, const QStringRef &path);
|
||||
|
||||
/** Warn users about an unreliable folder watcher */
|
||||
void slotWatcherUnreliable(const QString &message);
|
||||
|
||||
private:
|
||||
bool reloadExcludes();
|
||||
|
||||
|
||||
@@ -1242,25 +1242,45 @@ QString FolderMan::trayTooltipStatusString(
|
||||
return folderMessage;
|
||||
}
|
||||
|
||||
QString FolderMan::checkPathValidityForNewFolder(const QString &path, const QUrl &serverUrl, bool forNewDirectory) const
|
||||
static QString checkPathValidityRecursive(const QString &path)
|
||||
{
|
||||
if (path.isEmpty()) {
|
||||
return tr("No valid folder selected!");
|
||||
return FolderMan::tr("No valid folder selected!");
|
||||
}
|
||||
|
||||
QFileInfo selFile(path);
|
||||
|
||||
if (!selFile.exists()) {
|
||||
return checkPathValidityForNewFolder(selFile.dir().path(), serverUrl, true);
|
||||
return checkPathValidityRecursive(selFile.dir().path());
|
||||
}
|
||||
|
||||
if (!selFile.isDir()) {
|
||||
return tr("The selected path is not a folder!");
|
||||
return FolderMan::tr("The selected path is not a folder!");
|
||||
}
|
||||
|
||||
if (!selFile.isWritable()) {
|
||||
return tr("You have no permission to write to the selected folder!");
|
||||
return FolderMan::tr("You have no permission to write to the selected folder!");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
// QFileInfo::canonicalPath returns an empty string if the file does not exist.
|
||||
// This function also works with files that does not exist and resolve the symlinks in the
|
||||
// parent directories.
|
||||
static QString canonicalPath(const QString &path)
|
||||
{
|
||||
QFileInfo selFile(path);
|
||||
if (!selFile.exists()) {
|
||||
return canonicalPath(selFile.dir().path()) + '/' + selFile.fileName();
|
||||
}
|
||||
return selFile.canonicalFilePath();
|
||||
}
|
||||
|
||||
QString FolderMan::checkPathValidityForNewFolder(const QString &path, const QUrl &serverUrl) const
|
||||
{
|
||||
QString recursiveValidity = checkPathValidityRecursive(path);
|
||||
if (!recursiveValidity.isEmpty())
|
||||
return recursiveValidity;
|
||||
|
||||
// check if the local directory isn't used yet in another ownCloud sync
|
||||
Qt::CaseSensitivity cs = Qt::CaseSensitive;
|
||||
@@ -1268,57 +1288,28 @@ QString FolderMan::checkPathValidityForNewFolder(const QString &path, const QUrl
|
||||
cs = Qt::CaseInsensitive;
|
||||
}
|
||||
|
||||
const QString userDir = QDir::cleanPath(canonicalPath(path)) + '/';
|
||||
for (auto i = _folderMap.constBegin(); i != _folderMap.constEnd(); ++i) {
|
||||
Folder *f = static_cast<Folder *>(i.value());
|
||||
QString folderDir = QDir(f->path()).canonicalPath();
|
||||
if (folderDir.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!folderDir.endsWith(QLatin1Char('/'), cs))
|
||||
folderDir.append(QLatin1Char('/'));
|
||||
QString folderDir = QDir::cleanPath(canonicalPath(f->path())) + '/';
|
||||
|
||||
const QString folderDirClean = QDir::cleanPath(folderDir) + '/';
|
||||
const QString userDirClean = QDir::cleanPath(path) + '/';
|
||||
|
||||
// folderDir follows sym links, path not.
|
||||
bool differentPathes = !Utility::fileNamesEqual(QDir::cleanPath(folderDir), QDir::cleanPath(path));
|
||||
|
||||
if (!forNewDirectory && differentPathes && folderDirClean.startsWith(userDirClean, cs)) {
|
||||
bool differentPaths = QString::compare(folderDir, userDir, cs) != 0;
|
||||
if (differentPaths && folderDir.startsWith(userDir, cs)) {
|
||||
return tr("The local folder %1 already contains a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
// QDir::cleanPath keeps links
|
||||
// canonicalPath() remove symlinks and uses the symlink targets.
|
||||
QString absCleanUserFolder = QDir::cleanPath(QDir(path).canonicalPath()) + '/';
|
||||
|
||||
if ((forNewDirectory || differentPathes) && userDirClean.startsWith(folderDirClean, cs)) {
|
||||
if (differentPaths && userDir.startsWith(folderDir, cs)) {
|
||||
return tr("The local folder %1 is already contained in a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
// both follow symlinks.
|
||||
bool cleanUserEqualsCleanFolder = Utility::fileNamesEqual(absCleanUserFolder, folderDirClean);
|
||||
if (differentPathes && absCleanUserFolder.startsWith(folderDirClean, cs) && !cleanUserEqualsCleanFolder) {
|
||||
return tr("The local folder %1 is a symbolic link. "
|
||||
"The link target is already contained in a folder used in a folder sync connection. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
if (differentPathes && folderDirClean.startsWith(absCleanUserFolder, cs) && !cleanUserEqualsCleanFolder && !forNewDirectory) {
|
||||
return tr("The local folder %1 contains a symbolic link. "
|
||||
"The link target contains an already synced folder. "
|
||||
"Please pick another one!")
|
||||
.arg(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
// if both pathes are equal, the server url needs to be different
|
||||
// otherwise it would mean that a new connection from the same local folder
|
||||
// to the same account is added which is not wanted. The account must differ.
|
||||
if (serverUrl.isValid() && Utility::fileNamesEqual(absCleanUserFolder, folderDir)) {
|
||||
if (serverUrl.isValid() && !differentPaths) {
|
||||
QUrl folderUrl = f->accountState()->account()->url();
|
||||
QString user = f->accountState()->account()->credentials()->user();
|
||||
folderUrl.setUserName(user);
|
||||
@@ -1372,8 +1363,10 @@ QString FolderMan::findGoodPathForNewSyncFolder(const QString &basePath, const Q
|
||||
bool FolderMan::ignoreHiddenFiles() const
|
||||
{
|
||||
if (_folderMap.empty()) {
|
||||
return true;
|
||||
// Currently no folders in the manager -> return default
|
||||
return false;
|
||||
}
|
||||
// Since the hiddenFiles settings is the same for all folders, just return the settings of the first folder
|
||||
return _folderMap.begin().value()->ignoreHiddenFiles();
|
||||
}
|
||||
|
||||
|
||||
@@ -127,11 +127,9 @@ public:
|
||||
*
|
||||
* Note that different accounts are allowed to sync to the same folder.
|
||||
*
|
||||
* \a forNewDirectory is internal and is used for recursion.
|
||||
*
|
||||
* @returns an empty string if it is allowed, or an error if it is not allowed
|
||||
*/
|
||||
QString checkPathValidityForNewFolder(const QString &path, const QUrl &serverUrl = QUrl(), bool forNewDirectory = false) const;
|
||||
QString checkPathValidityForNewFolder(const QString &path, const QUrl &serverUrl = QUrl()) const;
|
||||
|
||||
/**
|
||||
* Attempts to find a non-existing, acceptable path for creating a new sync folder.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "folderstatusdelegate.h"
|
||||
#include "folderstatusmodel.h"
|
||||
#include "folderstatusview.h"
|
||||
#include "folderman.h"
|
||||
#include "accountstate.h"
|
||||
#include <theme.h>
|
||||
@@ -24,6 +25,7 @@
|
||||
#include <QFileIconProvider>
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QMouseEvent>
|
||||
|
||||
inline static QFont makeAliasFont(const QFont &normalFont)
|
||||
{
|
||||
@@ -110,6 +112,10 @@ int FolderStatusDelegate::rootFolderHeightWithoutErrors(const QFontMetrics &fm,
|
||||
void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (index.data(AddButton).toBool()) {
|
||||
const_cast<QStyleOptionViewItem &>(option).showDecorationSelected = false;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
auto textAlign = Qt::AlignLeft;
|
||||
@@ -129,15 +135,15 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
int margin = subFm.height() / 4;
|
||||
|
||||
if (index.data(AddButton).toBool()) {
|
||||
QSize hint = sizeHint(option, index);
|
||||
QStyleOptionButton opt;
|
||||
static_cast<QStyleOption &>(opt) = option;
|
||||
opt.state &= ~QStyle::State_Selected;
|
||||
opt.state |= QStyle::State_Raised;
|
||||
if (opt.state & QStyle::State_Enabled && opt.state & QStyle::State_MouseOver && index == _pressedIndex) {
|
||||
opt.state |= QStyle::State_Sunken;
|
||||
} else {
|
||||
opt.state |= QStyle::State_Raised;
|
||||
}
|
||||
opt.text = addFolderText();
|
||||
opt.rect.setWidth(qMin(opt.rect.width(), hint.width()));
|
||||
opt.rect.adjust(0, aliasMargin, 0, -aliasMargin);
|
||||
opt.rect = QStyle::visualRect(option.direction, option.rect, opt.rect);
|
||||
opt.rect = addButtonRect(option.rect, option.direction);
|
||||
painter->save();
|
||||
painter->setFont(qApp->font("QPushButton"));
|
||||
QApplication::style()->drawControl(QStyle::CE_PushButton, &opt, painter, option.widget);
|
||||
@@ -352,6 +358,27 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
||||
bool FolderStatusDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseMove:
|
||||
if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(option.widget)) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
QModelIndex index;
|
||||
if (me->buttons()) {
|
||||
index = view->indexAt(me->pos());
|
||||
}
|
||||
if (_pressedIndex != index) {
|
||||
_pressedIndex = index;
|
||||
view->viewport()->update();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
_pressedIndex = QModelIndex();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
@@ -375,6 +402,16 @@ QRect FolderStatusDelegate::optionsButtonRect(QRect within, Qt::LayoutDirection
|
||||
return QStyle::visualRect(direction, within, r);
|
||||
}
|
||||
|
||||
QRect FolderStatusDelegate::addButtonRect(QRect within, Qt::LayoutDirection direction)
|
||||
{
|
||||
QFontMetrics fm(qApp->font("QPushButton"));
|
||||
QStyleOptionButton opt;
|
||||
opt.text = addFolderText();
|
||||
QSize size = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text)).expandedTo(QApplication::globalStrut());
|
||||
QRect r(QPoint(within.left(), within.top() + within.height() / 2 - size.height() / 2), size);
|
||||
return QStyle::visualRect(direction, within, r);
|
||||
}
|
||||
|
||||
QRect FolderStatusDelegate::errorsListRect(QRect within)
|
||||
{
|
||||
QFont font = QFont();
|
||||
|
||||
@@ -57,11 +57,13 @@ public:
|
||||
* return the position of the option button within the item
|
||||
*/
|
||||
static QRect optionsButtonRect(QRect within, Qt::LayoutDirection direction);
|
||||
static QRect addButtonRect(QRect within, Qt::LayoutDirection direction);
|
||||
static QRect errorsListRect(QRect within);
|
||||
static int rootFolderHeightWithoutErrors(const QFontMetrics &fm, const QFontMetrics &aliasFm);
|
||||
|
||||
private:
|
||||
static QString addFolderText();
|
||||
QPersistentModelIndex _pressedIndex;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
42
src/gui/folderstatusview.cpp
Normal file
42
src/gui/folderstatusview.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by J-P Nurmi <jpnurmi@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "folderstatusview.h"
|
||||
#include "folderstatusdelegate.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
FolderStatusView::FolderStatusView(QWidget *parent) : QTreeView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex FolderStatusView::indexAt(const QPoint &point) const
|
||||
{
|
||||
QModelIndex index = QTreeView::indexAt(point);
|
||||
if (index.data(FolderStatusDelegate::AddButton).toBool() && !visualRect(index).contains(point)) {
|
||||
return QModelIndex();
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
QRect FolderStatusView::visualRect(const QModelIndex &index) const
|
||||
{
|
||||
QRect rect = QTreeView::visualRect(index);
|
||||
if (index.data(FolderStatusDelegate::AddButton).toBool()) {
|
||||
return FolderStatusDelegate::addButtonRect(rect, layoutDirection());
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
39
src/gui/folderstatusview.h
Normal file
39
src/gui/folderstatusview.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by J-P Nurmi <jpnurmi@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef FOLDERSTATUSVIEW_H
|
||||
#define FOLDERSTATUSVIEW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
/**
|
||||
* @brief The FolderStatusView class
|
||||
* @ingroup gui
|
||||
*/
|
||||
class FolderStatusView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FolderStatusView(QWidget *parent = nullptr);
|
||||
|
||||
QModelIndex indexAt(const QPoint &point) const override;
|
||||
QRect visualRect(const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
#endif // FOLDERSTATUSVIEW_H
|
||||
@@ -38,19 +38,22 @@ namespace OCC {
|
||||
|
||||
Q_LOGGING_CATEGORY(lcFolderWatcher, "nextcloud.gui.folderwatcher", QtInfoMsg)
|
||||
|
||||
FolderWatcher::FolderWatcher(const QString &root, Folder *folder)
|
||||
FolderWatcher::FolderWatcher(Folder *folder)
|
||||
: QObject(folder)
|
||||
, _folder(folder)
|
||||
{
|
||||
_d.reset(new FolderWatcherPrivate(this, root));
|
||||
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
FolderWatcher::~FolderWatcher()
|
||||
{
|
||||
}
|
||||
|
||||
void FolderWatcher::init(const QString &root)
|
||||
{
|
||||
_d.reset(new FolderWatcherPrivate(this, root));
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
bool FolderWatcher::pathIsIgnored(const QString &path)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
|
||||
@@ -55,11 +55,14 @@ class FolderWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Construct, connect signals, call init()
|
||||
explicit FolderWatcher(Folder *folder = 0L);
|
||||
virtual ~FolderWatcher();
|
||||
|
||||
/**
|
||||
* @param root Path of the root of the folder
|
||||
*/
|
||||
FolderWatcher(const QString &root, Folder *folder = 0L);
|
||||
virtual ~FolderWatcher();
|
||||
void init(const QString &root);
|
||||
|
||||
/**
|
||||
* Not all backends are recursive by default.
|
||||
@@ -96,6 +99,12 @@ signals:
|
||||
*/
|
||||
void lostChanges();
|
||||
|
||||
/**
|
||||
* Signals when the watcher became unreliable. The string is a translated
|
||||
* message that can be shown to users.
|
||||
*/
|
||||
void becameUnreliable(const QString &message);
|
||||
|
||||
protected slots:
|
||||
// called from the implementations to indicate a change in path
|
||||
void changeDetected(const QString &path);
|
||||
|
||||
@@ -81,8 +81,11 @@ void FolderWatcherPrivate::inotifyRegisterPath(const QString &path)
|
||||
} else {
|
||||
// If we're running out of memory or inotify watches, become
|
||||
// unreliable.
|
||||
if (errno == ENOMEM || errno == ENOSPC) {
|
||||
if (_parent->_isReliable && (errno == ENOMEM || errno == ENOSPC)) {
|
||||
_parent->_isReliable = false;
|
||||
emit _parent->becameUnreliable(
|
||||
tr("This problem usually happens when the inotify watches are exhausted. "
|
||||
"Check the FAQ for details."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +66,10 @@ FolderWizardLocalPath::FolderWizardLocalPath(const AccountPtr &account)
|
||||
connect(_ui.localFolderChooseBtn, &QAbstractButton::clicked, this, &FolderWizardLocalPath::slotChooseLocalFolder);
|
||||
_ui.localFolderChooseBtn->setToolTip(tr("Click to select a local folder to sync."));
|
||||
|
||||
QUrl serverUrl = _account->url();
|
||||
serverUrl.setUserName(_account->credentials()->user());
|
||||
QString defaultPath = QDir::homePath() + QLatin1Char('/') + Theme::instance()->appName();
|
||||
defaultPath = FolderMan::instance()->findGoodPathForNewSyncFolder(defaultPath, account->url());
|
||||
defaultPath = FolderMan::instance()->findGoodPathForNewSyncFolder(defaultPath, serverUrl);
|
||||
_ui.localFolderLineEdit->setText(QDir::toNativeSeparators(defaultPath));
|
||||
_ui.localFolderLineEdit->setToolTip(tr("Enter the path to the local folder."));
|
||||
|
||||
|
||||
@@ -62,21 +62,16 @@ const char propertyAccountC[] = "oc_account";
|
||||
ownCloudGui::ownCloudGui(Application *parent)
|
||||
: QObject(parent)
|
||||
, _tray(0)
|
||||
,
|
||||
#if defined(Q_OS_MAC)
|
||||
_settingsDialog(new SettingsDialogMac(this))
|
||||
,
|
||||
, _settingsDialog(new SettingsDialogMac(this))
|
||||
#else
|
||||
_settingsDialog(new SettingsDialog(this))
|
||||
,
|
||||
, _settingsDialog(new SettingsDialog(this))
|
||||
#endif
|
||||
_logBrowser(0)
|
||||
, _contextMenuVisibleOsx(false)
|
||||
, _logBrowser(0)
|
||||
#ifdef WITH_LIBCLOUDPROVIDERS
|
||||
, _bus(QDBusConnection::sessionBus())
|
||||
#endif
|
||||
, _recentActionsMenu(0)
|
||||
, _qdbusmenuWorkaround(false)
|
||||
, _app(parent)
|
||||
{
|
||||
_tray = new Systray();
|
||||
@@ -154,7 +149,7 @@ void ownCloudGui::slotOpenSettingsDialog()
|
||||
|
||||
void ownCloudGui::slotTrayClicked(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
if (_qdbusmenuWorkaround) {
|
||||
if (_workaroundFakeDoubleClick) {
|
||||
static QElapsedTimer last_click;
|
||||
if (last_click.isValid() && last_click.elapsed() < 200) {
|
||||
return;
|
||||
@@ -415,7 +410,7 @@ void ownCloudGui::addAccountContextMenu(AccountStatePtr accountState, QMenu *men
|
||||
menu->addSeparator();
|
||||
if (separateMenu) {
|
||||
if (onePaused) {
|
||||
QAction *enable = menu->addAction(tr("Unpause all folders"));
|
||||
QAction *enable = menu->addAction(tr("Resume all folders"));
|
||||
enable->setProperty(propertyAccountC, QVariant::fromValue(accountState));
|
||||
connect(enable, &QAction::triggered, this, &ownCloudGui::slotUnpauseAllFolders);
|
||||
}
|
||||
@@ -439,17 +434,19 @@ void ownCloudGui::addAccountContextMenu(AccountStatePtr accountState, QMenu *men
|
||||
|
||||
void ownCloudGui::slotContextMenuAboutToShow()
|
||||
{
|
||||
// For some reason on OS X _contextMenu->isVisible returns always false
|
||||
_contextMenuVisibleOsx = true;
|
||||
_contextMenuVisibleManual = true;
|
||||
|
||||
// Update icon in sys tray, as it might change depending on the context menu state
|
||||
slotComputeOverallSyncStatus();
|
||||
|
||||
if (!_workaroundNoAboutToShowUpdate) {
|
||||
updateContextMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::slotContextMenuAboutToHide()
|
||||
{
|
||||
// For some reason on OS X _contextMenu->isVisible returns always false
|
||||
_contextMenuVisibleOsx = false;
|
||||
_contextMenuVisibleManual = false;
|
||||
|
||||
// Update icon in sys tray, as it might change depending on the context menu state
|
||||
slotComputeOverallSyncStatus();
|
||||
@@ -457,11 +454,11 @@ void ownCloudGui::slotContextMenuAboutToHide()
|
||||
|
||||
bool ownCloudGui::contextMenuVisible() const
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
return _contextMenuVisibleOsx;
|
||||
#else
|
||||
// On some platforms isVisible doesn't work and always returns false,
|
||||
// elsewhere aboutToHide is unreliable.
|
||||
if (_workaroundManualVisibility)
|
||||
return _contextMenuVisibleManual;
|
||||
return _contextMenu->isVisible();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool minimalTrayMenu()
|
||||
@@ -484,12 +481,36 @@ static bool updateWhileVisible()
|
||||
}
|
||||
}
|
||||
|
||||
static QByteArray forceQDBusTrayWorkaround()
|
||||
static QByteArray envForceQDBusTrayWorkaround()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_QDBUS_TRAY_WORKAROUND");
|
||||
return var;
|
||||
}
|
||||
|
||||
static QByteArray envForceWorkaroundShowAndHideTray()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_TRAY_SHOW_HIDE");
|
||||
return var;
|
||||
}
|
||||
|
||||
static QByteArray envForceWorkaroundNoAboutToShowUpdate()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_TRAY_NO_ABOUT_TO_SHOW");
|
||||
return var;
|
||||
}
|
||||
|
||||
static QByteArray envForceWorkaroundFakeDoubleClick()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_TRAY_FAKE_DOUBLE_CLICK");
|
||||
return var;
|
||||
}
|
||||
|
||||
static QByteArray envForceWorkaroundManualVisibility()
|
||||
{
|
||||
static QByteArray var = qgetenv("OWNCLOUD_FORCE_TRAY_MANUAL_VISIBILITY");
|
||||
return var;
|
||||
}
|
||||
|
||||
void ownCloudGui::setupContextMenu()
|
||||
{
|
||||
if (_contextMenu) {
|
||||
@@ -512,51 +533,65 @@ void ownCloudGui::setupContextMenu()
|
||||
return;
|
||||
}
|
||||
|
||||
// Enables workarounds for bugs introduced in Qt 5.5.0
|
||||
// In particular QTBUG-47863 #3672 (tray menu fails to update and
|
||||
// becomes unresponsive) and QTBUG-48068 #3722 (click signal is
|
||||
// emitted several times)
|
||||
// The Qt version check intentionally uses 5.0.0 (where platformMenu()
|
||||
// was introduced) instead of 5.5.0 to avoid issues where the Qt
|
||||
// version used to build is different from the one used at runtime.
|
||||
// If we build with 5.6.1 or newer, we can skip this because the
|
||||
// bugs should be fixed there.
|
||||
#ifdef Q_OS_LINUX
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) && (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
|
||||
if (qVersion() == QByteArray("5.5.0")) {
|
||||
QObject *platformMenu = reinterpret_cast<QObject *>(_tray->contextMenu()->platformMenu());
|
||||
if (platformMenu
|
||||
&& platformMenu->metaObject()->className() == QLatin1String("QDBusPlatformMenu")) {
|
||||
_qdbusmenuWorkaround = true;
|
||||
qCWarning(lcApplication) << "Enabled QDBusPlatformMenu workaround";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
auto applyEnvVariable = [](bool *sw, const QByteArray &value) {
|
||||
if (value == "1")
|
||||
*sw = true;
|
||||
if (value == "0")
|
||||
*sw = false;
|
||||
};
|
||||
|
||||
if (forceQDBusTrayWorkaround() == "1") {
|
||||
_qdbusmenuWorkaround = true;
|
||||
} else if (forceQDBusTrayWorkaround() == "0") {
|
||||
_qdbusmenuWorkaround = false;
|
||||
// This is an old compound flag that people might still depend on
|
||||
bool qdbusmenuWorkarounds = false;
|
||||
applyEnvVariable(&qdbusmenuWorkarounds, envForceQDBusTrayWorkaround());
|
||||
if (qdbusmenuWorkarounds) {
|
||||
_workaroundFakeDoubleClick = true;
|
||||
_workaroundNoAboutToShowUpdate = true;
|
||||
_workaroundShowAndHideTray = true;
|
||||
}
|
||||
|
||||
// When the qdbusmenuWorkaround is necessary, we can't do on-demand updates
|
||||
// because the workaround is to hide and show the tray icon.
|
||||
if (_qdbusmenuWorkaround) {
|
||||
connect(&_workaroundBatchTrayUpdate, &QTimer::timeout, this, &ownCloudGui::updateContextMenu);
|
||||
_workaroundBatchTrayUpdate.setInterval(30 * 1000);
|
||||
_workaroundBatchTrayUpdate.setSingleShot(true);
|
||||
} else {
|
||||
// Update the context menu whenever we're about to show it
|
||||
// to the user.
|
||||
#ifdef Q_OS_MAC
|
||||
// https://bugreports.qt.io/browse/QTBUG-54633
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToShow()), SLOT(slotContextMenuAboutToShow()));
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToHide()), SLOT(slotContextMenuAboutToHide()));
|
||||
#else
|
||||
connect(_contextMenu.data(), &QMenu::aboutToShow, this, &ownCloudGui::updateContextMenu);
|
||||
// https://bugreports.qt.io/browse/QTBUG-54633
|
||||
_workaroundNoAboutToShowUpdate = true;
|
||||
_workaroundManualVisibility = true;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// For KDE sessions if the platform plugin is missing,
|
||||
// neither aboutToShow() updates nor the isVisible() call
|
||||
// work. At least aboutToHide is reliable.
|
||||
// https://github.com/owncloud/client/issues/6545
|
||||
static QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
|
||||
static QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
|
||||
bool isKde =
|
||||
xdgCurrentDesktop.contains("KDE")
|
||||
|| desktopSession.contains("plasma")
|
||||
|| desktopSession.contains("kde");
|
||||
QObject *platformMenu = reinterpret_cast<QObject *>(_tray->contextMenu()->platformMenu());
|
||||
if (isKde && platformMenu && platformMenu->metaObject()->className() == QLatin1String("QDBusPlatformMenu")) {
|
||||
_workaroundManualVisibility = true;
|
||||
_workaroundNoAboutToShowUpdate = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
applyEnvVariable(&_workaroundNoAboutToShowUpdate, envForceWorkaroundNoAboutToShowUpdate());
|
||||
applyEnvVariable(&_workaroundFakeDoubleClick, envForceWorkaroundFakeDoubleClick());
|
||||
applyEnvVariable(&_workaroundShowAndHideTray, envForceWorkaroundShowAndHideTray());
|
||||
applyEnvVariable(&_workaroundManualVisibility, envForceWorkaroundManualVisibility());
|
||||
|
||||
qCInfo(lcApplication) << "Tray menu workarounds:"
|
||||
<< "noabouttoshow:" << _workaroundNoAboutToShowUpdate
|
||||
<< "fakedoubleclick:" << _workaroundFakeDoubleClick
|
||||
<< "showhide:" << _workaroundShowAndHideTray
|
||||
<< "manualvisibility:" << _workaroundManualVisibility;
|
||||
|
||||
|
||||
connect(&_delayedTrayUpdateTimer, &QTimer::timeout, this, &ownCloudGui::updateContextMenu);
|
||||
_delayedTrayUpdateTimer.setInterval(2 * 1000);
|
||||
_delayedTrayUpdateTimer.setSingleShot(true);
|
||||
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToShow()), SLOT(slotContextMenuAboutToShow()));
|
||||
// unfortunately aboutToHide is unreliable, it seems to work on OSX though
|
||||
connect(_contextMenu.data(), SIGNAL(aboutToHide()), SLOT(slotContextMenuAboutToHide()));
|
||||
|
||||
// Populate the context menu now.
|
||||
updateContextMenu();
|
||||
@@ -568,13 +603,21 @@ void ownCloudGui::updateContextMenu()
|
||||
return;
|
||||
}
|
||||
|
||||
if (_qdbusmenuWorkaround) {
|
||||
// If it's visible, we can't update live, and it won't be updated lazily: reschedule
|
||||
if (contextMenuVisible() && !updateWhileVisible() && _workaroundNoAboutToShowUpdate) {
|
||||
if (!_delayedTrayUpdateTimer.isActive()) {
|
||||
_delayedTrayUpdateTimer.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_workaroundShowAndHideTray) {
|
||||
// To make tray menu updates work with these bugs (see setupContextMenu)
|
||||
// we need to hide and show the tray icon. We don't want to do that
|
||||
// while it's visible!
|
||||
if (contextMenuVisible()) {
|
||||
if (!_workaroundBatchTrayUpdate.isActive()) {
|
||||
_workaroundBatchTrayUpdate.start();
|
||||
if (!_delayedTrayUpdateTimer.isActive()) {
|
||||
_delayedTrayUpdateTimer.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -648,9 +691,9 @@ void ownCloudGui::updateContextMenu()
|
||||
if (atLeastOnePaused) {
|
||||
QString text;
|
||||
if (accountList.count() > 1) {
|
||||
text = tr("Unpause all synchronization");
|
||||
text = tr("Resume all synchronization");
|
||||
} else {
|
||||
text = tr("Unpause synchronization");
|
||||
text = tr("Resume synchronization");
|
||||
}
|
||||
QAction *action = _contextMenu->addAction(text);
|
||||
connect(action, &QAction::triggered, this, &ownCloudGui::slotUnpauseAllFolders);
|
||||
@@ -667,35 +710,30 @@ void ownCloudGui::updateContextMenu()
|
||||
}
|
||||
_contextMenu->addAction(_actionQuit);
|
||||
|
||||
if (_qdbusmenuWorkaround) {
|
||||
if (_workaroundShowAndHideTray) {
|
||||
_tray->show();
|
||||
}
|
||||
}
|
||||
|
||||
void ownCloudGui::updateContextMenuNeeded()
|
||||
{
|
||||
// For the workaround case updating while visible is impossible. Instead
|
||||
// occasionally update the menu when it's invisible.
|
||||
if (_qdbusmenuWorkaround) {
|
||||
if (!_workaroundBatchTrayUpdate.isActive()) {
|
||||
_workaroundBatchTrayUpdate.start();
|
||||
}
|
||||
// if it's visible and we can update live: update now
|
||||
if (contextMenuVisible() && updateWhileVisible()) {
|
||||
// Note: don't update while visible on OSX
|
||||
// https://bugreports.qt.io/browse/QTBUG-54845
|
||||
updateContextMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// https://bugreports.qt.io/browse/QTBUG-54845
|
||||
// We cannot update on demand or while visible -> update when invisible.
|
||||
if (!contextMenuVisible()) {
|
||||
updateContextMenu();
|
||||
// if we can't lazily update: update later
|
||||
if (_workaroundNoAboutToShowUpdate) {
|
||||
// Note: don't update immediately even in the invisible case
|
||||
// as that can lead to extremely frequent menu updates
|
||||
if (!_delayedTrayUpdateTimer.isActive()) {
|
||||
_delayedTrayUpdateTimer.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (updateWhileVisible() && contextMenuVisible())
|
||||
updateContextMenu();
|
||||
#endif
|
||||
|
||||
// If no update was done here, we might update it on-demand due to
|
||||
// the aboutToShow() signal.
|
||||
}
|
||||
|
||||
void ownCloudGui::slotShowTrayMessage(const QString &title, const QString &msg)
|
||||
|
||||
@@ -140,9 +140,11 @@ private:
|
||||
// tray's menu
|
||||
QScopedPointer<QMenu> _contextMenu;
|
||||
|
||||
// Manually tracking whether the context menu is visible, but only works
|
||||
// on OSX because aboutToHide is not reliable everywhere.
|
||||
bool _contextMenuVisibleOsx;
|
||||
// Manually tracking whether the context menu is visible via aboutToShow
|
||||
// and aboutToHide. Unfortunately aboutToHide isn't reliable everywhere
|
||||
// so this only gets used with _workaroundManualVisibility (when the tray's
|
||||
// isVisible() is unreliable)
|
||||
bool _contextMenuVisibleManual = false;
|
||||
|
||||
#ifdef WITH_LIBCLOUDPROVIDERS
|
||||
QDBusConnection _bus;
|
||||
@@ -150,8 +152,11 @@ private:
|
||||
|
||||
QMenu *_recentActionsMenu;
|
||||
QVector<QMenu *> _accountMenus;
|
||||
bool _qdbusmenuWorkaround;
|
||||
QTimer _workaroundBatchTrayUpdate;
|
||||
bool _workaroundShowAndHideTray = false;
|
||||
bool _workaroundNoAboutToShowUpdate = false;
|
||||
bool _workaroundFakeDoubleClick = false;
|
||||
bool _workaroundManualVisibility = false;
|
||||
QTimer _delayedTrayUpdateTimer;
|
||||
QMap<QString, QPointer<ShareDialog>> _shareDialogs;
|
||||
|
||||
QAction *_actionNewAccountWizard;
|
||||
|
||||
@@ -122,9 +122,6 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
|
||||
|
||||
QTimer::singleShot(1, this, &SettingsDialog::showFirstPage);
|
||||
|
||||
QPushButton *closeButton = _ui->buttonBox->button(QDialogButtonBox::Close);
|
||||
connect(closeButton, SIGNAL(clicked()), SLOT(accept()));
|
||||
|
||||
QAction *showLogWindow = new QAction(this);
|
||||
showLogWindow->setShortcut(QKeySequence("F12"));
|
||||
connect(showLogWindow, &QAction::triggered, gui, &ownCloudGui::slotToggleLogBrowser);
|
||||
@@ -244,6 +241,7 @@ void SettingsDialog::accountAdded(AccountState *s)
|
||||
_actionGroup->addAction(accountAction);
|
||||
_actionGroupWidgets.insert(accountAction, accountSettings);
|
||||
_actionForAccount.insert(s->account().data(), accountAction);
|
||||
accountAction->trigger();
|
||||
|
||||
connect(accountSettings, &AccountSettings::folderChanged, _gui, &ownCloudGui::slotFoldersChanged);
|
||||
connect(accountSettings, &AccountSettings::openFolderAlias,
|
||||
|
||||
@@ -29,28 +29,6 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::NoButton</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="palette">
|
||||
|
||||
@@ -167,6 +167,7 @@ void SettingsDialogMac::accountAdded(AccountState *s)
|
||||
_activitySettings[s]->setNotificationRefreshInterval(cfg.notificationRefreshInterval());
|
||||
|
||||
slotRefreshActivity(s);
|
||||
setCurrentPanelIndex(0);
|
||||
}
|
||||
|
||||
void SettingsDialogMac::accountRemoved(AccountState *s)
|
||||
|
||||
@@ -87,6 +87,7 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
|
||||
connect(_manager, &ShareManager::shareCreated, this, &ShareUserGroupWidget::getShares);
|
||||
connect(_manager, &ShareManager::serverError, this, &ShareUserGroupWidget::displayError);
|
||||
connect(_ui->shareeLineEdit, &QLineEdit::returnPressed, this, &ShareUserGroupWidget::slotLineEditReturn);
|
||||
connect(_ui->confirmShare, &QPushButton::clicked, this, &ShareUserGroupWidget::slotLineEditReturn);
|
||||
//TODO connect(_ui->privateLinkText, &QLabel::linkActivated, this, &ShareUserGroupWidget::slotPrivateLinkShare);
|
||||
|
||||
// By making the next two QueuedConnections we can override
|
||||
@@ -630,7 +631,7 @@ void ShareUserLine::displayPermissions()
|
||||
|
||||
// edit is independent of reshare
|
||||
if (perm & SharePermissionShare)
|
||||
_permissionReshare->setChecked(Qt::Checked);
|
||||
_permissionReshare->setChecked(true);
|
||||
|
||||
if(!_isFile){
|
||||
_permissionCreate->setChecked(perm & SharePermissionCreate);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// This file is generated by kxml_compiler from occinfo.xml.
|
||||
// All changes you do to this file will be lost.
|
||||
|
||||
#include "updateinfo.h"
|
||||
#include "updater.h"
|
||||
@@ -83,24 +82,6 @@ UpdateInfo UpdateInfo::parseElement(const QDomElement &element, bool *ok)
|
||||
return result;
|
||||
}
|
||||
|
||||
void UpdateInfo::writeElement(QXmlStreamWriter &xml)
|
||||
{
|
||||
xml.writeStartElement(QLatin1String("owncloudclient"));
|
||||
if (!version().isEmpty()) {
|
||||
xml.writeTextElement(QLatin1String("version"), version());
|
||||
}
|
||||
if (!versionString().isEmpty()) {
|
||||
xml.writeTextElement(QLatin1String("versionstring"), versionString());
|
||||
}
|
||||
if (!web().isEmpty()) {
|
||||
xml.writeTextElement(QLatin1String("web"), web());
|
||||
}
|
||||
if (!downloadUrl().isEmpty()) {
|
||||
xml.writeTextElement(QLatin1String("downloadurl"), web());
|
||||
}
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
UpdateInfo UpdateInfo::parseFile(const QString &filename, bool *ok)
|
||||
{
|
||||
QFile file(filename);
|
||||
@@ -149,23 +130,4 @@ UpdateInfo UpdateInfo::parseString(const QString &xml, bool *ok)
|
||||
return c;
|
||||
}
|
||||
|
||||
bool UpdateInfo::writeFile(const QString &filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qCCritical(lcUpdater) << "Unable to open file '" << filename << "'";
|
||||
return false;
|
||||
}
|
||||
|
||||
QXmlStreamWriter xml(&file);
|
||||
xml.setAutoFormatting(true);
|
||||
xml.setAutoFormattingIndent(2);
|
||||
xml.writeStartDocument(QLatin1String("1.0"));
|
||||
writeElement(xml);
|
||||
xml.writeEndDocument();
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// This file is generated by kxml_compiler from occinfo.xml.
|
||||
// All changes you do to this file will be lost.
|
||||
#ifndef UPDATEINFO_H
|
||||
#define UPDATEINFO_H
|
||||
|
||||
@@ -24,10 +23,8 @@ public:
|
||||
Parse XML object from DOM element.
|
||||
*/
|
||||
static UpdateInfo parseElement(const QDomElement &element, bool *ok);
|
||||
void writeElement(QXmlStreamWriter &xml);
|
||||
static UpdateInfo parseFile(const QString &filename, bool *ok);
|
||||
static UpdateInfo parseString(const QString &xml, bool *ok);
|
||||
bool writeFile(const QString &filename);
|
||||
|
||||
private:
|
||||
QString mVersion;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
*/
|
||||
|
||||
#include <QVariant>
|
||||
#include <QMenu>
|
||||
#include <QClipboard>
|
||||
|
||||
#include "wizard/owncloudoauthcredspage.h"
|
||||
#include "theme.h"
|
||||
@@ -48,6 +50,16 @@ OwncloudOAuthCredsPage::OwncloudOAuthCredsPage()
|
||||
if (_asyncAuth)
|
||||
_asyncAuth->openBrowser();
|
||||
});
|
||||
_ui.openLinkButton->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
QObject::connect(_ui.openLinkButton, &QWidget::customContextMenuRequested, [this](const QPoint &pos) {
|
||||
auto menu = new QMenu(_ui.openLinkButton);
|
||||
menu->addAction(tr("Copy link to clipboard"), this, [this] {
|
||||
if (_asyncAuth)
|
||||
QApplication::clipboard()->setText(_asyncAuth->authorisationLink().toString(QUrl::FullyEncoded));
|
||||
});
|
||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
menu->popup(_ui.openLinkButton->mapToGlobal(pos));
|
||||
});
|
||||
}
|
||||
|
||||
void OwncloudOAuthCredsPage::initializePage()
|
||||
|
||||
@@ -61,22 +61,11 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="hostButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<underline>true</underline>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QLabel" name="installLink">
|
||||
<property name="text">
|
||||
<string>Host your own server</string>
|
||||
<string><a href="https://docs.nextcloud.com/server/13/admin_manual/installation/index.html#installation"><span style=" text-decoration: underline; color:#0000ff;">Host your own server</span></a></string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -201,28 +190,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="slideImage">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../../theme.qrc">:/client/theme/colored/wizard-files.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
@@ -240,7 +207,7 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="slideLabel">
|
||||
<widget class="OCC::SlideShow" name="slideShow">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
@@ -248,12 +215,6 @@
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SlideshowLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
@@ -448,6 +409,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>wizard/postfixlineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>OCC::SlideShow</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>wizard/slideshow.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../theme.qrc"/>
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
|
||||
#include "wizard/owncloudwizardcommon.h"
|
||||
#include "wizard/owncloudsetuppage.h"
|
||||
#include "wizard/owncloudconnectionmethoddialog.h"
|
||||
#include "wizard/slideshow.h"
|
||||
#include "theme.h"
|
||||
#include "account.h"
|
||||
#include "config.h"
|
||||
@@ -80,43 +80,26 @@ OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
|
||||
connect(_ui.createAccountButton, &QPushButton::clicked, this, &OwncloudSetupPage::slotGotoProviderList);
|
||||
|
||||
_ui.login->hide();
|
||||
_slideshow.append(qMakePair(QString("nextcloud"), tr("Keep your data secure and under your control")));
|
||||
_slideshow.append(qMakePair(QString("files"), tr("Secure collaboration & file exchange")));
|
||||
_slideshow.append(qMakePair(QString("groupware"), tr("Easy-to-use web mail, calendaring & contacts")));
|
||||
_slideshow.append(qMakePair(QString("talk"), tr("Screensharing, online meetings & web conferences")));
|
||||
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-nextcloud.png"), tr("Keep your data secure and under your control"));
|
||||
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-files.png"), tr("Secure collaboration & file exchange"));
|
||||
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-groupware.png"), tr("Easy-to-use web mail, calendaring & contacts"));
|
||||
_ui.slideShow->addSlide(Theme::hidpiFileName(":/client/theme/colored/wizard-talk.png"), tr("Screensharing, online meetings & web conferences"));
|
||||
connect(_ui.slideShow, &SlideShow::clicked, _ui.slideShow, &SlideShow::nextSlide);
|
||||
_ui.slideShow->startShow(2500);
|
||||
|
||||
_ui.slideLabel->setStyleSheet(QString("color:%1;").arg(theme->wizardHeaderBackgroundColor().name()));
|
||||
_currentSlide = -1;
|
||||
nextSlide();
|
||||
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(nextSlide()));
|
||||
timer->start(2500);
|
||||
QPalette pal = _ui.slideShow->palette();
|
||||
pal.setColor(QPalette::WindowText, theme->wizardHeaderBackgroundColor());
|
||||
_ui.slideShow->setPalette(pal);
|
||||
#else
|
||||
_ui.createAccountButton->hide();
|
||||
_ui.slideImage->hide();
|
||||
_ui.slideLabel->hide();
|
||||
_ui.loginButton->hide();
|
||||
_ui.hostButton->hide();
|
||||
_ui.installLink->hide();
|
||||
#endif
|
||||
setStyleSheet(QString("background-color:%1; color:%2 QLabel { color:%2; } QSpacerItem { color: red; }").arg(theme->wizardHeaderBackgroundColor().name(), theme->wizardHeaderTitleColor().name()));
|
||||
|
||||
}
|
||||
|
||||
#ifdef WITH_PROVIDERS
|
||||
void OwncloudSetupPage::nextSlide()
|
||||
{
|
||||
if (_currentSlide < _slideshow.length()-1) {
|
||||
_currentSlide++;
|
||||
} else {
|
||||
_currentSlide = 0;
|
||||
}
|
||||
QPixmap pixmap = QIcon(Theme::hidpiFileName(":/client/theme/colored/wizard-" + _slideshow.at(_currentSlide).first + ".svg")).pixmap(QSize(1024, 1024));
|
||||
_ui.slideImage->setPixmap(pixmap.scaled(QSize(_ui.slideImage->size().height(), _ui.slideImage->size().height()), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
_ui.slideLabel->setText(_slideshow.at(_currentSlide).second);
|
||||
}
|
||||
#endif
|
||||
|
||||
void OwncloudSetupPage::setServerUrl(const QString &newUrl)
|
||||
{
|
||||
_ocWizard->setRegistration(false);
|
||||
@@ -155,6 +138,7 @@ void OwncloudSetupPage::slotLogin()
|
||||
animation->setStartValue(500);
|
||||
animation->setEndValue(500);
|
||||
_ui.login->show();
|
||||
_ui.loginButton->hide();
|
||||
wizard()->resize(wizard()->sizeHint());
|
||||
animation->start();
|
||||
}
|
||||
@@ -293,12 +277,19 @@ QString OwncloudSetupPage::url() const
|
||||
bool OwncloudSetupPage::validatePage()
|
||||
{
|
||||
if (!_authTypeKnown) {
|
||||
QString u = url();
|
||||
QUrl qurl(u);
|
||||
if (!qurl.isValid() || qurl.host().isEmpty()) {
|
||||
setErrorString(tr("Invalid URL"), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
setErrorString(QString(), false);
|
||||
_checking = true;
|
||||
startSpinner();
|
||||
emit completeChanged();
|
||||
|
||||
emit determineAuthType(url());
|
||||
emit determineAuthType(u);
|
||||
return false;
|
||||
} else {
|
||||
// connecting is running
|
||||
|
||||
@@ -62,9 +62,6 @@ public slots:
|
||||
void startSpinner();
|
||||
void stopSpinner();
|
||||
void slotCertificateAccepted();
|
||||
#ifdef WITH_PROVIDERS
|
||||
void nextSlide();
|
||||
#endif
|
||||
|
||||
protected slots:
|
||||
void slotUrlChanged(const QString &);
|
||||
@@ -96,10 +93,6 @@ private:
|
||||
QString _remoteFolder;
|
||||
AddCertificateDialog *addCertDial;
|
||||
OwncloudWizard *_ocWizard;
|
||||
|
||||
QList<QPair<QString, QString>> _slideshow;
|
||||
int _currentSlide;
|
||||
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
193
src/gui/wizard/slideshow.cpp
Normal file
193
src/gui/wizard/slideshow.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by J-P Nurmi <jpnurmi@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "slideshow.h"
|
||||
#include <QGuiApplication>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QStyleHints>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
static const int Spacing = 6;
|
||||
static const int SlideDuration = 1000;
|
||||
static const int SlideDistance = 400;
|
||||
|
||||
SlideShow::SlideShow(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
}
|
||||
|
||||
void SlideShow::addSlide(const QPixmap &pixmap, const QString &label)
|
||||
{
|
||||
_labels += label;
|
||||
_pixmaps += pixmap;
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
bool SlideShow::isActive() const
|
||||
{
|
||||
return _timer.isActive();
|
||||
}
|
||||
|
||||
int SlideShow::interval() const
|
||||
{
|
||||
return _interval;
|
||||
}
|
||||
|
||||
void SlideShow::setInterval(int interval)
|
||||
{
|
||||
if (_interval == interval)
|
||||
return;
|
||||
|
||||
_interval = interval;
|
||||
maybeRestartTimer();
|
||||
}
|
||||
|
||||
int SlideShow::currentSlide() const
|
||||
{
|
||||
return _currentIndex;
|
||||
}
|
||||
|
||||
void SlideShow::setCurrentSlide(int index)
|
||||
{
|
||||
if (_currentIndex == index)
|
||||
return;
|
||||
|
||||
if (!_animation) {
|
||||
_animation = new QVariantAnimation(this);
|
||||
_animation->setDuration(SlideDuration);
|
||||
_animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
_animation->setStartValue(static_cast<qreal>(_currentIndex));
|
||||
connect(_animation.data(), SIGNAL(valueChanged(QVariant)), this, SLOT(update()));
|
||||
}
|
||||
_animation->setEndValue(static_cast<qreal>(index));
|
||||
_animation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
|
||||
_reverse = index < _currentIndex;
|
||||
_currentIndex = index;
|
||||
maybeRestartTimer();
|
||||
update();
|
||||
emit currentSlideChanged(index);
|
||||
}
|
||||
|
||||
QSize SlideShow::sizeHint() const
|
||||
{
|
||||
QFontMetrics fm = fontMetrics();
|
||||
QSize labelSize(0, fm.height());
|
||||
for (const QString &label : _labels) {
|
||||
labelSize.setWidth(std::max(fm.width(label), labelSize.width()));
|
||||
}
|
||||
QSize pixmapSize;
|
||||
for (const QPixmap &pixmap : _pixmaps) {
|
||||
pixmapSize.setWidth(std::max(pixmap.width(), pixmapSize.width()));
|
||||
pixmapSize.setHeight(std::max(pixmap.height(), pixmapSize.height()));
|
||||
}
|
||||
return QSize(std::max(labelSize.width(), pixmapSize.width()), labelSize.height() + Spacing + pixmapSize.height());
|
||||
}
|
||||
|
||||
void SlideShow::startShow(int interval)
|
||||
{
|
||||
if (interval > 0)
|
||||
_interval = interval;
|
||||
_timer.start(_interval, this);
|
||||
}
|
||||
|
||||
void SlideShow::stopShow()
|
||||
{
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
void SlideShow::nextSlide()
|
||||
{
|
||||
setCurrentSlide((_currentIndex + 1) % _labels.count());
|
||||
_reverse = false;
|
||||
}
|
||||
|
||||
void SlideShow::previousSlide()
|
||||
{
|
||||
setCurrentSlide((_currentIndex > 0 ? _currentIndex : _labels.count()) - 1);
|
||||
_reverse = true;
|
||||
}
|
||||
|
||||
void SlideShow::reset()
|
||||
{
|
||||
stopShow();
|
||||
_pixmaps.clear();
|
||||
_labels.clear();
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
void SlideShow::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
_pressPoint = event->pos();
|
||||
}
|
||||
|
||||
void SlideShow::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (QLineF(_pressPoint, event->pos()).length() < QGuiApplication::styleHints()->startDragDistance())
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
void SlideShow::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
if (_animation) {
|
||||
int from = _animation->startValue().toInt();
|
||||
int to = _animation->endValue().toInt();
|
||||
qreal progress = _animation->easingCurve().valueForProgress(_animation->currentTime() / static_cast<qreal>(_animation->duration()));
|
||||
|
||||
painter.save();
|
||||
painter.setOpacity(1.0 - progress);
|
||||
painter.translate(progress * (_reverse ? SlideDistance : -SlideDistance), 0);
|
||||
drawSlide(&painter, from);
|
||||
|
||||
painter.restore();
|
||||
painter.setOpacity(progress);
|
||||
painter.translate((1.0 - progress) * (_reverse ? -SlideDistance : SlideDistance), 0);
|
||||
drawSlide(&painter, to);
|
||||
} else {
|
||||
drawSlide(&painter, _currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SlideShow::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (event->timerId() == _timer.timerId())
|
||||
nextSlide();
|
||||
}
|
||||
|
||||
void SlideShow::maybeRestartTimer()
|
||||
{
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
startShow();
|
||||
}
|
||||
|
||||
void SlideShow::drawSlide(QPainter *painter, int index)
|
||||
{
|
||||
QString label = _labels.value(index);
|
||||
QRect labelRect = style()->itemTextRect(fontMetrics(), rect(), Qt::AlignBottom | Qt::AlignHCenter, isEnabled(), label);
|
||||
style()->drawItemText(painter, labelRect, Qt::AlignCenter, palette(), isEnabled(), label, QPalette::WindowText);
|
||||
|
||||
QPixmap pixmap = _pixmaps.value(index);
|
||||
QRect pixmapRect = style()->itemPixmapRect(QRect(0, 0, width(), labelRect.top() - Spacing), Qt::AlignCenter, pixmap);
|
||||
style()->drawItemPixmap(painter, pixmapRect, Qt::AlignCenter, pixmap);
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
83
src/gui/wizard/slideshow.h
Normal file
83
src/gui/wizard/slideshow.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by J-P Nurmi <jpnurmi@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef OCC_SLIDESHOW_H
|
||||
#define OCC_SLIDESHOW_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QBasicTimer>
|
||||
#include <QPointer>
|
||||
#include <QVariantAnimation>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
/**
|
||||
* @brief The SlideShow class
|
||||
* @ingroup gui
|
||||
*/
|
||||
class SlideShow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int interval READ interval WRITE setInterval)
|
||||
Q_PROPERTY(int currentSlide READ currentSlide WRITE setCurrentSlide NOTIFY currentSlideChanged)
|
||||
|
||||
public:
|
||||
explicit SlideShow(QWidget* parent = nullptr);
|
||||
|
||||
void addSlide(const QPixmap &pixmap, const QString &label);
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
int interval() const;
|
||||
void setInterval(int interval);
|
||||
|
||||
int currentSlide() const;
|
||||
void setCurrentSlide(int index);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void startShow(int interval = 0);
|
||||
void stopShow();
|
||||
void nextSlide();
|
||||
void previousSlide();
|
||||
void reset();
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
void currentSlideChanged(int index);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
void maybeRestartTimer();
|
||||
void drawSlide(QPainter *painter, int index);
|
||||
|
||||
bool _reverse = false;
|
||||
int _interval = 2500;
|
||||
int _currentIndex = 0;
|
||||
QPoint _pressPoint;
|
||||
QBasicTimer _timer;
|
||||
QStringList _labels;
|
||||
QVector<QPixmap> _pixmaps;
|
||||
QPointer<QVariantAnimation> _animation = nullptr;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
#endif // OCC_SLIDESHOW_H
|
||||
@@ -41,6 +41,13 @@ class WebEnginePage : public QWebEnginePage {
|
||||
public:
|
||||
WebEnginePage(QWebEngineProfile *profile, QObject* parent = nullptr);
|
||||
QWebEnginePage * createWindow(QWebEnginePage::WebWindowType type) override;
|
||||
void setUrl(const QUrl &url);
|
||||
|
||||
protected:
|
||||
bool certificateError(const QWebEngineCertificateError &certificateError) override;
|
||||
|
||||
private:
|
||||
QUrl _rootUrl;
|
||||
};
|
||||
|
||||
// We need a separate class here, since we cannot simply return the same WebEnginePage object
|
||||
@@ -146,6 +153,19 @@ QWebEnginePage * WebEnginePage::createWindow(QWebEnginePage::WebWindowType type)
|
||||
return view;
|
||||
}
|
||||
|
||||
void WebEnginePage::setUrl(const QUrl &url) {
|
||||
QWebEnginePage::setUrl(url);
|
||||
_rootUrl = url;
|
||||
}
|
||||
|
||||
bool WebEnginePage::certificateError(const QWebEngineCertificateError &certificateError) {
|
||||
if (certificateError.error() == QWebEngineCertificateError::CertificateAuthorityInvalid) {
|
||||
return certificateError.url().host() == _rootUrl.host();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ExternalWebEnginePage::ExternalWebEnginePage(QWebEngineProfile *profile, QObject* parent) : QWebEnginePage(profile, parent) {
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user