mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2026-04-03 18:11:32 +02:00
Compare commits
558 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa32c10014 | ||
|
|
fe67d66d3d | ||
|
|
3a3a6dd6b8 | ||
|
|
328c673c29 | ||
|
|
49afad0474 | ||
|
|
7c3e91202e | ||
|
|
e94b18f97f | ||
|
|
79a0b937f5 | ||
|
|
e5fbc8c2dd | ||
|
|
3632cc659b | ||
|
|
1731bf7c86 | ||
|
|
936d37fd0b | ||
|
|
7259a0bc0d | ||
|
|
06de878b4b | ||
|
|
179ff27ab6 | ||
|
|
44da2f2ce2 | ||
|
|
92b302fb37 | ||
|
|
d2febdf17c | ||
|
|
9c4b4c6183 | ||
|
|
45029e9012 | ||
|
|
969b0e8e2e | ||
|
|
4b46da9370 | ||
|
|
8b5dd53519 | ||
|
|
5ee5b19406 | ||
|
|
8e1c62cc70 | ||
|
|
151e9300cd | ||
|
|
efc3116f30 | ||
|
|
4296a6041a | ||
|
|
0d1e0057b3 | ||
|
|
5aadc7a62d | ||
|
|
3c28e38089 | ||
|
|
dba8fd7c76 | ||
|
|
39c2bb555a | ||
|
|
39fc86cbcf | ||
|
|
8d574c11e8 | ||
|
|
c02d87f283 | ||
|
|
ddb5375c68 | ||
|
|
bd78604468 | ||
|
|
4920b4d4af | ||
|
|
d12d00562f | ||
|
|
b17bbb2b22 | ||
|
|
fc64edba11 | ||
|
|
b6c7581414 | ||
|
|
962850f307 | ||
|
|
88ab5557bd | ||
|
|
e3fb3bbe73 | ||
|
|
a86a1b4c17 | ||
|
|
4326a70ede | ||
|
|
2880bd62ce | ||
|
|
b49633a9f7 | ||
|
|
adfe7ad953 | ||
|
|
e45a01bc03 | ||
|
|
9bcbc15834 | ||
|
|
b4a19bb6d3 | ||
|
|
52db45c2b1 | ||
|
|
b3d8cacf8c | ||
|
|
c004db2070 | ||
|
|
48ada55e77 | ||
|
|
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 |
@@ -12,7 +12,7 @@
|
||||
BasedOnStyle: WebKit
|
||||
|
||||
Standard: Cpp11
|
||||
ColumnLimit: 0
|
||||
ColumnLimit: 120
|
||||
|
||||
# Disable reflow of qdoc comments: indentation rules are different.
|
||||
# Translation comments are also excluded
|
||||
@@ -61,3 +61,5 @@ ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCH
|
||||
MaxEmptyLinesToKeep: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
Cpp11BracedListStyle: true
|
||||
|
||||
@@ -24,7 +24,7 @@ Checks: '-*,
|
||||
modernize-use-nodiscard,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-noexcept,
|
||||
modernize-user-override,
|
||||
modernize-use-override,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-transparent-functors,
|
||||
modernize-use-uncaught-exceptions,
|
||||
|
||||
32
.drone.yml
32
.drone.yml
@@ -1,17 +1,17 @@
|
||||
kind: pipeline
|
||||
name: qt-5.12
|
||||
name: qt-5.15
|
||||
|
||||
steps:
|
||||
- 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:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
commands:
|
||||
- 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
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
@@ -19,7 +19,7 @@ steps:
|
||||
- cd /drone/build
|
||||
- make -j$(nproc)
|
||||
- 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:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
@@ -27,7 +27,7 @@ steps:
|
||||
- cd /drone/build
|
||||
- useradd -m -s /bin/bash 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:
|
||||
- name: build
|
||||
@@ -43,27 +43,27 @@ trigger:
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: qt-5.12-clang
|
||||
name: qt-5.15-clang
|
||||
|
||||
steps:
|
||||
- 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:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
commands:
|
||||
- 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
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
commands:
|
||||
- cd /drone/build
|
||||
- ninja 2>1 | /drone/src/admin/linux/count_compiler_warnings.py /drone/src
|
||||
- ninja
|
||||
- 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:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
@@ -71,9 +71,9 @@ steps:
|
||||
- cd /drone/build
|
||||
- useradd -m -s /bin/bash 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
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.12-18
|
||||
image: ghcr.io/nextcloud/continuous-integration-client:client-5.15-4
|
||||
volumes:
|
||||
- name: build
|
||||
path: /drone/build
|
||||
@@ -98,14 +98,14 @@ name: AppImage
|
||||
|
||||
steps:
|
||||
- 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:
|
||||
CI_UPLOAD_GIT_TOKEN:
|
||||
from_secret: CI_UPLOAD_GIT_TOKEN
|
||||
CI_UPLOAD_GIT_USERNAME:
|
||||
from_secret: CI_UPLOAD_GIT_USERNAME
|
||||
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."
|
||||
trigger:
|
||||
branch:
|
||||
|
||||
33
.github/workflows/command-rebase.yml
vendored
33
.github/workflows/command-rebase.yml
vendored
@@ -3,25 +3,44 @@
|
||||
# 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 ]
|
||||
name: Automatic Rebase
|
||||
types: created
|
||||
|
||||
jobs:
|
||||
rebase:
|
||||
name: Rebase
|
||||
# On pull requests and if the comment starts with `/rebase`
|
||||
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/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.GITHUB_TOKEN }}
|
||||
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"
|
||||
|
||||
50
.github/workflows/sonarcloud.yml
vendored
Normal file
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 }}"
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -184,6 +184,7 @@ compile_commands.json
|
||||
convert.exe
|
||||
.dir-locals.el
|
||||
*-icon.png
|
||||
*-icon-win-folder.png
|
||||
*-sidebar.png
|
||||
*-w10startmenu.png
|
||||
theme.qrc
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[bg_BG]=@APPLICATION_ICON_NAME@
|
||||
Name[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ десктоп клиент за синхронизиране
|
||||
GenericName[bg_BG]=Синхронизиране на папка
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[cy_GB]=@APPLICATION_ICON_NAME@
|
||||
Name[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
|
||||
Comment[cy_GB]=@APPLICATION_NAME@ cleient cydweddu bwrdd gwaith
|
||||
GenericName[cy_GB]=Cydweddu Ffolder
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[en_GB]=@APPLICATION_ICON_NAME@
|
||||
Name[en_GB]=@APPLICATION_NAME@ Desktop
|
||||
Comment[en_GB]=@APPLICATION_NAME@ desktop synchronisation client
|
||||
GenericName[en_GB]=Folder Sync
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[ko]=@APPLICATION_ICON_NAME@
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크탑
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[nb_NO]=@APPLICATION_ICON_NAME@
|
||||
Name[nb_NO]=@APPLICATION_NAME@ skrivebord
|
||||
Comment[nb_NO]=@APPLICATION_NAME@ klient for synkroinisering
|
||||
GenericName[nb_NO]=Mappe synkroinisering
|
||||
|
||||
@@ -22,5 +22,6 @@ Icon=@APPLICATION_EXECUTABLE@
|
||||
|
||||
# Translations
|
||||
Icon[ru]=@APPLICATION_ICON_NAME@
|
||||
Name[ru]=@APPLICATION_NAME@ Desktop
|
||||
Comment[ru]=Клиент синхронизации @APPLICATION_NAME@ для ПК
|
||||
GenericName[ru]=Синхронизация папок
|
||||
|
||||
27
.tx/nextcloud.client-desktop/vi_translation
Normal file
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
|
||||
@@ -42,11 +42,14 @@ if(NOT CRASHREPORTER_EXECUTABLE)
|
||||
set(CRASHREPORTER_EXECUTABLE "${APPLICATION_EXECUTABLE}_crash_reporter")
|
||||
endif()
|
||||
|
||||
set(synclib_NAME "${APPLICATION_EXECUTABLE}sync")
|
||||
set(csync_NAME "${APPLICATION_EXECUTABLE}_csync")
|
||||
|
||||
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)
|
||||
# For config.h
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
@@ -74,9 +77,9 @@ include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||
|
||||
add_definitions(
|
||||
-DQT_DISABLE_DEPRECATED_BEFORE=0x000000
|
||||
-DQT_USE_QSTRINGBUILDER
|
||||
-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)
|
||||
@@ -93,30 +96,15 @@ endif()
|
||||
message(STATUS "GIT_SHA1 ${GIT_SHA1}")
|
||||
|
||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||
set(DATADIR ${DATA_INSTALL_DIR})
|
||||
if(WIN32)
|
||||
set(DATADIR "share")
|
||||
endif(WIN32)
|
||||
set(SHAREDIR ${DATADIR})
|
||||
set(SHAREDIR ${CMAKE_INSTALL_DATADIR})
|
||||
|
||||
#####
|
||||
## handle BUILD_OWNCLOUD_OSX_BUNDLE
|
||||
# BUILD_OWNCLOUD_OSX_BUNDLE was not initialized OR set to true on OSX
|
||||
if(APPLE AND (NOT DEFINED BUILD_OWNCLOUD_OSX_BUNDLE OR BUILD_OWNCLOUD_OSX_BUNDLE))
|
||||
set(BUILD_OWNCLOUD_OSX_BUNDLE ON)
|
||||
# Build MacOS app bundle if wished
|
||||
if(APPLE AND BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
message(STATUS "Build MacOS app bundle")
|
||||
set(OWNCLOUD_OSX_BUNDLE "${APPLICATION_NAME}.app")
|
||||
set(LIB_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()
|
||||
#####
|
||||
|
||||
# this option removes Http authentication, keychain, shibboleth etc and is intended for
|
||||
# external authentication mechanisms
|
||||
|
||||
@@ -11,6 +11,8 @@ 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_REV_DOMAIN "com.nextcloud.desktopclient" )
|
||||
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( LINUX_PACKAGE_SHORTNAME "nextcloud" )
|
||||
set( LINUX_APPLICATION_ID "${APPLICATION_REV_DOMAIN}.${LINUX_PACKAGE_SHORTNAME}")
|
||||
@@ -32,6 +34,7 @@ option( BUILD_UPDATER "Build updater" OFF )
|
||||
|
||||
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
|
||||
set(NEXTCLOUD_BACKGROUND_COLOR "#0082c9" CACHE STRING "Default Nextcloud background color")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
set( MIRALL_VERSION_MAJOR 3 )
|
||||
set( MIRALL_VERSION_MINOR 3 )
|
||||
set( MIRALL_VERSION_MINOR 4 )
|
||||
set( MIRALL_VERSION_PATCH 1 )
|
||||
set( MIRALL_VERSION_YEAR 2021 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
# Minimum supported server version according to https://docs.nextcloud.com/server/latest/admin_manual/release_schedule.html
|
||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MAJOR 20)
|
||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MAJOR 16)
|
||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_MINOR 0)
|
||||
set(NEXTCLOUD_SERVER_VERSION_MIN_SUPPORTED_PATCH 0)
|
||||
|
||||
|
||||
@@ -2,78 +2,88 @@
|
||||
|
||||
set -xe
|
||||
|
||||
mkdir /app
|
||||
mkdir /build
|
||||
export APPNAME=${APPNAME:-nextcloud}
|
||||
export BUILD_UPDATER=${BUILD_UPDATER:-OFF}
|
||||
export BUILDNR=${BUILDNR:-0000}
|
||||
export DESKTOP_CLIENT_ROOT=${DESKTOP_CLIENT_ROOT:-/home/user}
|
||||
|
||||
#Set Qt-5.15
|
||||
export QT_BASE_DIR=/opt/qt5.15
|
||||
|
||||
#Set Qt-5.12
|
||||
export QT_BASE_DIR=/opt/qt5.12.10
|
||||
export QTDIR=$QT_BASE_DIR
|
||||
export PATH=$QT_BASE_DIR/bin:$PATH
|
||||
export LD_LIBRARY_PATH=$QT_BASE_DIR/lib/x86_64-linux-gnu:$QT_BASE_DIR/lib:$LD_LIBRARY_PATH
|
||||
export PKG_CONFIG_PATH=$QT_BASE_DIR/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||
|
||||
#Set APPID for .desktop file processing
|
||||
export LINUX_APPLICATION_ID=com.nextcloud.desktopclient.nextcloud
|
||||
|
||||
#set defaults
|
||||
# Set defaults
|
||||
export SUFFIX=${DRONE_PULL_REQUEST:=master}
|
||||
if [ $SUFFIX != "master" ]; then
|
||||
SUFFIX="PR-$SUFFIX"
|
||||
fi
|
||||
if [ "$BUILD_UPDATER" != "OFF" ]; then
|
||||
BUILD_UPDATER=ON
|
||||
fi
|
||||
|
||||
#QtKeyChain v0.10.0
|
||||
cd /build
|
||||
mkdir /app
|
||||
|
||||
# QtKeyChain
|
||||
git clone https://github.com/frankosterfeld/qtkeychain.git
|
||||
cd qtkeychain
|
||||
git checkout v0.10.0
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -D CMAKE_INSTALL_PREFIX=/usr ../
|
||||
make -j4
|
||||
make install
|
||||
cmake -G Ninja -D CMAKE_INSTALL_PREFIX=/app/usr ..
|
||||
cmake --build . --target all
|
||||
cmake --build . --target install
|
||||
|
||||
#Build client
|
||||
cd /build
|
||||
|
||||
# Build client
|
||||
mkdir 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_UPDATER=ON \
|
||||
-DMIRALL_VERSION_SUFFIX=PR-$DRONE_PULL_REQUEST \
|
||||
-DMIRALL_VERSION_BUILD=$DRONE_BUILD_NUMBER \
|
||||
$DRONE_WORKSPACE
|
||||
make -j4
|
||||
make DESTDIR=/app install
|
||||
-D BUILD_UPDATER=$BUILD_UPDATER \
|
||||
-D MIRALL_VERSION_BUILD=$BUILDNR \
|
||||
-D MIRALL_VERSION_SUFFIX="$VERSION_SUFFIX" \
|
||||
${DESKTOP_CLIENT_ROOT}
|
||||
cmake --build . --target all
|
||||
cmake --build . --target install
|
||||
|
||||
# Move stuff around
|
||||
cd /app
|
||||
|
||||
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/
|
||||
mv usr/lib/x86_64-linux-gnu/* usr/lib/
|
||||
|
||||
# Don't bundle nextcloudcmd as we don't run it anyway
|
||||
rm -rf ./usr/bin/nextcloudcmd
|
||||
mkdir usr/plugins
|
||||
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
|
||||
rm -rf ./usr/share/caja-python/
|
||||
rm -rf ./usr/share/nautilus-python/
|
||||
rm -rf ./usr/share/nemo-python/
|
||||
rm -rf usr/share/caja-python/
|
||||
rm -rf usr/share/nautilus-python/
|
||||
rm -rf usr/share/nemo-python/
|
||||
|
||||
# Move sync exclude to right location
|
||||
mv ./etc/Nextcloud/sync-exclude.lst ./usr/bin/
|
||||
rm -rf ./etc
|
||||
mv usr/etc/*/sync-exclude.lst usr/bin/
|
||||
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?
|
||||
cp ./usr/share/icons/hicolor/512x512/apps/Nextcloud.png . # Workaround for linuxeployqt bug, FIXME
|
||||
|
||||
|
||||
# Because distros need to get their shit together
|
||||
cp -R /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/libssl.so* ./usr/lib/
|
||||
cp -R /usr/lib/x86_64-linux-gnu/libcrypto.so* ./usr/lib/
|
||||
cp -P /usr/local/lib/libssl.so* ./usr/lib/
|
||||
cp -P /usr/local/lib/libcrypto.so* ./usr/lib/
|
||||
|
||||
@@ -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/
|
||||
|
||||
# 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
|
||||
./linuxdeployqt-continuous-x86_64.AppImage --appimage-extract
|
||||
rm ./linuxdeployqt-continuous-x86_64.AppImage
|
||||
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=/app/usr/lib/
|
||||
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=$DRONE_WORKSPACE/src/gui
|
||||
./squashfs-root/AppRun ${DESKTOP_FILE} -bundle-non-qt-libs -qmldir=${DESKTOP_CLIENT_ROOT}/src/gui
|
||||
|
||||
# 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
|
||||
./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)
|
||||
@@ -24,6 +24,7 @@ cd /build
|
||||
|
||||
# AppImage
|
||||
export APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
|
||||
export UPDATE=$(readlink -f ./Nextcloud*.AppImage.zsync)
|
||||
export BASENAME=$(basename ${APPIMAGE})
|
||||
|
||||
if ! test -e $APPIMAGE ; then
|
||||
@@ -70,6 +71,7 @@ upload_release_asset()
|
||||
{
|
||||
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 $UPDATE)
|
||||
}
|
||||
|
||||
delete_release_asset()
|
||||
@@ -132,4 +134,4 @@ if [ $TAG_NAME != "master" ]; then
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "AppImage link: $browserDownloadUrl"
|
||||
echo "AppImage link: $browserDownloadUrl"
|
||||
|
||||
@@ -9,7 +9,7 @@ else()
|
||||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
||||
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(macosx.pkgproj.cmake ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
|
||||
|
||||
@@ -695,7 +695,12 @@
|
||||
<key>PROJECT_SETTINGS</key>
|
||||
<dict>
|
||||
<key>ADVANCED_OPTIONS</key>
|
||||
<dict/>
|
||||
<dict>
|
||||
<key>installer-script.options:hostArchitectures</key>
|
||||
<array>
|
||||
<string>x86_64,arm64</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>BUILD_FORMAT</key>
|
||||
<integer>0</integer>
|
||||
<key>BUILD_PATH</key>
|
||||
|
||||
82
admin/osx/make_universal.py
Executable file
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
|
||||
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
|
||||
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
|
||||
sleep 10s
|
||||
# enable it
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
# kill the old version. see issue #2044
|
||||
killall @APPLICATION_EXECUTABLE@
|
||||
killall @APPLICATION_NAME@
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -32,9 +32,6 @@ install:
|
||||
build_script:
|
||||
- ps: |
|
||||
craft --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
|
||||
craft --package --src-dir $env:APPVEYOR_BUILD_FOLDER nextcloud-client
|
||||
cp C:\CraftMaster\windows-msvc2019_64-cl\tmp\*.7z $env:APPVEYOR_BUILD_FOLDER
|
||||
cp C:\CraftMaster\windows-msvc2019_64-cl\tmp\*.exe $env:APPVEYOR_BUILD_FOLDER
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
@@ -43,7 +40,3 @@ test_script:
|
||||
environment:
|
||||
matrix:
|
||||
- TARGET: windows-msvc2019_64-cl
|
||||
|
||||
artifacts:
|
||||
- path: '*.7z'
|
||||
- path: '*.exe'
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
# target does not have the ``WIN32_EXECUTABLE`` property set.
|
||||
# * One of the tools png2ico (See :find-module:`FindPng2Ico`) or
|
||||
# icotool (see :find-module:`FindIcoTool`) is required.
|
||||
# * Supported sizes: 16, 24, 32, 48, 64, 128, 256, 512 and 1024.
|
||||
# * Supported sizes: 16, 20, 24, 32, 40, 48, 64, 128, 256, 512 and 1024.
|
||||
#
|
||||
# Mac OS X notes
|
||||
# * The executable target must have the ``MACOSX_BUNDLE`` property set.
|
||||
@@ -102,9 +102,12 @@ include(CMakeParseArguments)
|
||||
|
||||
function(ecm_add_app_icon appsources)
|
||||
set(options)
|
||||
set(oneValueArgs OUTFILE_BASENAME)
|
||||
set(multiValueArgs ICONS SIDEBAR_ICONS)
|
||||
set(oneValueArgs OUTFILE_BASENAME ICON_INDEX)
|
||||
set(multiValueArgs ICONS SIDEBAR_ICONS RC_DEPENDENCIES)
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if (NOT ARG_ICON_INDEX)
|
||||
set(ARG_ICON_INDEX 1)
|
||||
endif()
|
||||
|
||||
if(NOT ARG_ICONS)
|
||||
message(FATAL_ERROR "No ICONS argument given to ecm_add_app_icon")
|
||||
@@ -138,8 +141,11 @@ function(ecm_add_app_icon appsources)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024")
|
||||
if (WIN32)
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;20;24;32;40;48;64;128;256;512;1024")
|
||||
else()
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_ICONS}" "icons" "16;24;32;48;64;128;256;512;1024")
|
||||
endif()
|
||||
if(ARG_SIDEBAR_ICONS)
|
||||
_ecm_add_app_icon_categorize_icons("${ARG_SIDEBAR_ICONS}" "sidebar_icons" "16;32;64;128;256")
|
||||
endif()
|
||||
@@ -168,8 +174,10 @@ function(ecm_add_app_icon appsources)
|
||||
|
||||
|
||||
set(windows_icons ${icons_at_16px}
|
||||
${icons_at_20px}
|
||||
${icons_at_24px}
|
||||
${icons_at_32px}
|
||||
${icons_at_40px}
|
||||
${icons_at_48px}
|
||||
${icons_at_64px}
|
||||
${icons_at_128px}
|
||||
@@ -204,12 +212,12 @@ function(ecm_add_app_icon appsources)
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
# this bit's a little hacky to make the dependency stuff work
|
||||
file(WRITE "${_outfilename}.rc.in" "IDI_ICON1 ICON DISCARDABLE \"${_outfilename}.ico\"\n")
|
||||
file(WRITE "${_outfilename}.rc.in" "IDI_ICON${ARG_ICON_INDEX} ICON DISCARDABLE \"${_outfilename}.ico\"\n")
|
||||
add_custom_command(
|
||||
OUTPUT "${_outfilename}.rc"
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E copy "${_outfilename}.rc.in" "${_outfilename}.rc"
|
||||
DEPENDS "${_outfilename}.ico"
|
||||
DEPENDS ${ARG_RC_DEPENDENCIES} "${_outfilename}.ico"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
)
|
||||
endfunction()
|
||||
@@ -226,7 +234,7 @@ function(ecm_add_app_icon appsources)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(size 16 24 32 48 64 128 ${maxSize})
|
||||
foreach(size 16 20 24 32 40 48 64 128 ${maxSize})
|
||||
if(NOT icons_at_${size}px)
|
||||
continue()
|
||||
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")
|
||||
endif()
|
||||
|
||||
if(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
endif(DEFINED MIRALL_FATAL_WARNINGS)
|
||||
endif()
|
||||
|
||||
@@ -29,7 +29,10 @@
|
||||
#cmakedefine APPLICATION_WIZARD_HEADER_TITLE_COLOR "@APPLICATION_WIZARD_HEADER_TITLE_COLOR@"
|
||||
#cmakedefine APPLICATION_WIZARD_USE_CUSTOM_LOGO "@APPLICATION_WIZARD_USE_CUSTOM_LOGO@"
|
||||
#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@"
|
||||
#define APPLICATION_DOTVIRTUALFILE_SUFFIX "." APPLICATION_VIRTUALFILE_SUFFIX
|
||||
#cmakedefine01 ENFORCE_VIRTUAL_FILES_SYNC_FOLDER
|
||||
|
||||
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@
|
||||
|
||||
|
||||
@@ -406,7 +406,7 @@ Virtual Files
|
||||
-------------
|
||||
|
||||
.. 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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
When one tries to open a file, for example by double clicking on a
|
||||
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
|
||||
:alt: VFS hydration progress bar
|
||||
|
||||
@@ -32,10 +32,9 @@ itself. Should the silent update fail, the client offers a manual download.
|
||||
macOS
|
||||
^^^^^
|
||||
|
||||
If a new update is available, the Nextcloud client initializes a pop-up dialog
|
||||
to alert you of the update and requesting that you update to the latest
|
||||
version. Due to their use of the Sparkle frameworks, this is the default
|
||||
process for macOS applications.
|
||||
There is no automatic updater on macOS. If a new update is available,
|
||||
the Nextcloud client initializes a pop-up dialog to alert you of the
|
||||
update and requesting that you update to the latest version manually.
|
||||
|
||||
Linux
|
||||
^^^^^
|
||||
@@ -96,14 +95,6 @@ To prevent automatic updates and disallow manual overrides:
|
||||
.. 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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -185,6 +185,8 @@ Then, in Terminal:
|
||||
.. code-block:: bash
|
||||
|
||||
% 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.
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ copyright = u'2013-2021, The Nextcloud developers'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '3.3'
|
||||
version = '3.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '3.3.1'
|
||||
release = '3.4.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# 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. |
|
||||
| | | 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. |
|
||||
+----------------------------------+------------------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
BIN
doc/images/user_status-selector_dialog.png
Normal file
BIN
doc/images/user_status-selector_dialog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/images/user_status_selector_main_dialog.png
Normal file
BIN
doc/images/user_status_selector_main_dialog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@@ -31,7 +31,7 @@ download page.
|
||||
System Requirements
|
||||
----------------------------------
|
||||
|
||||
- Windows 10+
|
||||
- Windows 8.1+
|
||||
- macOS 10.12+ (64-bit only)
|
||||
- Linux
|
||||
- FreeBSD
|
||||
|
||||
@@ -157,6 +157,35 @@ icon.
|
||||
If a directory includes ignored files that are marked with warning icons
|
||||
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
|
||||
-------------------------
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ the server URL.
|
||||
|
||||
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]``
|
||||
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>``
|
||||
Uses ``server`` as HTTP proxy.
|
||||
|
||||
``--nonshib``
|
||||
Uses Non Shibboleth WebDAV Authentication
|
||||
|
||||
``--davpath [path]``
|
||||
Overrides the WebDAV Path with ``path``
|
||||
|
||||
``--exclude [file]``
|
||||
Exclude list file
|
||||
|
||||
@@ -92,15 +89,15 @@ Credential Handling
|
||||
|
||||
::
|
||||
|
||||
$ nextcloudcmd /home/user/my_sync_folder https://carla:secret@server/nextcloud/remote.php/dav/
|
||||
$ nextcloudcmd /home/user/my_sync_folder https://carla:secret@server/nextcloud
|
||||
|
||||
To synchronize the Nextcloud directory ``Music`` to the local directory
|
||||
``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::
|
||||
|
||||
$ nextcloudcmd --httpproxy http://192.168.178.1:8080 \
|
||||
$ nextcloudcmd --httpproxy http://192.168.178.1:8080 --path /Music \
|
||||
$HOME/media/music \
|
||||
https://server/nextcloud/remote.php/dav/Music
|
||||
https://server/nextcloud
|
||||
|
||||
``nextcloudcmd`` will prompt for the user name and password, unless they have
|
||||
been specified on the command line or ``-n`` has been passed.
|
||||
@@ -120,5 +117,5 @@ Example
|
||||
|
||||
::
|
||||
|
||||
$ nextcloudcmd /home/user/<my_sync_folder> \
|
||||
https://<username>:<secret>@<server_address>/remote.php/dav/<Directory_that_has_been_created>
|
||||
$ nextcloudcmd --path /<Directory_that_has_been_created> /home/user/<my_sync_folder> \
|
||||
https://<username>:<secret>@<server_address>
|
||||
|
||||
@@ -24,11 +24,14 @@ The first parameter is the local directory. The second parameter is
|
||||
the server URL.
|
||||
|
||||
.. 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.
|
||||
|
||||
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]``
|
||||
Use ``user`` as the login name.
|
||||
|
||||
@@ -50,12 +53,6 @@ OPTIONS
|
||||
``—httpproxy http://[user@pass:]<server>:<port>``
|
||||
Uses ``server`` as HTTP proxy.
|
||||
|
||||
``—nonshib``
|
||||
Uses Non Shibboleth WebDAV Authentication
|
||||
|
||||
``—davpath [path]``
|
||||
Overrides the WebDAV Path with ``path``
|
||||
|
||||
``—exclude [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``,
|
||||
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 \
|
||||
https://server/nextcloud/remote.php/dav/Music
|
||||
https://server/nextcloud
|
||||
|
||||
``nextcloudcmd`` will enquire user name and password, unless they have
|
||||
been specified on the command line or ``-n`` (see `netrc(5)`) has been passed.
|
||||
|
||||
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 \
|
||||
nextclouds://server/nextcloud/remote.php/dav/Music
|
||||
ownclouds://server/nextcloud
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
<RCC>
|
||||
<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/UserLine.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/qmldir</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>
|
||||
</RCC>
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
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
|
||||
# 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
|
||||
# those user-defined settings to build the plist.
|
||||
add_custom_target( mac_overlayplugin ALL
|
||||
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
|
||||
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
|
||||
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
|
||||
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
|
||||
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
|
||||
# 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.
|
||||
# Pass the info through the xcodebuild command line and make sure that the project uses
|
||||
# those user-defined settings to build the plist.
|
||||
add_custom_target( mac_overlayplugin ALL
|
||||
xcodebuild ARCHS=${CMAKE_OSX_ARCHITECTURES} ONLY_ACTIVE_ARCH=NO
|
||||
-project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
|
||||
-target FinderSyncExt -configuration Release "SYMROOT=${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"OC_OEM_SHARE_ICNS=${OC_OEM_SHARE_ICNS}"
|
||||
"OC_APPLICATION_NAME=${APPLICATION_NAME}"
|
||||
"OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}"
|
||||
"OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}"
|
||||
COMMENT building Mac Overlay icons
|
||||
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
|
||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
endif(APPLE)
|
||||
if (BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
|
||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ project(dolphin-owncloud)
|
||||
|
||||
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(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>&)
|
||||
: 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();
|
||||
if (!helper->isConnected() || !fileItemInfos.isLocal())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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)
|
||||
file(GLOB files "${size}/*.png")
|
||||
|
||||
@@ -41,7 +41,7 @@ macro(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)
|
||||
STRING(TOLOWER "${APPLICATION_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)
|
||||
|
||||
|
||||
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_nemo.py DESTINATION ${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.py DESTINATION ${CMAKE_INSTALL_DATADIR}/nautilus-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 ${CMAKE_INSTALL_DATADIR}/caja-python/extensions RENAME syncstate-${APPLICATION_SHORTNAME}.py)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class __declspec(dllexport) RemotePathChecker {
|
||||
class RemotePathChecker {
|
||||
public:
|
||||
enum FileState {
|
||||
// Order synced with NCOverlay
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
<File Id="NCContextMenu.dll" KeyPath="yes" Source="$(var.HarvestAppDir)\shellext\NCContextMenu.dll">
|
||||
<Class Id="$(var.ContextMenuGuid)" Context="InprocServer32" Description="$(var.ContextMenuDescription)" ThreadingModel="apartment" />
|
||||
</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" />
|
||||
</Component>
|
||||
|
||||
|
||||
12
sonar-project.properties
Normal file
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; }
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
int heightForWidth(int w) const;
|
||||
QSize sizeHint() const override;
|
||||
int heightForWidth(int w) const override;
|
||||
public slots:
|
||||
/*! Starts the spin animation.
|
||||
\sa stopAnimation isAnimated
|
||||
@@ -98,8 +98,8 @@ public slots:
|
||||
*/
|
||||
void setColor(const QColor & color);
|
||||
protected:
|
||||
virtual void timerEvent(QTimerEvent * event);
|
||||
virtual void paintEvent(QPaintEvent * event);
|
||||
void timerEvent(QTimerEvent * event) override;
|
||||
void paintEvent(QPaintEvent * event) override;
|
||||
private:
|
||||
int m_angle = 0;
|
||||
int m_timerId = -1;
|
||||
|
||||
280
src/3rdparty/kirigami/wheelhandler.cpp
vendored
Normal file
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
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/libcrashreporter-qt
vendored
Submodule src/3rdparty/libcrashreporter-qt updated: 34b4665bd7...5423c0ef54
2
src/3rdparty/qtlockedfile/qtlockedfile.h
vendored
2
src/3rdparty/qtlockedfile/qtlockedfile.h
vendored
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
QtLockedFile();
|
||||
QtLockedFile(const QString &name);
|
||||
~QtLockedFile();
|
||||
~QtLockedFile() override;
|
||||
|
||||
bool lock(LockMode mode, bool block = true);
|
||||
bool unlock();
|
||||
|
||||
@@ -44,13 +44,13 @@ class QtSingleApplication : public QApplication
|
||||
|
||||
public:
|
||||
QtSingleApplication(const QString &id, int &argc, char **argv);
|
||||
~QtSingleApplication();
|
||||
~QtSingleApplication() override;
|
||||
|
||||
bool isRunning(qint64 pid = -1);
|
||||
|
||||
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
|
||||
QWidget* activationWindow() const;
|
||||
bool event(QEvent *event) Q_DECL_OVERRIDE;
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
QString applicationId() const;
|
||||
void setBlock(bool value);
|
||||
|
||||
@@ -4,10 +4,8 @@ endif()
|
||||
|
||||
include(ECMEnableSanitizers)
|
||||
|
||||
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
|
||||
|
||||
find_package(Qt5 5.12 COMPONENTS Core Network Xml Concurrent REQUIRED)
|
||||
find_package(Qt5 5.12 COMPONENTS WebEngineWidgets WebEngine)
|
||||
find_package(Qt5 5.15 COMPONENTS Core Network Xml Concurrent REQUIRED)
|
||||
find_package(Qt5 5.15 COMPONENTS WebEngineWidgets WebEngine)
|
||||
|
||||
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||
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")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty
|
||||
)
|
||||
|
||||
set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/theme CACHE STRING "" FORCE)
|
||||
|
||||
add_subdirectory(csync)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
project(cmd)
|
||||
set(CMAKE_AUTOMOC TRUE)
|
||||
|
||||
set(cmd_NAME ${APPLICATION_EXECUTABLE}cmd)
|
||||
|
||||
add_library(cmdCore STATIC simplesslerrorhandler.cpp netrcparser.cpp)
|
||||
|
||||
target_link_libraries(cmdCore
|
||||
PUBLIC
|
||||
"${csync_NAME}"
|
||||
"${synclib_NAME}"
|
||||
Nextcloud::sync
|
||||
Qt5::Core
|
||||
Qt5::Network
|
||||
)
|
||||
@@ -27,20 +24,22 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
endif()
|
||||
|
||||
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)
|
||||
set_target_properties(${cmd_NAME} PROPERTIES
|
||||
set_target_properties(nextcloudcmd PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS")
|
||||
else()
|
||||
set_target_properties(${cmd_NAME} PROPERTIES
|
||||
set_target_properties(nextcloudcmd PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY})
|
||||
|
||||
install(TARGETS ${cmd_NAME}
|
||||
install(TARGETS nextcloudcmd
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${cmd_NAME} cmdCore)
|
||||
endif()
|
||||
|
||||
@@ -66,6 +66,7 @@ struct CmdOptions
|
||||
{
|
||||
QString source_dir;
|
||||
QString target_url;
|
||||
QString remotePath = QStringLiteral("/");
|
||||
QString config_directory;
|
||||
QString user;
|
||||
QString password;
|
||||
@@ -77,7 +78,6 @@ struct CmdOptions
|
||||
bool ignoreHiddenFiles;
|
||||
QString exclude;
|
||||
QString unsyncedfolders;
|
||||
QString davPath;
|
||||
int restartTimes;
|
||||
int downlimit;
|
||||
int uplimit;
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void askFromUser() Q_DECL_OVERRIDE
|
||||
void askFromUser() override
|
||||
{
|
||||
_password = ::queryPassword(user());
|
||||
_ready = true;
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
_sslTrusted = isTrusted;
|
||||
}
|
||||
|
||||
bool sslIsTrusted() Q_DECL_OVERRIDE
|
||||
bool sslIsTrusted() override
|
||||
{
|
||||
return _sslTrusted;
|
||||
}
|
||||
@@ -193,6 +193,7 @@ void help()
|
||||
std::cout << " -h Sync hidden files, do not ignore them" << std::endl;
|
||||
std::cout << " --version, -v Display version and exit" << 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;
|
||||
exit(0);
|
||||
}
|
||||
@@ -269,7 +270,10 @@ void parseOptions(const QStringList &app_args, CmdOptions *options)
|
||||
} else if (option == "--logdebug") {
|
||||
Logger::instance()->setLogFile("-");
|
||||
Logger::instance()->setLogDebug(true);
|
||||
} else {
|
||||
} else if (option == "--path" && !it.peekNext().startsWith("-")) {
|
||||
options->remotePath = it.next();
|
||||
}
|
||||
else {
|
||||
help();
|
||||
}
|
||||
}
|
||||
@@ -291,9 +295,10 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
||||
|
||||
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) {
|
||||
auto blackListSet = newList.toSet();
|
||||
const QSet<QString> blackListSet(newList.begin(), newList.end());
|
||||
const auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||
for (const auto &it : changes) {
|
||||
journal->schedulePathForRemoteDiscovery(it);
|
||||
@@ -305,6 +310,9 @@ void selectiveSyncFixup(OCC::SyncJournalDb *journal, const QStringList &newList)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
SetDllDirectory(L"");
|
||||
#endif
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -313,8 +321,6 @@ int main(int argc, char **argv)
|
||||
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
|
||||
#endif
|
||||
|
||||
qsrand(std::random_device()());
|
||||
|
||||
CmdOptions options;
|
||||
options.silent = false;
|
||||
options.trustSSL = false;
|
||||
@@ -339,16 +345,15 @@ int main(int argc, char **argv)
|
||||
qFatal("Could not initialize account!");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// check if the webDAV path was added to the url and append if not.
|
||||
if (!options.target_url.endsWith("/")) {
|
||||
options.target_url.append("/");
|
||||
|
||||
if (options.target_url.contains("/webdav", Qt::CaseInsensitive) || options.target_url.contains("/dav", Qt::CaseInsensitive)) {
|
||||
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.target_url.contains(account->davPath())) {
|
||||
options.target_url.append(account->davPath());
|
||||
}
|
||||
|
||||
QUrl url = QUrl::fromUserInput(options.target_url);
|
||||
QUrl hostUrl = QUrl::fromUserInput((options.target_url.endsWith(QLatin1Char('/')) || options.target_url.endsWith(QLatin1Char('\\'))) ? options.target_url.chopped(1) : options.target_url);
|
||||
|
||||
// Order of retrieval attempt (later attempts override earlier ones):
|
||||
// 1. From URL
|
||||
@@ -356,8 +361,8 @@ int main(int argc, char **argv)
|
||||
// 3. From netrc (if enabled)
|
||||
// 4. From prompt (if interactive)
|
||||
|
||||
QString user = url.userName();
|
||||
QString password = url.password();
|
||||
QString user = hostUrl.userName();
|
||||
QString password = hostUrl.password();
|
||||
|
||||
if (!options.user.isEmpty()) {
|
||||
user = options.user;
|
||||
@@ -370,7 +375,7 @@ int main(int argc, char **argv)
|
||||
if (options.useNetrc) {
|
||||
NetrcParser parser;
|
||||
if (parser.parse()) {
|
||||
NetrcParser::LoginPair pair = parser.find(url.host());
|
||||
NetrcParser::LoginPair pair = parser.find(hostUrl.host());
|
||||
user = pair.first;
|
||||
password = pair.second;
|
||||
}
|
||||
@@ -388,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
|
||||
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.setPassword(QString());
|
||||
|
||||
// Remote folders typically start with a / and don't end with one
|
||||
QString folder = "/" + splitted.value(1);
|
||||
if (folder.endsWith("/") && folder != "/") {
|
||||
folder.chop(1);
|
||||
}
|
||||
const QString folder = options.remotePath;
|
||||
|
||||
if (!options.proxy.isNull()) {
|
||||
QString host;
|
||||
@@ -442,7 +438,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
account->setUrl(url);
|
||||
account->setUrl(hostUrl);
|
||||
account->setSslErrorHandler(sslErrorHandler);
|
||||
|
||||
QEventLoop loop;
|
||||
@@ -487,7 +483,7 @@ restart_sync:
|
||||
qCritical() << "Could not open file containing the list of unsynced folders: " << options.unsyncedfolders;
|
||||
} else {
|
||||
// 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) {
|
||||
if (!selectiveSyncList.at(i).endsWith(QLatin1Char('/'))) {
|
||||
@@ -505,6 +501,9 @@ restart_sync:
|
||||
selectiveSyncFixup(&db, selectiveSyncList);
|
||||
}
|
||||
|
||||
SyncOptions opt;
|
||||
opt.fillFromEnvironmentVariables();
|
||||
opt.verifyChunkSizes();
|
||||
SyncEngine engine(account, options.source_dir, folder, &db);
|
||||
engine.setIgnoreHiddenFiles(options.ignoreHiddenFiles);
|
||||
engine.setNetworkLimits(options.uplimit, options.downlimit);
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OCC {
|
||||
class SimpleSslErrorHandler : public OCC::AbstractSslErrorHandler
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
QByteArray findBestChecksum(const QByteArray &checksums)
|
||||
QByteArray findBestChecksum(const QByteArray &_checksums)
|
||||
{
|
||||
if (_checksums.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const auto checksums = QString::fromUtf8(_checksums);
|
||||
int i = 0;
|
||||
// The order of the searches here defines the preference ordering.
|
||||
if (-1 != (i = checksums.indexOf("SHA3-256:"))
|
||||
|| -1 != (i = checksums.indexOf("SHA256:"))
|
||||
|| -1 != (i = checksums.indexOf("SHA1:"))
|
||||
|| -1 != (i = checksums.indexOf("MD5:"))
|
||||
|| -1 != (i = checksums.indexOf("Adler32:"))) {
|
||||
if (-1 != (i = checksums.indexOf(QLatin1String("SHA3-256:"), 0, Qt::CaseInsensitive))
|
||||
|| -1 != (i = checksums.indexOf(QLatin1String("SHA256:"), 0, Qt::CaseInsensitive))
|
||||
|| -1 != (i = checksums.indexOf(QLatin1String("SHA1:"), 0, Qt::CaseInsensitive))
|
||||
|| -1 != (i = checksums.indexOf(QLatin1String("MD5:"), 0, Qt::CaseInsensitive))
|
||||
|| -1 != (i = checksums.indexOf(QLatin1String("ADLER32:"), 0, Qt::CaseInsensitive))) {
|
||||
// Now i is the start of the best checksum
|
||||
// Grab it until the next space or end of string.
|
||||
auto checksum = checksums.mid(i);
|
||||
return checksum.mid(0, checksum.indexOf(" "));
|
||||
// Grab it until the next space or end of xml or end of string.
|
||||
int end = _checksums.indexOf(' ', i);
|
||||
// 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)
|
||||
@@ -355,11 +364,11 @@ void ValidateChecksumHeader::slotChecksumCalculated(const QByteArray &checksumTy
|
||||
const QByteArray &checksum)
|
||||
{
|
||||
if (checksumType != _expectedChecksumType) {
|
||||
emit validationFailed(tr("The checksum header contained an unknown checksum type '%1'").arg(QString::fromLatin1(_expectedChecksumType)));
|
||||
emit validationFailed(tr("The checksum header contained an unknown checksum type \"%1\"").arg(QString::fromLatin1(_expectedChecksumType)));
|
||||
return;
|
||||
}
|
||||
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)));
|
||||
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;
|
||||
}
|
||||
emit validated(checksumType, checksum);
|
||||
|
||||
@@ -81,7 +81,7 @@ class OCSYNC_EXPORT ComputeChecksum : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComputeChecksum(QObject *parent = nullptr);
|
||||
~ComputeChecksum();
|
||||
~ComputeChecksum() override;
|
||||
|
||||
/**
|
||||
* Sets the checksum type to be used. The default is empty.
|
||||
|
||||
@@ -5,6 +5,7 @@ set(common_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/checksums.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/ownsql.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/preparedsqlquerymanager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/syncjournaldb.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/syncjournalfilerecord.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/utility.cpp
|
||||
|
||||
23
src/common/constants.h
Normal file
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++;
|
||||
}
|
||||
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));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
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());
|
||||
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
|
||||
|
||||
@@ -103,12 +103,6 @@ public:
|
||||
explicit SqlQuery() = default;
|
||||
explicit SqlQuery(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.
|
||||
* If the query was already prepared, this will first call finish(), and re-prepare it.
|
||||
@@ -161,10 +155,10 @@ public:
|
||||
const QByteArray &lastQuery() const;
|
||||
int numRowsAffected();
|
||||
void reset_and_clear_bindings();
|
||||
void finish();
|
||||
|
||||
private:
|
||||
void bindValueInternal(int pos, const QVariant &value);
|
||||
void finish();
|
||||
|
||||
SqlDatabase *_sqldb = nullptr;
|
||||
sqlite3 *_db = nullptr;
|
||||
@@ -172,6 +166,9 @@ private:
|
||||
QString _error;
|
||||
int _errId;
|
||||
QByteArray _sql;
|
||||
|
||||
friend class SqlDatabase;
|
||||
friend class PreparedSqlQueryManager;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -77,7 +77,7 @@ enum class PinState {
|
||||
*/
|
||||
Unspecified = 3,
|
||||
};
|
||||
Q_ENUM_NS(PinState);
|
||||
Q_ENUM_NS(PinState)
|
||||
|
||||
/** A user-facing version of PinState.
|
||||
*
|
||||
|
||||
56
src/common/preparedsqlquerymanager.cpp
Normal file
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
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)
|
||||
};
|
||||
|
||||
}
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
ASSERT(!_isError);
|
||||
return _result;
|
||||
}
|
||||
|
||||
T operator*() &&
|
||||
{
|
||||
ASSERT(!_isError);
|
||||
@@ -116,6 +117,12 @@ public:
|
||||
return &_result;
|
||||
}
|
||||
|
||||
const T &get() const
|
||||
{
|
||||
ASSERT(!_isError)
|
||||
return _result;
|
||||
}
|
||||
|
||||
const Error &error() const &
|
||||
{
|
||||
ASSERT(_isError);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "common/utility.h"
|
||||
#include "common/ownsql.h"
|
||||
#include "common/preparedsqlquerymanager.h"
|
||||
#include "common/syncjournalfilerecord.h"
|
||||
#include "common/result.h"
|
||||
#include "common/pinstate.h"
|
||||
@@ -46,7 +47,7 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SyncJournalDb(const QString &dbFilePath, QObject *parent = nullptr);
|
||||
virtual ~SyncJournalDb();
|
||||
~SyncJournalDb() override;
|
||||
|
||||
/// Create a journal path for a specific configuration
|
||||
static QString makeDbName(const QString &localPath,
|
||||
@@ -69,7 +70,6 @@ public:
|
||||
|
||||
void keyValueStoreSet(const QString &key, QVariant value);
|
||||
qint64 keyValueStoreGetInt(const QString &key, qint64 defaultValue);
|
||||
QVariant keyValueStoreGet(const QString &key, QVariant defaultValue = {});
|
||||
void keyValueStoreDelete(const QString &key);
|
||||
|
||||
bool deleteFileRecord(const QString &filename, bool recursively = false);
|
||||
@@ -392,51 +392,11 @@ private:
|
||||
|
||||
SqlDatabase _db;
|
||||
QString _dbFile;
|
||||
QMutex _mutex; // Public functions are protected with the mutex.
|
||||
QRecursiveMutex _mutex; // Public functions are protected with the mutex.
|
||||
QMap<QByteArray, int> _checksymTypeCache;
|
||||
int _transaction;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
QByteArray _journalMode;
|
||||
|
||||
PreparedSqlQueryManager _queryManager;
|
||||
};
|
||||
|
||||
bool OCSYNC_EXPORT
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QCollator>
|
||||
#include <QSysInfo>
|
||||
#include <qrandom.h>
|
||||
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
@@ -64,14 +65,13 @@ Q_LOGGING_CATEGORY(lcUtility, "nextcloud.sync.utility", QtInfoMsg)
|
||||
bool Utility::writeRandomFile(const QString &fname, int size)
|
||||
{
|
||||
int maxSize = 10 * 10 * 1024;
|
||||
qsrand(QDateTime::currentMSecsSinceEpoch());
|
||||
|
||||
if (size == -1)
|
||||
size = qrand() % maxSize;
|
||||
size = rand() % maxSize;
|
||||
|
||||
QString randString;
|
||||
for (int i = 0; i < size; i++) {
|
||||
int r = qrand() % 128;
|
||||
int r = rand() % 128;
|
||||
randString.append(QChar(r));
|
||||
}
|
||||
|
||||
@@ -109,6 +109,11 @@ void Utility::setupFavLink(const QString &folder)
|
||||
setupFavLink_private(folder);
|
||||
}
|
||||
|
||||
void Utility::removeFavLink(const QString &folder)
|
||||
{
|
||||
removeFavLink_private(folder);
|
||||
}
|
||||
|
||||
QString Utility::octetsToString(qint64 octets)
|
||||
{
|
||||
#define THE_FACTOR 1024
|
||||
@@ -259,6 +264,11 @@ QString Utility::escape(const QString &in)
|
||||
return in.toHtmlEscaped();
|
||||
}
|
||||
|
||||
int Utility::rand()
|
||||
{
|
||||
return QRandomGenerator::global()->bounded(0, RAND_MAX);
|
||||
}
|
||||
|
||||
void Utility::sleep(int sec)
|
||||
{
|
||||
QThread::sleep(sec);
|
||||
|
||||
@@ -50,10 +50,12 @@ Q_DECLARE_LOGGING_CATEGORY(lcUtility)
|
||||
* @{
|
||||
*/
|
||||
namespace Utility {
|
||||
OCSYNC_EXPORT int rand();
|
||||
OCSYNC_EXPORT void sleep(int sec);
|
||||
OCSYNC_EXPORT void usleep(int usec);
|
||||
OCSYNC_EXPORT QString formatFingerprint(const QByteArray &, bool colonSeparated = true);
|
||||
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 QString octetsToString(qint64 octets);
|
||||
OCSYNC_EXPORT QByteArray userAgentString();
|
||||
@@ -240,6 +242,11 @@ namespace Utility {
|
||||
*/
|
||||
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
|
||||
OCSYNC_EXPORT bool registryKeyExists(HKEY hRootKey, const QString &subKey);
|
||||
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);
|
||||
}
|
||||
|
||||
static void removeFavLink_private(const QString &folder)
|
||||
{
|
||||
Q_UNUSED(folder)
|
||||
}
|
||||
|
||||
bool hasLaunchOnStartup_private(const QString &)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
QString Utility::getCurrentUserName()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
} // 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
|
||||
// and respects the XDG_CONFIG_HOME env variable
|
||||
QString getUserAutostartDir_private()
|
||||
@@ -80,17 +85,17 @@ void setLaunchOnStartup_private(const QString &appName, const QString &guiName,
|
||||
|
||||
QTextStream ts(&iniFile);
|
||||
ts.setCodec("UTF-8");
|
||||
ts << QLatin1String("[Desktop Entry]") << endl
|
||||
<< QLatin1String("Name=") << guiName << endl
|
||||
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer") << endl
|
||||
<< QLatin1String("Exec=\"") << executablePath << "\" --background" << endl
|
||||
<< QLatin1String("Terminal=") << "false" << endl
|
||||
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << endl
|
||||
<< QLatin1String("Categories=") << QLatin1String("Network") << endl
|
||||
<< QLatin1String("Type=") << QLatin1String("Application") << endl
|
||||
<< QLatin1String("StartupNotify=") << "false" << endl
|
||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true" << endl
|
||||
<< QLatin1String("X-GNOME-Autostart-Delay=10") << endl;
|
||||
ts << QLatin1String("[Desktop Entry]\n")
|
||||
<< QLatin1String("Name=") << guiName << QLatin1Char('\n')
|
||||
<< QLatin1String("GenericName=") << QLatin1String("File Synchronizer\n")
|
||||
<< QLatin1String("Exec=\"") << executablePath << "\" --background\n"
|
||||
<< QLatin1String("Terminal=") << "false\n"
|
||||
<< QLatin1String("Icon=") << APPLICATION_ICON_NAME << QLatin1Char('\n')
|
||||
<< QLatin1String("Categories=") << QLatin1String("Network\n")
|
||||
<< QLatin1String("Type=") << QLatin1String("Application\n")
|
||||
<< QLatin1String("StartupNotify=") << "false\n"
|
||||
<< QLatin1String("X-GNOME-Autostart-enabled=") << "true\n"
|
||||
<< QLatin1String("X-GNOME-Autostart-Delay=10") << Qt::endl;
|
||||
} else {
|
||||
if (!QFile::remove(desktopFileLocation)) {
|
||||
qCWarning(lcUtility) << "Could not remove autostart desktop file";
|
||||
@@ -103,4 +108,9 @@ static inline bool hasDarkSystray_private()
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Utility::getCurrentUserName()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
#include "asserts.h"
|
||||
#include "utility.h"
|
||||
#include "gui/configgui.h"
|
||||
|
||||
#include <comdef.h>
|
||||
#include <Lmcons.h>
|
||||
#include <shlguid.h>
|
||||
#include <shlobj.h>
|
||||
#include <string>
|
||||
@@ -47,7 +49,14 @@ static void setupFavLink_private(const QString &folder)
|
||||
desktopIni.open(QFile::WriteOnly);
|
||||
desktopIni.write("[.ShellClassInfo]\r\nIconResource=");
|
||||
desktopIni.write(QDir::toNativeSeparators(qApp->applicationFilePath()).toUtf8());
|
||||
desktopIni.write(",0\r\n");
|
||||
#ifdef APPLICATION_FOLDER_ICON_INDEX
|
||||
const auto iconIndex = APPLICATION_FOLDER_ICON_INDEX;
|
||||
#else
|
||||
const auto iconIndex = "0";
|
||||
#endif
|
||||
desktopIni.write(",");
|
||||
desktopIni.write(iconIndex);
|
||||
desktopIni.write("\r\n");
|
||||
desktopIni.close();
|
||||
|
||||
// Set the folder as system and Desktop.ini as hidden+system for explorer to pick it.
|
||||
@@ -74,6 +83,40 @@ static void setupFavLink_private(const QString &folder)
|
||||
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)
|
||||
{
|
||||
QString runPath = QLatin1String(systemRunPathC);
|
||||
@@ -346,6 +389,17 @@ QString Utility::formatWinError(long errorCode)
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "vfs.h"
|
||||
#include "plugin.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
|
||||
public:
|
||||
explicit Vfs(QObject* parent = nullptr);
|
||||
virtual ~Vfs();
|
||||
~Vfs() override;
|
||||
|
||||
virtual Mode mode() const = 0;
|
||||
|
||||
@@ -291,7 +291,7 @@ class OCSYNC_EXPORT VfsOff : public Vfs
|
||||
|
||||
public:
|
||||
VfsOff(QObject* parent = nullptr);
|
||||
virtual ~VfsOff();
|
||||
~VfsOff() override;
|
||||
|
||||
Mode mode() const override { return Vfs::Off; }
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <libcrashreporter-gui/CrashReporter.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -52,6 +54,14 @@ int main(int argc, char *argv[])
|
||||
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>");
|
||||
|
||||
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("ProductName", CRASHREPORTER_PRODUCT_NAME);
|
||||
reporter.setReportData("Version", CRASHREPORTER_VERSION_STRING);
|
||||
|
||||
@@ -58,10 +58,11 @@ endif()
|
||||
|
||||
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(
|
||||
"${csync_NAME}"
|
||||
nextcloud_csync
|
||||
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")
|
||||
add_library(sqlite3 STATIC "${CMAKE_SOURCE_DIR}/src/3rdparty/sqlite3/sqlite3.c")
|
||||
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()
|
||||
target_include_directories("${csync_NAME}" PUBLIC ${SQLITE3_INCLUDE_DIR})
|
||||
target_link_libraries("${csync_NAME}" PUBLIC ${SQLITE3_LIBRARIES})
|
||||
target_include_directories(nextcloud_csync PUBLIC ${SQLITE3_INCLUDE_DIR})
|
||||
target_link_libraries(nextcloud_csync PUBLIC ${SQLITE3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
generate_export_header("${csync_NAME}"
|
||||
generate_export_header(nextcloud_csync
|
||||
EXPORT_MACRO_NAME OCSYNC_EXPORT
|
||||
EXPORT_FILE_NAME ocsynclib.h
|
||||
)
|
||||
|
||||
target_link_libraries("${csync_NAME}"
|
||||
target_link_libraries(nextcloud_csync
|
||||
PUBLIC
|
||||
${CSYNC_REQUIRED_LIBRARIES}
|
||||
Qt5::Core Qt5::Concurrent
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
target_link_libraries("${csync_NAME}" PUBLIC ZLIB::ZLIB)
|
||||
target_link_libraries(nextcloud_csync PUBLIC ZLIB::ZLIB)
|
||||
endif(ZLIB_FOUND)
|
||||
|
||||
|
||||
@@ -96,11 +97,11 @@ endif(ZLIB_FOUND)
|
||||
if (APPLE)
|
||||
find_library(FOUNDATION_LIBRARY NAMES Foundation)
|
||||
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()
|
||||
|
||||
set_target_properties(
|
||||
"${csync_NAME}"
|
||||
nextcloud_csync
|
||||
PROPERTIES
|
||||
VERSION
|
||||
${LIBRARY_VERSION}
|
||||
@@ -108,11 +109,15 @@ set_target_properties(
|
||||
${LIBRARY_SOVERSION}
|
||||
RUNTIME_OUTPUT_DIRECTORY
|
||||
${BIN_OUTPUT_DIRECTORY}
|
||||
LIBRARY_OUTPUT_NAME
|
||||
${APPLICATION_EXECUTABLE}_csync
|
||||
RUNTIME_OUTPUT_NAME
|
||||
${APPLICATION_EXECUTABLE}_csync
|
||||
)
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
INSTALL(
|
||||
TARGETS
|
||||
"${csync_NAME}"
|
||||
nextcloud_csync
|
||||
LIBRARY DESTINATION
|
||||
${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION
|
||||
@@ -123,7 +128,7 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
else()
|
||||
INSTALL(
|
||||
TARGETS
|
||||
"${csync_NAME}"
|
||||
nextcloud_csync
|
||||
LIBRARY DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION
|
||||
|
||||
@@ -7,7 +7,6 @@ include(CheckCXXSourceCompiles)
|
||||
|
||||
set(PACKAGE ${APPLICATION_NAME})
|
||||
set(VERSION ${APPLICATION_VERSION})
|
||||
set(DATADIR ${DATA_INSTALL_DIR})
|
||||
set(LIBDIR ${LIB_INSTALL_DIR})
|
||||
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||
|
||||
@@ -23,6 +22,12 @@ if (NOT LINUX)
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
|
||||
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)
|
||||
|
||||
if(WIN32)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
#include <qglobal.h>
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
@@ -34,10 +35,8 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
|
||||
/** Expands C-like escape sequences (in place)
|
||||
*/
|
||||
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
|
||||
|
||||
/* We create a Desktop.ini on Windows for the sidebar icon, make sure we don't sync it. */
|
||||
if (blen == 11 && path == bname) {
|
||||
if (bname.compare(QLatin1String("Desktop.ini"), Qt::CaseInsensitive) == 0) {
|
||||
return CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
}
|
||||
/* Do not sync desktop.ini files anywhere in the tree. */
|
||||
const auto desktopIniFile = QStringLiteral("desktop.ini");
|
||||
if (blen == static_cast<qsizetype>(desktopIniFile.length()) && bname.compare(desktopIniFile, Qt::CaseInsensitive) == 0) {
|
||||
return CSYNC_FILE_SILENTLY_EXCLUDED;
|
||||
}
|
||||
|
||||
|
||||
if (excludeConflictFiles && OCC::Utility::isConflictFile(path)) {
|
||||
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
|
||||
if (_localPath.isEmpty())
|
||||
return;
|
||||
|
||||
// Load exclude file from base dir
|
||||
QFileInfo fi(_localPath + QStringLiteral(".sync-exclude.lst"));
|
||||
if (fi.isReadable())
|
||||
addInTreeExcludeFilePath(fi.absoluteFilePath());
|
||||
}
|
||||
|
||||
ExcludedFiles::~ExcludedFiles() = default;
|
||||
|
||||
void ExcludedFiles::addExcludeFilePath(const QString &path)
|
||||
{
|
||||
_excludeFiles[_localPath].append(path);
|
||||
}
|
||||
|
||||
void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
|
||||
{
|
||||
BasePathString basePath = leftIncludeLast(path, QLatin1Char('/'));
|
||||
_excludeFiles[basePath].append(path);
|
||||
const QFileInfo excludeFileInfo(path);
|
||||
const auto fileName = excludeFileInfo.fileName();
|
||||
const auto basePath = fileName.compare(QStringLiteral("sync-exclude.lst"), Qt::CaseInsensitive) == 0
|
||||
? _localPath
|
||||
: leftIncludeLast(path, QLatin1Char('/'));
|
||||
auto &excludeFilesLocalPath = _excludeFiles[basePath];
|
||||
if (std::find(excludeFilesLocalPath.cbegin(), excludeFilesLocalPath.cend(), path) == excludeFilesLocalPath.cend()) {
|
||||
excludeFilesLocalPath.append(path);
|
||||
}
|
||||
}
|
||||
|
||||
void ExcludedFiles::setExcludeConflictFiles(bool onoff)
|
||||
@@ -288,32 +284,26 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version 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;
|
||||
while (!f.atEnd()) {
|
||||
QByteArray line = f.readLine().trimmed();
|
||||
while (!file.atEnd()) {
|
||||
QByteArray line = file.readLine().trimmed();
|
||||
if (line.startsWith("#!version")) {
|
||||
if (!versionDirectiveKeepNextLine(line))
|
||||
f.readLine();
|
||||
file.readLine();
|
||||
}
|
||||
if (line.isEmpty() || line.startsWith('#'))
|
||||
continue;
|
||||
csync_exclude_expand_escapes(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
|
||||
if (!_allExcludes.value(basePath).isEmpty()){
|
||||
prepare(basePath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExcludedFiles::reloadExcludeFiles()
|
||||
@@ -330,8 +320,14 @@ bool ExcludedFiles::reloadExcludeFiles()
|
||||
bool success = true;
|
||||
const auto keys = _excludeFiles.keys();
|
||||
for (const auto& basePath : keys) {
|
||||
for (const auto& file : _excludeFiles.value(basePath)) {
|
||||
success = loadExcludeFile(basePath, file);
|
||||
for (const auto &excludeFile : _excludeFiles.value(basePath)) {
|
||||
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
|
||||
if (filetype == ItemTypeDirectory) {
|
||||
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()) {
|
||||
addInTreeExcludeFilePath(fi.absoluteFilePath());
|
||||
loadExcludeFile(basePath, fi.absoluteFilePath());
|
||||
if (excludeFileInfo.isReadable()) {
|
||||
addExcludeFilePath(absolutePath);
|
||||
reloadExcludeFiles();
|
||||
} else {
|
||||
qWarning() << "System exclude list file could not be read:" << absolutePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ enum CSYNC_EXCLUDE_TYPE {
|
||||
};
|
||||
|
||||
class ExcludedFilesTest;
|
||||
class QFile;
|
||||
|
||||
/**
|
||||
* Manages file/directory exclusion.
|
||||
@@ -69,7 +70,7 @@ public:
|
||||
using Version = std::tuple<int, int, int>;
|
||||
|
||||
explicit ExcludedFiles(const QString &localPath = QStringLiteral("/"));
|
||||
~ExcludedFiles();
|
||||
~ExcludedFiles() override;
|
||||
|
||||
/**
|
||||
* Adds a new path to a file containing exclude patterns.
|
||||
@@ -77,7 +78,6 @@ public:
|
||||
* Does not load the file. Use reloadExcludeFiles() afterwards.
|
||||
*/
|
||||
void addExcludeFilePath(const QString &path);
|
||||
void addInTreeExcludeFilePath(const QString &path);
|
||||
|
||||
/**
|
||||
* Whether conflict files shall be excluded.
|
||||
@@ -148,7 +148,7 @@ public slots:
|
||||
/**
|
||||
* Loads the exclude patterns from file the registered base paths.
|
||||
*/
|
||||
bool loadExcludeFile(const QString &basePath, const QString &file);
|
||||
void loadExcludeFilePatterns(const QString &basePath, QFile &file);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -124,7 +124,8 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
|
||||
if (vfs) {
|
||||
// Directly modifies file_stat->type.
|
||||
// We can ignore the return value since we're done here anyway.
|
||||
vfs->statTypeVirtualFile(file_stat.get(), &handle->path);
|
||||
const auto result = vfs->statTypeVirtualFile(file_stat.get(), &handle->path);
|
||||
Q_UNUSED(result)
|
||||
}
|
||||
|
||||
return file_stat;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "csync.h"
|
||||
#include "vio/csync_vio_local.h"
|
||||
#include "common/filesystembase.h"
|
||||
#include "common/utility.h"
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
@@ -52,8 +53,6 @@ struct csync_vio_handle_t {
|
||||
QString path; // Always ends with '\'
|
||||
};
|
||||
|
||||
static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf);
|
||||
|
||||
csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
|
||||
|
||||
QScopedPointer<csync_vio_handle_t> handle(new csync_vio_handle_t{});
|
||||
@@ -175,12 +174,9 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
|
||||
file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
|
||||
file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
|
||||
|
||||
QString fullPath;
|
||||
fullPath.reserve(handle->path.size() + std::wcslen(handle->ffd.cFileName));
|
||||
fullPath += handle->path; // path always ends with '\', by construction
|
||||
fullPath += QString::fromWCharArray(handle->ffd.cFileName);
|
||||
// path always ends with '\', by construction
|
||||
|
||||
if (_csync_vio_local_stat_mb(fullPath, file_stat.get()) < 0) {
|
||||
if (csync_vio_local_stat(handle->path + QString::fromWCharArray(handle->ffd.cFileName), file_stat.get()) < 0) {
|
||||
// Will get excluded by _csync_detect_update.
|
||||
file_stat->type = ItemTypeSkip;
|
||||
}
|
||||
@@ -188,14 +184,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
|
||||
int csync_vio_local_stat(const QString &uri, csync_file_stat_t *buf)
|
||||
{
|
||||
int rc = _csync_vio_local_stat_mb(uri, buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
|
||||
{
|
||||
/* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
|
||||
But we still need to fetch the file ID.
|
||||
@@ -206,21 +195,19 @@ static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
|
||||
BY_HANDLE_FILE_INFORMATION fileInfo;
|
||||
ULARGE_INTEGER FileIndex;
|
||||
|
||||
const auto longPath = OCC::FileSystem::longWinPath(path);
|
||||
|
||||
h = CreateFileW(longPath.toStdWString().data(), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
nullptr );
|
||||
h = CreateFileW(reinterpret_cast<const wchar_t *>(OCC::FileSystem::longWinPath(uri).utf16()), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
NULL);
|
||||
if( h == INVALID_HANDLE_VALUE ) {
|
||||
qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << longPath;
|
||||
errno = GetLastError();
|
||||
qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << uri << OCC::Utility::formatWinError(errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!GetFileInformationByHandle( h, &fileInfo ) ) {
|
||||
qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << longPath;
|
||||
errno = GetLastError();
|
||||
qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << uri << OCC::Utility::formatWinError(errno);
|
||||
CloseHandle(h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
project(gui)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets Svg Qml Quick QuickControls2 Xml Network)
|
||||
if (NOT TARGET Qt5::GuiPrivate)
|
||||
message(FATAL_ERROR "Could not find GuiPrivate component of Qt5. It might be shipped as a separate package, please check that.")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
add_definitions(-DQT_QML_DEBUG)
|
||||
@@ -18,6 +21,7 @@ set(theme_dir ${CMAKE_SOURCE_DIR}/theme)
|
||||
set(client_UI_SRCS
|
||||
accountsettings.ui
|
||||
conflictdialog.ui
|
||||
invalidfilenamedialog.ui
|
||||
foldercreationdialog.ui
|
||||
folderwizardsourcepage.ui
|
||||
folderwizardtargetpage.ui
|
||||
@@ -35,17 +39,27 @@ set(client_UI_SRCS
|
||||
addcertificatedialog.ui
|
||||
proxyauthdialog.ui
|
||||
mnemonicdialog.ui
|
||||
UserStatusSelector.qml
|
||||
UserStatusSelectorDialog.qml
|
||||
tray/ActivityActionButton.qml
|
||||
tray/ActivityItem.qml
|
||||
tray/ActivityList.qml
|
||||
tray/Window.qml
|
||||
tray/UserLine.qml
|
||||
tray/UnifiedSearchInputContainer.qml
|
||||
tray/UnifiedSearchResultFetchMoreTrigger.qml
|
||||
tray/UnifiedSearchResultItem.qml
|
||||
tray/UnifiedSearchResultItemSkeleton.qml
|
||||
tray/UnifiedSearchResultItemSkeletonContainer.qml
|
||||
tray/UnifiedSearchResultListItem.qml
|
||||
tray/UnifiedSearchResultNothingFound.qml
|
||||
tray/UnifiedSearchResultSectionItem.qml
|
||||
wizard/flow2authwidget.ui
|
||||
wizard/owncloudadvancedsetuppage.ui
|
||||
wizard/owncloudconnectionmethoddialog.ui
|
||||
wizard/owncloudhttpcredspage.ui
|
||||
wizard/owncloudoauthcredspage.ui
|
||||
wizard/owncloudsetupnocredspage.ui
|
||||
wizard/owncloudwizardresultpage.ui
|
||||
wizard/webview.ui
|
||||
wizard/welcomepage.ui
|
||||
)
|
||||
@@ -54,6 +68,7 @@ set(client_SRCS
|
||||
accountmanager.cpp
|
||||
accountsettings.cpp
|
||||
application.cpp
|
||||
invalidfilenamedialog.cpp
|
||||
conflictdialog.cpp
|
||||
conflictsolver.cpp
|
||||
connectionvalidator.cpp
|
||||
@@ -86,15 +101,14 @@ set(client_SRCS
|
||||
sharelinkwidget.cpp
|
||||
sharemanager.cpp
|
||||
shareusergroupwidget.cpp
|
||||
profilepagewidget.cpp
|
||||
sharee.cpp
|
||||
socketapi.cpp
|
||||
sslbutton.cpp
|
||||
sslerrordialog.cpp
|
||||
syncrunfilelog.cpp
|
||||
systray.cpp
|
||||
thumbnailjob.cpp
|
||||
userinfo.cpp
|
||||
userstatus.cpp
|
||||
accountstate.cpp
|
||||
addcertificatedialog.cpp
|
||||
authenticationdialog.cpp
|
||||
@@ -105,13 +119,21 @@ set(client_SRCS
|
||||
guiutility.cpp
|
||||
elidedlabel.cpp
|
||||
headerbanner.cpp
|
||||
iconjob.cpp
|
||||
iconutils.cpp
|
||||
remotewipe.cpp
|
||||
tray/ActivityData.cpp
|
||||
tray/ActivityListModel.cpp
|
||||
tray/UserModel.cpp
|
||||
tray/NotificationHandler.cpp
|
||||
tray/NotificationCache.cpp
|
||||
userstatusselectormodel.cpp
|
||||
emojimodel.cpp
|
||||
fileactivitylistmodel.cpp
|
||||
tray/svgimageprovider.cpp
|
||||
tray/syncstatussummary.cpp
|
||||
tray/activitydata.cpp
|
||||
tray/activitylistmodel.cpp
|
||||
tray/unifiedsearchresult.cpp
|
||||
tray/unifiedsearchresultimageprovider.cpp
|
||||
tray/unifiedsearchresultslistmodel.cpp
|
||||
tray/usermodel.cpp
|
||||
tray/notificationhandler.cpp
|
||||
tray/notificationcache.cpp
|
||||
creds/credentialsfactory.cpp
|
||||
creds/httpcredentialsgui.cpp
|
||||
creds/oauth.cpp
|
||||
@@ -129,7 +151,6 @@ set(client_SRCS
|
||||
wizard/owncloudsetuppage.cpp
|
||||
wizard/owncloudwizardcommon.cpp
|
||||
wizard/owncloudwizard.cpp
|
||||
wizard/owncloudwizardresultpage.cpp
|
||||
wizard/slideshow.cpp
|
||||
wizard/welcomepage.cpp
|
||||
wizard/linklabel.cpp
|
||||
@@ -152,7 +173,6 @@ endif()
|
||||
|
||||
IF( APPLE )
|
||||
list(APPEND client_SRCS cocoainitializer_mac.mm)
|
||||
list(APPEND client_SRCS socketapisocket_mac.mm)
|
||||
list(APPEND client_SRCS systray.mm)
|
||||
|
||||
if(SPARKLE_FOUND AND BUILD_UPDATER)
|
||||
@@ -186,6 +206,7 @@ set(3rdparty_SRC
|
||||
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
|
||||
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
|
||||
../3rdparty/kmessagewidget/kmessagewidget.cpp
|
||||
../3rdparty/kirigami/wheelhandler.cpp
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
@@ -237,20 +258,39 @@ if (NOT DEFINED APPLICATION_ICON_NAME)
|
||||
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED APPLICATION_FOLDER_ICON_INDEX)
|
||||
set(APPLICATION_FOLDER_ICON_INDEX 0)
|
||||
endif()
|
||||
|
||||
# Generate png icons from svg
|
||||
find_program(INKSCAPE
|
||||
NAMES inkscape inkscape.exe
|
||||
find_program(SVG_CONVERTER
|
||||
NAMES inkscape inkscape.exe rsvg-convert
|
||||
REQUIRED
|
||||
HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV INKSCAPE_DIR)
|
||||
HINTS "C:\\Program Files\\Inkscape\\bin" "/usr/bin" ENV SVG_CONVERTER_DIR)
|
||||
# REQUIRED keyword is only supported on CMake 3.18 and above
|
||||
if (NOT INKSCAPE)
|
||||
message(FATAL_ERROR "Could not find inkscape. Set INKSCAPE_DIR to the path of executable.")
|
||||
if (NOT SVG_CONVERTER)
|
||||
message(FATAL_ERROR "Could not find a suitable svg converter. Set SVG_CONVERTER_DIR to the path of either the inkscape or rsvg-convert executable.")
|
||||
endif()
|
||||
|
||||
function(generate_sized_png_from_svg icon_path size)
|
||||
set(options)
|
||||
set(oneValueArgs OUTPUT_ICON_NAME OUTPUT_ICON_PATH)
|
||||
set(multiValueArgs)
|
||||
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
get_filename_component(icon_name_dir ${icon_path} DIRECTORY)
|
||||
get_filename_component(icon_name_wle ${icon_path} NAME_WLE)
|
||||
|
||||
if (ARG_OUTPUT_ICON_NAME)
|
||||
set(icon_name_wle ${ARG_OUTPUT_ICON_NAME})
|
||||
endif ()
|
||||
|
||||
if (ARG_OUTPUT_ICON_PATH)
|
||||
set(icon_name_dir ${ARG_OUTPUT_ICON_PATH})
|
||||
endif ()
|
||||
|
||||
|
||||
if (EXISTS "${icon_name_dir}/${size}-${icon_name_wle}.png")
|
||||
return()
|
||||
endif()
|
||||
@@ -258,16 +298,16 @@ function(generate_sized_png_from_svg icon_path size)
|
||||
set(icon_output_name "${size}-${icon_name_wle}.png")
|
||||
message(STATUS "Generate ${icon_output_name}")
|
||||
execute_process(COMMAND
|
||||
"${INKSCAPE}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
|
||||
"${SVG_CONVERTER}" -w ${size} -h ${size} "${icon_path}" -o "${icon_output_name}"
|
||||
WORKING_DIRECTORY "${icon_name_dir}"
|
||||
RESULT_VARIABLE
|
||||
INKSCAPE_SIDEBAR_ERROR
|
||||
SVG_CONVERTER_SIDEBAR_ERROR
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET)
|
||||
|
||||
if (INKSCAPE_SIDEBAR_ERROR)
|
||||
if (SVG_CONVERTER_SIDEBAR_ERROR)
|
||||
message(FATAL_ERROR
|
||||
"inkscape could not generate icon: ${INKSCAPE_SIDEBAR_ERROR}")
|
||||
"${SVG_CONVERTER} could not generate icon: ${SVG_CONVERTER_SIDEBAR_ERROR}")
|
||||
else()
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -296,22 +336,86 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
set(APP_ICON_SVG "${theme_dir}/colored/${APPLICATION_ICON_NAME}-icon.svg")
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 16)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 24)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 32)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 48)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 64)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 128)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 256)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 512)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} 1024)
|
||||
|
||||
# generate secondary icon if available (currently for Windows only)--------------------------------------
|
||||
set(APP_SECONDARY_ICONS "${theme_dir}/colored/icons")
|
||||
set(APP_ICON_WIN_FOLDER_SVG "${APP_SECONDARY_ICONS}/${APPLICATION_ICON_NAME}-icon-win-folder.svg")
|
||||
|
||||
set(RC_DEPENDENCIES "")
|
||||
|
||||
if(WIN32)
|
||||
if (EXISTS ${APP_ICON_WIN_FOLDER_SVG})
|
||||
get_filename_component(output_icon_name_win ${APP_ICON_WIN_FOLDER_SVG} NAME_WLE)
|
||||
# Product icon (for smallest size)
|
||||
foreach(size IN ITEMS 16;20)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/")
|
||||
endforeach()
|
||||
|
||||
# Product icon with Windows folder (for sizes larger than 20)
|
||||
foreach(size IN ITEMS 24;32;40;48;64;128;256;512;1024)
|
||||
generate_sized_png_from_svg(${APP_ICON_WIN_FOLDER_SVG} ${size} OUTPUT_ICON_NAME ${output_icon_name_win} OUTPUT_ICON_PATH "${APP_SECONDARY_ICONS}/")
|
||||
endforeach()
|
||||
|
||||
file(GLOB_RECURSE OWNCLOUD_ICONS_WIN_FOLDER "${APP_SECONDARY_ICONS}/*-${APPLICATION_ICON_NAME}-icon*")
|
||||
set(APP_ICON_WIN_FOLDER_ICO_NAME "${APPLICATION_ICON_NAME}-win-folder")
|
||||
set(RC_DEPENDENCIES "${RC_DEPENDENCIES} ${APP_ICON_WIN_FOLDER_ICO_NAME}.ico")
|
||||
ecm_add_app_icon(APP_ICON_WIN_FOLDER ICONS "${OWNCLOUD_ICONS_WIN_FOLDER}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APP_ICON_WIN_FOLDER_ICO_NAME}" ICON_INDEX 2)
|
||||
endif()
|
||||
endif()
|
||||
# --------------------------------------
|
||||
|
||||
if (NOT ${RC_DEPENDENCIES} STREQUAL "")
|
||||
string(STRIP ${RC_DEPENDENCIES} RC_DEPENDENCIES)
|
||||
endif()
|
||||
|
||||
# generate primary icon from SVG (due to Win .ico vs .rc dependency issues, primary icon must always be generated last)--------------------------------------
|
||||
if(WIN32)
|
||||
foreach(size IN ITEMS 16;20;24;32;40;48;64;128;256;512;1024)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} ${size})
|
||||
endforeach()
|
||||
else()
|
||||
foreach(size IN ITEMS 16;24;32;48;64;128;256;512;1024)
|
||||
generate_sized_png_from_svg(${APP_ICON_SVG} ${size})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE OWNCLOUD_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-icon*")
|
||||
|
||||
if(APPLE)
|
||||
file(GLOB_RECURSE OWNCLOUD_SIDEBAR_ICONS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-sidebar*")
|
||||
MESSAGE(STATUS "OWNCLOUD_SIDEBAR_ICONS: ${APPLICATION_ICON_NAME}: ${OWNCLOUD_SIDEBAR_ICONS}")
|
||||
endif()
|
||||
ecm_add_app_icon(APP_ICON ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}")
|
||||
|
||||
ecm_add_app_icon(APP_ICON RC_DEPENDENCIES ${RC_DEPENDENCIES} ICONS "${OWNCLOUD_ICONS}" SIDEBAR_ICONS "${OWNCLOUD_SIDEBAR_ICONS}" OUTFILE_BASENAME "${APPLICATION_ICON_NAME}" ICON_INDEX 1)
|
||||
# --------------------------------------
|
||||
|
||||
if(WIN32)
|
||||
# merge *.rc.in files for Windows (multiple ICON resources must be placed in a single file, otherwise, this won't work de to a bug in Windows compiler https://developercommunity.visualstudio.com/t/visual-studio-2017-prof-1557-cvt1100-duplicate-res/363156)
|
||||
function(merge_files IN_FILE OUT_FILE)
|
||||
file(READ ${IN_FILE} CONTENTS)
|
||||
message("Merging ${IN_FILE} into ${OUT_FILE}")
|
||||
file(APPEND ${OUT_FILE} "${CONTENTS}")
|
||||
endfunction()
|
||||
message("APP_ICON is: ${APP_ICON}")
|
||||
if(APP_ICON)
|
||||
get_filename_component(RC_IN_FOLDER ${APP_ICON}} DIRECTORY)
|
||||
|
||||
file(GLOB_RECURSE RC_IN_FILES "${RC_IN_FOLDER}/*rc.in")
|
||||
|
||||
foreach(rc_in_file IN ITEMS ${RC_IN_FILES})
|
||||
get_filename_component(rc_in_file_name ${rc_in_file} NAME)
|
||||
get_filename_component(app_icon_name "${APP_ICON}.in" NAME)
|
||||
if(NOT "${rc_in_file_name}" STREQUAL "${app_icon_name}")
|
||||
merge_files(${rc_in_file} "${APP_ICON}.in")
|
||||
if (DEFINED APPLICATION_FOLDER_ICON_INDEX)
|
||||
MATH(EXPR APPLICATION_FOLDER_ICON_INDEX "${APPLICATION_FOLDER_ICON_INDEX}+1")
|
||||
message("APPLICATION_FOLDER_ICON_INDEX is now set to: ${APPLICATION_FOLDER_ICON_INDEX}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
# --------------------------------------
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
|
||||
@@ -327,6 +431,7 @@ add_library(nextcloudCore STATIC ${final_src})
|
||||
|
||||
target_link_libraries(nextcloudCore
|
||||
PUBLIC
|
||||
Nextcloud::sync
|
||||
Qt5::Widgets
|
||||
Qt5::GuiPrivate
|
||||
Qt5::Svg
|
||||
@@ -335,9 +440,10 @@ target_link_libraries(nextcloudCore
|
||||
Qt5::Qml
|
||||
Qt5::Quick
|
||||
Qt5::QuickControls2
|
||||
${synclib_NAME}
|
||||
)
|
||||
|
||||
add_subdirectory(socketapi)
|
||||
|
||||
if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND)
|
||||
target_link_libraries(nextcloudCore PUBLIC Qt5::WebEngineWidgets)
|
||||
endif()
|
||||
@@ -353,6 +459,7 @@ target_include_directories(nextcloudCore
|
||||
PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/QProgressIndicator
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/qtlockedfile
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/kirigami
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/qtsingleapplication
|
||||
${CMAKE_SOURCE_DIR}/src/3rdparty/kmessagewidget
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
@@ -365,9 +472,9 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
foreach(_file ${_icons})
|
||||
string(REPLACE "${theme_dir}/colored/" "" _res ${_file})
|
||||
string(REPLACE "-${APPLICATION_ICON_NAME}-icon.png" "" _res ${_res})
|
||||
install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps)
|
||||
install(FILES ${_file} RENAME ${APPLICATION_ICON_NAME}.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}x${_res}/apps)
|
||||
endforeach(_file)
|
||||
install(FILES ${client_I18N} DESTINATION ${SHAREDIR}/${APPLICATION_EXECUTABLE}/i18n)
|
||||
install(FILES ${client_I18N} DESTINATION ${CMAKE_INSTALL_DATADIR}/${APPLICATION_EXECUTABLE}/i18n)
|
||||
else()
|
||||
file(GLOB_RECURSE VISUAL_ELEMENTS "${theme_dir}/colored/*-${APPLICATION_ICON_NAME}-w10startmenu*")
|
||||
install(FILES ${VISUAL_ELEMENTS} DESTINATION bin/visualelements)
|
||||
@@ -376,17 +483,23 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
endif()
|
||||
|
||||
# we may not add MACOSX_BUNDLE here, if not building one
|
||||
add_executable(${APPLICATION_EXECUTABLE} WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
|
||||
add_executable(nextcloud WIN32 main.cpp ${client_version} ${client_manifest} ${APP_ICON})
|
||||
set_target_properties(nextcloud PROPERTIES
|
||||
OUTPUT_NAME "${APPLICATION_EXECUTABLE}"
|
||||
)
|
||||
else()
|
||||
# set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
|
||||
set(MACOSX_BUNDLE_ICON_FILE "${APPLICATION_ICON_NAME}.icns")
|
||||
|
||||
# we must add MACOSX_BUNDLE only if building a bundle
|
||||
add_executable(${APPLICATION_EXECUTABLE} WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
|
||||
add_executable(nextcloud WIN32 MACOSX_BUNDLE main.cpp ${APP_ICON})
|
||||
|
||||
if (BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
set_target_properties(${APPLICATION_EXECUTABLE} PROPERTIES
|
||||
set_target_properties(nextcloud PROPERTIES
|
||||
OUTPUT_NAME "${APPLICATION_NAME}")
|
||||
else()
|
||||
set_target_properties(nextcloud PROPERTIES
|
||||
OUTPUT_NAME "${APPLICATION_EXECUTABLE}")
|
||||
endif()
|
||||
|
||||
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
|
||||
@@ -406,22 +519,17 @@ endif()
|
||||
|
||||
IF(BUILD_UPDATER)
|
||||
add_library(updater STATIC ${updater_SRCS})
|
||||
target_link_libraries(updater ${synclib_NAME} ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
|
||||
target_link_libraries(updater Nextcloud::sync ${updater_DEPS} Qt5::Widgets Qt5::Svg Qt5::Network Qt5::Xml)
|
||||
target_include_directories(updater PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set_target_properties(updater PROPERTIES AUTOMOC ON)
|
||||
target_link_libraries(nextcloudCore PUBLIC updater)
|
||||
endif()
|
||||
|
||||
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
|
||||
set_target_properties(nextcloud PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
target_link_libraries(${APPLICATION_EXECUTABLE} nextcloudCore)
|
||||
|
||||
IF(BUILD_UPDATER)
|
||||
target_link_libraries(nextcloudCore PUBLIC updater)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nextcloudCore PUBLIC ${OS_SPECIFIC_LINK_LIBRARIES})
|
||||
target_link_libraries(nextcloud PRIVATE nextcloudCore)
|
||||
|
||||
if(TARGET PkgConfig::CLOUDPROVIDERS)
|
||||
message("Building with libcloudproviderssupport")
|
||||
@@ -467,11 +575,7 @@ if(WITH_CRASHREPORTER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# application.cpp still uses QDesktopServices::storageLocation
|
||||
target_compile_definitions(nextcloudCore PRIVATE "QT_DISABLE_DEPRECATED_BEFORE=0")
|
||||
|
||||
|
||||
install(TARGETS ${APPLICATION_EXECUTABLE}
|
||||
install(TARGETS nextcloud
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
@@ -498,12 +602,12 @@ if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
|
||||
set(NO_STRIP "")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET ${APPLICATION_EXECUTABLE} POST_BUILD
|
||||
add_custom_command(TARGET nextcloud POST_BUILD
|
||||
COMMAND "${MACDEPLOYQT_EXECUTABLE}"
|
||||
"$<TARGET_FILE_DIR:${APPLICATION_EXECUTABLE}>/../.."
|
||||
"$<TARGET_FILE_DIR:nextcloud>/../.."
|
||||
-qmldir=${CMAKE_SOURCE_DIR}/src/gui
|
||||
-always-overwrite
|
||||
-executable="$<TARGET_FILE_DIR:${APPLICATION_EXECUTABLE}>/${cmd_NAME}"
|
||||
-executable="$<TARGET_FILE_DIR:nextcloud>/${cmd_NAME}"
|
||||
${NO_STRIP}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-E rm -rf "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/bearer"
|
||||
@@ -514,13 +618,15 @@ endif()
|
||||
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT WIN32)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${DATADIR}/applications )
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINUX_APPLICATION_ID}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
|
||||
|
||||
configure_file(owncloud.xml.in ${APPLICATION_EXECUTABLE}.xml)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${DATADIR}/mime/packages )
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages )
|
||||
|
||||
find_package(SharedMimeInfo)
|
||||
if(SharedMimeInfo_FOUND)
|
||||
update_xdg_mimetypes( ${DATADIR}/mime/packages )
|
||||
update_xdg_mimetypes( ${CMAKE_INSTALL_DATADIR}/mime/packages )
|
||||
endif(SharedMimeInfo_FOUND)
|
||||
endif()
|
||||
|
||||
configure_file(configgui.h.in ${CMAKE_CURRENT_BINARY_DIR}/configgui.h)
|
||||
|
||||
112
src/gui/EmojiPicker.qml
Normal file
112
src/gui/EmojiPicker.qml
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) by Felix Weilbach <felix.weilbach@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.
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import com.nextcloud.desktopclient 1.0 as NC
|
||||
|
||||
ColumnLayout {
|
||||
NC.EmojiModel {
|
||||
id: emojiModel
|
||||
}
|
||||
|
||||
signal chosen(string emoji)
|
||||
|
||||
spacing: 0
|
||||
|
||||
FontMetrics {
|
||||
id: metrics
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: headerLayout
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: contentItem.childrenRect.width
|
||||
implicitHeight: metrics.height * 2
|
||||
|
||||
orientation: ListView.Horizontal
|
||||
|
||||
model: emojiModel.emojiCategoriesModel
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: metrics.height * 2
|
||||
height: headerLayout.height
|
||||
|
||||
contentItem: Text {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: emoji
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
width: parent.width
|
||||
height: 2
|
||||
|
||||
visible: ListView.isCurrentItem
|
||||
|
||||
color: "grey"
|
||||
}
|
||||
|
||||
|
||||
onClicked: {
|
||||
emojiModel.setCategory(label)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
Layout.fillWidth: true
|
||||
color: "grey"
|
||||
}
|
||||
|
||||
GridView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredHeight: metrics.height * 8
|
||||
|
||||
cellWidth: metrics.height * 2
|
||||
cellHeight: metrics.height * 2
|
||||
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
clip: true
|
||||
|
||||
model: emojiModel.model
|
||||
|
||||
delegate: ItemDelegate {
|
||||
|
||||
width: metrics.height * 2
|
||||
height: metrics.height * 2
|
||||
|
||||
contentItem: Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData === undefined ? "" : modelData.unicode
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
chosen(modelData.unicode);
|
||||
emojiModel.emojiUsed(modelData);
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
32
src/gui/ErrorBox.qml
Normal file
32
src/gui/ErrorBox.qml
Normal file
@@ -0,0 +1,32 @@
|
||||
import QtQuick 2.15
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Item {
|
||||
id: errorBox
|
||||
|
||||
property var text: ""
|
||||
|
||||
property color color: Style.errorBoxTextColor
|
||||
property color backgroundColor: Style.errorBoxBackgroundColor
|
||||
property color borderColor: Style.errorBoxBorderColor
|
||||
|
||||
implicitHeight: errorMessage.implicitHeight + 2 * 8
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: errorBox.backgroundColor
|
||||
border.color: errorBox.borderColor
|
||||
}
|
||||
|
||||
Text {
|
||||
id: errorMessage
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
width: parent.width
|
||||
color: errorBox.color
|
||||
wrapMode: Text.WordWrap
|
||||
text: errorBox.text
|
||||
}
|
||||
}
|
||||
200
src/gui/UserStatusSelector.qml
Normal file
200
src/gui/UserStatusSelector.qml
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) by Felix Weilbach <felix.weilbach@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.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import com.nextcloud.desktopclient 1.0 as NC
|
||||
|
||||
ColumnLayout {
|
||||
id: rootLayout
|
||||
spacing: 0
|
||||
property NC.UserStatusSelectorModel userStatusSelectorModel
|
||||
|
||||
FontMetrics {
|
||||
id: metrics
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.bottomMargin: 8
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
font.bold: true
|
||||
text: qsTr("Online status")
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.margins: 8
|
||||
Layout.alignment: Qt.AlignTop
|
||||
columns: 2
|
||||
rows: 2
|
||||
columnSpacing: 8
|
||||
rowSpacing: 8
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
checked: NC.UserStatus.Online == userStatusSelectorModel.onlineStatus
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.onlineIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Online")
|
||||
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Online)
|
||||
implicitWidth: 100
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
checked: NC.UserStatus.Away == userStatusSelectorModel.onlineStatus
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.awayIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Away")
|
||||
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Away)
|
||||
implicitWidth: 100
|
||||
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
checked: NC.UserStatus.DoNotDisturb == userStatusSelectorModel.onlineStatus
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.dndIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Do not disturb")
|
||||
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.DoNotDisturb)
|
||||
implicitWidth: 100
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
checked: NC.UserStatus.Invisible == userStatusSelectorModel.onlineStatus
|
||||
checkable: true
|
||||
icon.source: userStatusSelectorModel.invisibleIcon
|
||||
icon.color: "transparent"
|
||||
text: qsTr("Invisible")
|
||||
onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Invisible)
|
||||
implicitWidth: 100
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.bottomMargin: 8
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
font.bold: true
|
||||
text: qsTr("Status message")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.bottomMargin: 16
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
|
||||
Button {
|
||||
Layout.preferredWidth: userStatusMessageTextField.height // metrics.height * 2
|
||||
Layout.preferredHeight: userStatusMessageTextField.height // metrics.height * 2
|
||||
text: userStatusSelectorModel.userStatusEmoji
|
||||
onClicked: emojiDialog.open()
|
||||
}
|
||||
|
||||
Popup {
|
||||
id: emojiDialog
|
||||
padding: 0
|
||||
margins: 0
|
||||
|
||||
anchors.centerIn: Overlay.overlay
|
||||
|
||||
EmojiPicker {
|
||||
id: emojiPicker
|
||||
|
||||
onChosen: {
|
||||
userStatusSelectorModel.userStatusEmoji = emoji
|
||||
emojiDialog.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: userStatusMessageTextField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("What is your status?")
|
||||
text: userStatusSelectorModel.userStatusMessage
|
||||
selectByMouse: true
|
||||
onEditingFinished: userStatusSelectorModel.setUserStatusMessage(text)
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: userStatusSelectorModel.predefinedStatusesCount
|
||||
|
||||
Button {
|
||||
id: control
|
||||
Layout.fillWidth: true
|
||||
flat: !hovered
|
||||
hoverEnabled: true
|
||||
text: userStatusSelectorModel.predefinedStatus(index).icon + " <b>" + userStatusSelectorModel.predefinedStatus(index).message + "</b> - " + userStatusSelectorModel.predefinedStatusClearAt(index)
|
||||
onClicked: userStatusSelectorModel.setPredefinedStatus(index)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
Layout.bottomMargin: 8
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Text {
|
||||
text: qsTr("Clear status message after")
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
Layout.fillWidth: true
|
||||
model: userStatusSelectorModel.clearAtValues
|
||||
displayText: userStatusSelectorModel.clearAt
|
||||
onActivated: userStatusSelectorModel.setClearAt(index)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.margins: 8
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Clear status message")
|
||||
onClicked: userStatusSelectorModel.clearUserStatus()
|
||||
}
|
||||
Button {
|
||||
highlighted: true
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Set status message")
|
||||
onClicked: userStatusSelectorModel.setUserStatus()
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBox {
|
||||
Layout.margins: 8
|
||||
Layout.fillWidth: true
|
||||
|
||||
visible: userStatusSelectorModel.errorMessage != ""
|
||||
text: "<b>Error:</b> " + userStatusSelectorModel.errorMessage
|
||||
}
|
||||
}
|
||||
27
src/gui/UserStatusSelectorDialog.qml
Normal file
27
src/gui/UserStatusSelectorDialog.qml
Normal file
@@ -0,0 +1,27 @@
|
||||
import QtQuick.Window 2.15
|
||||
|
||||
import com.nextcloud.desktopclient 1.0 as NC
|
||||
|
||||
Window {
|
||||
id: dialog
|
||||
|
||||
property NC.UserStatusSelectorModel model: NC.UserStatusSelectorModel {
|
||||
onFinished: dialog.close()
|
||||
}
|
||||
|
||||
minimumWidth: view.implicitWidth
|
||||
minimumHeight: view.implicitHeight
|
||||
maximumWidth: view.implicitWidth
|
||||
maximumHeight: view.implicitHeight
|
||||
width: maximumWidth
|
||||
height: maximumHeight
|
||||
|
||||
visible: true
|
||||
|
||||
flags: Qt.Dialog
|
||||
|
||||
UserStatusSelector {
|
||||
id: view
|
||||
userStatusSelectorModel: model
|
||||
}
|
||||
}
|
||||
@@ -380,6 +380,8 @@ void AccountManager::deleteAccount(AccountState *account)
|
||||
// Forget E2E keys
|
||||
account->account()->e2e()->forgetSensitiveData(account->account());
|
||||
|
||||
account->account()->deleteAppToken();
|
||||
|
||||
emit accountSyncConnectionRemoved(account);
|
||||
emit accountRemoved(account);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class AccountManager : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
static AccountManager *instance();
|
||||
~AccountManager() = default;
|
||||
~AccountManager() override = default;
|
||||
|
||||
/**
|
||||
* Saves the accounts to a given settings file
|
||||
|
||||
@@ -86,11 +86,11 @@ void showEnableE2eeWithVirtualFilesWarningDialog(std::function<void(void)> onAcc
|
||||
const auto messageBox = new QMessageBox;
|
||||
messageBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
messageBox->setText(AccountSettings::tr("End-to-End Encryption with Virtual Files"));
|
||||
messageBox->setInformativeText(AccountSettings::tr("You seem to have the Virtual Files feature enabled on this folder. At "
|
||||
" the moment, it is not possible to implicitly download virtual files that are "
|
||||
"End-to-End encrypted. To get the best experience with Virtual Files and"
|
||||
" End-to-End Encryption, make sure the encrypted folder is marked with"
|
||||
" \"Make always available locally\"."));
|
||||
messageBox->setInformativeText(AccountSettings::tr("You seem to have the Virtual Files feature enabled on this folder. "
|
||||
"At the moment, it is not possible to implicitly download virtual files that are "
|
||||
"End-to-End encrypted. To get the best experience with Virtual Files and "
|
||||
"End-to-End Encryption, make sure the encrypted folder is marked with "
|
||||
"\"Make always available locally\"."));
|
||||
messageBox->setIcon(QMessageBox::Warning);
|
||||
const auto dontEncryptButton = messageBox->addButton(QMessageBox::StandardButton::Cancel);
|
||||
Q_ASSERT(dontEncryptButton);
|
||||
@@ -587,12 +587,14 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
|
||||
ac = availabilityMenu->addAction(Utility::vfsPinActionText());
|
||||
connect(ac, &QAction::triggered, this, [this]() { slotSetCurrentFolderAvailability(PinState::AlwaysLocal); });
|
||||
ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder());
|
||||
|
||||
ac = availabilityMenu->addAction(Utility::vfsFreeSpaceActionText());
|
||||
connect(ac, &QAction::triggered, this, [this]() { slotSetCurrentFolderAvailability(PinState::OnlineOnly); });
|
||||
|
||||
ac = menu->addAction(tr("Disable virtual file support …"));
|
||||
connect(ac, &QAction::triggered, this, &AccountSettings::slotDisableVfsCurrentFolder);
|
||||
ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder());
|
||||
}
|
||||
|
||||
if (Theme::instance()->showVirtualFilesOption()
|
||||
@@ -760,6 +762,7 @@ void AccountSettings::slotRemoveCurrentFolder()
|
||||
messageBox->addButton(tr("Cancel"), QMessageBox::NoRole);
|
||||
connect(messageBox, &QMessageBox::finished, this, [messageBox, yesButton, folder, row, this]{
|
||||
if (messageBox->clickedButton() == yesButton) {
|
||||
Utility::removeFavLink(folder->path());
|
||||
FolderMan::instance()->removeFolder(folder);
|
||||
_model->removeRow(row);
|
||||
|
||||
@@ -826,7 +829,9 @@ void AccountSettings::slotEnableVfsCurrentFolder()
|
||||
folder->setRootPinState(PinState::Unspecified);
|
||||
for (const auto &entry : oldBlacklist) {
|
||||
folder->journalDb()->schedulePathForRemoteDiscovery(entry);
|
||||
folder->vfs().setPinState(entry, PinState::OnlineOnly);
|
||||
if (!folder->vfs().setPinState(entry, PinState::OnlineOnly)) {
|
||||
qCWarning(lcAccountSettings) << "Could not set pin state of" << entry << "to online only";
|
||||
}
|
||||
}
|
||||
folder->slotNextSyncFullLocalDiscovery();
|
||||
|
||||
@@ -932,7 +937,9 @@ void AccountSettings::slotSetSubFolderAvailability(Folder *folder, const QString
|
||||
Q_ASSERT(!path.endsWith('/'));
|
||||
|
||||
// Update the pin state on all items
|
||||
folder->vfs().setPinState(path, state);
|
||||
if (!folder->vfs().setPinState(path, state)) {
|
||||
qCWarning(lcAccountSettings) << "Could not set pin state of" << path << "to" << state;
|
||||
}
|
||||
|
||||
// Trigger sync
|
||||
folder->schedulePathForLocalDiscovery(path);
|
||||
|
||||
@@ -55,7 +55,7 @@ class AccountSettings : public QWidget
|
||||
|
||||
public:
|
||||
explicit AccountSettings(AccountState *accountState, QWidget *parent = nullptr);
|
||||
~AccountSettings();
|
||||
~AccountSettings() override;
|
||||
QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
|
||||
bool canEncryptOrDecrypt(const FolderStatusModel::SubFolderInfo* folderInfo);
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ AccountState::AccountState(AccountPtr account)
|
||||
, _waitingForNewCredentials(false)
|
||||
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
|
||||
, _remoteWipe(new RemoteWipe(_account))
|
||||
, _userStatus(new UserStatus(this))
|
||||
, _isDesktopNotificationsAllowed(true)
|
||||
{
|
||||
qRegisterMetaType<AccountState *>("AccountState*");
|
||||
@@ -127,26 +126,6 @@ void AccountState::setState(State state)
|
||||
emit stateChanged(_state);
|
||||
}
|
||||
|
||||
UserStatus::Status AccountState::status() const
|
||||
{
|
||||
return _userStatus->status();
|
||||
}
|
||||
|
||||
QString AccountState::statusMessage() const
|
||||
{
|
||||
return _userStatus->message();
|
||||
}
|
||||
|
||||
QUrl AccountState::statusIcon() const
|
||||
{
|
||||
return _userStatus->icon();
|
||||
}
|
||||
|
||||
QString AccountState::statusEmoji() const
|
||||
{
|
||||
return _userStatus->emoji();
|
||||
}
|
||||
|
||||
QString AccountState::stateString(State state)
|
||||
{
|
||||
switch (state) {
|
||||
@@ -462,12 +441,6 @@ void AccountState::fetchNavigationApps(){
|
||||
job->getNavigationApps();
|
||||
}
|
||||
|
||||
void AccountState::fetchUserStatus()
|
||||
{
|
||||
connect(_userStatus, &UserStatus::fetchUserStatusFinished, this, &AccountState::statusChanged);
|
||||
_userStatus->fetchUserStatus(_account);
|
||||
}
|
||||
|
||||
void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
|
||||
if(statusCode == 200){
|
||||
qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <QPointer>
|
||||
#include "connectionvalidator.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "userstatus.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QSettings;
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
|
||||
/// Use the account as parent
|
||||
explicit AccountState(AccountPtr account);
|
||||
~AccountState();
|
||||
~AccountState() override;
|
||||
|
||||
/** Creates an account state from settings and an Account object.
|
||||
*
|
||||
@@ -162,23 +162,6 @@ public:
|
||||
///Asks for user credentials
|
||||
void handleInvalidCredentials();
|
||||
|
||||
/** Returns the user status (Online, Dnd, Away, Offline, Invisible)
|
||||
* https://gist.github.com/georgehrke/55a0412007f13be1551d1f9436a39675
|
||||
*/
|
||||
UserStatus::Status status() const;
|
||||
|
||||
/** Returns the user status Message (text)
|
||||
*/
|
||||
QString statusMessage() const;
|
||||
|
||||
/** Returns the user status icon url
|
||||
*/
|
||||
QUrl statusIcon() const;
|
||||
|
||||
/** Returns the user status emoji
|
||||
*/
|
||||
QString statusEmoji() const;
|
||||
|
||||
/** Returns the notifications status retrieved by the notificatons endpoint
|
||||
* https://github.com/nextcloud/desktop/issues/2318#issuecomment-680698429
|
||||
*/
|
||||
@@ -188,10 +171,6 @@ public:
|
||||
*/
|
||||
void setDesktopNotificationsAllowed(bool isAllowed);
|
||||
|
||||
/** Fetch the user status (status, icon, message)
|
||||
*/
|
||||
void fetchUserStatus();
|
||||
|
||||
public slots:
|
||||
/// Triggers a ping to the server to update state and
|
||||
/// connection status and errors.
|
||||
@@ -256,7 +235,6 @@ private:
|
||||
*/
|
||||
AccountAppList _apps;
|
||||
|
||||
UserStatus *_userStatus;
|
||||
bool _isDesktopNotificationsAllowed;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class AddCertificateDialog : public QDialog
|
||||
|
||||
public:
|
||||
explicit AddCertificateDialog(QWidget *parent = nullptr);
|
||||
~AddCertificateDialog();
|
||||
~AddCertificateDialog() override;
|
||||
QString getCertificatePath();
|
||||
QString getCertificatePasswd();
|
||||
void showErrorMessage(const QString message);
|
||||
|
||||
@@ -27,13 +27,14 @@
|
||||
#include "folderman.h"
|
||||
#include "logger.h"
|
||||
#include "configfile.h"
|
||||
#include "socketapi.h"
|
||||
#include "socketapi/socketapi.h"
|
||||
#include "sslerrordialog.h"
|
||||
#include "theme.h"
|
||||
#include "clientproxy.h"
|
||||
#include "sharedialog.h"
|
||||
#include "accountmanager.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "pushnotifications.h"
|
||||
|
||||
#if defined(BUILD_UPDATER)
|
||||
#include "updater/ocupdater.h"
|
||||
@@ -178,7 +179,7 @@ Application::Application(int &argc, char **argv)
|
||||
, _showLogWindow(false)
|
||||
, _logExpire(0)
|
||||
, _logFlush(false)
|
||||
, _logDebug(false)
|
||||
, _logDebug(true)
|
||||
, _userTriggeredConnect(false)
|
||||
, _debugMode(false)
|
||||
, _backgroundMode(false)
|
||||
@@ -349,6 +350,9 @@ Application::Application(int &argc, char **argv)
|
||||
connect(FolderMan::instance()->socketApi(), &SocketApi::shareCommandReceived,
|
||||
_gui.data(), &ownCloudGui::slotShowShareDialog);
|
||||
|
||||
connect(FolderMan::instance()->socketApi(), &SocketApi::fileActivityCommandReceived,
|
||||
Systray::instance(), &Systray::showFileActivityDialog);
|
||||
|
||||
// startup procedure.
|
||||
connect(&_checkConnectionTimer, &QTimer::timeout, this, &Application::slotCheckConnection);
|
||||
_checkConnectionTimer.setInterval(ConnectionValidator::DefaultCallingIntervalMsec); // check for connection every 32 seconds.
|
||||
@@ -456,9 +460,10 @@ void Application::slotCheckConnection()
|
||||
|
||||
// Don't check if we're manually signed out or
|
||||
// when the error is permanent.
|
||||
if (state != AccountState::SignedOut
|
||||
&& state != AccountState::ConfigurationError
|
||||
&& state != AccountState::AskingCredentials) {
|
||||
const auto pushNotifications = accountState->account()->pushNotifications();
|
||||
const auto pushNotificationsAvailable = (pushNotifications && pushNotifications->isReady());
|
||||
if (state != AccountState::SignedOut && state != AccountState::ConfigurationError
|
||||
&& state != AccountState::AskingCredentials && !pushNotificationsAvailable) {
|
||||
accountState->checkConnectivity();
|
||||
}
|
||||
}
|
||||
@@ -478,7 +483,6 @@ void Application::slotCrash()
|
||||
|
||||
void Application::slotownCloudWizardDone(int res)
|
||||
{
|
||||
AccountManager *accountMan = AccountManager::instance();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
|
||||
// During the wizard, scheduling of new syncs is disabled
|
||||
@@ -491,7 +495,7 @@ void Application::slotownCloudWizardDone(int res)
|
||||
|
||||
// If one account is configured: enable autostart
|
||||
#ifndef QT_DEBUG
|
||||
bool shouldSetAutoStart = (accountMan->accounts().size() == 1);
|
||||
bool shouldSetAutoStart = AccountManager::instance()->accounts().size() == 1;
|
||||
#else
|
||||
bool shouldSetAutoStart = false;
|
||||
#endif
|
||||
@@ -525,7 +529,12 @@ void Application::setupLogging()
|
||||
|
||||
logger->enterNextLogFile();
|
||||
|
||||
qCInfo(lcApplication) << QString::fromLatin1("################## %1 locale:[%2] ui_lang:[%3] version:[%4] os:[%5]").arg(_theme->appName()).arg(QLocale::system().name()).arg(property("ui_lang").toString()).arg(_theme->version()).arg(Utility::platformName());
|
||||
qCInfo(lcApplication) << "##################" << _theme->appName()
|
||||
<< "locale:" << QLocale::system().name()
|
||||
<< "ui_lang:" << property("ui_lang")
|
||||
<< "version:" << _theme->version()
|
||||
<< "os:" << Utility::platformName();
|
||||
qCInfo(lcApplication) << "Arguments:" << qApp->arguments();
|
||||
}
|
||||
|
||||
void Application::slotUseMonoIconsChanged(bool)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user