Compare commits
585 Commits
v3.3.0-rc1
...
v3.4.0-do-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd60e60541 | ||
|
|
fb833ed311 | ||
|
|
1440c53ed6 | ||
|
|
bd42c35e80 | ||
|
|
a5c82670c9 | ||
|
|
3c966a77df | ||
|
|
1a9aade28e | ||
|
|
34c4c28879 | ||
|
|
a272b34809 | ||
|
|
05b8d1e40d | ||
|
|
18ef471332 | ||
|
|
e14502606c | ||
|
|
59953d857b | ||
|
|
436eced9fb | ||
|
|
f56985938d | ||
|
|
56f4198b28 | ||
|
|
6b22081f61 | ||
|
|
a5fa53c460 | ||
|
|
426e0af8cd | ||
|
|
e2f1854b1e | ||
|
|
c194605c35 | ||
|
|
112be18635 | ||
|
|
802c7ac906 | ||
|
|
f575cc1860 | ||
|
|
b03bf1c1f0 | ||
|
|
9bebda057a | ||
|
|
83a8058b51 | ||
|
|
072e9d44bd | ||
|
|
a3013de6ea | ||
|
|
9eed62a854 | ||
|
|
79282a8df9 | ||
|
|
ec64246dc7 | ||
|
|
c89d2abf5a | ||
|
|
b3914f627d | ||
|
|
998236dcc5 | ||
|
|
d9626bf311 | ||
|
|
684d70985e | ||
|
|
e92842d837 | ||
|
|
12c6d6e3bd | ||
|
|
1d704d9352 | ||
|
|
38ac585e7c | ||
|
|
892d289f38 | ||
|
|
5294c5135c | ||
|
|
8e6896ba03 | ||
|
|
b2e86c2ea3 | ||
|
|
8cc58dd8b0 | ||
|
|
ca1620ef42 | ||
|
|
f1d834df8e | ||
|
|
502ffc62ef | ||
|
|
73db636361 | ||
|
|
b222785dc2 | ||
|
|
5454004ef9 | ||
|
|
ed9671c2a6 | ||
|
|
911e35bc50 | ||
|
|
898949d1bc | ||
|
|
ef8fe58245 | ||
|
|
9e792369b2 | ||
|
|
c76a77e431 | ||
|
|
2308c9da49 | ||
|
|
c59f88ca82 | ||
|
|
3edfcff1a0 | ||
|
|
d84673376d | ||
|
|
69def04ec2 | ||
|
|
3e1a46f2de | ||
|
|
113ba716e6 | ||
|
|
703037cbfb | ||
|
|
07a8e8c91d | ||
|
|
df745ef39c | ||
|
|
2665c8fc16 | ||
|
|
cb34fec596 | ||
|
|
d8560dcb19 | ||
|
|
0e5f1d9a30 | ||
|
|
ad814f175e | ||
|
|
94dec9d9bb | ||
|
|
56bb3e7938 | ||
|
|
263cdd3c8b | ||
|
|
6d5597e93e | ||
|
|
41b2d7744d | ||
|
|
7e45dd9d14 | ||
|
|
48a8085453 | ||
|
|
3e368ee4df | ||
|
|
db337c4457 | ||
|
|
4bd9972d46 | ||
|
|
5ab13b2adc | ||
|
|
845e258031 | ||
|
|
416d98716f | ||
|
|
30d4a62707 | ||
|
|
2f3c58daac | ||
|
|
0b8ab5c079 | ||
|
|
0d8375e798 | ||
|
|
7dd09b8d8a | ||
|
|
d661e91a58 | ||
|
|
d11935b6fc | ||
|
|
650578ee64 | ||
|
|
43ec429fe4 | ||
|
|
9658aea963 | ||
|
|
6ad63fb770 | ||
|
|
d88e086b94 | ||
|
|
6c3c45dadd | ||
|
|
f3af4ce098 | ||
|
|
511da0f3c7 | ||
|
|
c52718c104 | ||
|
|
e4eaf9d88d | ||
|
|
a62905f17a | ||
|
|
3a98abb6ba | ||
|
|
dd4d7e3162 | ||
|
|
ce062aeb3b | ||
|
|
78301c6f83 | ||
|
|
487cc7e9c0 | ||
|
|
7dacabf07c | ||
|
|
8226c30d84 | ||
|
|
9281350b4c | ||
|
|
d68b8604ac | ||
|
|
ab524d2392 | ||
|
|
72c91362f2 | ||
|
|
c13668c0e9 | ||
|
|
5decbd0b21 | ||
|
|
5788f35e82 | ||
|
|
5d08936e37 | ||
|
|
acd8553be9 | ||
|
|
db4e54025a | ||
|
|
907ebc1959 | ||
|
|
f760d610e9 | ||
|
|
2a108b86c7 | ||
|
|
87c583dcb6 | ||
|
|
c6344c05be | ||
|
|
24428d9980 | ||
|
|
b0ef5e0635 | ||
|
|
51a77bac28 | ||
|
|
c39b97adb3 | ||
|
|
beffd63512 | ||
|
|
856d269657 | ||
|
|
28248f3332 | ||
|
|
69d6f4acec | ||
|
|
a71bf73e4d | ||
|
|
1b8448402a | ||
|
|
c1dab7e4cb | ||
|
|
b8e2dc24f3 | ||
|
|
31e278ffb6 | ||
|
|
a444eb8d44 | ||
|
|
91884eef4a | ||
|
|
fb3c740129 | ||
|
|
359d85dd66 | ||
|
|
b5462e1059 | ||
|
|
37a64ab19b | ||
|
|
0ee6eb8bbb | ||
|
|
4e48837b91 | ||
|
|
33cb02e416 | ||
|
|
da03acc656 | ||
|
|
ed7abc4a93 | ||
|
|
3ab698a0c5 | ||
|
|
c2dd75df12 | ||
|
|
9f35fa6d3d | ||
|
|
d14be7c2c0 | ||
|
|
7a6bc830dd | ||
|
|
a10ffb1676 | ||
|
|
597e29ebe9 | ||
|
|
1156d82594 | ||
|
|
6b32d9a694 | ||
|
|
3d795b0547 | ||
|
|
daa205bcef | ||
|
|
4008bdd295 | ||
|
|
426fd2238d | ||
|
|
bd731a9cda | ||
|
|
fb74fdf114 | ||
|
|
3c749bd383 | ||
|
|
24f6bc5203 | ||
|
|
e5b3e9ed18 | ||
|
|
c6e629c30d | ||
|
|
62af1fa4e6 | ||
|
|
101c2ba10d | ||
|
|
d8d0886d44 | ||
|
|
3b1f1952ab | ||
|
|
f8a8e3f2f9 | ||
|
|
2a68abfc6d | ||
|
|
22b0a2e196 | ||
|
|
00dab13b39 | ||
|
|
bc53c3454c | ||
|
|
d51bfec61d | ||
|
|
f27ef02273 | ||
|
|
7206d626ee | ||
|
|
a663d235ef | ||
|
|
f2811ea027 | ||
|
|
df11424596 | ||
|
|
af3021913b | ||
|
|
51b6d5e28f | ||
|
|
81c5c81cb5 | ||
|
|
ddf2dd657c | ||
|
|
46bc0452c7 | ||
|
|
4296eb3571 | ||
|
|
0792dc36c2 | ||
|
|
1fb5eadbd2 | ||
|
|
0861be0937 | ||
|
|
4c11f6763e | ||
|
|
375dc92454 | ||
|
|
5667a6aad2 | ||
|
|
bfc7c862e6 | ||
|
|
34b12b7420 | ||
|
|
de2b25b563 | ||
|
|
d76778e3ee | ||
|
|
59b3971d37 | ||
|
|
57a74eabcc | ||
|
|
b6530a3992 | ||
|
|
14e294e574 | ||
|
|
2da6dab403 | ||
|
|
18b8693c43 | ||
|
|
98a3682ac3 | ||
|
|
0b2a055c79 | ||
|
|
91a9e82fc8 | ||
|
|
5fe63a4d9a | ||
|
|
820ca38270 | ||
|
|
833237b2e4 | ||
|
|
c751fd5672 | ||
|
|
f7a34b8bdc | ||
|
|
a2a08ebd21 | ||
|
|
0c9dce1154 | ||
|
|
883c78ea61 | ||
|
|
db3a38751f | ||
|
|
ae3d10d3a7 | ||
|
|
087b908445 | ||
|
|
40ffc3fd44 | ||
|
|
d86f349dad | ||
|
|
19f3f11b8d | ||
|
|
6cafcc1124 | ||
|
|
a7be4044bc | ||
|
|
b566f19538 | ||
|
|
b0b70d1e77 | ||
|
|
5f036641b9 | ||
|
|
5fa0828724 | ||
|
|
fe344462a3 | ||
|
|
51cfe76d65 | ||
|
|
155f686c4f | ||
|
|
739a5f5fdc | ||
|
|
b6108cb9fe | ||
|
|
6f03a9ffe1 | ||
|
|
d6e60cd8d4 | ||
|
|
26a361973c | ||
|
|
b10be3e52e | ||
|
|
2a6886dc70 | ||
|
|
8af4d905f1 | ||
|
|
1de38a13f3 | ||
|
|
df38e5c08b | ||
|
|
8f847906c6 | ||
|
|
c521ca0949 | ||
|
|
dc22307a42 | ||
|
|
e16402a102 | ||
|
|
ef3afd741a | ||
|
|
68e02bc62d | ||
|
|
49e1b12eb1 | ||
|
|
e1b9d7ecdb | ||
|
|
dcf7905bcd | ||
|
|
295a5a376e | ||
|
|
da076cf6bf | ||
|
|
3caef6e1a6 | ||
|
|
d3d8b1c631 | ||
|
|
8a411bd640 | ||
|
|
71a5e2d477 | ||
|
|
ac28cc1cf5 | ||
|
|
ae5b1e9d10 | ||
|
|
856f64a766 | ||
|
|
59199fc907 | ||
|
|
4992977167 | ||
|
|
db447c4676 | ||
|
|
ba8ec56e65 | ||
|
|
d0d4b08a09 | ||
|
|
19b77416da | ||
|
|
6342451937 | ||
|
|
76a80fc974 | ||
|
|
af49a7993a | ||
|
|
63a5f7e348 | ||
|
|
039b579d3e | ||
|
|
be0d7a6444 | ||
|
|
b816c0e507 | ||
|
|
88e7861239 | ||
|
|
0074d6c40a | ||
|
|
fb1b3481d1 | ||
|
|
1eb9c6f993 | ||
|
|
65f2fd2450 | ||
|
|
c1b404952a | ||
|
|
e4e74ff38f | ||
|
|
4581279d23 | ||
|
|
0d5084468e | ||
|
|
cdbea182b4 | ||
|
|
dc0954d653 | ||
|
|
cc05e474cd | ||
|
|
8370c9c1ca | ||
|
|
5dabb3a36f | ||
|
|
86da74908a | ||
|
|
9aee46b3a4 | ||
|
|
be8f60fa8e | ||
|
|
d3ea46ece9 | ||
|
|
cffceaae1f | ||
|
|
5f232c30be | ||
|
|
8351c398bc | ||
|
|
608fc5fb3a | ||
|
|
229aefba2a | ||
|
|
4aba80e58a | ||
|
|
53c2516bae | ||
|
|
a5c9b80add | ||
|
|
a441d733dc | ||
|
|
06f37234dc | ||
|
|
49f41b813c | ||
|
|
bccca235a2 | ||
|
|
ea6a56d9f6 | ||
|
|
8a8d488454 | ||
|
|
f34d663029 | ||
|
|
4018f8d554 | ||
|
|
d649865bce | ||
|
|
3fd4d5cd4b | ||
|
|
5622c33f40 | ||
|
|
93f590c6de | ||
|
|
c9863dc225 | ||
|
|
45f59e7eca | ||
|
|
b6e3c6d718 | ||
|
|
0af83dd1b6 | ||
|
|
2fe3a7947e | ||
|
|
c7c05173b5 | ||
|
|
127b8c0b2d | ||
|
|
95e3ecfd3c | ||
|
|
46f7d07889 | ||
|
|
6fd0adda52 | ||
|
|
68a433d9bc | ||
|
|
17044317ba | ||
|
|
031b2e0683 | ||
|
|
8385eeeab2 | ||
|
|
24ad43a208 | ||
|
|
a3fc812539 | ||
|
|
3f6defe594 | ||
|
|
41ecb2c160 | ||
|
|
e5517c343d | ||
|
|
e56e9acf79 | ||
|
|
0b14c340f2 | ||
|
|
1274959434 | ||
|
|
02bb5db544 | ||
|
|
f396c58b5f | ||
|
|
fa37f5c2bc | ||
|
|
8a2097e7b9 | ||
|
|
c07aec320a | ||
|
|
ba2d8e8201 | ||
|
|
9e6e4095a8 | ||
|
|
d8618d2447 | ||
|
|
19ee6560a9 | ||
|
|
bc3eb7845d | ||
|
|
72277726a3 | ||
|
|
18ddb9df4a | ||
|
|
d247e4791a | ||
|
|
49a3a7d7c7 | ||
|
|
9ce161679a | ||
|
|
727de34879 | ||
|
|
8b71a1f305 | ||
|
|
d17d831205 | ||
|
|
25669938fd | ||
|
|
0c3f5cde12 | ||
|
|
843b9d45f4 | ||
|
|
494e100b0f | ||
|
|
02e518381c | ||
|
|
1d4f6ab19d | ||
|
|
6ae83c25ed | ||
|
|
e83d441d42 | ||
|
|
44df9283fe | ||
|
|
23fca8019b | ||
|
|
4d72d375f2 | ||
|
|
210e736bf5 | ||
|
|
601c4fb3c0 | ||
|
|
fbe39db773 | ||
|
|
4927e48bf3 | ||
|
|
3feba08965 | ||
|
|
c263c8b8ca | ||
|
|
23bd4675fd | ||
|
|
99c022cb00 | ||
|
|
86cb56757e | ||
|
|
89cb1f437c | ||
|
|
df36c97bb5 | ||
|
|
ecb13d36f3 | ||
|
|
df1bc519b7 | ||
|
|
9c01989370 | ||
|
|
22a5fadc13 | ||
|
|
1bbb09a7ef | ||
|
|
f00c27b4f3 | ||
|
|
138323b79d | ||
|
|
0456cacd79 | ||
|
|
c273c8f71b | ||
|
|
4b0122093a | ||
|
|
010fccb4fa | ||
|
|
ebaa98fa7a | ||
|
|
10e02b0031 | ||
|
|
44fa4aad88 | ||
|
|
d16b2bd369 | ||
|
|
1ff3a0f8b6 | ||
|
|
6324ac9cac | ||
|
|
df567efd37 | ||
|
|
990ce6ed05 | ||
|
|
48f4c1e9e1 | ||
|
|
acd83a2998 | ||
|
|
1eee5c849e | ||
|
|
6c1073db92 | ||
|
|
5b457a1663 | ||
|
|
5a7fd3f316 | ||
|
|
d16befd1fd | ||
|
|
c4f4fb48a4 | ||
|
|
cb57d8e54c | ||
|
|
baa571018e | ||
|
|
8ca5035c42 | ||
|
|
789e0e45d5 | ||
|
|
56364f1c70 | ||
|
|
a72ff9ea7f | ||
|
|
90b733801e | ||
|
|
73549a0529 | ||
|
|
7715583b14 | ||
|
|
3a87067348 | ||
|
|
557b11aca7 | ||
|
|
324d5a04c6 | ||
|
|
de2d11125b | ||
|
|
5e6ab82094 | ||
|
|
ad06b8ca67 | ||
|
|
f522cd66a0 | ||
|
|
b5b235c75f | ||
|
|
fce4e8cedb | ||
|
|
ba73b6d914 | ||
|
|
289df252b5 | ||
|
|
c28cac8479 | ||
|
|
2c78925acb | ||
|
|
154d47565d | ||
|
|
b6d216b794 | ||
|
|
0b2b076712 | ||
|
|
ef6bd0e7a9 | ||
|
|
332a48e6a1 | ||
|
|
748521e4fe | ||
|
|
3d72e24bb8 | ||
|
|
43cccb0a73 | ||
|
|
3d5d78f7a7 | ||
|
|
079a4f65d6 | ||
|
|
547c1f57d9 | ||
|
|
b808a4e087 | ||
|
|
d241c21c28 | ||
|
|
65d22c08b7 | ||
|
|
473553b3eb | ||
|
|
440a32b697 | ||
|
|
ef78b9d9ea | ||
|
|
4d5f3d42e1 | ||
|
|
55d732cce8 | ||
|
|
30d1c707a9 | ||
|
|
d706125b15 | ||
|
|
35f91945b7 | ||
|
|
fe65715b97 | ||
|
|
ccd27870a7 | ||
|
|
acf6cc0527 | ||
|
|
d72f7e9109 | ||
|
|
b7f67c0adf | ||
|
|
9ffa7bcd4d | ||
|
|
3b99b11849 | ||
|
|
6e0a43b570 | ||
|
|
45f3a97997 | ||
|
|
989390bc41 | ||
|
|
3bc026a557 | ||
|
|
f977a54694 | ||
|
|
d60eb67c2e | ||
|
|
8468e70cba | ||
|
|
926a52b33d | ||
|
|
1284d78599 | ||
|
|
b01973f95f | ||
|
|
ec0466ed73 | ||
|
|
1b3502bd5a | ||
|
|
556baae087 | ||
|
|
f9daa27a5d | ||
|
|
b4d1d98868 | ||
|
|
5195264a20 | ||
|
|
f932638054 | ||
|
|
b80e2b7e00 | ||
|
|
188b06b7bb | ||
|
|
5f0ac9a1f3 | ||
|
|
1f8840cab0 | ||
|
|
f241e44da0 | ||
|
|
1d543ccf9a | ||
|
|
199c6b07a7 | ||
|
|
3bab989aad | ||
|
|
30a2f6ac71 | ||
|
|
4106c646f9 | ||
|
|
a92d28988a | ||
|
|
c930d8e30f | ||
|
|
376a730146 | ||
|
|
31e16f2620 | ||
|
|
dbd061c44b | ||
|
|
60c0e5e97a | ||
|
|
2855f89e53 | ||
|
|
37b012fcbd | ||
|
|
4c5f12200d | ||
|
|
2857c16c61 | ||
|
|
7cc71deec7 | ||
|
|
ca4b4cde61 | ||
|
|
2c95b9519c | ||
|
|
f02b8f4a15 | ||
|
|
fc75b94524 | ||
|
|
71b2b73881 | ||
|
|
7ebbb499e0 | ||
|
|
10b7907fa2 | ||
|
|
417fd44cb2 | ||
|
|
22b10e20e4 | ||
|
|
78d92f4425 | ||
|
|
efd9c6ef45 | ||
|
|
acf3bf0959 | ||
|
|
49647c6267 | ||
|
|
0569b2bab3 | ||
|
|
badb5c1fba | ||
|
|
391935c90f | ||
|
|
9808f83913 | ||
|
|
ae33a89844 | ||
|
|
e0697eefa0 | ||
|
|
b50851726d | ||
|
|
55067c55a7 | ||
|
|
8d5612219c | ||
|
|
7bb0c588c1 | ||
|
|
d5857730d1 | ||
|
|
d2133da3ee | ||
|
|
c40d276770 | ||
|
|
77433f7e1d | ||
|
|
6ac719d74c | ||
|
|
f9bfd8adec | ||
|
|
1e91e1bd96 | ||
|
|
88d18fd5f3 | ||
|
|
98ae715905 | ||
|
|
e3ca1f09de | ||
|
|
8122c63ebc | ||
|
|
76308d5155 | ||
|
|
f5210c893e | ||
|
|
7c54065ed7 | ||
|
|
dd9836ea5f | ||
|
|
ac6cf3ef96 | ||
|
|
a87c3f28a2 | ||
|
|
afac8c384d | ||
|
|
b628349dc7 | ||
|
|
a4dc7a938a | ||
|
|
9dee4b1a7a | ||
|
|
2addea18ff | ||
|
|
8bbe71c8a2 | ||
|
|
bc9d3c5936 | ||
|
|
7db51e9029 | ||
|
|
a421ebf01c | ||
|
|
2e07e93a42 | ||
|
|
d9a8a7e0ac | ||
|
|
898fb3c6a8 | ||
|
|
a8aa035065 | ||
|
|
302651620b | ||
|
|
3f6bb4a929 | ||
|
|
ee49a7ed52 | ||
|
|
e4f92ad1a1 | ||
|
|
15affdbfda | ||
|
|
6886d6213a | ||
|
|
79dd4f73fe | ||
|
|
b536b73c97 | ||
|
|
a8ef8bdcb8 | ||
|
|
45538857cf | ||
|
|
2bf757a657 | ||
|
|
bbcfe56cfd | ||
|
|
360118634d | ||
|
|
9295bb42d6 | ||
|
|
505121f394 | ||
|
|
309e8bd183 | ||
|
|
801e4ad363 | ||
|
|
58cf46f435 | ||
|
|
1fca07546c | ||
|
|
9d2cb53cff | ||
|
|
4e95e32791 | ||
|
|
89fea30a3b | ||
|
|
e283c166de | ||
|
|
12bdd8742b | ||
|
|
38467b2e30 | ||
|
|
e46ac74ba4 | ||
|
|
07b390fccc | ||
|
|
c1b807dbff | ||
|
|
dc452feadd | ||
|
|
064f64f06d | ||
|
|
260e1d77f5 | ||
|
|
1eca55a386 | ||
|
|
c2602135ab | ||
|
|
b72d1af50a | ||
|
|
3e61bdc431 | ||
|
|
545592c472 | ||
|
|
de627a9b7c | ||
|
|
5fe4784cbc | ||
|
|
ff4f4255b3 | ||
|
|
c00f871b95 | ||
|
|
3a99010cdb | ||
|
|
d9246910b4 | ||
|
|
387bb29cbd |
@@ -12,7 +12,7 @@
|
|||||||
BasedOnStyle: WebKit
|
BasedOnStyle: WebKit
|
||||||
|
|
||||||
Standard: Cpp11
|
Standard: Cpp11
|
||||||
ColumnLimit: 0
|
ColumnLimit: 120
|
||||||
|
|
||||||
# Disable reflow of qdoc comments: indentation rules are different.
|
# Disable reflow of qdoc comments: indentation rules are different.
|
||||||
# Translation comments are also excluded
|
# Translation comments are also excluded
|
||||||
@@ -61,3 +61,5 @@ ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCH
|
|||||||
MaxEmptyLinesToKeep: 2
|
MaxEmptyLinesToKeep: 2
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Checks: '-*,
|
|||||||
modernize-use-nodiscard,
|
modernize-use-nodiscard,
|
||||||
modernize-use-equals-default,
|
modernize-use-equals-default,
|
||||||
modernize-use-noexcept,
|
modernize-use-noexcept,
|
||||||
modernize-user-override,
|
modernize-use-override,
|
||||||
modernize-use-nullptr,
|
modernize-use-nullptr,
|
||||||
modernize-use-transparent-functors,
|
modernize-use-transparent-functors,
|
||||||
modernize-use-uncaught-exceptions,
|
modernize-use-uncaught-exceptions,
|
||||||
|
|||||||
32
.drone.yml
@@ -1,17 +1,17 @@
|
|||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: qt-5.12
|
name: qt-5.15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: cmake
|
- name: cmake
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
commands:
|
commands:
|
||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address ../src
|
- cmake -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror ../src
|
||||||
- name: compile
|
- name: compile
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
@@ -19,7 +19,7 @@ steps:
|
|||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- make -j$(nproc)
|
- make -j$(nproc)
|
||||||
- name: test
|
- name: test
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
@@ -27,7 +27,7 @@ steps:
|
|||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- useradd -m -s /bin/bash test
|
- useradd -m -s /bin/bash test
|
||||||
- chown -R test:test .
|
- chown -R test:test .
|
||||||
- su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test
|
- su -c 'ASAN_OPTIONS=detect_leaks=0 xvfb-run ctest --output-on-failure' test
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
@@ -43,27 +43,27 @@ trigger:
|
|||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: qt-5.12-clang
|
name: qt-5.15-clang
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: cmake
|
- name: cmake
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
commands:
|
commands:
|
||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clazy -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address ../src
|
- cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 -DCMAKE_BUILD_TYPE=Debug -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DECM_ENABLE_SANITIZERS=address -DCMAKE_CXX_FLAGS=-Werror ../src
|
||||||
- name: compile
|
- name: compile
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
commands:
|
commands:
|
||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- ninja 2>1 | /drone/src/admin/linux/count_compiler_warnings.py /drone/src
|
- ninja
|
||||||
- name: test
|
- name: test
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
@@ -71,9 +71,9 @@ steps:
|
|||||||
- cd /drone/build
|
- cd /drone/build
|
||||||
- useradd -m -s /bin/bash test
|
- useradd -m -s /bin/bash test
|
||||||
- chown -R test:test .
|
- chown -R test:test .
|
||||||
- su -c 'ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure' test
|
- su -c 'ASAN_OPTIONS=detect_leaks=0 xvfb-run ctest --output-on-failure' test
|
||||||
- name: clang-tidy
|
- name: clang-tidy
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
volumes:
|
volumes:
|
||||||
- name: build
|
- name: build
|
||||||
path: /drone/build
|
path: /drone/build
|
||||||
@@ -98,14 +98,14 @@ name: AppImage
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
image: ghcr.io/nextcloud/continuous-integration-client-appimage:client-appimage-1
|
image: ghcr.io/nextcloud/continuous-integration-client-appimage:client-appimage-3
|
||||||
environment:
|
environment:
|
||||||
CI_UPLOAD_GIT_TOKEN:
|
CI_UPLOAD_GIT_TOKEN:
|
||||||
from_secret: CI_UPLOAD_GIT_TOKEN
|
from_secret: CI_UPLOAD_GIT_TOKEN
|
||||||
CI_UPLOAD_GIT_USERNAME:
|
CI_UPLOAD_GIT_USERNAME:
|
||||||
from_secret: CI_UPLOAD_GIT_USERNAME
|
from_secret: CI_UPLOAD_GIT_USERNAME
|
||||||
commands:
|
commands:
|
||||||
- /bin/bash -c "./admin/linux/build-appimage.sh"
|
- BUILDNR=$DRONE_BUILD_NUMBER VERSION_SUFFIX=$DRONE_PULL_REQUEST BUILD_UPDATER=ON DESKTOP_CLIENT_ROOT=$DRONE_WORKSPACE /bin/bash -c "./admin/linux/build-appimage.sh"
|
||||||
- /bin/bash -c "./admin/linux/upload-appimage.sh" || echo "Upload failed, however this is an optional step."
|
- /bin/bash -c "./admin/linux/upload-appimage.sh" || echo "Upload failed, however this is an optional step."
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
|||||||
46
.github/workflows/command-rebase.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# This workflow is provided via the organization template repository
|
||||||
|
#
|
||||||
|
# https://github.com/nextcloud/.github
|
||||||
|
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||||
|
|
||||||
|
name: Rebase command
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: created
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rebase:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# On pull requests and if the comment starts with `/rebase`
|
||||||
|
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Add reaction on start
|
||||||
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||||
|
repository: ${{ github.event.repository.full_name }}
|
||||||
|
comment-id: ${{ github.event.comment.id }}
|
||||||
|
reaction-type: "+1"
|
||||||
|
|
||||||
|
- name: Checkout the latest code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||||
|
|
||||||
|
- name: Automatic Rebase
|
||||||
|
uses: cirrus-actions/rebase@1.5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
|
||||||
|
|
||||||
|
- name: Add reaction on failure
|
||||||
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||||
|
repository: ${{ github.event.repository.full_name }}
|
||||||
|
comment-id: ${{ github.event.comment.id }}
|
||||||
|
reaction-type: "-1"
|
||||||
18
.github/workflows/rebase.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
name: Automatic Rebase
|
|
||||||
jobs:
|
|
||||||
rebase:
|
|
||||||
name: Rebase
|
|
||||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout the latest code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Automatic Rebase
|
|
||||||
uses: cirrus-actions/rebase@1.3.1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
50
.github/workflows/sonarcloud.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: SonarCloud analysis
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||||
|
env:
|
||||||
|
SONAR_SERVER_URL: "https://sonarcloud.io"
|
||||||
|
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
|
|
||||||
|
- name: Restore cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /cache
|
||||||
|
key: ${{ runner.os }}
|
||||||
|
|
||||||
|
- name: Run build-wrapper
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10 -DBUILD_UPDATER=ON -DBUILD_TESTING=1 -DBUILD_COVERAGE=ON
|
||||||
|
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make -j 2
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
useradd -m -s /bin/bash test
|
||||||
|
chown -R test:test .
|
||||||
|
su -c 'xvfb-run ctest --output-on-failure --output-junit testResult.xml' test
|
||||||
|
- name: Generate coverage report
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
su -c 'ctest -T Coverage' test
|
||||||
|
- name: Run sonar-scanner
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
run: |
|
||||||
|
cp sonar-project.properties build
|
||||||
|
cd build
|
||||||
|
sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
|
||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[bg_BG]=@APPLICATION_ICON_NAME@
|
Icon[bg_BG]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
|
||||||
Comment[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
|
Comment[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
|
||||||
GenericName[bg_BG]=Синхронизиране на папка
|
GenericName[bg_BG]=Синхронизиране на папка
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[cy_GB]=@APPLICATION_ICON_NAME@
|
Icon[cy_GB]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
|
||||||
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
|
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
|
||||||
GenericName[cy_GB]=Cydweddu Ffolder
|
GenericName[cy_GB]=Cydweddu Ffolder
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[en_GB]=@APPLICATION_ICON_NAME@
|
Icon[en_GB]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[en_GB]=@APPLICATION_NAME@ Desktop
|
||||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||||
GenericName[en_GB]=Folder Sync
|
GenericName[en_GB]=Folder Sync
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[hr]=@APPLICATION_ICON_NAME@
|
Icon[hr]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[hr]=@APPLICATION_NAME@ Desktop
|
||||||
Comment[hr]=@APPLICATION_NAME@ klijent za sinkronizaciju računala
|
Comment[hr]=@APPLICATION_NAME@ klijent za sinkronizaciju računala
|
||||||
GenericName[hr]=Sinkronizacija mapa
|
GenericName[hr]=Sinkronizacija mapa
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[ko]=@APPLICATION_ICON_NAME@
|
Icon[ko]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[ko]=@APPLICATION_NAME@ 데스크탑
|
||||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||||
GenericName[ko]=폴더 동기화
|
GenericName[ko]=폴더 동기화
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[mk]=@APPLICATION_ICON_NAME@
|
Icon[mk]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[mk]=@APPLICATION_NAME@ Десктоп
|
||||||
Comment[mk]=@APPLICATION_NAME@ клиент за синхронизација на компјутер
|
Comment[mk]=@APPLICATION_NAME@ клиент за синхронизација на компјутер
|
||||||
GenericName[mk]=Папка за синхронизација
|
GenericName[mk]=Папка за синхронизација
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[ro]=@APPLICATION_ICON_NAME@
|
Icon[ro]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[ro]=@Numele_aplicației@ Client de sincronizare pentru PC
|
||||||
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
|
Comment[ro]=@APPLICATION_NAME@ client de sincronizare pentru desktop
|
||||||
GenericName[ro]=Sincronizare director
|
GenericName[ro]=Sincronizare director
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[ru]=@APPLICATION_ICON_NAME@
|
Icon[ru]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[ru]=@APPLICATION_NAME@ Desktop
|
||||||
Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК
|
Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК
|
||||||
GenericName[ru]=Синхронизация папок
|
GenericName[ru]=Синхронизация папок
|
||||||
|
|||||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
|||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
Icon[sc]=@NÙMENE_ICONA_APLICATZIONE@
|
Icon[sc]=@NÙMENE_ICONA_APLICATZIONE@
|
||||||
|
Name[sc]=@NÙMENE_APLICATZIONE@ Iscrivania
|
||||||
Comment[sc]=@NÙMENE_APLICATZIONE@ cliente de sincronizatzione iscrivania
|
Comment[sc]=@NÙMENE_APLICATZIONE@ cliente de sincronizatzione iscrivania
|
||||||
GenericName[sc]=Sincronizadore de cartellas
|
GenericName[sc]=Sincronizadore de cartellas
|
||||||
|
|||||||
27
.tx/nextcloud.client-desktop/th_translation
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Categories=Utility;X-SuSE-SyncUtility;
|
||||||
|
Type=Application
|
||||||
|
Exec=@APPLICATION_EXECUTABLE@
|
||||||
|
Name=@APPLICATION_NAME@ Desktop
|
||||||
|
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||||
|
GenericName=Folder Sync
|
||||||
|
Icon=@APPLICATION_ICON_NAME@
|
||||||
|
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||||
|
X-GNOME-Autostart-Delay=3
|
||||||
|
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
|
||||||
|
Actions=Quit;
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
|
||||||
|
|
||||||
|
[Desktop Action Quit]
|
||||||
|
Exec=@APPLICATION_EXECUTABLE@ --quit
|
||||||
|
Name=Quit @APPLICATION_NAME@
|
||||||
|
Icon=@APPLICATION_EXECUTABLE@
|
||||||
|
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
Icon[th_TH]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[th_TH]=@APPLICATION_NAME@ เดสก์ท็อป
|
||||||
|
Comment[th_TH]=ไคลเอ็นต์ซิงโครไนซ์ @APPLICATION_NAME@ บนเดสก์ท็อป
|
||||||
|
GenericName[th_TH]=ซิงค์โฟลเดอร์
|
||||||
27
.tx/nextcloud.client-desktop/vi_translation
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Categories=Utility;X-SuSE-SyncUtility;
|
||||||
|
Type=Application
|
||||||
|
Exec=@APPLICATION_EXECUTABLE@
|
||||||
|
Name=@APPLICATION_NAME@ Desktop
|
||||||
|
Comment=@APPLICATION_NAME@ desktop synchronization client
|
||||||
|
GenericName=Folder Sync
|
||||||
|
Icon=@APPLICATION_ICON_NAME@
|
||||||
|
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||||
|
X-GNOME-Autostart-Delay=3
|
||||||
|
MimeType=application/vnd.@APPLICATION_EXECUTABLE@;
|
||||||
|
Actions=Quit;
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
|
||||||
|
|
||||||
|
[Desktop Action Quit]
|
||||||
|
Exec=@APPLICATION_EXECUTABLE@ --quit
|
||||||
|
Name=Quit @APPLICATION_NAME@
|
||||||
|
Icon=@APPLICATION_EXECUTABLE@
|
||||||
|
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
Icon[vi]=@APPLICATION_ICON_NAME@
|
||||||
|
Name[vi]=@APPLICATION_NAME@ Máy tính
|
||||||
|
Comment[vi]=Ứng dụng đồng bộ @APPLICATION_NAME@ cho máy tính
|
||||||
|
GenericName[vi]=Đồng bộ thư mục
|
||||||
@@ -36,15 +36,20 @@ endif()
|
|||||||
|
|
||||||
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
||||||
|
|
||||||
|
include(ECMCoverageOption)
|
||||||
|
|
||||||
if(NOT CRASHREPORTER_EXECUTABLE)
|
if(NOT CRASHREPORTER_EXECUTABLE)
|
||||||
set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter")
|
set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(synclib_NAME "${APPLICATION_EXECUTABLE}sync")
|
|
||||||
set(csync_NAME "${APPLICATION_EXECUTABLE}_csync")
|
|
||||||
|
|
||||||
include(Warnings)
|
include(Warnings)
|
||||||
|
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
add_compile_options(-fdiagnostics-color=always)
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
add_compile_options(-fcolor-diagnostics)
|
||||||
|
endif()
|
||||||
|
|
||||||
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
||||||
# For config.h
|
# For config.h
|
||||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
@@ -72,9 +77,9 @@ include(GetGitRevisionDescription)
|
|||||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
|
-DQT_DISABLE_DEPRECATED_BEFORE=0x000000
|
||||||
-DQT_USE_QSTRINGBUILDER
|
-DQT_USE_QSTRINGBUILDER
|
||||||
-DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output
|
-DQT_MESSAGELOGCONTEXT #enable function name and line number in debug output
|
||||||
-DQT_DEPRECATED_WARNINGS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# if we cannot get it from git, directly try .tag (packages)
|
# if we cannot get it from git, directly try .tag (packages)
|
||||||
@@ -91,30 +96,15 @@ endif()
|
|||||||
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
|
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
|
||||||
|
|
||||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||||
set(DATADIR ${DATA_INSTALL_DIR})
|
set(SHAREDIR ${CMAKE_INSTALL_DATADIR})
|
||||||
if(WIN32)
|
|
||||||
set(DATADIR "share")
|
|
||||||
endif(WIN32)
|
|
||||||
set(SHAREDIR ${DATADIR})
|
|
||||||
|
|
||||||
#####
|
# Build MacOS app bundle if wished
|
||||||
## handle BUILD_OWNCLOUD_OSX_BUNDLE
|
if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
# BUILD_OWNCLOUD_OSX_BUNDLE was not initialized OR set to true on OSX
|
message(STATUS "Build MacOS app bundle")
|
||||||
if(APPLE AND (NOT DEFINED BUILD_OWNCLOUD_OSX_BUNDLE OR BUILD_OWNCLOUD_OSX_BUNDLE))
|
|
||||||
set(BUILD_OWNCLOUD_OSX_BUNDLE ON)
|
|
||||||
set(OWNCLOUD_OSX_BUNDLE "${APPLICATION_NAME}.app")
|
set(OWNCLOUD_OSX_BUNDLE "${APPLICATION_NAME}.app")
|
||||||
set(LIB_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
|
set(LIB_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
|
||||||
set(BIN_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
|
set(BIN_INSTALL_DIR "${APPLICATION_NAME}.app/Contents/MacOS")
|
||||||
|
|
||||||
# BUILD_OWNCLOUD_OSX_BUNDLE was disabled on OSX
|
|
||||||
elseif(APPLE AND NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
|
||||||
message(FATAL_ERROR "Building in non-bundle mode on OSX is currently not supported. Comment this error out if you want to work on/test it.")
|
|
||||||
|
|
||||||
# any other platform
|
|
||||||
else()
|
|
||||||
set(BUILD_OWNCLOUD_OSX_BUNDLE OFF)
|
|
||||||
endif()
|
endif()
|
||||||
#####
|
|
||||||
|
|
||||||
# this option removes Http authentication, keychain, shibboleth etc and is intended for
|
# this option removes Http authentication, keychain, shibboleth etc and is intended for
|
||||||
# external authentication mechanisms
|
# external authentication mechanisms
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ set( APPLICATION_SERVER_URL "" CACHE STRING "URL for the server to use. If enter
|
|||||||
set( APPLICATION_SERVER_URL_ENFORCE ON ) # If set and APPLICATION_SERVER_URL is defined, the server can only connect to the pre-defined URL
|
set( APPLICATION_SERVER_URL_ENFORCE ON ) # If set and APPLICATION_SERVER_URL is defined, the server can only connect to the pre-defined URL
|
||||||
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
|
set( APPLICATION_REV_DOMAIN "com.nextcloud.desktopclient" )
|
||||||
set( APPLICATION_VIRTUALFILE_SUFFIX "nextcloud" CACHE STRING "Virtual file suffix (not including the .)")
|
set( APPLICATION_VIRTUALFILE_SUFFIX "nextcloud" CACHE STRING "Virtual file suffix (not including the .)")
|
||||||
|
set( APPLICATION_OCSP_STAPLING_ENABLED OFF )
|
||||||
|
set( APPLICATION_FORBID_BAD_SSL OFF )
|
||||||
|
set( APPLICATION_LOGIN_WITH_SYSTEM_USERNAME OFF )
|
||||||
|
|
||||||
set( LINUX_PACKAGE_SHORTNAME "nextcloud" )
|
set( LINUX_PACKAGE_SHORTNAME "nextcloud" )
|
||||||
set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}")
|
set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}")
|
||||||
@@ -32,6 +35,7 @@ option( BUILD_UPDATER "Build updater" OFF )
|
|||||||
|
|
||||||
option( WITH_PROVIDERS "Build with providers list" ON )
|
option( WITH_PROVIDERS "Build with providers list" ON )
|
||||||
|
|
||||||
|
option( ENFORCE_VIRTUAL_FILES_SYNC_FOLDER "Enforce use of virtual files sync folder when available" OFF )
|
||||||
|
|
||||||
## Theming options
|
## Theming options
|
||||||
set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color")
|
set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ The :computer: Nextcloud Desktop Client is a tool to synchronize files from Next
|
|||||||
with your computer.
|
with your computer.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://nextcloud.com/wp-content/themes/next/assets/img/clients/desktop/macsettings.png?x16328" alt="Desktop Client on Mac OS]">
|
<img src="doc/images/main_dialog_christine.png" alt="Desktop Client on Windows" width="450">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## :blue_heart: :tada: Contributing
|
## :blue_heart: :tada: Contributing
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
set( MIRALL_VERSION_MAJOR 3 )
|
set( MIRALL_VERSION_MAJOR 3 )
|
||||||
set( MIRALL_VERSION_MINOR 2 )
|
set( MIRALL_VERSION_MINOR 4 )
|
||||||
set( MIRALL_VERSION_PATCH 81 )
|
set( MIRALL_VERSION_PATCH 0 )
|
||||||
set( MIRALL_VERSION_YEAR 2021 )
|
set( MIRALL_VERSION_YEAR 2021 )
|
||||||
set( MIRALL_SOVERSION 0 )
|
set( MIRALL_SOVERSION 0 )
|
||||||
|
|
||||||
# Minimum supported server version according to https://docs.nextcloud.com/server/latest/admin_manual/release_schedule.html
|
# Minimum supported server version according to https://docs.nextcloud.com/server/latest/admin_manual/release_schedule.html
|
||||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MAJOR 19)
|
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MAJOR 16)
|
||||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MINOR 0)
|
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MINOR 0)
|
||||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_PATCH 0)
|
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_PATCH 0)
|
||||||
|
|
||||||
|
|||||||
@@ -2,78 +2,88 @@
|
|||||||
|
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
mkdir /app
|
export APPNAME=${APPNAME:-nextcloud}
|
||||||
mkdir /build
|
export BUILD_UPDATER=${BUILD_UPDATER:-OFF}
|
||||||
|
export BUILDNR=${BUILDNR:-0000}
|
||||||
|
export DESKTOP_CLIENT_ROOT=${DESKTOP_CLIENT_ROOT:-/home/user}
|
||||||
|
|
||||||
|
#Set Qt-5.15
|
||||||
|
export QT_BASE_DIR=/opt/qt5.15
|
||||||
|
|
||||||
#Set Qt-5.12
|
|
||||||
export QT_BASE_DIR=/opt/qt5.12.10
|
|
||||||
export QTDIR=$QT_BASE_DIR
|
export QTDIR=$QT_BASE_DIR
|
||||||
export PATH=$QT_BASE_DIR/bin:$PATH
|
export PATH=$QT_BASE_DIR/bin:$PATH
|
||||||
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
|
||||||
export PKG_CONFIG_PATH=$QT_BASE_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
|
export PKG_CONFIG_PATH=$QT_BASE_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||||
|
|
||||||
#Set APPID for .desktop file processing
|
# Set defaults
|
||||||
export LINUX_APPLICATION_ID=com.nextcloud.desktopclient.nextcloud
|
|
||||||
|
|
||||||
#set defaults
|
|
||||||
export SUFFIX=${DRONE_PULL_REQUEST:=master}
|
export SUFFIX=${DRONE_PULL_REQUEST:=master}
|
||||||
if [ $SUFFIX != "master" ]; then
|
if [ $SUFFIX != "master" ]; then
|
||||||
SUFFIX="PR-$SUFFIX"
|
SUFFIX="PR-$SUFFIX"
|
||||||
fi
|
fi
|
||||||
|
if [ "$BUILD_UPDATER" != "OFF" ]; then
|
||||||
|
BUILD_UPDATER=ON
|
||||||
|
fi
|
||||||
|
|
||||||
#QtKeyChain v0.10.0
|
mkdir /app
|
||||||
cd /build
|
|
||||||
|
# QtKeyChain
|
||||||
git clone https://github.com/frankosterfeld/qtkeychain.git
|
git clone https://github.com/frankosterfeld/qtkeychain.git
|
||||||
cd qtkeychain
|
cd qtkeychain
|
||||||
git checkout v0.10.0
|
git checkout v0.10.0
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -D CMAKE_INSTALL_PREFIX=/usr ../
|
cmake -G Ninja -D CMAKE_INSTALL_PREFIX=/app/usr ..
|
||||||
make -j4
|
cmake --build . --target all
|
||||||
make install
|
cmake --build . --target install
|
||||||
|
|
||||||
#Build client
|
|
||||||
cd /build
|
# Build client
|
||||||
mkdir build-client
|
mkdir build-client
|
||||||
cd build-client
|
cd build-client
|
||||||
cmake -D CMAKE_INSTALL_PREFIX=/usr \
|
cmake \
|
||||||
|
-G Ninja \
|
||||||
|
-D CMAKE_INSTALL_PREFIX=/app/usr \
|
||||||
-D BUILD_TESTING=OFF \
|
-D BUILD_TESTING=OFF \
|
||||||
-D BUILD_UPDATER=ON \
|
-D BUILD_UPDATER=$BUILD_UPDATER \
|
||||||
-DMIRALL_VERSION_SUFFIX=PR-$DRONE_PULL_REQUEST \
|
-D MIRALL_VERSION_BUILD=$BUILDNR \
|
||||||
-DMIRALL_VERSION_BUILD=$DRONE_BUILD_NUMBER \
|
-D MIRALL_VERSION_SUFFIX="$VERSION_SUFFIX" \
|
||||||
$DRONE_WORKSPACE
|
${DESKTOP_CLIENT_ROOT}
|
||||||
make -j4
|
cmake --build . --target all
|
||||||
make DESTDIR=/app install
|
cmake --build . --target install
|
||||||
|
|
||||||
# Move stuff around
|
# Move stuff around
|
||||||
cd /app
|
cd /app
|
||||||
|
|
||||||
mv ./usr/lib/x86_64-linux-gnu/* ./usr/lib/
|
mv usr/lib/x86_64-linux-gnu/* usr/lib/
|
||||||
rm -rf ./usr/lib/cmake
|
|
||||||
rm -rf ./usr/include
|
|
||||||
rm -rf ./usr/mkspecs
|
|
||||||
rm -rf ./usr/lib/x86_64-linux-gnu/
|
|
||||||
|
|
||||||
# Don't bundle nextcloudcmd as we don't run it anyway
|
mkdir usr/plugins
|
||||||
rm -rf ./usr/bin/nextcloudcmd
|
mv usr/lib/${APPNAME}sync_vfs_suffix.so usr/plugins
|
||||||
|
mv usr/lib/${APPNAME}sync_vfs_xattr.so usr/plugins
|
||||||
|
|
||||||
|
|
||||||
|
rm -rf usr/lib/cmake
|
||||||
|
rm -rf usr/include
|
||||||
|
rm -rf usr/mkspecs
|
||||||
|
rm -rf usr/lib/x86_64-linux-gnu/
|
||||||
|
|
||||||
# Don't bundle the explorer extentions as we can't do anything with them in the AppImage
|
# Don't bundle the explorer extentions as we can't do anything with them in the AppImage
|
||||||
rm -rf ./usr/share/caja-python/
|
rm -rf usr/share/caja-python/
|
||||||
rm -rf ./usr/share/nautilus-python/
|
rm -rf usr/share/nautilus-python/
|
||||||
rm -rf ./usr/share/nemo-python/
|
rm -rf usr/share/nemo-python/
|
||||||
|
|
||||||
# Move sync exclude to right location
|
# Move sync exclude to right location
|
||||||
mv ./etc/Nextcloud/sync-exclude.lst ./usr/bin/
|
mv usr/etc/*/sync-exclude.lst usr/bin/
|
||||||
rm -rf ./etc
|
rm -rf etc
|
||||||
|
|
||||||
DESKTOP_FILE=/app/usr/share/applications/${LINUX_APPLICATION_ID}.desktop
|
# com.nextcloud.desktopclient.nextcloud.desktop
|
||||||
|
DESKTOP_FILE=$(ls /app/usr/share/applications/*.desktop)
|
||||||
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
|
sed -i -e 's|Icon=nextcloud|Icon=Nextcloud|g' ${DESKTOP_FILE} # Bug in desktop file?
|
||||||
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
|
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
|
||||||
|
|
||||||
|
|
||||||
# Because distros need to get their shit together
|
# Because distros need to get their shit together
|
||||||
cp -R /lib/x86_64-linux-gnu/libssl.so* ./usr/lib/
|
cp -R /usr/lib/x86_64-linux-gnu/libssl.so* ./usr/lib/
|
||||||
cp -R /lib/x86_64-linux-gnu/libcrypto.so* ./usr/lib/
|
cp -R /usr/lib/x86_64-linux-gnu/libcrypto.so* ./usr/lib/
|
||||||
cp -P /usr/local/lib/libssl.so* ./usr/lib/
|
cp -P /usr/local/lib/libssl.so* ./usr/lib/
|
||||||
cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
|
cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
|
||||||
|
|
||||||
@@ -81,19 +91,23 @@ cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
|
|||||||
cp -P -r /usr/lib/x86_64-linux-gnu/nss ./usr/lib/
|
cp -P -r /usr/lib/x86_64-linux-gnu/nss ./usr/lib/
|
||||||
|
|
||||||
# Use linuxdeployqt to deploy
|
# Use linuxdeployqt to deploy
|
||||||
cd /build
|
wget --ca-directory=/etc/ssl/certs -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||||
wget --ca-directory=/etc/ssl/certs/ -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
|
||||||
chmod a+x linuxdeployqt*.AppImage
|
chmod a+x linuxdeployqt*.AppImage
|
||||||
./linuxdeployqt-continuous-x86_64.AppImage --appimage-extract
|
./linuxdeployqt-continuous-x86_64.AppImage --appimage-extract
|
||||||
rm ./linuxdeployqt-continuous-x86_64.AppImage
|
rm ./linuxdeployqt-continuous-x86_64.AppImage
|
||||||
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
||||||
export LD_LIBRARY_PATH=/app/usr/lib/
|
export LD_LIBRARY_PATH=/app/usr/lib/
|
||||||
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=$DRONE_WORKSPACE/src/gui
|
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=${DESKTOP_CLIENT_ROOT}/src/gui
|
||||||
|
|
||||||
# Set origin
|
# Set origin
|
||||||
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/libnextcloudsync.so.0
|
./squashfs-root/usr/bin/patchelf --set-rpath '$ORIGIN/' /app/usr/lib/lib${APPNAME}sync.so.0
|
||||||
|
|
||||||
# Build AppImage
|
# Build AppImage
|
||||||
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage
|
./squashfs-root/AppRun ${DESKTOP_FILE} -appimage -updateinformation="gh-releases-zsync|nextcloud-releases|desktop|latest|Nextcloud-*-x86_64.AppImage.zsync"
|
||||||
|
|
||||||
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
|
#move AppImage
|
||||||
|
if [ ! -z "$DRONE_COMMIT" ]
|
||||||
|
then
|
||||||
|
mv Nextcloud*.AppImage Nextcloud-${SUFFIX}-${DRONE_COMMIT}-x86_64.AppImage
|
||||||
|
fi
|
||||||
|
mv *.AppImage ${DESKTOP_CLIENT_ROOT}/
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Small script that counts the warnings which the compiler emits
|
|
||||||
# and takes care that not more warnings are added.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
print(f"Usage: {sys.argv[0]} REPOSITORY_PATH")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
repository_path = sys.argv[1]
|
|
||||||
warning_regex = re.compile(r'warning:', re.M)
|
|
||||||
max_allowed_warnings_count_response = requests.get(
|
|
||||||
"https://nextclouddesktopwarningscount.felixweilbach.de")
|
|
||||||
|
|
||||||
if max_allowed_warnings_count_response.status_code != 200:
|
|
||||||
print('Can not get maximum number of allowed warnings')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
max_allowed_warnings_count = int(max_allowed_warnings_count_response.content)
|
|
||||||
|
|
||||||
print("Max number of allowed warnings:", max_allowed_warnings_count)
|
|
||||||
|
|
||||||
warnings_count = 0
|
|
||||||
|
|
||||||
for line in sys.stdin:
|
|
||||||
if warning_regex.findall(line):
|
|
||||||
warnings_count += 1
|
|
||||||
|
|
||||||
print(line, end="")
|
|
||||||
|
|
||||||
if warnings_count > max_allowed_warnings_count:
|
|
||||||
print("Error: Too many warnings! You probably introduced a new warning!")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
print("Total number of warnings:", warnings_count)
|
|
||||||
@@ -15,10 +15,10 @@ OBS_PROJECT_BETA=home:ivaradi:beta
|
|||||||
OBS_PACKAGE=nextcloud-desktop
|
OBS_PACKAGE=nextcloud-desktop
|
||||||
|
|
||||||
if test "${DRONE_TARGET_BRANCH}" = "stable-2.6"; then
|
if test "${DRONE_TARGET_BRANCH}" = "stable-2.6"; then
|
||||||
UBUNTU_DISTRIBUTIONS="bionic focal groovy hirsute impish"
|
UBUNTU_DISTRIBUTIONS="bionic focal hirsute impish"
|
||||||
DEBIAN_DISTRIBUTIONS="buster stretch testing"
|
DEBIAN_DISTRIBUTIONS="buster stretch testing"
|
||||||
else
|
else
|
||||||
UBUNTU_DISTRIBUTIONS="focal groovy hirsute impish"
|
UBUNTU_DISTRIBUTIONS="focal hirsute impish"
|
||||||
DEBIAN_DISTRIBUTIONS="testing"
|
DEBIAN_DISTRIBUTIONS="testing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ cd /build
|
|||||||
|
|
||||||
# AppImage
|
# AppImage
|
||||||
export APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
|
export APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
|
||||||
|
export UPDATE=$(readlink -f ./Nextcloud*.AppImage.zsync)
|
||||||
export BASENAME=$(basename ${APPIMAGE})
|
export BASENAME=$(basename ${APPIMAGE})
|
||||||
|
|
||||||
if ! test -e $APPIMAGE ; then
|
if ! test -e $APPIMAGE ; then
|
||||||
@@ -70,6 +71,7 @@ upload_release_asset()
|
|||||||
{
|
{
|
||||||
uploadUrl=$1
|
uploadUrl=$1
|
||||||
echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $APPIMAGE)
|
echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $APPIMAGE)
|
||||||
|
echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $UPDATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_release_asset()
|
delete_release_asset()
|
||||||
@@ -132,4 +134,4 @@ if [ $TAG_NAME != "master" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "AppImage link: $browserDownloadUrl"
|
echo "AppImage link: $browserDownloadUrl"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ else()
|
|||||||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Qt5 5.12 COMPONENTS Core REQUIRED)
|
find_package(Qt5 5.15 COMPONENTS Core REQUIRED)
|
||||||
configure_file(create_mac.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
configure_file(create_mac.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
||||||
configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
configure_file(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||||
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
|
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
|
||||||
|
|||||||
@@ -695,7 +695,12 @@
|
|||||||
<key>PROJECT_SETTINGS</key>
|
<key>PROJECT_SETTINGS</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>ADVANCED_OPTIONS</key>
|
<key>ADVANCED_OPTIONS</key>
|
||||||
<dict/>
|
<dict>
|
||||||
|
<key>installer-script.options:hostArchitectures</key>
|
||||||
|
<array>
|
||||||
|
<string>x86_64,arm64</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
<key>BUILD_FORMAT</key>
|
<key>BUILD_FORMAT</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
<key>BUILD_PATH</key>
|
<key>BUILD_PATH</key>
|
||||||
|
|||||||
82
admin/osx/make_universal.py
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
# A general note: We first produce a x86_64 and a arm64 app package
|
||||||
|
# and then merge them together instead of compiling the desktop client
|
||||||
|
# with the CMake option CMAKE_OSX_ARCHITECTURES="x86_64;arm64" because
|
||||||
|
# macdeployqt can not handle universal binaries well. In the future
|
||||||
|
# with Qt6 this might change and this script will become obsolete.
|
||||||
|
|
||||||
|
|
||||||
|
def usage(program_name):
|
||||||
|
print("Creates a universal app package from a x86_64 and a arm64 app package.")
|
||||||
|
print("Usage: {} x86_64_app_file arm64_app_file output_directory".format(program_name))
|
||||||
|
print("Example: {} some_dir/Nextcloud.app some_other_dir/Nextcloud.app output_dir".format(program_name))
|
||||||
|
|
||||||
|
|
||||||
|
def execute(command):
|
||||||
|
return subprocess.check_output(command)
|
||||||
|
|
||||||
|
|
||||||
|
def path_relative_to_package(app_package_file_path, file_path):
|
||||||
|
if file_path.startswith(app_package_file_path):
|
||||||
|
relative_path = file_path[len(app_package_file_path):]
|
||||||
|
if relative_path.startswith("/"):
|
||||||
|
return relative_path[1:]
|
||||||
|
return relative_path
|
||||||
|
return file_path
|
||||||
|
|
||||||
|
|
||||||
|
def is_executable(file_path):
|
||||||
|
output = str(execute(["file", file_path]))
|
||||||
|
if (("Mach-O 64-bit dynamically linked shared library" in output)
|
||||||
|
or ("Mach-O 64-bit executable" in output)):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 4:
|
||||||
|
usage(sys.argv[0])
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
x86_64_app_file = sys.argv[1]
|
||||||
|
if not os.path.exists(x86_64_app_file):
|
||||||
|
print("Can't create universal: Path {} already exists".format(x86_64_app_file))
|
||||||
|
sys.exit(1)
|
||||||
|
arm64_app_file = sys.argv[2]
|
||||||
|
if not os.path.exists(arm64_app_file):
|
||||||
|
print("Can't create universal: Path {} already exists".format(arm64_app_file))
|
||||||
|
sys.exit(1)
|
||||||
|
output_dir = sys.argv[3]
|
||||||
|
|
||||||
|
# Copy the Arm64 variant to the output location if possible
|
||||||
|
if not os.path.exists(output_dir):
|
||||||
|
os.makedirs(output_dir)
|
||||||
|
app_file_name = os.path.basename(arm64_app_file)
|
||||||
|
universal_app_file = os.path.join(output_dir, app_file_name)
|
||||||
|
if os.path.exists(universal_app_file):
|
||||||
|
print("Can't create universal: Path {} already exists".format(universal_app_file))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
execute(["cp", "-a", arm64_app_file, output_dir])
|
||||||
|
|
||||||
|
# Now walk through the copied arm64 version and replace the binaries
|
||||||
|
for root, dirs, files in os.walk(universal_app_file):
|
||||||
|
for f in files:
|
||||||
|
absoulte_file_path = os.path.join(root, f)
|
||||||
|
root_relative = path_relative_to_package(universal_app_file, root)
|
||||||
|
x86_64_absolute_path = os.path.join(x86_64_app_file, root_relative, f)
|
||||||
|
arm64_absolute_path = os.path.join(arm64_app_file, root_relative, f)
|
||||||
|
if os.path.islink(absoulte_file_path) or not is_executable(absoulte_file_path):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
execute(["lipo", "-create", "-output", absoulte_file_path, arm64_absolute_path, x86_64_absolute_path])
|
||||||
|
except:
|
||||||
|
print("Could not merge {} with {} into {}!".format(arm64_absolute_path, x86_64_absolute_path, absoulte_file_path))
|
||||||
|
|
||||||
|
print("Finished :)")
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
# Always enable the new 10.10 finder plugin if available
|
# Always enable the new 10.10 finder plugin if available
|
||||||
if [ -x "$(command -v pluginkit)" ]; then
|
if [ -x "$(command -v pluginkit)" ]; then
|
||||||
# add it to DB. This happens automatically too but we try to push it a bit harder for issue #3463
|
# add it to DB. This happens automatically too but we try to push it a bit harder for issue #3463
|
||||||
pluginkit -a "/Applications/@APPLICATION_EXECUTABLE@.app/Contents/PlugIns/FinderSyncExt.appex/"
|
pluginkit -a "/Applications/@APPLICATION_NAME@.app/Contents/PlugIns/FinderSyncExt.appex/"
|
||||||
# Since El Capitan we need to sleep #4650
|
# Since El Capitan we need to sleep #4650
|
||||||
sleep 10s
|
sleep 10s
|
||||||
# enable it
|
# enable it
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
|
|
||||||
# kill the old version. see issue #2044
|
# kill the old version. see issue #2044
|
||||||
killall @APPLICATION_EXECUTABLE@
|
killall @APPLICATION_EXECUTABLE@
|
||||||
|
killall @APPLICATION_NAME@
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
46
appveyor.ini
@@ -1,7 +1,6 @@
|
|||||||
[General]
|
[General]
|
||||||
Branch = master
|
Branch = master
|
||||||
ShallowClone = True
|
ShallowClone = True
|
||||||
Command=craft
|
|
||||||
|
|
||||||
# Variables defined here override the default value
|
# Variables defined here override the default value
|
||||||
# The variable names are casesensitive
|
# The variable names are casesensitive
|
||||||
@@ -13,33 +12,42 @@ CreateCache = False
|
|||||||
# Settings applicable for all Crafts matrices
|
# Settings applicable for all Crafts matrices
|
||||||
# Settings are Category/key=value
|
# Settings are Category/key=value
|
||||||
# Category is case sensitive
|
# Category is case sensitive
|
||||||
|
|
||||||
[GeneralSettings]
|
[GeneralSettings]
|
||||||
General/EMERGE_PKGDSTDIR=${Variables:APPVEYOR_BUILD_FOLDER}/binaries
|
|
||||||
Paths/python = C:\Python36
|
## This is the location of your python installation.
|
||||||
Paths/python27 = C:\Python27
|
## This value must be set.
|
||||||
|
Paths/Python = C:\Python39-x64
|
||||||
|
Paths/Python27 = C:\Python27-x64
|
||||||
|
|
||||||
|
Compile/BuildType = RelWithDebInfo
|
||||||
|
|
||||||
|
Compile/UseNinja = True
|
||||||
|
|
||||||
Paths/downloaddir = ${Variables:Root}\downloads
|
Paths/downloaddir = ${Variables:Root}\downloads
|
||||||
ShortPath/Enabled = False
|
ShortPath/Enabled = False
|
||||||
ShortPath/EnableJunctions = True
|
ShortPath/EnableJunctions = True
|
||||||
ShortPath/JunctionDir = C:\CM-SP\
|
ShortPath/JunctionDir = C:\CM-SP\
|
||||||
Packager/CacheDir = ${Variables:Root}\cache
|
|
||||||
|
; Packager/RepositoryUrl = https://files.kde.org/craft/
|
||||||
|
Packager/PackageType = NullsoftInstallerPackager
|
||||||
|
Packager/RepositoryUrl = http://ftp.acc.umu.se/mirror/kde.org/files/craft/master/
|
||||||
|
|
||||||
|
ContinuousIntegration/Enabled = True
|
||||||
|
|
||||||
|
## This option can be used to override the default make program
|
||||||
|
## change the value to the path of the executable you want to use instead.
|
||||||
|
Compile/MakeProgram = jom
|
||||||
|
|
||||||
Packager/UseCache = ${Variables:UseCache}
|
Packager/UseCache = ${Variables:UseCache}
|
||||||
Packager/CreateCache = ${Variables:CreateCache}
|
Packager/CreateCache = ${Variables:CreateCache}
|
||||||
; Packager/RepositoryUrl = https://files.kde.org/craft/
|
Packager/CacheDir = ${Variables:Root}\cache
|
||||||
Packager/PackageType = PortablePackager
|
|
||||||
Packager/RepositoryUrl = http://ftp.acc.umu.se/mirror/kde.org/files/craft/master/
|
|
||||||
Compile/BuildType = RelWithDebInfo
|
|
||||||
ContinuousIntegration/Enabled = True
|
|
||||||
|
|
||||||
[BlueprintSettings]
|
[BlueprintSettings]
|
||||||
# don't try to pip install on the ci
|
# don't try to pip install on the ci
|
||||||
python-modules.ignored = True
|
python-modules.ignored = True
|
||||||
|
nextcloud-client.buildTests = True
|
||||||
|
binary/mysql.useMariaDB = False
|
||||||
|
|
||||||
libs/qt5.version = 5.9.3
|
[windows-msvc2019_64-cl]
|
||||||
craft/craft-core.version = master
|
QtSDK/Compiler = msvc2019_64
|
||||||
|
General/ABI = windows-msvc2019_64-cl
|
||||||
[windows-msvc2017_64-cl]
|
|
||||||
General/ABI = windows-msvc2017_64-cl
|
|
||||||
|
|
||||||
[windows-msvc2017_32-cl]
|
|
||||||
General/ABI = windows-msvc2017_32-cl
|
|
||||||
|
|||||||
44
appveyor.yml
@@ -1,50 +1,42 @@
|
|||||||
version: '{build}-{branch}'
|
version: '{build}-{branch}'
|
||||||
|
|
||||||
|
image: Visual Studio 2019
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
clone_depth: 50
|
clone_depth: 1
|
||||||
|
|
||||||
|
|
||||||
init:
|
init:
|
||||||
- ps: |
|
- ps: |
|
||||||
function craft($target) {
|
function craft() {
|
||||||
& C:\Python36\python.exe "C:\CraftMaster\CraftMaster\CraftMaster.py" --config "$env:APPVEYOR_BUILD_FOLDER\appveyor.ini" --variables "APPVEYOR_BUILD_FOLDER=$env:APPVEYOR_BUILD_FOLDER" --target $target -c $args
|
cmd /C "echo %PATH%"
|
||||||
|
& "C:\Python39-x64\python.exe" "C:\CraftMaster\CraftMaster\CraftMaster.py" --config "$env:APPVEYOR_BUILD_FOLDER\appveyor.ini" --variables "APPVEYOR_BUILD_FOLDER=$env:APPVEYOR_BUILD_FOLDER" --target $env:TARGET -c $args
|
||||||
if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
||||||
}
|
}
|
||||||
|
function crafttests() {
|
||||||
|
cmd /C "echo %PATH%"
|
||||||
|
& "C:\Python39-x64\python.exe" "C:\CraftMaster\CraftMaster\CraftMaster.py" --config "$env:APPVEYOR_BUILD_FOLDER\appveyor.ini" --variables "APPVEYOR_BUILD_FOLDER=$env:APPVEYOR_BUILD_FOLDER" --target $env:TARGET -c $args
|
||||||
|
}
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: |
|
- ps: |
|
||||||
#use cmd to silence powershell behaviour for stderr
|
#use cmd to silence powershell behaviour for stderr
|
||||||
& cmd /C "git clone -q --depth=1 git://anongit.kde.org/craftmaster.git C:\CraftMaster\CraftMaster 2>&1"
|
& cmd /C "git clone -q --depth=1 https://invent.kde.org/packaging/craftmaster.git C:\CraftMaster\CraftMaster 2>&1"
|
||||||
|
craft --add-blueprint-repository [git]https://github.com/nextcloud/desktop-client-blueprints.git
|
||||||
craft $env:TARGET -i craft
|
craft craft
|
||||||
craft $env:TARGET --install-deps owncloud-client
|
craft --install-deps nextcloud-client
|
||||||
|
craft nsis
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
craft $env:TARGET --no-cache --src-dir $env:APPVEYOR_BUILD_FOLDER owncloud-client
|
craft --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
|
||||||
|
|
||||||
after_build:
|
|
||||||
- ps: |
|
|
||||||
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --package owncloud-client
|
|
||||||
|
|
||||||
|
|
||||||
on_finish:
|
|
||||||
- ps: |
|
|
||||||
Get-ChildItem $env:USERPROFILE\.craft\* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
craft $env:TARGET --src-dir $env:APPVEYOR_BUILD_FOLDER --test owncloud-client
|
crafttests --test --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- TARGET: windows-msvc2017_32-cl
|
- TARGET: windows-msvc2019_64-cl
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
- TARGET: windows-msvc2017_64-cl
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
- path: binaries/*
|
|
||||||
|
|||||||
29
cmake/modules/ECMCoverageOption.cmake
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
ECMCoverageOption
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Allow users to easily enable GCov code coverage support.
|
||||||
|
|
||||||
|
Code coverage allows you to check how much of your codebase is covered by
|
||||||
|
your tests. This module makes it easy to build with support for
|
||||||
|
`GCov <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_.
|
||||||
|
|
||||||
|
When this module is included, a ``BUILD_COVERAGE`` option is added (default
|
||||||
|
OFF). Turning this option on enables GCC's coverage instrumentation, and
|
||||||
|
links against ``libgcov``.
|
||||||
|
|
||||||
|
Note that this will probably break the build if you are not using GCC.
|
||||||
|
|
||||||
|
Since 1.3.0.
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
option(BUILD_COVERAGE "Build the project with gcov support" OFF)
|
||||||
|
|
||||||
|
if(BUILD_COVERAGE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
|
||||||
|
endif()
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# GNUInstallDirs
|
|
||||||
# --------------
|
|
||||||
#
|
|
||||||
# Define GNU standard installation directories
|
|
||||||
#
|
|
||||||
# Provides install directory variables as defined for GNU software:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
|
|
||||||
#
|
|
||||||
# Inclusion of this module defines the following variables:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# CMAKE_INSTALL_<dir> - destination for files of a given type
|
|
||||||
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
|
|
||||||
#
|
|
||||||
# where <dir> is one of:
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# BINDIR - user executables (bin)
|
|
||||||
# SBINDIR - system admin executables (sbin)
|
|
||||||
# LIBEXECDIR - program executables (libexec)
|
|
||||||
# SYSCONFDIR - read-only single-machine data (etc)
|
|
||||||
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
|
|
||||||
# LOCALSTATEDIR - modifiable single-machine data (var)
|
|
||||||
# LIBDIR - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
|
|
||||||
# INCLUDEDIR - C header files (include)
|
|
||||||
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
|
|
||||||
# DATAROOTDIR - read-only architecture-independent data root (share)
|
|
||||||
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
|
|
||||||
# INFODIR - info documentation (DATAROOTDIR/info)
|
|
||||||
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
|
|
||||||
# MANDIR - man documentation (DATAROOTDIR/man)
|
|
||||||
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
|
|
||||||
#
|
|
||||||
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION
|
|
||||||
# options of install() commands for the corresponding file type. If the
|
|
||||||
# includer does not define a value the above-shown default will be used
|
|
||||||
# and the value will appear in the cache for editing by the user. Each
|
|
||||||
# CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
|
|
||||||
# from the corresponding destination by prepending (if necessary) the
|
|
||||||
# value of CMAKE_INSTALL_PREFIX.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
|
|
||||||
# Copyright 2011 Kitware, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
|
||||||
# License text for the above reference.)
|
|
||||||
|
|
||||||
# Installation directories
|
|
||||||
#
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
|
|
||||||
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
|
|
||||||
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
|
|
||||||
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
|
|
||||||
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
|
|
||||||
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
|
|
||||||
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# We check if the variable was manually set and not cached, in order to
|
|
||||||
# allow projects to set the values as normal variables before including
|
|
||||||
# GNUInstallDirs to avoid having the entries cached or user-editable. It
|
|
||||||
# replaces the "if(NOT DEFINED CMAKE_INSTALL_XXX)" checks in all the
|
|
||||||
# other cases.
|
|
||||||
# If CMAKE_INSTALL_LIBDIR is defined, if _libdir_set is false, then the
|
|
||||||
# variable is a normal one, otherwise it is a cache one.
|
|
||||||
get_property(_libdir_set CACHE CMAKE_INSTALL_LIBDIR PROPERTY TYPE SET)
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
|
|
||||||
AND DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX
|
|
||||||
AND NOT "${_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX}" STREQUAL "${CMAKE_INSTALL_PREFIX}"))
|
|
||||||
# If CMAKE_INSTALL_LIBDIR is not defined, it is always executed.
|
|
||||||
# Otherwise:
|
|
||||||
# * if _libdir_set is false it is not executed (meaning that it is
|
|
||||||
# not a cache variable)
|
|
||||||
# * if _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX is not defined it is
|
|
||||||
# not executed
|
|
||||||
# * if _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX and
|
|
||||||
# CMAKE_INSTALL_PREFIX are the same string it is not executed.
|
|
||||||
# _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX is updated after the
|
|
||||||
# execution, of this part of code, therefore at the next inclusion
|
|
||||||
# of the file, CMAKE_INSTALL_LIBDIR is defined, and the 2 strings
|
|
||||||
# are equal, meaning that the if is not executed the code the
|
|
||||||
# second time.
|
|
||||||
|
|
||||||
set(_LIBDIR_DEFAULT "lib")
|
|
||||||
# Override this default 'lib' with 'lib64' iff:
|
|
||||||
# - we are on Linux system but NOT cross-compiling
|
|
||||||
# - we are NOT on debian
|
|
||||||
# - we are on a 64 bits system
|
|
||||||
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
|
|
||||||
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
|
|
||||||
# CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
|
|
||||||
# and CMAKE_INSTALL_PREFIX is "/usr"
|
|
||||||
# See http://wiki.debian.org/Multiarch
|
|
||||||
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX)
|
|
||||||
set(__LAST_LIBDIR_DEFAULT "lib")
|
|
||||||
# __LAST_LIBDIR_DEFAULT is the default value that we compute from
|
|
||||||
# _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX, not a cache entry for
|
|
||||||
# the value that was last used as the default.
|
|
||||||
# This value is used to figure out whether the user changed the
|
|
||||||
# CMAKE_INSTALL_LIBDIR value manually, or if the value was the
|
|
||||||
# default one. When CMAKE_INSTALL_PREFIX changes, the value is
|
|
||||||
# updated to the new default, unless the user explicitly changed it.
|
|
||||||
endif()
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$"
|
|
||||||
AND NOT CMAKE_CROSSCOMPILING)
|
|
||||||
if (EXISTS "/etc/debian_version") # is this a debian system ?
|
|
||||||
if(CMAKE_LIBRARY_ARCHITECTURE)
|
|
||||||
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
|
||||||
endif()
|
|
||||||
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
|
|
||||||
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
|
|
||||||
message(AUTHOR_WARNING
|
|
||||||
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
|
|
||||||
"Please enable at least one language before including GNUInstallDirs.")
|
|
||||||
else()
|
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
|
||||||
set(_LIBDIR_DEFAULT "lib64")
|
|
||||||
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX)
|
|
||||||
set(__LAST_LIBDIR_DEFAULT "lib64")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
|
||||||
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
|
|
||||||
elseif(DEFINED __LAST_LIBDIR_DEFAULT
|
|
||||||
AND "${__LAST_LIBDIR_DEFAULT}" STREQUAL "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
set_property(CACHE CMAKE_INSTALL_LIBDIR PROPERTY VALUE "${_LIBDIR_DEFAULT}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
# Save for next run
|
|
||||||
set(_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE INTERNAL "CMAKE_INSTALL_PREFIX during last run")
|
|
||||||
unset(_libdir_set)
|
|
||||||
unset(__LAST_LIBDIR_DEFAULT)
|
|
||||||
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
|
|
||||||
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
|
|
||||||
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
|
|
||||||
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
|
|
||||||
# the cache and store the defaults in local variables if the cache values are
|
|
||||||
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
|
|
||||||
|
|
||||||
if(NOT CMAKE_INSTALL_DATADIR)
|
|
||||||
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
|
|
||||||
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INSTALL_INFODIR)
|
|
||||||
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
|
|
||||||
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INSTALL_LOCALEDIR)
|
|
||||||
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
|
|
||||||
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INSTALL_MANDIR)
|
|
||||||
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
|
|
||||||
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INSTALL_DOCDIR)
|
|
||||||
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
|
|
||||||
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
CMAKE_INSTALL_BINDIR
|
|
||||||
CMAKE_INSTALL_SBINDIR
|
|
||||||
CMAKE_INSTALL_LIBEXECDIR
|
|
||||||
CMAKE_INSTALL_SYSCONFDIR
|
|
||||||
CMAKE_INSTALL_SHAREDSTATEDIR
|
|
||||||
CMAKE_INSTALL_LOCALSTATEDIR
|
|
||||||
CMAKE_INSTALL_LIBDIR
|
|
||||||
CMAKE_INSTALL_INCLUDEDIR
|
|
||||||
CMAKE_INSTALL_OLDINCLUDEDIR
|
|
||||||
CMAKE_INSTALL_DATAROOTDIR
|
|
||||||
CMAKE_INSTALL_DATADIR
|
|
||||||
CMAKE_INSTALL_INFODIR
|
|
||||||
CMAKE_INSTALL_LOCALEDIR
|
|
||||||
CMAKE_INSTALL_MANDIR
|
|
||||||
CMAKE_INSTALL_DOCDIR
|
|
||||||
)
|
|
||||||
|
|
||||||
# Result directories
|
|
||||||
#
|
|
||||||
foreach(dir
|
|
||||||
BINDIR
|
|
||||||
SBINDIR
|
|
||||||
LIBEXECDIR
|
|
||||||
SYSCONFDIR
|
|
||||||
SHAREDSTATEDIR
|
|
||||||
LOCALSTATEDIR
|
|
||||||
LIBDIR
|
|
||||||
INCLUDEDIR
|
|
||||||
OLDINCLUDEDIR
|
|
||||||
DATAROOTDIR
|
|
||||||
DATADIR
|
|
||||||
INFODIR
|
|
||||||
LOCALEDIR
|
|
||||||
MANDIR
|
|
||||||
DOCDIR
|
|
||||||
)
|
|
||||||
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
|
|
||||||
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
|
|
||||||
else()
|
|
||||||
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
@@ -27,7 +27,4 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DEFINED MIRALL_FATAL_WARNINGS)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
|
||||||
endif(DEFINED MIRALL_FATAL_WARNINGS)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -29,7 +29,11 @@
|
|||||||
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
|
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
|
||||||
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
|
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
|
||||||
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
|
#cmakedefine APPLICATION_VIRTUALFILE_SUFFIX "@APPLICATION_VIRTUALFILE_SUFFIX@"
|
||||||
|
#cmakedefine APPLICATION_OCSP_STAPLING_ENABLED "@APPLICATION_OCSP_STAPLING_ENABLED@"
|
||||||
|
#cmakedefine APPLICATION_FORBID_BAD_SSL "@APPLICATION_FORBID_BAD_SSL@"
|
||||||
|
#cmakedefine APPLICATION_LOGIN_WITH_SYSTEM_USERNAME "@APPLICATION_LOGIN_WITH_SYSTEM_USERNAME@"
|
||||||
#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX
|
#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX
|
||||||
|
#cmakedefine01 ENFORCE_VIRTUAL_FILES_SYNC_FOLDER
|
||||||
|
|
||||||
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@
|
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ Conflict files are always created on the client and never on the server.
|
|||||||
"capabilities":{
|
"capabilities":{
|
||||||
"core":{
|
"core":{
|
||||||
"pollinterval":60,
|
"pollinterval":60,
|
||||||
"webdav-root":"remote.php/webdav"
|
"webdav-root":"remote.php/dav"
|
||||||
},
|
},
|
||||||
"dav":{
|
"dav":{
|
||||||
"chunking":"1.0"
|
"chunking":"1.0"
|
||||||
@@ -406,7 +406,7 @@ Virtual Files
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
* This feature is currently only available on ``Windows`` by default. ``Linux`` implementation is experimental and must be enabled by adding ``showExperimentalOptions=true`` to the ``nextcloud.cfg`` configuration file in the ``App Data`` folder. ``macOS``, at the moment, is using the same backend as ``Linux`` one. It can be enabled with the same ``showExperimentalOptions`` flag.
|
* This feature is currently only available on ``Windows`` by default. ``Linux`` and ``macOS`` implementations are experimental and must be enabled by adding ``showExperimentalOptions=true`` to the ``nextcloud.cfg`` configuration file in the ``App Data`` folder.
|
||||||
|
|
||||||
Oftentimes, users are working with a huge amount of files that are big in size. Synchronizing every such file to a device that's running a Nextcloud desktop client is not always possible due to the user's device storage space limitation.
|
Oftentimes, users are working with a huge amount of files that are big in size. Synchronizing every such file to a device that's running a Nextcloud desktop client is not always possible due to the user's device storage space limitation.
|
||||||
Let's assume that your desktop client is connected to a server that has 1TB of data. You want all those files at hand, so you can quickly access any file via the file explorer. Your device has 512GB local storage device.
|
Let's assume that your desktop client is connected to a server that has 1TB of data. You want all those files at hand, so you can quickly access any file via the file explorer. Your device has 512GB local storage device.
|
||||||
@@ -416,8 +416,15 @@ Needless to say, this is far from being convenient.
|
|||||||
That's why, starting from 3.2.0, we are introducing the VFS (Virtual Files) feature. You may have had experience working with a similar feature in other cloud sync clients. This feature is known by different names: Files On-Demand, SmartSync, etc.
|
That's why, starting from 3.2.0, we are introducing the VFS (Virtual Files) feature. You may have had experience working with a similar feature in other cloud sync clients. This feature is known by different names: Files On-Demand, SmartSync, etc.
|
||||||
The VFS does not occupy much space on the user's storage. It just creates placeholders for each file and folder. These files are quite small and only contain metadata needed to display them properly and to fetch the actual file when needed.
|
The VFS does not occupy much space on the user's storage. It just creates placeholders for each file and folder. These files are quite small and only contain metadata needed to display them properly and to fetch the actual file when needed.
|
||||||
|
|
||||||
One will see a hydration (in other words - file download) process when double-clicking on a file that must become available. There will be a progress-bar popup displayed if the file is large enough. So, the hydration process can be observed and it makes it easy to then find out, how long, it would take to fetch the actual file from the server.
|
When one tries to open a file, for example by double clicking on a
|
||||||
The "Hydration" can be thought of as "downloading" or "fetching" the file contents. As soon as hydration is complete, the file will then be opened normally as now it is a real file on the user's storage. It won't disappear, and, from now on, will always be available, unless it is manually dehydrated.
|
file in the Windows Explorer, one will see that the file gets
|
||||||
|
downloaded and becomes available locally. This can be observed by a
|
||||||
|
small progress-bar popup if the file is large enough.
|
||||||
|
|
||||||
|
As soon as the download is complete, the file will then be opened
|
||||||
|
normally as now it is a real file on the user's storage. It won't
|
||||||
|
disappear, and, from now on, will always be available, unless it is
|
||||||
|
manually dehydrated.
|
||||||
|
|
||||||
.. image:: images/vfs_hydration_progress_bar.png
|
.. image:: images/vfs_hydration_progress_bar.png
|
||||||
:alt: VFS hydration progress bar
|
:alt: VFS hydration progress bar
|
||||||
|
|||||||
@@ -32,10 +32,9 @@ itself. Should the silent update fail, the client offers a manual download.
|
|||||||
macOS
|
macOS
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
If a new update is available, the Nextcloud client initializes a pop-up dialog
|
There is no automatic updater on macOS. If a new update is available,
|
||||||
to alert you of the update and requesting that you update to the latest
|
the Nextcloud client initializes a pop-up dialog to alert you of the
|
||||||
version. Due to their use of the Sparkle frameworks, this is the default
|
update and requesting that you update to the latest version manually.
|
||||||
process for macOS applications.
|
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
^^^^^
|
^^^^^
|
||||||
@@ -96,14 +95,6 @@ To prevent automatic updates and disallow manual overrides:
|
|||||||
.. note:: branded clients have different key names
|
.. note:: branded clients have different key names
|
||||||
|
|
||||||
|
|
||||||
Preventing Automatic Updates in macOS Environments
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
You can disable the automatic update mechanism, in the macOS operating system,
|
|
||||||
by copying the file
|
|
||||||
``nextcloud.app/Contents/Resources/deny_autoupdate_com.nextcloud.desktopclient.plist``
|
|
||||||
to ``/Library/Preferences/com.nextcloud.desktopclient.plist``.
|
|
||||||
|
|
||||||
Preventing Automatic Updates in Linux Environments
|
Preventing Automatic Updates in Linux Environments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ Then, in Terminal:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
% echo 'export CMAKE_INSTALL_PREFIX=~/Builds' >> ~/.nextcloud_build_variables
|
% echo 'export CMAKE_INSTALL_PREFIX=~/Builds' >> ~/.nextcloud_build_variables
|
||||||
|
# If you want to build a macOS app bundle for distribution
|
||||||
|
% echo 'export BUILD_OWNCLOUD_OSX_BUNDLE=ON' >> ~/.nextcloud_build_variables
|
||||||
|
|
||||||
Replace ``~/Builds`` with a different directory if you'd like the build to end up elsewhere.
|
Replace ``~/Builds`` with a different directory if you'd like the build to end up elsewhere.
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ copyright = u'2013-2021, The Nextcloud developers'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '3.2'
|
version = '3.4'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '3.2.81'
|
release = '3.4.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Some interesting values that can be set on the configuration file are:
|
|||||||
| ``chunkSize`` | ``10000000`` (10 MB) | Specifies the chunk size of uploaded files in bytes. |
|
| ``chunkSize`` | ``10000000`` (10 MB) | Specifies the chunk size of uploaded files in bytes. |
|
||||||
| | | The client will dynamically adjust this size within the maximum and minimum bounds (see below). |
|
| | | The client will dynamically adjust this size within the maximum and minimum bounds (see below). |
|
||||||
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
||||||
| ``maxChunkSize`` | ``100000000`` (100 MB) | Specifies the maximum chunk size of uploaded files in bytes. |
|
| ``maxChunkSize`` | ``1000000000`` (1000 MB) | Specifies the maximum chunk size of uploaded files in bytes. |
|
||||||
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
||||||
| ``minChunkSize`` | ``1000000`` (1 MB) | Specifies the minimum chunk size of uploaded files in bytes. |
|
| ``minChunkSize`` | ``1000000`` (1 MB) | Specifies the minimum chunk size of uploaded files in bytes. |
|
||||||
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
||||||
|
|||||||
BIN
doc/images/main_dialog_christine.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 98 KiB |
BIN
doc/images/user_status-selector_dialog.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/images/user_status_selector_main_dialog.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 100 KiB |
@@ -8,7 +8,7 @@ There are clients for Linux, macOs, and Microsoft Windows.
|
|||||||
|
|
||||||
The currently supported server releases are the latest three stable versions
|
The currently supported server releases are the latest three stable versions
|
||||||
at time of publication. It means that the |version| release series is supporting
|
at time of publication. It means that the |version| release series is supporting
|
||||||
server major version 19, 20 and 21.
|
server major version 20, 21 and 22.
|
||||||
|
|
||||||
Installation on Mac OS X and Windows is the same as for any software
|
Installation on Mac OS X and Windows is the same as for any software
|
||||||
application: download the program and then double-click it to launch the
|
application: download the program and then double-click it to launch the
|
||||||
@@ -31,7 +31,7 @@ download page.
|
|||||||
System Requirements
|
System Requirements
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
- Windows 10+
|
- Windows 8.1+
|
||||||
- macOS 10.12+ (64-bit only)
|
- macOS 10.12+ (64-bit only)
|
||||||
- Linux
|
- Linux
|
||||||
- FreeBSD
|
- FreeBSD
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ Improvements and New Features
|
|||||||
The |version| release of the Nextcloud desktop sync client has many new features and
|
The |version| release of the Nextcloud desktop sync client has many new features and
|
||||||
improvements.
|
improvements.
|
||||||
|
|
||||||
* Virtual Files on Windows
|
* Main dialog will be a regular window if tray icons are not available on the system.
|
||||||
* Support for the user status from the server
|
* Virtual files wil be optional. That enables the desktop client to run on older Windows versions.
|
||||||
* Many improvements to the sync engine
|
* Improvements for the virtual files on Windows
|
||||||
* Make the end-to-end encryption work more reliable
|
* Network traffic performance improvements
|
||||||
* Improve sync performance
|
* Improvements to the sync engine
|
||||||
|
|||||||
@@ -157,6 +157,35 @@ icon.
|
|||||||
If a directory includes ignored files that are marked with warning icons
|
If a directory includes ignored files that are marked with warning icons
|
||||||
that does not change the status of the parent directories.
|
that does not change the status of the parent directories.
|
||||||
|
|
||||||
|
Set the user status
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
If you have the user status app installed on your Nextcloud server,
|
||||||
|
you can set your user status from the desktop client. To do so, open
|
||||||
|
the main dialog. Then click on your avatar and then click on the three
|
||||||
|
dots. In the menu that opens click on **Set status**.
|
||||||
|
|
||||||
|
.. figure:: images/user_status_selector_main_dialog.png
|
||||||
|
:alt: Open user status dialog from main dialog.
|
||||||
|
|
||||||
|
In the dialog that opens, you can set your online status if
|
||||||
|
you click on either **Online**, **Away**, **Do not disturb** or
|
||||||
|
**Invisible**. You can also set a custom status message with the text
|
||||||
|
field below or choose one of the predefined status messages below. It
|
||||||
|
is also possible to set a custom emoji if you click on the button with
|
||||||
|
the emoji beside the text input field. The last thing you might want
|
||||||
|
to set is when your user status should be cleared. You can choose the
|
||||||
|
period after which the user status will be cleared by clicking on the
|
||||||
|
button on the left hand side of the text **Clear status message after**.
|
||||||
|
|
||||||
|
.. figure:: images/user_status-selector_dialog.png
|
||||||
|
:alt: Dialog to set user status.
|
||||||
|
|
||||||
|
If you are happy with the status you have created you can enable this
|
||||||
|
status with the button **Set status message**. If you had already a
|
||||||
|
status set, you can clear the status by clicking the cutton **Clear
|
||||||
|
status message**.
|
||||||
|
|
||||||
Sharing From Your Desktop
|
Sharing From Your Desktop
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ the server URL.
|
|||||||
|
|
||||||
Other command line switches supported by ``nextcloudcmd`` include the following:
|
Other command line switches supported by ``nextcloudcmd`` include the following:
|
||||||
|
|
||||||
|
``--path``
|
||||||
|
Overrides default remote root folder to a specific subfolder on the server(e.g.: /Documents would sync the Documents subfolder on the server)
|
||||||
|
|
||||||
``--user``, ``-u`` ``[user]``
|
``--user``, ``-u`` ``[user]``
|
||||||
Use ``user`` as the login name.
|
Use ``user`` as the login name.
|
||||||
|
|
||||||
@@ -67,12 +70,6 @@ Other command line switches supported by ``nextcloudcmd`` include the following:
|
|||||||
``--httpproxy http://[user@pass:]<server>:<port>``
|
``--httpproxy http://[user@pass:]<server>:<port>``
|
||||||
Uses ``server`` as HTTP proxy.
|
Uses ``server`` as HTTP proxy.
|
||||||
|
|
||||||
``--nonshib``
|
|
||||||
Uses Non Shibboleth WebDAV Authentication
|
|
||||||
|
|
||||||
``--davpath [path]``
|
|
||||||
Overrides the WebDAV Path with ``path``
|
|
||||||
|
|
||||||
``--exclude [file]``
|
``--exclude [file]``
|
||||||
Exclude list file
|
Exclude list file
|
||||||
|
|
||||||
@@ -92,15 +89,15 @@ Credential Handling
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ nextcloudcmd /home/user/my_sync_folder https://carla:secret@server/nextcloud/remote.php/webdav/
|
$ nextcloudcmd /home/user/my_sync_folder https://carla:secret@server/nextcloud
|
||||||
|
|
||||||
To synchronize the Nextcloud directory ``Music`` to the local directory
|
To synchronize the Nextcloud directory ``Music`` to the local directory
|
||||||
``media/music``, through a proxy listening on port ``8080``, and on a gateway
|
``media/music``, through a proxy listening on port ``8080``, and on a gateway
|
||||||
machine using IP address ``192.168.178.1``, the command line would be::
|
machine using IP address ``192.168.178.1``, the command line would be::
|
||||||
|
|
||||||
$ nextcloudcmd --httpproxy http://192.168.178.1:8080 \
|
$ nextcloudcmd --httpproxy http://192.168.178.1:8080 --path /Music \
|
||||||
$HOME/media/music \
|
$HOME/media/music \
|
||||||
https://server/nextcloud/remote.php/webdav/Music
|
https://server/nextcloud
|
||||||
|
|
||||||
``nextcloudcmd`` will prompt for the user name and password, unless they have
|
``nextcloudcmd`` will prompt for the user name and password, unless they have
|
||||||
been specified on the command line or ``-n`` has been passed.
|
been specified on the command line or ``-n`` has been passed.
|
||||||
@@ -120,5 +117,5 @@ Example
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ nextcloudcmd /home/user/<my_sync_folder> \
|
$ nextcloudcmd --path /<Directory_that_has_been_created> /home/user/<my_sync_folder> \
|
||||||
https://<username>:<secret>@<server_address>/remote.php/webdav/<Directory_that_has_been_created>
|
https://<username>:<secret>@<server_address>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Identifying Basic Functionality Problems
|
|||||||
|
|
||||||
For example, if your Nextcloud instance is installed at
|
For example, if your Nextcloud instance is installed at
|
||||||
``http://yourserver.com/nextcloud``, your WebDAV server address is
|
``http://yourserver.com/nextcloud``, your WebDAV server address is
|
||||||
``http://yourserver.com/nextcloud/remote.php/webdav``.
|
``http://yourserver.com/nextcloud/remote.php/dav``.
|
||||||
|
|
||||||
If you are prompted for your username and password but, after providing the
|
If you are prompted for your username and password but, after providing the
|
||||||
correct credentials, authentication fails, please ensure that your
|
correct credentials, authentication fails, please ensure that your
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ The first parameter is the local directory. The second parameter is
|
|||||||
the server URL.
|
the server URL.
|
||||||
|
|
||||||
.. note:: Prior to the 1.6 release of nextcloudcmd, the tool only accepted
|
.. note:: Prior to the 1.6 release of nextcloudcmd, the tool only accepted
|
||||||
``nextcloud://`` or ``nextclouds://`` in place of ``http://`` and ``https://`` as
|
``owncloud://`` or ``ownclouds://`` in place of ``http://`` and ``https://`` as
|
||||||
a scheme. See ``Examples`` for details.
|
a scheme. See ``Examples`` for details.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
=======
|
=======
|
||||||
|
``--path``
|
||||||
|
Overrides default remote root folder to a specific subfolder on the server(e.g.: /Documents would sync the Documents subfolder on the server)
|
||||||
|
|
||||||
``—user``, ``-u`` ``[user]``
|
``—user``, ``-u`` ``[user]``
|
||||||
Use ``user`` as the login name.
|
Use ``user`` as the login name.
|
||||||
|
|
||||||
@@ -50,12 +53,6 @@ OPTIONS
|
|||||||
``—httpproxy http://[user@pass:]<server>:<port>``
|
``—httpproxy http://[user@pass:]<server>:<port>``
|
||||||
Uses ``server`` as HTTP proxy.
|
Uses ``server`` as HTTP proxy.
|
||||||
|
|
||||||
``—nonshib``
|
|
||||||
Uses Non Shibboleth WebDAV Authentication
|
|
||||||
|
|
||||||
``—davpath [path]``
|
|
||||||
Overrides the WebDAV Path with ``path``
|
|
||||||
|
|
||||||
``—exclude [file]``
|
``—exclude [file]``
|
||||||
Exclude list file
|
Exclude list file
|
||||||
|
|
||||||
@@ -74,18 +71,18 @@ To synchronize the nextCloud directory ``Music`` to the local directory ``media/
|
|||||||
through a proxy listening on port ``8080`` on the gateway machine ``192.168.178.1``,
|
through a proxy listening on port ``8080`` on the gateway machine ``192.168.178.1``,
|
||||||
the command line would be::
|
the command line would be::
|
||||||
|
|
||||||
$ nextcloudcmd —httpproxy http://192.168.178.1:8080 \
|
$ nextcloudcmd —httpproxy http://192.168.178.1:8080 --path /Music \
|
||||||
$HOME/media/music \
|
$HOME/media/music \
|
||||||
https://server/nextcloud/remote.php/webdav/Music
|
https://server/nextcloud
|
||||||
|
|
||||||
``nextcloudcmd`` will enquire user name and password, unless they have
|
``nextcloudcmd`` will enquire user name and password, unless they have
|
||||||
been specified on the command line or ``-n`` (see `netrc(5)`) has been passed.
|
been specified on the command line or ``-n`` (see `netrc(5)`) has been passed.
|
||||||
|
|
||||||
Using the legacy scheme, it would be::
|
Using the legacy scheme, it would be::
|
||||||
|
|
||||||
$ nextcloudcmd —httpproxy http://192.168.178.1:8080 \
|
$ nextcloudcmd —httpproxy http://192.168.178.1:8080 --path /Music \
|
||||||
$HOME/media/music \
|
$HOME/media/music \
|
||||||
nextclouds://server/nextcloud/remote.php/webdav/Music
|
ownclouds://server/nextcloud
|
||||||
|
|
||||||
|
|
||||||
BUGS
|
BUGS
|
||||||
|
|||||||
@@ -1,10 +1,27 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/qml">
|
<qresource prefix="/qml">
|
||||||
|
<file>src/gui/UserStatusSelector.qml</file>
|
||||||
|
<file>src/gui/UserStatusSelectorDialog.qml</file>
|
||||||
|
<file>src/gui/EmojiPicker.qml</file>
|
||||||
|
<file>src/gui/ErrorBox.qml</file>
|
||||||
<file>src/gui/tray/Window.qml</file>
|
<file>src/gui/tray/Window.qml</file>
|
||||||
<file>src/gui/tray/UserLine.qml</file>
|
<file>src/gui/tray/UserLine.qml</file>
|
||||||
<file>src/gui/tray/HeaderButton.qml</file>
|
<file>src/gui/tray/HeaderButton.qml</file>
|
||||||
|
<file>src/gui/tray/SyncStatus.qml</file>
|
||||||
<file>theme/Style/Style.qml</file>
|
<file>theme/Style/Style.qml</file>
|
||||||
<file>theme/Style/qmldir</file>
|
<file>theme/Style/qmldir</file>
|
||||||
<file>src/gui/tray/ActivityActionButton.qml</file>
|
<file>src/gui/tray/ActivityActionButton.qml</file>
|
||||||
|
<file>src/gui/tray/ActivityItem.qml</file>
|
||||||
|
<file>src/gui/tray/AutoSizingMenu.qml</file>
|
||||||
|
<file>src/gui/tray/ActivityList.qml</file>
|
||||||
|
<file>src/gui/tray/FileActivityDialog.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchInputContainer.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultFetchMoreTrigger.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultItem.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultItemSkeleton.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultItemSkeletonContainer.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultListItem.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultNothingFound.qml</file>
|
||||||
|
<file>src/gui/tray/UnifiedSearchResultSectionItem.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
|
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/${APPLICATION_ICON_NAME}.icns")
|
||||||
|
|
||||||
# The bundle identifier and application group need to have compatible values with the client
|
# The bundle identifier and application group need to have compatible values with the client
|
||||||
# to be able to open a Mach port across the extension's sandbox boundary.
|
# to be able to open a Mach port across the extension's sandbox boundary.
|
||||||
# Pass the info through the xcodebuild command line and make sure that the project uses
|
# Pass the info through the xcodebuild command line and make sure that the project uses
|
||||||
# those user-defined settings to build the plist.
|
# those user-defined settings to build the plist.
|
||||||
add_custom_target( mac_overlayplugin ALL
|
add_custom_target( mac_overlayplugin ALL
|
||||||
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
|
xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO
|
||||||
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
|
-project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
|
||||||
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
|
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
|
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
|
||||||
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
|
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
|
||||||
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
|
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
|
||||||
|
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
|
||||||
COMMENT building Mac Overlay icons
|
COMMENT building Mac Overlay icons
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
add_dependencies(mac_overlayplugin ${APPLICATION_EXECUTABLE}) # for the ownCloud.icns to be generated
|
add_dependencies(mac_overlayplugin nextcloud) # for the ownCloud.icns to be generated
|
||||||
|
|
||||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
|
if (BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
|
||||||
USE_SOURCE_PERMISSIONS)
|
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
||||||
endif(APPLE)
|
USE_SOURCE_PERMISSIONS)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ project(dolphin-owncloud)
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
set(QT_MIN_VERSION "5.12.0")
|
set(QT_MIN_VERSION "5.15.0")
|
||||||
set(KF5_MIN_VERSION "5.16.0")
|
set(KF5_MIN_VERSION "5.16.0")
|
||||||
set(KDE_INSTALL_USE_QT_SYS_PATHS ON CACHE BOOL "Install the plugin in the right directory")
|
set(KDE_INSTALL_USE_QT_SYS_PATHS ON CACHE BOOL "Install the plugin in the right directory")
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
|
explicit OwncloudDolphinPluginAction(QObject* parent, const QList<QVariant>&)
|
||||||
: KAbstractFileItemActionPlugin(parent) { }
|
: KAbstractFileItemActionPlugin(parent) { }
|
||||||
|
|
||||||
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) Q_DECL_OVERRIDE
|
QList<QAction*> actions(const KFileItemListProperties& fileItemInfos, QWidget* parentWidget) override
|
||||||
{
|
{
|
||||||
auto helper = OwncloudDolphinPluginHelper::instance();
|
auto helper = OwncloudDolphinPluginHelper::instance();
|
||||||
if (!helper->isConnected() || !fileItemInfos.isLocal())
|
if (!helper->isConnected() || !fileItemInfos.isLocal())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
if( UNIX AND NOT APPLE )
|
if( UNIX AND NOT APPLE )
|
||||||
|
|
||||||
SET(ICON_DIR ${DATADIR}/icons/hicolor)
|
SET(ICON_DIR ${CMAKE_INSTALL_DATADIR}/icons/hicolor)
|
||||||
|
|
||||||
FOREACH(size 128x128 16x16 256x256 32x32 48x48 64x64 72x72)
|
FOREACH(size 128x128 16x16 256x256 32x32 48x48 64x64 72x72)
|
||||||
file(GLOB files "${size}/*.png")
|
file(GLOB files "${size}/*.png")
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ macro(libcloudproviders_add_config _sources)
|
|||||||
endmacro(libcloudproviders_add_config _sources)
|
endmacro(libcloudproviders_add_config _sources)
|
||||||
|
|
||||||
|
|
||||||
find_package(Qt5 5.12 COMPONENTS DBus)
|
find_package(Qt5 5.15 COMPONENTS DBus)
|
||||||
IF (Qt5DBus_FOUND)
|
IF (Qt5DBus_FOUND)
|
||||||
STRING(TOLOWER "${APPLICATION_VENDOR}" DBUS_VENDOR)
|
STRING(TOLOWER "${APPLICATION_VENDOR}" DBUS_VENDOR)
|
||||||
STRING(REGEX REPLACE "[^A-z0-9]" "" DBUS_VENDOR "${DBUS_VENDOR}")
|
STRING(REGEX REPLACE "[^A-z0-9]" "" DBUS_VENDOR "${DBUS_VENDOR}")
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ if( UNIX AND NOT APPLE )
|
|||||||
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
|
ERROR_VARIABLE errors OUTPUT_VARIABLE out)
|
||||||
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate.py DESTINATION ${CMAKE_INSTALL_DATADIR}/nautilus-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_nemo.py DESTINATION ${CMAKE_INSTALL_DATADIR}/nemo-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syncstate_caja.py DESTINATION ${CMAKE_INSTALL_DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class __declspec(dllexport) RemotePathChecker {
|
class RemotePathChecker {
|
||||||
public:
|
public:
|
||||||
enum FileState {
|
enum FileState {
|
||||||
// Order synced with NCOverlay
|
// Order synced with NCOverlay
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
<File Id="NCContextMenu.dll" KeyPath="yes" Source="$(var.HarvestAppDir)\shellext\NCContextMenu.dll">
|
<File Id="NCContextMenu.dll" KeyPath="yes" Source="$(var.HarvestAppDir)\shellext\NCContextMenu.dll">
|
||||||
<Class Id="$(var.ContextMenuGuid)" Context="InprocServer32" Description="$(var.ContextMenuDescription)" ThreadingModel="apartment" />
|
<Class Id="$(var.ContextMenuGuid)" Context="InprocServer32" Description="$(var.ContextMenuDescription)" ThreadingModel="apartment" />
|
||||||
</File>
|
</File>
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\$(var.ContextMenuGuid)" Name="ContextMenuOptIn" Value="" Type="string" Action="write" />
|
||||||
<RegistryValue Root="HKCR" Key="AllFileSystemObjects\shellex\ContextMenuHandlers\$(var.ContextMenuRegKeyName)" Value="$(var.ContextMenuGuid)" Type="string" Action="write" />
|
<RegistryValue Root="HKCR" Key="AllFileSystemObjects\shellex\ContextMenuHandlers\$(var.ContextMenuRegKeyName)" Value="$(var.ContextMenuGuid)" Type="string" Action="write" />
|
||||||
</Component>
|
</Component>
|
||||||
|
|
||||||
|
|||||||
12
sonar-project.properties
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
sonar.projectKey=nextcloud_desktop
|
||||||
|
sonar.organization=nextcloud
|
||||||
|
sonar.projectBaseDir=..
|
||||||
|
sonar.sources=src
|
||||||
|
sonar.exclusions=3rdparty/**
|
||||||
|
sonar.language=c++
|
||||||
|
sonar.cfamily.cache.enabled=false
|
||||||
|
sonar.sourceEncoding=UTF-8
|
||||||
|
sonar.cfamily.threads=2
|
||||||
|
sonar.cfamily.gcov.reportsPath=build/Testing/CoverageInfo
|
||||||
|
sonar.cfamily.cache.enabled=true,
|
||||||
|
sonar.cfamily.cache.path=/cache/sonarcloud
|
||||||
@@ -67,8 +67,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
const QColor & color() const { return m_color; }
|
const QColor & color() const { return m_color; }
|
||||||
|
|
||||||
virtual QSize sizeHint() const;
|
QSize sizeHint() const override;
|
||||||
int heightForWidth(int w) const;
|
int heightForWidth(int w) const override;
|
||||||
public slots:
|
public slots:
|
||||||
/*! Starts the spin animation.
|
/*! Starts the spin animation.
|
||||||
\sa stopAnimation isAnimated
|
\sa stopAnimation isAnimated
|
||||||
@@ -98,8 +98,8 @@ public slots:
|
|||||||
*/
|
*/
|
||||||
void setColor(const QColor & color);
|
void setColor(const QColor & color);
|
||||||
protected:
|
protected:
|
||||||
virtual void timerEvent(QTimerEvent * event);
|
void timerEvent(QTimerEvent * event) override;
|
||||||
virtual void paintEvent(QPaintEvent * event);
|
void paintEvent(QPaintEvent * event) override;
|
||||||
private:
|
private:
|
||||||
int m_angle = 0;
|
int m_angle = 0;
|
||||||
int m_timerId = -1;
|
int m_timerId = -1;
|
||||||
|
|||||||
280
src/3rdparty/kirigami/wheelhandler.cpp
vendored
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wheelhandler.h"
|
||||||
|
#include <QWheelEvent>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class GlobalWheelFilterSingleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GlobalWheelFilter self;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC(GlobalWheelFilterSingleton, privateGlobalWheelFilterSelf)
|
||||||
|
|
||||||
|
GlobalWheelFilter::GlobalWheelFilter(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalWheelFilter::~GlobalWheelFilter() = default;
|
||||||
|
|
||||||
|
GlobalWheelFilter *GlobalWheelFilter::self()
|
||||||
|
{
|
||||||
|
return &privateGlobalWheelFilterSelf()->self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalWheelFilter::setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
|
||||||
|
{
|
||||||
|
if (!m_handlersForItem.contains(handler->target())) {
|
||||||
|
handler->target()->installEventFilter(this);
|
||||||
|
}
|
||||||
|
m_handlersForItem.insert(item, handler);
|
||||||
|
|
||||||
|
connect(item, &QObject::destroyed, this, [this](QObject *obj) {
|
||||||
|
auto item = static_cast<QQuickItem *>(obj);
|
||||||
|
m_handlersForItem.remove(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(handler, &QObject::destroyed, this, [this](QObject *obj) {
|
||||||
|
auto handler = static_cast<WheelHandler *>(obj);
|
||||||
|
removeItemHandlerAssociation(handler->target(), handler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalWheelFilter::removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler)
|
||||||
|
{
|
||||||
|
if (!item || !handler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_handlersForItem.remove(item, handler);
|
||||||
|
if (!m_handlersForItem.contains(item)) {
|
||||||
|
item->removeEventFilter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalWheelFilter::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::Wheel) {
|
||||||
|
auto item = qobject_cast<QQuickItem *>(watched);
|
||||||
|
if (!item || !item->isEnabled()) {
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
auto we = static_cast<QWheelEvent *>(event);
|
||||||
|
m_wheelEvent.initializeFromEvent(we);
|
||||||
|
|
||||||
|
bool shouldBlock = false;
|
||||||
|
bool shouldScrollFlickable = false;
|
||||||
|
|
||||||
|
for (auto *handler : m_handlersForItem.values(item)) {
|
||||||
|
if (handler->m_blockTargetWheel) {
|
||||||
|
shouldBlock = true;
|
||||||
|
}
|
||||||
|
if (handler->m_scrollFlickableTarget) {
|
||||||
|
shouldScrollFlickable = true;
|
||||||
|
}
|
||||||
|
emit handler->wheel(&m_wheelEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldScrollFlickable && !m_wheelEvent.isAccepted()) {
|
||||||
|
manageWheel(item, we);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldBlock) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalWheelFilter::manageWheel(QQuickItem *target, QWheelEvent *event)
|
||||||
|
{
|
||||||
|
// Duck typing: accept everyhint that has all the properties we need
|
||||||
|
if (target->metaObject()->indexOfProperty("contentX") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("contentY") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("contentWidth") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("contentHeight") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("topMargin") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("bottomMargin") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("leftMargin") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("rightMargin") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("originX") == -1
|
||||||
|
|| target->metaObject()->indexOfProperty("originY") == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal contentWidth = target->property("contentWidth").toReal();
|
||||||
|
qreal contentHeight = target->property("contentHeight").toReal();
|
||||||
|
qreal contentX = target->property("contentX").toReal();
|
||||||
|
qreal contentY = target->property("contentY").toReal();
|
||||||
|
qreal topMargin = target->property("topMargin").toReal();
|
||||||
|
qreal bottomMargin = target->property("bottomMargin").toReal();
|
||||||
|
qreal leftMargin = target->property("leftMaring").toReal();
|
||||||
|
qreal rightMargin = target->property("rightMargin").toReal();
|
||||||
|
qreal originX = target->property("originX").toReal();
|
||||||
|
qreal originY = target->property("originY").toReal();
|
||||||
|
|
||||||
|
// Scroll Y
|
||||||
|
if (contentHeight > target->height()) {
|
||||||
|
|
||||||
|
int y = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
|
||||||
|
|
||||||
|
//if we don't have a pixeldelta, apply the configured mouse wheel lines
|
||||||
|
if (!event->pixelDelta().y()) {
|
||||||
|
y *= 3; // Magic copied value from Kirigami::Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll one page regardless of delta:
|
||||||
|
if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
|
||||||
|
if (y > 0) {
|
||||||
|
y = target->height();
|
||||||
|
} else if (y < 0) {
|
||||||
|
y = -target->height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal minYExtent = topMargin - originY;
|
||||||
|
qreal maxYExtent = target->height() - (contentHeight + bottomMargin + originY);
|
||||||
|
|
||||||
|
target->setProperty("contentY", qMin(-maxYExtent, qMax(-minYExtent, contentY - y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scroll X
|
||||||
|
if (contentWidth > target->width()) {
|
||||||
|
|
||||||
|
int x = event->pixelDelta().x() != 0 ? event->pixelDelta().x() : event->angleDelta().x() / 8;
|
||||||
|
|
||||||
|
// Special case: when can't scroll vertically, scroll horizontally with vertical wheel as well
|
||||||
|
if (x == 0 && contentHeight <= target->height()) {
|
||||||
|
x = event->pixelDelta().y() != 0 ? event->pixelDelta().y() : event->angleDelta().y() / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we don't have a pixeldelta, apply the configured mouse wheel lines
|
||||||
|
if (!event->pixelDelta().x()) {
|
||||||
|
x *= 3; // Magic copied value from Kirigami::Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll one page regardless of delta:
|
||||||
|
if ((event->modifiers() & Qt::ControlModifier) || (event->modifiers() & Qt::ShiftModifier)) {
|
||||||
|
if (x > 0) {
|
||||||
|
x = target->width();
|
||||||
|
} else if (x < 0) {
|
||||||
|
x = -target->width();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal minXExtent = leftMargin - originX;
|
||||||
|
qreal maxXExtent = target->width() - (contentWidth + rightMargin + originX);
|
||||||
|
|
||||||
|
target->setProperty("contentX", qMin(-maxXExtent, qMax(-minXExtent, contentX - x)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//this is just for making the scrollbar
|
||||||
|
target->metaObject()->invokeMethod(target, "flick", Q_ARG(double, 0), Q_ARG(double, 1));
|
||||||
|
target->metaObject()->invokeMethod(target, "cancelFlick");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
KirigamiWheelEvent::KirigamiWheelEvent(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
KirigamiWheelEvent::~KirigamiWheelEvent() = default;
|
||||||
|
|
||||||
|
void KirigamiWheelEvent::initializeFromEvent(QWheelEvent *event)
|
||||||
|
{
|
||||||
|
m_x = event->position().x();
|
||||||
|
m_y = event->position().y();
|
||||||
|
m_angleDelta = event->angleDelta();
|
||||||
|
m_pixelDelta = event->pixelDelta();
|
||||||
|
m_buttons = event->buttons();
|
||||||
|
m_modifiers = event->modifiers();
|
||||||
|
m_accepted = false;
|
||||||
|
m_inverted = event->inverted();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal KirigamiWheelEvent::x() const
|
||||||
|
{
|
||||||
|
return m_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal KirigamiWheelEvent::y() const
|
||||||
|
{
|
||||||
|
return m_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF KirigamiWheelEvent::angleDelta() const
|
||||||
|
{
|
||||||
|
return m_angleDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF KirigamiWheelEvent::pixelDelta() const
|
||||||
|
{
|
||||||
|
return m_pixelDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KirigamiWheelEvent::buttons() const
|
||||||
|
{
|
||||||
|
return m_buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KirigamiWheelEvent::modifiers() const
|
||||||
|
{
|
||||||
|
return m_modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KirigamiWheelEvent::inverted() const
|
||||||
|
{
|
||||||
|
return m_inverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KirigamiWheelEvent::isAccepted()
|
||||||
|
{
|
||||||
|
return m_accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KirigamiWheelEvent::setAccepted(bool accepted)
|
||||||
|
{
|
||||||
|
m_accepted = accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
WheelHandler::WheelHandler(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WheelHandler::~WheelHandler() = default;
|
||||||
|
|
||||||
|
QQuickItem *WheelHandler::target() const
|
||||||
|
{
|
||||||
|
return m_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WheelHandler::setTarget(QQuickItem *target)
|
||||||
|
{
|
||||||
|
if (m_target == target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_target) {
|
||||||
|
GlobalWheelFilter::self()->removeItemHandlerAssociation(m_target, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_target = target;
|
||||||
|
|
||||||
|
GlobalWheelFilter::self()->setItemHandlerAssociation(target, this);
|
||||||
|
|
||||||
|
emit targetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "moc_wheelhandler.cpp"
|
||||||
213
src/3rdparty/kirigami/wheelhandler.h
vendored
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtQml>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QWheelEvent;
|
||||||
|
|
||||||
|
class WheelHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the mouse wheel event
|
||||||
|
*/
|
||||||
|
class KirigamiWheelEvent : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x: real
|
||||||
|
*
|
||||||
|
* X coordinate of the mouse pointer
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(qreal x READ x CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* y: real
|
||||||
|
*
|
||||||
|
* Y coordinate of the mouse pointer
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(qreal y READ y CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* angleDelta: point
|
||||||
|
*
|
||||||
|
* The distance the wheel is rotated in degrees.
|
||||||
|
* The x and y coordinates indicate the horizontal and vertical wheels respectively.
|
||||||
|
* A positive value indicates it was rotated up/right, negative, bottom/left
|
||||||
|
* This value is more likely to be set in traditional mice.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QPointF angleDelta READ angleDelta CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pixelDelta: point
|
||||||
|
*
|
||||||
|
* provides the delta in screen pixels available on high resolution trackpads
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QPointF pixelDelta READ pixelDelta CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buttons: int
|
||||||
|
*
|
||||||
|
* it contains an OR combination of the buttons that were pressed during the wheel, they can be:
|
||||||
|
* Qt.LeftButton, Qt.MiddleButton, Qt.RightButton
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(int buttons READ buttons CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* modifiers: int
|
||||||
|
*
|
||||||
|
* Keyboard mobifiers that were pressed during the wheel event, such as:
|
||||||
|
* Qt.NoModifier (default, no modifiers)
|
||||||
|
* Qt.ControlModifier
|
||||||
|
* Qt.ShiftModifier
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(int modifiers READ modifiers CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inverted: bool
|
||||||
|
*
|
||||||
|
* Whether the delta values are inverted
|
||||||
|
* On some platformsthe returned delta are inverted, so positive values would mean bottom/left
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool inverted READ inverted CONSTANT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* accepted: bool
|
||||||
|
*
|
||||||
|
* If set, the event shouldn't be managed anymore,
|
||||||
|
* for instance it can be used to block the handler to manage the scroll of a view on some scenarios
|
||||||
|
* @code
|
||||||
|
* // This handler handles automatically the scroll of
|
||||||
|
* // flickableItem, unless Ctrl is pressed, in this case the
|
||||||
|
* // app has custom code to handle Ctrl+wheel zooming
|
||||||
|
* Kirigami.WheelHandler {
|
||||||
|
* target: flickableItem
|
||||||
|
* blockTargetWheel: true
|
||||||
|
* scrollFlickableTarget: true
|
||||||
|
* onWheel: {
|
||||||
|
* if (wheel.modifiers & Qt.ControlModifier) {
|
||||||
|
* wheel.accepted = true;
|
||||||
|
* // Handle scaling of the view
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
||||||
|
|
||||||
|
public:
|
||||||
|
KirigamiWheelEvent(QObject *parent = nullptr);
|
||||||
|
~KirigamiWheelEvent() override;
|
||||||
|
|
||||||
|
void initializeFromEvent(QWheelEvent *event);
|
||||||
|
|
||||||
|
qreal x() const;
|
||||||
|
qreal y() const;
|
||||||
|
QPointF angleDelta() const;
|
||||||
|
QPointF pixelDelta() const;
|
||||||
|
int buttons() const;
|
||||||
|
int modifiers() const;
|
||||||
|
bool inverted() const;
|
||||||
|
bool isAccepted();
|
||||||
|
void setAccepted(bool accepted);
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal m_x = 0;
|
||||||
|
qreal m_y = 0;
|
||||||
|
QPointF m_angleDelta;
|
||||||
|
QPointF m_pixelDelta;
|
||||||
|
Qt::MouseButtons m_buttons = Qt::NoButton;
|
||||||
|
Qt::KeyboardModifiers m_modifiers = Qt::NoModifier;
|
||||||
|
bool m_inverted = false;
|
||||||
|
bool m_accepted = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GlobalWheelFilter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlobalWheelFilter(QObject *parent = nullptr);
|
||||||
|
~GlobalWheelFilter() override;
|
||||||
|
|
||||||
|
static GlobalWheelFilter *self();
|
||||||
|
|
||||||
|
void setItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
|
||||||
|
void removeItemHandlerAssociation(QQuickItem *item, WheelHandler *handler);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void manageWheel(QQuickItem *target, QWheelEvent *wheel);
|
||||||
|
|
||||||
|
QMultiHash<QQuickItem *, WheelHandler *> m_handlersForItem;
|
||||||
|
KirigamiWheelEvent m_wheelEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class intercepts the mouse wheel events of its target, and gives them to the user code as a signal, which can be used for custom mouse wheel management code.
|
||||||
|
* The handler can block completely the wheel events from its target, and if it's a Flickable, it can automatically handle scrolling on it
|
||||||
|
*/
|
||||||
|
class WheelHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* target: Item
|
||||||
|
*
|
||||||
|
* The target we want to manage wheel events.
|
||||||
|
* We will receive wheel() signals every time the user moves
|
||||||
|
* the mouse wheel (or scrolls with the touchpad) on top
|
||||||
|
* of that item.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* blockTargetWheel: bool
|
||||||
|
*
|
||||||
|
* If true, the target won't receive any wheel event at all (default true)
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool blockTargetWheel MEMBER m_blockTargetWheel NOTIFY blockTargetWheelChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scrollFlickableTarget: bool
|
||||||
|
* If this property is true and the target is a Flickable, wheel events will cause the Flickable to scroll (default true)
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool scrollFlickableTarget MEMBER m_scrollFlickableTarget NOTIFY scrollFlickableTargetChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit WheelHandler(QObject *parent = nullptr);
|
||||||
|
~WheelHandler() override;
|
||||||
|
|
||||||
|
QQuickItem *target() const;
|
||||||
|
void setTarget(QQuickItem *target);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void targetChanged();
|
||||||
|
void blockTargetWheelChanged();
|
||||||
|
void scrollFlickableTargetChanged();
|
||||||
|
void wheel(KirigamiWheelEvent *wheel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointer<QQuickItem> m_target;
|
||||||
|
bool m_blockTargetWheel = true;
|
||||||
|
bool m_scrollFlickableTarget = true;
|
||||||
|
KirigamiWheelEvent m_wheelEvent;
|
||||||
|
|
||||||
|
friend class GlobalWheelFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
2
src/3rdparty/libcrashreporter-qt
vendored
2
src/3rdparty/qtlockedfile/qtlockedfile.h
vendored
@@ -57,7 +57,7 @@ public:
|
|||||||
|
|
||||||
QtLockedFile();
|
QtLockedFile();
|
||||||
QtLockedFile(const QString &name);
|
QtLockedFile(const QString &name);
|
||||||
~QtLockedFile();
|
~QtLockedFile() override;
|
||||||
|
|
||||||
bool lock(LockMode mode, bool block = true);
|
bool lock(LockMode mode, bool block = true);
|
||||||
bool unlock();
|
bool unlock();
|
||||||
|
|||||||
@@ -44,13 +44,13 @@ class QtSingleApplication : public QApplication
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QtSingleApplication(const QString &id, int &argc, char **argv);
|
QtSingleApplication(const QString &id, int &argc, char **argv);
|
||||||
~QtSingleApplication();
|
~QtSingleApplication() override;
|
||||||
|
|
||||||
bool isRunning(qint64 pid = -1);
|
bool isRunning(qint64 pid = -1);
|
||||||
|
|
||||||
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
|
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
|
||||||
QWidget* activationWindow() const;
|
QWidget* activationWindow() const;
|
||||||
bool event(QEvent *event) Q_DECL_OVERRIDE;
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
QString applicationId() const;
|
QString applicationId() const;
|
||||||
void setBlock(bool value);
|
void setBlock(bool value);
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ endif()
|
|||||||
|
|
||||||
include(ECMEnableSanitizers)
|
include(ECMEnableSanitizers)
|
||||||
|
|
||||||
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
|
find_package(Qt5 5.15 COMPONENTS Core Network Xml Concurrent REQUIRED)
|
||||||
|
find_package(Qt5 5.15 COMPONENTS WebEngineWidgets WebEngine)
|
||||||
find_package(Qt5 5.12 COMPONENTS Core Network Xml Concurrent REQUIRED)
|
|
||||||
find_package(Qt5 5.12 COMPONENTS WebEngineWidgets WebEngine)
|
|
||||||
|
|
||||||
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||||
add_compile_definitions(WITH_WEBENGINE=1)
|
add_compile_definitions(WITH_WEBENGINE=1)
|
||||||
@@ -61,10 +59,6 @@ elseif(UNIX AND NOT APPLE)
|
|||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${CMAKE_SOURCE_DIR}/src/3rdparty
|
|
||||||
)
|
|
||||||
|
|
||||||
set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/theme CACHE STRING "" FORCE)
|
set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/theme CACHE STRING "" FORCE)
|
||||||
|
|
||||||
add_subdirectory(csync)
|
add_subdirectory(csync)
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
project(cmd)
|
project(cmd)
|
||||||
set(CMAKE_AUTOMOC TRUE)
|
set(CMAKE_AUTOMOC TRUE)
|
||||||
|
|
||||||
set(cmd_NAME ${APPLICATION_EXECUTABLE}cmd)
|
|
||||||
|
|
||||||
add_library(cmdCore STATIC simplesslerrorhandler.cpp netrcparser.cpp)
|
add_library(cmdCore STATIC simplesslerrorhandler.cpp netrcparser.cpp)
|
||||||
|
|
||||||
target_link_libraries(cmdCore
|
target_link_libraries(cmdCore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
"${csync_NAME}"
|
Nextcloud::sync
|
||||||
"${synclib_NAME}"
|
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Network
|
Qt5::Network
|
||||||
)
|
)
|
||||||
@@ -27,20 +24,22 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT BUILD_LIBRARIES_ONLY)
|
if(NOT BUILD_LIBRARIES_ONLY)
|
||||||
add_executable(${cmd_NAME} cmd.cpp)
|
add_executable(nextcloudcmd cmd.cpp)
|
||||||
|
set_target_properties(nextcloudcmd PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_NAME "${APPLICATION_EXECUTABLE}cmd")
|
||||||
|
|
||||||
|
target_link_libraries(nextcloudcmd cmdCore)
|
||||||
|
|
||||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
set_target_properties(${cmd_NAME} PROPERTIES
|
set_target_properties(nextcloudcmd PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS")
|
RUNTIME_OUTPUT_DIRECTORY "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS")
|
||||||
else()
|
else()
|
||||||
set_target_properties(${cmd_NAME} PROPERTIES
|
set_target_properties(nextcloudcmd PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY})
|
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY})
|
||||||
|
|
||||||
install(TARGETS ${cmd_NAME}
|
install(TARGETS nextcloudcmd
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${cmd_NAME} cmdCore)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
137
src/cmd/cmd.cpp
@@ -66,6 +66,7 @@ struct CmdOptions
|
|||||||
{
|
{
|
||||||
QString source_dir;
|
QString source_dir;
|
||||||
QString target_url;
|
QString target_url;
|
||||||
|
QString remotePath = QStringLiteral("/");
|
||||||
QString config_directory;
|
QString config_directory;
|
||||||
QString user;
|
QString user;
|
||||||
QString password;
|
QString password;
|
||||||
@@ -75,10 +76,8 @@ struct CmdOptions
|
|||||||
bool useNetrc;
|
bool useNetrc;
|
||||||
bool interactive;
|
bool interactive;
|
||||||
bool ignoreHiddenFiles;
|
bool ignoreHiddenFiles;
|
||||||
bool nonShib;
|
|
||||||
QString exclude;
|
QString exclude;
|
||||||
QString unsyncedfolders;
|
QString unsyncedfolders;
|
||||||
QString davPath;
|
|
||||||
int restartTimes;
|
int restartTimes;
|
||||||
int downlimit;
|
int downlimit;
|
||||||
int uplimit;
|
int uplimit;
|
||||||
@@ -143,7 +142,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void askFromUser() Q_DECL_OVERRIDE
|
void askFromUser() override
|
||||||
{
|
{
|
||||||
_password = ::queryPassword(user());
|
_password = ::queryPassword(user());
|
||||||
_ready = true;
|
_ready = true;
|
||||||
@@ -156,7 +155,7 @@ public:
|
|||||||
_sslTrusted = isTrusted;
|
_sslTrusted = isTrusted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sslIsTrusted() Q_DECL_OVERRIDE
|
bool sslIsTrusted() override
|
||||||
{
|
{
|
||||||
return _sslTrusted;
|
return _sslTrusted;
|
||||||
}
|
}
|
||||||
@@ -188,14 +187,13 @@ void help()
|
|||||||
std::cout << " --password, -p [pass] Use [pass] as password" << std::endl;
|
std::cout << " --password, -p [pass] Use [pass] as password" << std::endl;
|
||||||
std::cout << " -n Use netrc (5) for login" << std::endl;
|
std::cout << " -n Use netrc (5) for login" << std::endl;
|
||||||
std::cout << " --non-interactive Do not block execution with interaction" << std::endl;
|
std::cout << " --non-interactive Do not block execution with interaction" << std::endl;
|
||||||
std::cout << " --nonshib Use Non Shibboleth WebDAV authentication" << std::endl;
|
|
||||||
std::cout << " --davpath [path] Custom themed dav path, overrides --nonshib" << std::endl;
|
|
||||||
std::cout << " --max-sync-retries [n] Retries maximum n times (default to 3)" << std::endl;
|
std::cout << " --max-sync-retries [n] Retries maximum n times (default to 3)" << std::endl;
|
||||||
std::cout << " --uplimit [n] Limit the upload speed of files to n KB/s" << std::endl;
|
std::cout << " --uplimit [n] Limit the upload speed of files to n KB/s" << std::endl;
|
||||||
std::cout << " --downlimit [n] Limit the download speed of files to n KB/s" << std::endl;
|
std::cout << " --downlimit [n] Limit the download speed of files to n KB/s" << std::endl;
|
||||||
std::cout << " -h Sync hidden files, do not ignore them" << std::endl;
|
std::cout << " -h Sync hidden files, do not ignore them" << std::endl;
|
||||||
std::cout << " --version, -v Display version and exit" << std::endl;
|
std::cout << " --version, -v Display version and exit" << std::endl;
|
||||||
std::cout << " --logdebug More verbose logging" << std::endl;
|
std::cout << " --logdebug More verbose logging" << std::endl;
|
||||||
|
std::cout << " --path Path to a folder on a remote server" << std::endl;
|
||||||
std::cout << "" << std::endl;
|
std::cout << "" << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -263,10 +261,6 @@ void parseOptions(const QStringList &app_args, CmdOptions *options)
|
|||||||
options->exclude = it.next();
|
options->exclude = it.next();
|
||||||
} else if (option == "--unsyncedfolders" && !it.peekNext().startsWith("-")) {
|
} else if (option == "--unsyncedfolders" && !it.peekNext().startsWith("-")) {
|
||||||
options->unsyncedfolders = it.next();
|
options->unsyncedfolders = it.next();
|
||||||
} else if (option == "--nonshib") {
|
|
||||||
options->nonShib = true;
|
|
||||||
} else if (option == "--davpath" && !it.peekNext().startsWith("-")) {
|
|
||||||
options->davPath = it.next();
|
|
||||||
} else if (option == "--max-sync-retries" && !it.peekNext().startsWith("-")) {
|
} else if (option == "--max-sync-retries" && !it.peekNext().startsWith("-")) {
|
||||||
options->restartTimes = it.next().toInt();
|
options->restartTimes = it.next().toInt();
|
||||||
} else if (option == "--uplimit" && !it.peekNext().startsWith("-")) {
|
} else if (option == "--uplimit" && !it.peekNext().startsWith("-")) {
|
||||||
@@ -276,7 +270,10 @@ void parseOptions(const QStringList &app_args, CmdOptions *options)
|
|||||||
} else if (option == "--logdebug") {
|
} else if (option == "--logdebug") {
|
||||||
Logger::instance()->setLogFile("-");
|
Logger::instance()->setLogFile("-");
|
||||||
Logger::instance()->setLogDebug(true);
|
Logger::instance()->setLogDebug(true);
|
||||||
} else {
|
} else if (option == "--path" && !it.peekNext().startsWith("-")) {
|
||||||
|
options->remotePath = it.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
help();
|
help();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,9 +295,10 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
|||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
auto oldBlackListSet = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok).toSet();
|
const auto selectiveSyncList = journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok);
|
||||||
|
const QSet<QString> oldBlackListSet(selectiveSyncList.begin(), selectiveSyncList.end());
|
||||||
if (ok) {
|
if (ok) {
|
||||||
auto blackListSet = newList.toSet();
|
const QSet<QString> blackListSet(newList.begin(), newList.end());
|
||||||
const auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
const auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||||
for (const auto &it : changes) {
|
for (const auto &it : changes) {
|
||||||
journal->schedulePathForRemoteDiscovery(it);
|
journal->schedulePathForRemoteDiscovery(it);
|
||||||
@@ -312,6 +310,9 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
SetDllDirectory(L"");
|
||||||
|
#endif
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -320,15 +321,12 @@ int main(int argc, char **argv)
|
|||||||
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
|
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qsrand(std::random_device()());
|
|
||||||
|
|
||||||
CmdOptions options;
|
CmdOptions options;
|
||||||
options.silent = false;
|
options.silent = false;
|
||||||
options.trustSSL = false;
|
options.trustSSL = false;
|
||||||
options.useNetrc = false;
|
options.useNetrc = false;
|
||||||
options.interactive = true;
|
options.interactive = true;
|
||||||
options.ignoreHiddenFiles = false; // Default is to sync hidden files
|
options.ignoreHiddenFiles = false; // Default is to sync hidden files
|
||||||
options.nonShib = false;
|
|
||||||
options.restartTimes = 3;
|
options.restartTimes = 3;
|
||||||
options.uplimit = 0;
|
options.uplimit = 0;
|
||||||
options.downlimit = 0;
|
options.downlimit = 0;
|
||||||
@@ -347,24 +345,15 @@ int main(int argc, char **argv)
|
|||||||
qFatal("Could not initialize account!");
|
qFatal("Could not initialize account!");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
// check if the webDAV path was added to the url and append if not.
|
|
||||||
if (!options.target_url.endsWith("/")) {
|
if (options.target_url.contains("/webdav", Qt::CaseInsensitive) || options.target_url.contains("/dav", Qt::CaseInsensitive)) {
|
||||||
options.target_url.append("/");
|
qWarning("Dav or webdav in server URL.");
|
||||||
|
std::cerr << "Error! Please specify only the base URL of your host with username and password. Example:" << std::endl
|
||||||
|
<< "http(s)://username:password@cloud.example.com" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.nonShib) {
|
QUrl hostUrl = QUrl::fromUserInput((options.target_url.endsWith(QLatin1Char('/')) || options.target_url.endsWith(QLatin1Char('\\'))) ? options.target_url.chopped(1) : options.target_url);
|
||||||
account->setNonShib(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.davPath.isEmpty()) {
|
|
||||||
account->setDavPath(options.davPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.target_url.contains(account->davPath())) {
|
|
||||||
options.target_url.append(account->davPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl url = QUrl::fromUserInput(options.target_url);
|
|
||||||
|
|
||||||
// Order of retrieval attempt (later attempts override earlier ones):
|
// Order of retrieval attempt (later attempts override earlier ones):
|
||||||
// 1. From URL
|
// 1. From URL
|
||||||
@@ -372,8 +361,8 @@ int main(int argc, char **argv)
|
|||||||
// 3. From netrc (if enabled)
|
// 3. From netrc (if enabled)
|
||||||
// 4. From prompt (if interactive)
|
// 4. From prompt (if interactive)
|
||||||
|
|
||||||
QString user = url.userName();
|
QString user = hostUrl.userName();
|
||||||
QString password = url.password();
|
QString password = hostUrl.password();
|
||||||
|
|
||||||
if (!options.user.isEmpty()) {
|
if (!options.user.isEmpty()) {
|
||||||
user = options.user;
|
user = options.user;
|
||||||
@@ -386,7 +375,7 @@ int main(int argc, char **argv)
|
|||||||
if (options.useNetrc) {
|
if (options.useNetrc) {
|
||||||
NetrcParser parser;
|
NetrcParser parser;
|
||||||
if (parser.parse()) {
|
if (parser.parse()) {
|
||||||
NetrcParser::LoginPair pair = parser.find(url.host());
|
NetrcParser::LoginPair pair = parser.find(hostUrl.host());
|
||||||
user = pair.first;
|
user = pair.first;
|
||||||
password = pair.second;
|
password = pair.second;
|
||||||
}
|
}
|
||||||
@@ -404,24 +393,15 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// take the unmodified url to pass to csync_create()
|
|
||||||
QByteArray remUrl = options.target_url.toUtf8();
|
|
||||||
|
|
||||||
// Find the folder and the original owncloud url
|
// Find the folder and the original owncloud url
|
||||||
QStringList splitted = url.path().split("/" + account->davPath());
|
|
||||||
url.setPath(splitted.value(0));
|
|
||||||
|
|
||||||
url.setScheme(url.scheme().replace("owncloud", "http"));
|
hostUrl.setScheme(hostUrl.scheme().replace("owncloud", "http"));
|
||||||
|
|
||||||
QUrl credentialFreeUrl = url;
|
QUrl credentialFreeUrl = hostUrl;
|
||||||
credentialFreeUrl.setUserName(QString());
|
credentialFreeUrl.setUserName(QString());
|
||||||
credentialFreeUrl.setPassword(QString());
|
credentialFreeUrl.setPassword(QString());
|
||||||
|
|
||||||
// Remote folders typically start with a / and don't end with one
|
const QString folder = options.remotePath;
|
||||||
QString folder = "/" + splitted.value(1);
|
|
||||||
if (folder.endsWith("/") && folder != "/") {
|
|
||||||
folder.chop(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.proxy.isNull()) {
|
if (!options.proxy.isNull()) {
|
||||||
QString host;
|
QString host;
|
||||||
@@ -458,44 +438,36 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
account->setUrl(url);
|
account->setUrl(hostUrl);
|
||||||
account->setSslErrorHandler(sslErrorHandler);
|
account->setSslErrorHandler(sslErrorHandler);
|
||||||
|
|
||||||
// Perform a call to get the capabilities.
|
QEventLoop loop;
|
||||||
if (!options.nonShib) {
|
auto *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
|
||||||
// Do not do it if '--nonshib' was passed. This mean we should only connect to the 'nonshib'
|
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
|
||||||
// dav endpoint. Since we do not get the capabilities, in that case, this has the additional
|
auto caps = json.object().value("ocs").toObject().value("data").toObject().value("capabilities").toObject();
|
||||||
// side effect that chunking-ng will be disabled. (because otherwise it would use the new
|
qDebug() << "Server capabilities" << caps;
|
||||||
// 'dav' endpoint instead of the nonshib one (which still use the old chunking)
|
account->setCapabilities(caps.toVariantMap());
|
||||||
|
account->setServerVersion(caps["core"].toObject()["status"].toObject()["version"].toString());
|
||||||
|
loop.quit();
|
||||||
|
});
|
||||||
|
job->start();
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
QEventLoop loop;
|
if (job->reply()->error() != QNetworkReply::NoError){
|
||||||
auto *job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/capabilities"));
|
std::cout<<"Error connecting to server\n";
|
||||||
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
|
return EXIT_FAILURE;
|
||||||
auto caps = json.object().value("ocs").toObject().value("data").toObject().value("capabilities").toObject();
|
|
||||||
qDebug() << "Server capabilities" << caps;
|
|
||||||
account->setCapabilities(caps.toVariantMap());
|
|
||||||
account->setServerVersion(caps["core"].toObject()["status"].toObject()["version"].toString());
|
|
||||||
loop.quit();
|
|
||||||
});
|
|
||||||
job->start();
|
|
||||||
loop.exec();
|
|
||||||
|
|
||||||
if (job->reply()->error() != QNetworkReply::NoError){
|
|
||||||
std::cout<<"Error connecting to server\n";
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/user"));
|
|
||||||
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
|
|
||||||
const QJsonObject data = json.object().value("ocs").toObject().value("data").toObject();
|
|
||||||
account->setDavUser(data.value("id").toString());
|
|
||||||
account->setDavDisplayName(data.value("display-name").toString());
|
|
||||||
loop.quit();
|
|
||||||
});
|
|
||||||
job->start();
|
|
||||||
loop.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
job = new JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/user"));
|
||||||
|
QObject::connect(job, &JsonApiJob::jsonReceived, [&](const QJsonDocument &json) {
|
||||||
|
const QJsonObject data = json.object().value("ocs").toObject().value("data").toObject();
|
||||||
|
account->setDavUser(data.value("id").toString());
|
||||||
|
account->setDavDisplayName(data.value("display-name").toString());
|
||||||
|
loop.quit();
|
||||||
|
});
|
||||||
|
job->start();
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
// much lower age than the default since this utility is usually made to be run right after a change in the tests
|
// much lower age than the default since this utility is usually made to be run right after a change in the tests
|
||||||
SyncEngine::minimumFileAgeForUpload = std::chrono::milliseconds(0);
|
SyncEngine::minimumFileAgeForUpload = std::chrono::milliseconds(0);
|
||||||
|
|
||||||
@@ -511,7 +483,7 @@ restart_sync:
|
|||||||
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
|
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
|
||||||
} else {
|
} else {
|
||||||
// filter out empty lines and comments
|
// filter out empty lines and comments
|
||||||
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegExp("\\S+")).filter(QRegExp("^[^#]"));
|
selectiveSyncList = QString::fromUtf8(f.readAll()).split('\n').filter(QRegularExpression("\\S+")).filter(QRegularExpression("^[^#]"));
|
||||||
|
|
||||||
for (int i = 0; i < selectiveSyncList.count(); ++i) {
|
for (int i = 0; i < selectiveSyncList.count(); ++i) {
|
||||||
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
|
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
|
||||||
@@ -529,6 +501,9 @@ restart_sync:
|
|||||||
selectiveSyncFixup(&db, selectiveSyncList);
|
selectiveSyncFixup(&db, selectiveSyncList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncOptions opt;
|
||||||
|
opt.fillFromEnvironmentVariables();
|
||||||
|
opt.verifyChunkSizes();
|
||||||
SyncEngine engine(account, options.source_dir, folder, &db);
|
SyncEngine engine(account, options.source_dir, folder, &db);
|
||||||
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
||||||
engine.setNetworkLimits(options.uplimit, options.downlimit);
|
engine.setNetworkLimits(options.uplimit, options.downlimit);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OCC {
|
|||||||
class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler
|
class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr) Q_DECL_OVERRIDE;
|
bool handleErrors(QList<QSslError> errors, const QSslConfiguration &conf, QList<QSslCertificate> *certs, OCC::AccountPtr) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,21 +142,30 @@ QByteArray makeChecksumHeader(const QByteArray &checksumType, const QByteArray &
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray findBestChecksum(const QByteArray &checksums)
|
QByteArray findBestChecksum(const QByteArray &_checksums)
|
||||||
{
|
{
|
||||||
|
if (_checksums.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto checksums = QString::fromUtf8(_checksums);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// The order of the searches here defines the preference ordering.
|
// The order of the searches here defines the preference ordering.
|
||||||
if (-1 != (i = checksums.indexOf("SHA3-256:"))
|
if (-1 != (i = checksums.indexOf(QLatin1String("SHA3-256:"), 0, Qt::CaseInsensitive))
|
||||||
|| -1 != (i = checksums.indexOf("SHA256:"))
|
|| -1 != (i = checksums.indexOf(QLatin1String("SHA256:"), 0, Qt::CaseInsensitive))
|
||||||
|| -1 != (i = checksums.indexOf("SHA1:"))
|
|| -1 != (i = checksums.indexOf(QLatin1String("SHA1:"), 0, Qt::CaseInsensitive))
|
||||||
|| -1 != (i = checksums.indexOf("MD5:"))
|
|| -1 != (i = checksums.indexOf(QLatin1String("MD5:"), 0, Qt::CaseInsensitive))
|
||||||
|| -1 != (i = checksums.indexOf("Adler32:"))) {
|
|| -1 != (i = checksums.indexOf(QLatin1String("ADLER32:"), 0, Qt::CaseInsensitive))) {
|
||||||
// Now i is the start of the best checksum
|
// Now i is the start of the best checksum
|
||||||
// Grab it until the next space or end of string.
|
// Grab it until the next space or end of xml or end of string.
|
||||||
auto checksum = checksums.mid(i);
|
int end = _checksums.indexOf(' ', i);
|
||||||
return checksum.mid(0, checksum.indexOf(" "));
|
// workaround for https://github.com/owncloud/core/pull/38304
|
||||||
|
if (end == -1) {
|
||||||
|
end = _checksums.indexOf('<', i);
|
||||||
|
}
|
||||||
|
return _checksums.mid(i, end - i);
|
||||||
}
|
}
|
||||||
return QByteArray();
|
qCWarning(lcChecksums) << "Failed to parse" << _checksums;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseChecksumHeader(const QByteArray &header, QByteArray *type, QByteArray *checksum)
|
bool parseChecksumHeader(const QByteArray &header, QByteArray *type, QByteArray *checksum)
|
||||||
@@ -328,7 +337,7 @@ ComputeChecksum *ValidateChecksumHeader::prepareStart(const QByteArray &checksum
|
|||||||
|
|
||||||
if (!parseChecksumHeader(checksumHeader, &_expectedChecksumType, &_expectedChecksum)) {
|
if (!parseChecksumHeader(checksumHeader, &_expectedChecksumType, &_expectedChecksum)) {
|
||||||
qCWarning(lcChecksums) << "Checksum header malformed:" << checksumHeader;
|
qCWarning(lcChecksums) << "Checksum header malformed:" << checksumHeader;
|
||||||
emit validationFailed(tr("The checksum header is malformed."), {}, {}, _filePath);
|
emit validationFailed(tr("The checksum header is malformed."));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +350,6 @@ ComputeChecksum *ValidateChecksumHeader::prepareStart(const QByteArray &checksum
|
|||||||
|
|
||||||
void ValidateChecksumHeader::start(const QString &filePath, const QByteArray &checksumHeader)
|
void ValidateChecksumHeader::start(const QString &filePath, const QByteArray &checksumHeader)
|
||||||
{
|
{
|
||||||
_filePath = filePath;
|
|
||||||
if (auto calculator = prepareStart(checksumHeader))
|
if (auto calculator = prepareStart(checksumHeader))
|
||||||
calculator->start(filePath);
|
calculator->start(filePath);
|
||||||
}
|
}
|
||||||
@@ -356,11 +364,11 @@ void ValidateChecksumHeader::slotChecksumCalculated(const QByteArray &checksumTy
|
|||||||
const QByteArray &checksum)
|
const QByteArray &checksum)
|
||||||
{
|
{
|
||||||
if (checksumType != _expectedChecksumType) {
|
if (checksumType != _expectedChecksumType) {
|
||||||
emit validationFailed(tr("The checksum header contained an unknown checksum type '%1'").arg(QString::fromLatin1(_expectedChecksumType)), {}, {}, _filePath);
|
emit validationFailed(tr("The checksum header contained an unknown checksum type \"%1\"").arg(QString::fromLatin1(_expectedChecksumType)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (checksum != _expectedChecksum) {
|
if (checksum != _expectedChecksum) {
|
||||||
emit validationFailed(tr("The downloaded file does not match the checksum, it will be resumed. '%1' != '%2'").arg(QString::fromUtf8(_expectedChecksum), QString::fromUtf8(checksum)), checksumType, checksum, _filePath);
|
emit validationFailed(tr(R"(The downloaded file does not match the checksum, it will be resumed. "%1" != "%2")").arg(QString::fromUtf8(_expectedChecksum), QString::fromUtf8(checksum)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit validated(checksumType, checksum);
|
emit validated(checksumType, checksum);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class OCSYNC_EXPORT ComputeChecksum : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ComputeChecksum(QObject *parent = nullptr);
|
explicit ComputeChecksum(QObject *parent = nullptr);
|
||||||
~ComputeChecksum();
|
~ComputeChecksum() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the checksum type to be used. The default is empty.
|
* Sets the checksum type to be used. The default is empty.
|
||||||
@@ -163,7 +163,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void validated(const QByteArray &checksumType, const QByteArray &checksum);
|
void validated(const QByteArray &checksumType, const QByteArray &checksum);
|
||||||
void validationFailed(const QString &errMsg, const QByteArray &checksumType, const QByteArray &checksum, const QString &filePath);
|
void validationFailed(const QString &errMsg);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotChecksumCalculated(const QByteArray &checksumType, const QByteArray &checksum);
|
void slotChecksumCalculated(const QByteArray &checksumType, const QByteArray &checksum);
|
||||||
@@ -173,8 +173,6 @@ private:
|
|||||||
|
|
||||||
QByteArray _expectedChecksumType;
|
QByteArray _expectedChecksumType;
|
||||||
QByteArray _expectedChecksum;
|
QByteArray _expectedChecksum;
|
||||||
|
|
||||||
QString _filePath;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ set(common_SOURCES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/checksums.cpp
|
${CMAKE_CURRENT_LIST_DIR}/checksums.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
|
${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ownsql.cpp
|
${CMAKE_CURRENT_LIST_DIR}/ownsql.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/preparedsqlquerymanager.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/syncjournaldb.cpp
|
${CMAKE_CURRENT_LIST_DIR}/syncjournaldb.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/syncjournalfilerecord.cpp
|
${CMAKE_CURRENT_LIST_DIR}/syncjournalfilerecord.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/utility.cpp
|
${CMAKE_CURRENT_LIST_DIR}/utility.cpp
|
||||||
|
|||||||
23
src/common/constants.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Oleksandr Zolotov <alex@nextcloud.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
namespace OCC {
|
||||||
|
namespace Constants {
|
||||||
|
constexpr qint32 e2EeTagSize = 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -395,13 +395,13 @@ bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
|
|||||||
suffix_number++;
|
suffix_number++;
|
||||||
}
|
}
|
||||||
if (!file.rename(f.absoluteFilePath(), path + QString::number(suffix_number))) { // rename(file old path, file trash path)
|
if (!file.rename(f.absoluteFilePath(), path + QString::number(suffix_number))) { // rename(file old path, file trash path)
|
||||||
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
|
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
|
||||||
.arg(f.absoluteFilePath(), path + QString::number(suffix_number));
|
.arg(f.absoluteFilePath(), path + QString::number(suffix_number));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!file.rename(f.absoluteFilePath(), trashFilePath + f.fileName())) { // rename(file old path, file trash path)
|
if (!file.rename(f.absoluteFilePath(), trashFilePath + f.fileName())) { // rename(file old path, file trash path)
|
||||||
*errorString = QCoreApplication::translate("FileSystem", "Could not move '%1' to '%2'")
|
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
|
||||||
.arg(f.absoluteFilePath(), trashFilePath + f.fileName());
|
.arg(f.absoluteFilePath(), trashFilePath + f.fileName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -490,18 +490,4 @@ void SqlQuery::reset_and_clear_bindings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SqlQuery::initOrReset(const QByteArray &sql, OCC::SqlDatabase &db)
|
|
||||||
{
|
|
||||||
ENFORCE(!_sqldb || &db == _sqldb);
|
|
||||||
_sqldb = &db;
|
|
||||||
_db = db.sqliteDb();
|
|
||||||
if (_stmt) {
|
|
||||||
reset_and_clear_bindings();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return prepare(sql) == 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|||||||
@@ -103,12 +103,6 @@ public:
|
|||||||
explicit SqlQuery() = default;
|
explicit SqlQuery() = default;
|
||||||
explicit SqlQuery(SqlDatabase &db);
|
explicit SqlQuery(SqlDatabase &db);
|
||||||
explicit SqlQuery(const QByteArray &sql, SqlDatabase &db);
|
explicit SqlQuery(const QByteArray &sql, SqlDatabase &db);
|
||||||
/**
|
|
||||||
* Prepare the SqlQuery if it was not prepared yet.
|
|
||||||
* Otherwise, clear the results and the bindings.
|
|
||||||
* return false if there is an error
|
|
||||||
*/
|
|
||||||
bool initOrReset(const QByteArray &sql, SqlDatabase &db);
|
|
||||||
/**
|
/**
|
||||||
* Prepare the SqlQuery.
|
* Prepare the SqlQuery.
|
||||||
* If the query was already prepared, this will first call finish(), and re-prepare it.
|
* If the query was already prepared, this will first call finish(), and re-prepare it.
|
||||||
@@ -161,10 +155,10 @@ public:
|
|||||||
const QByteArray &lastQuery() const;
|
const QByteArray &lastQuery() const;
|
||||||
int numRowsAffected();
|
int numRowsAffected();
|
||||||
void reset_and_clear_bindings();
|
void reset_and_clear_bindings();
|
||||||
void finish();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void bindValueInternal(int pos, const QVariant &value);
|
void bindValueInternal(int pos, const QVariant &value);
|
||||||
|
void finish();
|
||||||
|
|
||||||
SqlDatabase *_sqldb = nullptr;
|
SqlDatabase *_sqldb = nullptr;
|
||||||
sqlite3 *_db = nullptr;
|
sqlite3 *_db = nullptr;
|
||||||
@@ -172,6 +166,9 @@ private:
|
|||||||
QString _error;
|
QString _error;
|
||||||
int _errId;
|
int _errId;
|
||||||
QByteArray _sql;
|
QByteArray _sql;
|
||||||
|
|
||||||
|
friend class SqlDatabase;
|
||||||
|
friend class PreparedSqlQueryManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ enum class PinState {
|
|||||||
*/
|
*/
|
||||||
Unspecified = 3,
|
Unspecified = 3,
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(PinState);
|
Q_ENUM_NS(PinState)
|
||||||
|
|
||||||
/** A user-facing version of PinState.
|
/** A user-facing version of PinState.
|
||||||
*
|
*
|
||||||
|
|||||||
56
src/common/preparedsqlquerymanager.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "preparedsqlquerymanager.h"
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
using namespace OCC;
|
||||||
|
|
||||||
|
PreparedSqlQuery::PreparedSqlQuery(SqlQuery *query, bool ok)
|
||||||
|
: _query(query)
|
||||||
|
, _ok(ok)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PreparedSqlQuery::~PreparedSqlQuery()
|
||||||
|
{
|
||||||
|
_query->reset_and_clear_bindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
const PreparedSqlQuery PreparedSqlQueryManager::get(PreparedSqlQueryManager::Key key)
|
||||||
|
{
|
||||||
|
auto &query = _queries[key];
|
||||||
|
ENFORCE(query._stmt)
|
||||||
|
Q_ASSERT(!sqlite3_stmt_busy(query._stmt));
|
||||||
|
return { &query };
|
||||||
|
}
|
||||||
|
|
||||||
|
const PreparedSqlQuery PreparedSqlQueryManager::get(PreparedSqlQueryManager::Key key, const QByteArray &sql, SqlDatabase &db)
|
||||||
|
{
|
||||||
|
auto &query = _queries[key];
|
||||||
|
Q_ASSERT(!sqlite3_stmt_busy(query._stmt));
|
||||||
|
ENFORCE(!query._sqldb || &db == query._sqldb)
|
||||||
|
if (!query._stmt) {
|
||||||
|
query._sqldb = &db;
|
||||||
|
query._db = db.sqliteDb();
|
||||||
|
return { &query, query.prepare(sql) == 0 };
|
||||||
|
}
|
||||||
|
return { &query };
|
||||||
|
}
|
||||||
119
src/common/preparedsqlquerymanager.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ocsynclib.h"
|
||||||
|
#include "ownsql.h"
|
||||||
|
#include "common/asserts.h"
|
||||||
|
|
||||||
|
namespace OCC {
|
||||||
|
|
||||||
|
class OCSYNC_EXPORT PreparedSqlQuery
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~PreparedSqlQuery();
|
||||||
|
|
||||||
|
explicit operator bool() const { return _ok; }
|
||||||
|
|
||||||
|
SqlQuery *operator->() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(_ok);
|
||||||
|
return _query;
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlQuery &operator*() const &
|
||||||
|
{
|
||||||
|
Q_ASSERT(_ok);
|
||||||
|
return *_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PreparedSqlQuery(SqlQuery *query, bool ok = true);
|
||||||
|
|
||||||
|
SqlQuery *_query;
|
||||||
|
bool _ok;
|
||||||
|
|
||||||
|
friend class PreparedSqlQueryManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Manage PreparedSqlQuery
|
||||||
|
*/
|
||||||
|
class OCSYNC_EXPORT PreparedSqlQueryManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Key {
|
||||||
|
GetFileRecordQuery,
|
||||||
|
GetFileRecordQueryByMangledName,
|
||||||
|
GetFileRecordQueryByInode,
|
||||||
|
GetFileRecordQueryByFileId,
|
||||||
|
GetFilesBelowPathQuery,
|
||||||
|
GetAllFilesQuery,
|
||||||
|
ListFilesInPathQuery,
|
||||||
|
SetFileRecordQuery,
|
||||||
|
SetFileRecordChecksumQuery,
|
||||||
|
SetFileRecordLocalMetadataQuery,
|
||||||
|
GetDownloadInfoQuery,
|
||||||
|
SetDownloadInfoQuery,
|
||||||
|
DeleteDownloadInfoQuery,
|
||||||
|
GetUploadInfoQuery,
|
||||||
|
SetUploadInfoQuery,
|
||||||
|
DeleteUploadInfoQuery,
|
||||||
|
DeleteFileRecordPhash,
|
||||||
|
DeleteFileRecordRecursively,
|
||||||
|
GetErrorBlacklistQuery,
|
||||||
|
SetErrorBlacklistQuery,
|
||||||
|
GetSelectiveSyncListQuery,
|
||||||
|
GetChecksumTypeIdQuery,
|
||||||
|
GetChecksumTypeQuery,
|
||||||
|
InsertChecksumTypeQuery,
|
||||||
|
GetDataFingerprintQuery,
|
||||||
|
SetDataFingerprintQuery1,
|
||||||
|
SetDataFingerprintQuery2,
|
||||||
|
SetKeyValueStoreQuery,
|
||||||
|
GetKeyValueStoreQuery,
|
||||||
|
DeleteKeyValueStoreQuery,
|
||||||
|
GetConflictRecordQuery,
|
||||||
|
SetConflictRecordQuery,
|
||||||
|
DeleteConflictRecordQuery,
|
||||||
|
GetRawPinStateQuery,
|
||||||
|
GetEffectivePinStateQuery,
|
||||||
|
GetSubPinsQuery,
|
||||||
|
CountDehydratedFilesQuery,
|
||||||
|
SetPinStateQuery,
|
||||||
|
WipePinStateQuery,
|
||||||
|
|
||||||
|
PreparedQueryCount
|
||||||
|
};
|
||||||
|
PreparedSqlQueryManager() = default;
|
||||||
|
/**
|
||||||
|
* The queries are reset in the destructor to prevent wal locks
|
||||||
|
*/
|
||||||
|
const PreparedSqlQuery get(Key key);
|
||||||
|
/**
|
||||||
|
* Prepare the SqlQuery if it was not prepared yet.
|
||||||
|
*/
|
||||||
|
const PreparedSqlQuery get(Key key, const QByteArray &sql, SqlDatabase &db);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SqlQuery _queries[PreparedQueryCount];
|
||||||
|
Q_DISABLE_COPY(PreparedSqlQueryManager)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -99,7 +99,7 @@ public:
|
|||||||
|
|
||||||
friend QDebug operator<<(QDebug &dbg, RemotePermissions p)
|
friend QDebug operator<<(QDebug &dbg, RemotePermissions p)
|
||||||
{
|
{
|
||||||
return dbg << p.toString().constData();
|
return dbg << p.toString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ public:
|
|||||||
ASSERT(!_isError);
|
ASSERT(!_isError);
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
T operator*() &&
|
T operator*() &&
|
||||||
{
|
{
|
||||||
ASSERT(!_isError);
|
ASSERT(!_isError);
|
||||||
@@ -116,6 +117,12 @@ public:
|
|||||||
return &_result;
|
return &_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const T &get() const
|
||||||
|
{
|
||||||
|
ASSERT(!_isError)
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
|
||||||
const Error &error() const &
|
const Error &error() const &
|
||||||
{
|
{
|
||||||
ASSERT(_isError);
|
ASSERT(_isError);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "common/utility.h"
|
#include "common/utility.h"
|
||||||
#include "common/ownsql.h"
|
#include "common/ownsql.h"
|
||||||
|
#include "common/preparedsqlquerymanager.h"
|
||||||
#include "common/syncjournalfilerecord.h"
|
#include "common/syncjournalfilerecord.h"
|
||||||
#include "common/result.h"
|
#include "common/result.h"
|
||||||
#include "common/pinstate.h"
|
#include "common/pinstate.h"
|
||||||
@@ -46,7 +47,7 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SyncJournalDb(const QString &dbFilePath, QObject *parent = nullptr);
|
explicit SyncJournalDb(const QString &dbFilePath, QObject *parent = nullptr);
|
||||||
virtual ~SyncJournalDb();
|
~SyncJournalDb() override;
|
||||||
|
|
||||||
/// Create a journal path for a specific configuration
|
/// Create a journal path for a specific configuration
|
||||||
static QString makeDbName(const QString &localPath,
|
static QString makeDbName(const QString &localPath,
|
||||||
@@ -69,7 +70,6 @@ public:
|
|||||||
|
|
||||||
void keyValueStoreSet(const QString &key, QVariant value);
|
void keyValueStoreSet(const QString &key, QVariant value);
|
||||||
qint64 keyValueStoreGetInt(const QString &key, qint64 defaultValue);
|
qint64 keyValueStoreGetInt(const QString &key, qint64 defaultValue);
|
||||||
QVariant keyValueStoreGet(const QString &key, QVariant defaultValue = {});
|
|
||||||
void keyValueStoreDelete(const QString &key);
|
void keyValueStoreDelete(const QString &key);
|
||||||
|
|
||||||
bool deleteFileRecord(const QString &filename, bool recursively = false);
|
bool deleteFileRecord(const QString &filename, bool recursively = false);
|
||||||
@@ -392,51 +392,11 @@ private:
|
|||||||
|
|
||||||
SqlDatabase _db;
|
SqlDatabase _db;
|
||||||
QString _dbFile;
|
QString _dbFile;
|
||||||
QMutex _mutex; // Public functions are protected with the mutex.
|
QRecursiveMutex _mutex; // Public functions are protected with the mutex.
|
||||||
QMap<QByteArray, int> _checksymTypeCache;
|
QMap<QByteArray, int> _checksymTypeCache;
|
||||||
int _transaction;
|
int _transaction;
|
||||||
bool _metadataTableIsEmpty;
|
bool _metadataTableIsEmpty;
|
||||||
|
|
||||||
SqlQuery _getFileRecordQuery;
|
|
||||||
SqlQuery _getFileRecordQueryByMangledName;
|
|
||||||
SqlQuery _getFileRecordQueryByInode;
|
|
||||||
SqlQuery _getFileRecordQueryByFileId;
|
|
||||||
SqlQuery _getFilesBelowPathQuery;
|
|
||||||
SqlQuery _getAllFilesQuery;
|
|
||||||
SqlQuery _listFilesInPathQuery;
|
|
||||||
SqlQuery _setFileRecordQuery;
|
|
||||||
SqlQuery _setFileRecordChecksumQuery;
|
|
||||||
SqlQuery _setFileRecordLocalMetadataQuery;
|
|
||||||
SqlQuery _getDownloadInfoQuery;
|
|
||||||
SqlQuery _setDownloadInfoQuery;
|
|
||||||
SqlQuery _deleteDownloadInfoQuery;
|
|
||||||
SqlQuery _getUploadInfoQuery;
|
|
||||||
SqlQuery _setUploadInfoQuery;
|
|
||||||
SqlQuery _deleteUploadInfoQuery;
|
|
||||||
SqlQuery _deleteFileRecordPhash;
|
|
||||||
SqlQuery _deleteFileRecordRecursively;
|
|
||||||
SqlQuery _getErrorBlacklistQuery;
|
|
||||||
SqlQuery _setErrorBlacklistQuery;
|
|
||||||
SqlQuery _getSelectiveSyncListQuery;
|
|
||||||
SqlQuery _getChecksumTypeIdQuery;
|
|
||||||
SqlQuery _getChecksumTypeQuery;
|
|
||||||
SqlQuery _insertChecksumTypeQuery;
|
|
||||||
SqlQuery _getDataFingerprintQuery;
|
|
||||||
SqlQuery _setDataFingerprintQuery1;
|
|
||||||
SqlQuery _setDataFingerprintQuery2;
|
|
||||||
SqlQuery _setKeyValueStoreQuery;
|
|
||||||
SqlQuery _getKeyValueStoreQuery;
|
|
||||||
SqlQuery _deleteKeyValueStoreQuery;
|
|
||||||
SqlQuery _getConflictRecordQuery;
|
|
||||||
SqlQuery _setConflictRecordQuery;
|
|
||||||
SqlQuery _deleteConflictRecordQuery;
|
|
||||||
SqlQuery _getRawPinStateQuery;
|
|
||||||
SqlQuery _getEffectivePinStateQuery;
|
|
||||||
SqlQuery _getSubPinsQuery;
|
|
||||||
SqlQuery _countDehydratedFilesQuery;
|
|
||||||
SqlQuery _setPinStateQuery;
|
|
||||||
SqlQuery _wipePinStateQuery;
|
|
||||||
|
|
||||||
/* Storing etags to these folders, or their parent folders, is filtered out.
|
/* Storing etags to these folders, or their parent folders, is filtered out.
|
||||||
*
|
*
|
||||||
* When schedulePathForRemoteDiscovery() is called some etags to _invalid_ in the
|
* When schedulePathForRemoteDiscovery() is called some etags to _invalid_ in the
|
||||||
@@ -458,6 +418,8 @@ private:
|
|||||||
* variable, for specific filesystems, or when WAL fails in a particular way.
|
* variable, for specific filesystems, or when WAL fails in a particular way.
|
||||||
*/
|
*/
|
||||||
QByteArray _journalMode;
|
QByteArray _journalMode;
|
||||||
|
|
||||||
|
PreparedSqlQueryManager _queryManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool OCSYNC_EXPORT
|
bool OCSYNC_EXPORT
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QCollator>
|
#include <QCollator>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
|
#include <qrandom.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
@@ -64,14 +65,13 @@ Q_LOGGING_CATEGORY(lcUtility, "nextcloud.sync.utility", QtInfoMsg)
|
|||||||
bool Utility::writeRandomFile(const QString &fname, int size)
|
bool Utility::writeRandomFile(const QString &fname, int size)
|
||||||
{
|
{
|
||||||
int maxSize = 10 * 10 * 1024;
|
int maxSize = 10 * 10 * 1024;
|
||||||
qsrand(QDateTime::currentMSecsSinceEpoch());
|
|
||||||
|
|
||||||
if (size == -1)
|
if (size == -1)
|
||||||
size = qrand() % maxSize;
|
size = rand() % maxSize;
|
||||||
|
|
||||||
QString randString;
|
QString randString;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
int r = qrand() % 128;
|
int r = rand() % 128;
|
||||||
randString.append(QChar(r));
|
randString.append(QChar(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +109,11 @@ void Utility::setupFavLink(const QString &folder)
|
|||||||
setupFavLink_private(folder);
|
setupFavLink_private(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utility::removeFavLink(const QString &folder)
|
||||||
|
{
|
||||||
|
removeFavLink_private(folder);
|
||||||
|
}
|
||||||
|
|
||||||
QString Utility::octetsToString(qint64 octets)
|
QString Utility::octetsToString(qint64 octets)
|
||||||
{
|
{
|
||||||
#define THE_FACTOR 1024
|
#define THE_FACTOR 1024
|
||||||
@@ -259,6 +264,11 @@ QString Utility::escape(const QString &in)
|
|||||||
return in.toHtmlEscaped();
|
return in.toHtmlEscaped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Utility::rand()
|
||||||
|
{
|
||||||
|
return QRandomGenerator::global()->bounded(0, RAND_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
void Utility::sleep(int sec)
|
void Utility::sleep(int sec)
|
||||||
{
|
{
|
||||||
QThread::sleep(sec);
|
QThread::sleep(sec);
|
||||||
|
|||||||
@@ -50,10 +50,12 @@ Q_DECLARE_LOGGING_CATEGORY(lcUtility)
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
namespace Utility {
|
namespace Utility {
|
||||||
|
OCSYNC_EXPORT int rand();
|
||||||
OCSYNC_EXPORT void sleep(int sec);
|
OCSYNC_EXPORT void sleep(int sec);
|
||||||
OCSYNC_EXPORT void usleep(int usec);
|
OCSYNC_EXPORT void usleep(int usec);
|
||||||
OCSYNC_EXPORT QString formatFingerprint(const QByteArray &, bool colonSeparated = true);
|
OCSYNC_EXPORT QString formatFingerprint(const QByteArray &, bool colonSeparated = true);
|
||||||
OCSYNC_EXPORT void setupFavLink(const QString &folder);
|
OCSYNC_EXPORT void setupFavLink(const QString &folder);
|
||||||
|
OCSYNC_EXPORT void removeFavLink(const QString &folder);
|
||||||
OCSYNC_EXPORT bool writeRandomFile(const QString &fname, int size = -1);
|
OCSYNC_EXPORT bool writeRandomFile(const QString &fname, int size = -1);
|
||||||
OCSYNC_EXPORT QString octetsToString(qint64 octets);
|
OCSYNC_EXPORT QString octetsToString(qint64 octets);
|
||||||
OCSYNC_EXPORT QByteArray userAgentString();
|
OCSYNC_EXPORT QByteArray userAgentString();
|
||||||
@@ -240,6 +242,11 @@ namespace Utility {
|
|||||||
*/
|
*/
|
||||||
OCSYNC_EXPORT bool isPathWindowsDrivePartitionRoot(const QString &path);
|
OCSYNC_EXPORT bool isPathWindowsDrivePartitionRoot(const QString &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves current logged-in user name from the OS
|
||||||
|
*/
|
||||||
|
OCSYNC_EXPORT QString getCurrentUserName();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
OCSYNC_EXPORT bool registryKeyExists(HKEY hRootKey, const QString &subKey);
|
OCSYNC_EXPORT bool registryKeyExists(HKEY hRootKey, const QString &subKey);
|
||||||
OCSYNC_EXPORT QVariant registryGetKeyValue(HKEY hRootKey, const QString &subKey, const QString &valueName);
|
OCSYNC_EXPORT QVariant registryGetKeyValue(HKEY hRootKey, const QString &subKey, const QString &valueName);
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ static void setupFavLink_private(const QString &folder)
|
|||||||
CFRelease(urlRef);
|
CFRelease(urlRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void removeFavLink_private(const QString &folder)
|
||||||
|
{
|
||||||
|
Q_UNUSED(folder)
|
||||||
|
}
|
||||||
|
|
||||||
bool hasLaunchOnStartup_private(const QString &)
|
bool hasLaunchOnStartup_private(const QString &)
|
||||||
{
|
{
|
||||||
// this is quite some duplicate code with setLaunchOnStartup, at some point we should fix this FIXME.
|
// this is quite some duplicate code with setLaunchOnStartup, at some point we should fix this FIXME.
|
||||||
@@ -131,4 +136,9 @@ static bool hasDarkSystray_private()
|
|||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utility::getCurrentUserName()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ static void setupFavLink_private(const QString &folder)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void removeFavLink_private(const QString &folder)
|
||||||
|
{
|
||||||
|
Q_UNUSED(folder)
|
||||||
|
}
|
||||||
|
|
||||||
// returns the autostart directory the linux way
|
// returns the autostart directory the linux way
|
||||||
// and respects the XDG_CONFIG_HOME env variable
|
// and respects the XDG_CONFIG_HOME env variable
|
||||||
QString getUserAutostartDir_private()
|
QString getUserAutostartDir_private()
|
||||||
@@ -80,17 +85,17 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
|
|||||||
|
|
||||||
QTextStream ts(&iniFile);
|
QTextStream ts(&iniFile);
|
||||||
ts.setCodec("UTF-8");
|
ts.setCodec("UTF-8");
|
||||||
ts << QLatin1String("[Desktop Entry]") << endl
|
ts << QLatin1String("[Desktop Entry]\n")
|
||||||
<< QLatin1String("Name=") << guiName << endl
|
<< QLatin1String("Name=") << guiName << QLatin1Char('\n')
|
||||||
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer") << endl
|
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer\n")
|
||||||
<< QLatin1String("Exec=\"") << executablePath << "\" --background" << endl
|
<< QLatin1String("Exec=\"") << executablePath << "\" --background\n"
|
||||||
<< QLatin1String("Terminal=") << "false" << endl
|
<< QLatin1String("Terminal=") << "false\n"
|
||||||
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << endl
|
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << QLatin1Char('\n')
|
||||||
<< QLatin1String("Categories=") << QLatin1String("Network") << endl
|
<< QLatin1String("Categories=") << QLatin1String("Network\n")
|
||||||
<< QLatin1String("Type=") << QLatin1String("Application") << endl
|
<< QLatin1String("Type=") << QLatin1String("Application\n")
|
||||||
<< QLatin1String("StartupNotify=") << "false" << endl
|
<< QLatin1String("StartupNotify=") << "false\n"
|
||||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl
|
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true\n"
|
||||||
<< QLatin1String("X-GNOME-Autostart-Delay=10") << endl;
|
<< QLatin1String("X-GNOME-Autostart-Delay=10") << Qt::endl;
|
||||||
} else {
|
} else {
|
||||||
if (!QFile::remove(desktopFileLocation)) {
|
if (!QFile::remove(desktopFileLocation)) {
|
||||||
qCWarning(lcUtility) << "Could not remove autostart desktop file";
|
qCWarning(lcUtility) << "Could not remove autostart desktop file";
|
||||||
@@ -103,4 +108,9 @@ static inline bool hasDarkSystray_private()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utility::getCurrentUserName()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
|
#include <Lmcons.h>
|
||||||
#include <shlguid.h>
|
#include <shlguid.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -74,6 +75,40 @@ static void setupFavLink_private(const QString &folder)
|
|||||||
qCWarning(lcUtility) << "linking" << folder << "to" << linkName << "failed!";
|
qCWarning(lcUtility) << "linking" << folder << "to" << linkName << "failed!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void removeFavLink_private(const QString &folder)
|
||||||
|
{
|
||||||
|
const QDir folderDir(folder);
|
||||||
|
|
||||||
|
// #1 Remove the Desktop.ini to reset the folder icon
|
||||||
|
if (!QFile::remove(folderDir.absoluteFilePath(QLatin1String("Desktop.ini")))) {
|
||||||
|
qCWarning(lcUtility) << "Remove Desktop.ini from" << folder
|
||||||
|
<< " has failed. Make sure it exists and is not locked by another process.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// #2 Remove the system file attribute
|
||||||
|
const auto folderAttrs = GetFileAttributesW(folder.toStdWString().c_str());
|
||||||
|
if (!SetFileAttributesW(folder.toStdWString().c_str(), folderAttrs & ~FILE_ATTRIBUTE_SYSTEM)) {
|
||||||
|
qCWarning(lcUtility) << "Remove system file attribute failed for:" << folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #3 Remove the link to this folder
|
||||||
|
PWSTR path;
|
||||||
|
if (!SHGetKnownFolderPath(FOLDERID_Links, 0, nullptr, &path) == S_OK) {
|
||||||
|
qCWarning(lcUtility) << "SHGetKnownFolderPath for " << folder << "has failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QDir links(QString::fromWCharArray(path));
|
||||||
|
CoTaskMemFree(path);
|
||||||
|
|
||||||
|
const auto linkName = QDir(links).absoluteFilePath(folderDir.dirName() + QLatin1String(".lnk"));
|
||||||
|
|
||||||
|
qCInfo(lcUtility) << "Removing favorite link from" << folder << "to" << linkName;
|
||||||
|
if (!QFile::remove(linkName)) {
|
||||||
|
qCWarning(lcUtility) << "Removing a favorite link from" << folder << "to" << linkName << "failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool hasSystemLaunchOnStartup_private(const QString &appName)
|
bool hasSystemLaunchOnStartup_private(const QString &appName)
|
||||||
{
|
{
|
||||||
QString runPath = QLatin1String(systemRunPathC);
|
QString runPath = QLatin1String(systemRunPathC);
|
||||||
@@ -346,6 +381,17 @@ QString Utility::formatWinError(long errorCode)
|
|||||||
return QStringLiteral("WindowsError: %1: %2").arg(QString::number(errorCode, 16), QString::fromWCharArray(_com_error(errorCode).ErrorMessage()));
|
return QStringLiteral("WindowsError: %1: %2").arg(QString::number(errorCode, 16), QString::fromWCharArray(_com_error(errorCode).ErrorMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utility::getCurrentUserName()
|
||||||
|
{
|
||||||
|
TCHAR username[UNLEN + 1] = {0};
|
||||||
|
DWORD len = sizeof(username) / sizeof(TCHAR);
|
||||||
|
|
||||||
|
if (!GetUserName(username, &len)) {
|
||||||
|
qCWarning(lcUtility) << "Could not retrieve Windows user name." << formatWinError(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::fromWCharArray(username);
|
||||||
|
}
|
||||||
|
|
||||||
Utility::NtfsPermissionLookupRAII::NtfsPermissionLookupRAII()
|
Utility::NtfsPermissionLookupRAII::NtfsPermissionLookupRAII()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Vfs(QObject* parent = nullptr);
|
explicit Vfs(QObject* parent = nullptr);
|
||||||
virtual ~Vfs();
|
~Vfs() override;
|
||||||
|
|
||||||
virtual Mode mode() const = 0;
|
virtual Mode mode() const = 0;
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ class OCSYNC_EXPORT VfsOff : public Vfs
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VfsOff(QObject* parent = nullptr);
|
VfsOff(QObject* parent = nullptr);
|
||||||
virtual ~VfsOff();
|
~VfsOff() override;
|
||||||
|
|
||||||
Mode mode() const override { return Vfs::Off; }
|
Mode mode() const override { return Vfs::Off; }
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
#include <libcrashreporter-gui/CrashReporter.h>
|
#include <libcrashreporter-gui/CrashReporter.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDir>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,14 @@ int main(int argc, char *argv[])
|
|||||||
reporter.setWindowTitle(CRASHREPORTER_PRODUCT_NAME);
|
reporter.setWindowTitle(CRASHREPORTER_PRODUCT_NAME);
|
||||||
reporter.setText("<html><head/><body><p><span style=\" font-weight:600;\">Sorry!</span> " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.</p></body></html>");
|
reporter.setText("<html><head/><body><p><span style=\" font-weight:600;\">Sorry!</span> " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.</p></body></html>");
|
||||||
|
|
||||||
|
const QFileInfo crashLog(QDir::tempPath() + QStringLiteral("/" CRASHREPORTER_PRODUCT_NAME "-crash.log"));
|
||||||
|
if (crashLog.exists()) {
|
||||||
|
QFile inFile(crashLog.filePath());
|
||||||
|
if (inFile.open(QFile::ReadOnly)) {
|
||||||
|
reporter.setComment(inFile.readAll());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reporter.setReportData("BuildID", CRASHREPORTER_BUILD_ID);
|
reporter.setReportData("BuildID", CRASHREPORTER_BUILD_ID);
|
||||||
reporter.setReportData("ProductName", CRASHREPORTER_PRODUCT_NAME);
|
reporter.setReportData("ProductName", CRASHREPORTER_PRODUCT_NAME);
|
||||||
reporter.setReportData("Version", CRASHREPORTER_VERSION_STRING);
|
reporter.setReportData("Version", CRASHREPORTER_VERSION_STRING);
|
||||||
|
|||||||
@@ -58,10 +58,11 @@ endif()
|
|||||||
|
|
||||||
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
|
configure_file(csync_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/csync_version.h)
|
||||||
|
|
||||||
add_library("${csync_NAME}" SHARED ${common_SOURCES} ${csync_SRCS})
|
add_library(nextcloud_csync SHARED ${common_SOURCES} ${csync_SRCS})
|
||||||
|
add_library(Nextcloud::csync ALIAS nextcloud_csync)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
"${csync_NAME}"
|
nextcloud_csync
|
||||||
PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/std
|
PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/std
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -69,26 +70,26 @@ if(USE_OUR_OWN_SQLITE3)
|
|||||||
message(STATUS "Using own sqlite3 version")
|
message(STATUS "Using own sqlite3 version")
|
||||||
add_library(sqlite3 STATIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3/sqlite3.c")
|
add_library(sqlite3 STATIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3/sqlite3.c")
|
||||||
target_include_directories(sqlite3 PUBLIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3")
|
target_include_directories(sqlite3 PUBLIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3")
|
||||||
target_link_libraries("${csync_NAME}" PUBLIC sqlite3)
|
target_link_libraries(nextcloud_csync PUBLIC sqlite3)
|
||||||
else()
|
else()
|
||||||
target_include_directories("${csync_NAME}" PUBLIC ${SQLITE3_INCLUDE_DIR})
|
target_include_directories(nextcloud_csync PUBLIC ${SQLITE3_INCLUDE_DIR})
|
||||||
target_link_libraries("${csync_NAME}" PUBLIC ${SQLITE3_LIBRARIES})
|
target_link_libraries(nextcloud_csync PUBLIC ${SQLITE3_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
generate_export_header("${csync_NAME}"
|
generate_export_header(nextcloud_csync
|
||||||
EXPORT_MACRO_NAME OCSYNC_EXPORT
|
EXPORT_MACRO_NAME OCSYNC_EXPORT
|
||||||
EXPORT_FILE_NAME ocsynclib.h
|
EXPORT_FILE_NAME ocsynclib.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries("${csync_NAME}"
|
target_link_libraries(nextcloud_csync
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${CSYNC_REQUIRED_LIBRARIES}
|
${CSYNC_REQUIRED_LIBRARIES}
|
||||||
Qt5::Core Qt5::Concurrent
|
Qt5::Core Qt5::Concurrent
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ZLIB_FOUND)
|
if(ZLIB_FOUND)
|
||||||
target_link_libraries("${csync_NAME}" PUBLIC ZLIB::ZLIB)
|
target_link_libraries(nextcloud_csync PUBLIC ZLIB::ZLIB)
|
||||||
endif(ZLIB_FOUND)
|
endif(ZLIB_FOUND)
|
||||||
|
|
||||||
|
|
||||||
@@ -96,11 +97,11 @@ endif(ZLIB_FOUND)
|
|||||||
if (APPLE)
|
if (APPLE)
|
||||||
find_library(FOUNDATION_LIBRARY NAMES Foundation)
|
find_library(FOUNDATION_LIBRARY NAMES Foundation)
|
||||||
find_library(CORESERVICES_LIBRARY NAMES CoreServices)
|
find_library(CORESERVICES_LIBRARY NAMES CoreServices)
|
||||||
target_link_libraries("${csync_NAME}" PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
|
target_link_libraries(nextcloud_csync PUBLIC ${FOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
"${csync_NAME}"
|
nextcloud_csync
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
VERSION
|
VERSION
|
||||||
${LIBRARY_VERSION}
|
${LIBRARY_VERSION}
|
||||||
@@ -108,11 +109,15 @@ set_target_properties(
|
|||||||
${LIBRARY_SOVERSION}
|
${LIBRARY_SOVERSION}
|
||||||
RUNTIME_OUTPUT_DIRECTORY
|
RUNTIME_OUTPUT_DIRECTORY
|
||||||
${BIN_OUTPUT_DIRECTORY}
|
${BIN_OUTPUT_DIRECTORY}
|
||||||
|
LIBRARY_OUTPUT_NAME
|
||||||
|
${APPLICATION_EXECUTABLE}_csync
|
||||||
|
RUNTIME_OUTPUT_NAME
|
||||||
|
${APPLICATION_EXECUTABLE}_csync
|
||||||
)
|
)
|
||||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
INSTALL(
|
INSTALL(
|
||||||
TARGETS
|
TARGETS
|
||||||
"${csync_NAME}"
|
nextcloud_csync
|
||||||
LIBRARY DESTINATION
|
LIBRARY DESTINATION
|
||||||
${LIB_INSTALL_DIR}
|
${LIB_INSTALL_DIR}
|
||||||
ARCHIVE DESTINATION
|
ARCHIVE DESTINATION
|
||||||
@@ -123,7 +128,7 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
|||||||
else()
|
else()
|
||||||
INSTALL(
|
INSTALL(
|
||||||
TARGETS
|
TARGETS
|
||||||
"${csync_NAME}"
|
nextcloud_csync
|
||||||
LIBRARY DESTINATION
|
LIBRARY DESTINATION
|
||||||
${CMAKE_INSTALL_LIBDIR}
|
${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION
|
ARCHIVE DESTINATION
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ include(CheckCXXSourceCompiles)
|
|||||||
|
|
||||||
set(PACKAGE ${APPLICATION_NAME})
|
set(PACKAGE ${APPLICATION_NAME})
|
||||||
set(VERSION ${APPLICATION_VERSION})
|
set(VERSION ${APPLICATION_VERSION})
|
||||||
set(DATADIR ${DATA_INSTALL_DIR})
|
|
||||||
set(LIBDIR ${LIB_INSTALL_DIR})
|
set(LIBDIR ${LIB_INSTALL_DIR})
|
||||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||||
|
|
||||||
@@ -23,6 +22,12 @@ if (NOT LINUX)
|
|||||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} )
|
||||||
|
|
||||||
|
# Systems not using glibc require linker flag for argp
|
||||||
|
check_library_exists(argp argp_parse "" HAVE_LIBARGP)
|
||||||
|
if(HAVE_ARGP_H AND HAVE_LIBARGP)
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} argp)
|
||||||
|
endif()
|
||||||
endif (NOT LINUX)
|
endif (NOT LINUX)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config_csync.h"
|
#include "config_csync.h"
|
||||||
|
#include <qglobal.h>
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
@@ -34,10 +35,8 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QFile>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
|
|
||||||
/** Expands C-like escape sequences (in place)
|
/** Expands C-like escape sequences (in place)
|
||||||
*/
|
*/
|
||||||
OCSYNC_EXPORT void csync_exclude_expand_escapes(QByteArray &input)
|
OCSYNC_EXPORT void csync_exclude_expand_escapes(QByteArray &input)
|
||||||
@@ -199,13 +198,13 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QString &path, bool exclu
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We create a Desktop.ini on Windows for the sidebar icon, make sure we don't sync it. */
|
/* Do not sync desktop.ini files anywhere in the tree. */
|
||||||
if (blen == 11 && path == bname) {
|
const auto desktopIniFile = QStringLiteral("desktop.ini");
|
||||||
if (bname.compare(QLatin1String("Desktop.ini"), Qt::CaseInsensitive) == 0) {
|
if (blen == static_cast<qsizetype>(desktopIniFile.length()) && bname.compare(desktopIniFile, Qt::CaseInsensitive) == 0) {
|
||||||
return CSYNC_FILE_SILENTLY_EXCLUDED;
|
return CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (excludeConflictFiles && OCC::Utility::isConflictFile(path)) {
|
if (excludeConflictFiles && OCC::Utility::isConflictFile(path)) {
|
||||||
return CSYNC_FILE_EXCLUDE_CONFLICT;
|
return CSYNC_FILE_EXCLUDE_CONFLICT;
|
||||||
}
|
}
|
||||||
@@ -231,24 +230,21 @@ ExcludedFiles::ExcludedFiles(const QString &localPath)
|
|||||||
// We're in a detached exclude probably coming from a partial sync or test
|
// We're in a detached exclude probably coming from a partial sync or test
|
||||||
if (_localPath.isEmpty())
|
if (_localPath.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Load exclude file from base dir
|
|
||||||
QFileInfo fi(_localPath + QStringLiteral(".sync-exclude.lst"));
|
|
||||||
if (fi.isReadable())
|
|
||||||
addInTreeExcludeFilePath(fi.absoluteFilePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExcludedFiles::~ExcludedFiles() = default;
|
ExcludedFiles::~ExcludedFiles() = default;
|
||||||
|
|
||||||
void ExcludedFiles::addExcludeFilePath(const QString &path)
|
void ExcludedFiles::addExcludeFilePath(const QString &path)
|
||||||
{
|
{
|
||||||
_excludeFiles[_localPath].append(path);
|
const QFileInfo excludeFileInfo(path);
|
||||||
}
|
const auto fileName = excludeFileInfo.fileName();
|
||||||
|
const auto basePath = fileName.compare(QStringLiteral("sync-exclude.lst"), Qt::CaseInsensitive) == 0
|
||||||
void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
|
? _localPath
|
||||||
{
|
: leftIncludeLast(path, QLatin1Char('/'));
|
||||||
BasePathString basePath = leftIncludeLast(path, QLatin1Char('/'));
|
auto &excludeFilesLocalPath = _excludeFiles[basePath];
|
||||||
_excludeFiles[basePath].append(path);
|
if (std::find(excludeFilesLocalPath.cbegin(), excludeFilesLocalPath.cend(), path) == excludeFilesLocalPath.cend()) {
|
||||||
|
excludeFilesLocalPath.append(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExcludedFiles::setExcludeConflictFiles(bool onoff)
|
void ExcludedFiles::setExcludeConflictFiles(bool onoff)
|
||||||
@@ -288,32 +284,26 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
|
|||||||
_clientVersion = version;
|
_clientVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExcludedFiles::loadExcludeFile(const QString &basePath, const QString & file)
|
void ExcludedFiles::loadExcludeFilePatterns(const QString &basePath, QFile &file)
|
||||||
{
|
{
|
||||||
QFile f(file);
|
|
||||||
if (!f.open(QIODevice::ReadOnly))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QStringList patterns;
|
QStringList patterns;
|
||||||
while (!f.atEnd()) {
|
while (!file.atEnd()) {
|
||||||
QByteArray line = f.readLine().trimmed();
|
QByteArray line = file.readLine().trimmed();
|
||||||
if (line.startsWith("#!version")) {
|
if (line.startsWith("#!version")) {
|
||||||
if (!versionDirectiveKeepNextLine(line))
|
if (!versionDirectiveKeepNextLine(line))
|
||||||
f.readLine();
|
file.readLine();
|
||||||
}
|
}
|
||||||
if (line.isEmpty() || line.startsWith('#'))
|
if (line.isEmpty() || line.startsWith('#'))
|
||||||
continue;
|
continue;
|
||||||
csync_exclude_expand_escapes(line);
|
csync_exclude_expand_escapes(line);
|
||||||
patterns.append(QString::fromUtf8(line));
|
patterns.append(QString::fromUtf8(line));
|
||||||
}
|
}
|
||||||
_allExcludes.insert(basePath, patterns);
|
_allExcludes[basePath].append(patterns);
|
||||||
|
|
||||||
// nothing to prepare if the user decided to not exclude anything
|
// nothing to prepare if the user decided to not exclude anything
|
||||||
if (!_allExcludes.value(basePath).isEmpty()){
|
if (!_allExcludes.value(basePath).isEmpty()){
|
||||||
prepare(basePath);
|
prepare(basePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExcludedFiles::reloadExcludeFiles()
|
bool ExcludedFiles::reloadExcludeFiles()
|
||||||
@@ -330,8 +320,14 @@ bool ExcludedFiles::reloadExcludeFiles()
|
|||||||
bool success = true;
|
bool success = true;
|
||||||
const auto keys = _excludeFiles.keys();
|
const auto keys = _excludeFiles.keys();
|
||||||
for (const auto& basePath : keys) {
|
for (const auto& basePath : keys) {
|
||||||
for (const auto& file : _excludeFiles.value(basePath)) {
|
for (const auto &excludeFile : _excludeFiles.value(basePath)) {
|
||||||
success = loadExcludeFile(basePath, file);
|
QFile file(excludeFile);
|
||||||
|
if (file.exists() && file.open(QIODevice::ReadOnly)) {
|
||||||
|
loadExcludeFilePatterns(basePath, file);
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
qWarning() << "System exclude list file could not be opened:" << excludeFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,11 +418,14 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
|
|||||||
// Directories are guaranteed to be visited before their files
|
// Directories are guaranteed to be visited before their files
|
||||||
if (filetype == ItemTypeDirectory) {
|
if (filetype == ItemTypeDirectory) {
|
||||||
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
|
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
|
||||||
const auto fi = QFileInfo(basePath + QStringLiteral(".sync-exclude.lst"));
|
const QString absolutePath = basePath + QStringLiteral(".sync-exclude.lst");
|
||||||
|
QFileInfo excludeFileInfo(absolutePath);
|
||||||
|
|
||||||
if (fi.isReadable()) {
|
if (excludeFileInfo.isReadable()) {
|
||||||
addInTreeExcludeFilePath(fi.absoluteFilePath());
|
addExcludeFilePath(absolutePath);
|
||||||
loadExcludeFile(basePath, fi.absoluteFilePath());
|
reloadExcludeFiles();
|
||||||
|
} else {
|
||||||
|
qWarning() << "System exclude list file could not be read:" << absolutePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||