Compare commits
522 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
856d2597df | ||
![]() |
44a0d75996 | ||
![]() |
62f6b7f3c5 | ||
![]() |
6150d327da | ||
![]() |
522ccfecc4 | ||
![]() |
4788ae4ccf | ||
![]() |
c3191e8f88 | ||
![]() |
4952c88b2e | ||
![]() |
ebd4489adf | ||
![]() |
d9aee037ad | ||
![]() |
87e87619fb | ||
![]() |
8494a714cd | ||
![]() |
3ec78f4c36 | ||
![]() |
a27485c021 | ||
![]() |
713b98f29e | ||
![]() |
82b0ec751d | ||
![]() |
a7348c0aa0 | ||
![]() |
85d2ee950d | ||
![]() |
b0b51570b0 | ||
![]() |
a5a9b32ea3 | ||
![]() |
ac20b7f80c | ||
![]() |
b462337824 | ||
![]() |
bbb88ded57 | ||
![]() |
0f0995d4fe | ||
![]() |
0881dd581a | ||
![]() |
c4512bb69a | ||
![]() |
5e4a6fa72a | ||
![]() |
5da9268aa7 | ||
![]() |
f1af78573a | ||
![]() |
a7600fa7f7 | ||
![]() |
78de724757 | ||
![]() |
05078a7857 | ||
![]() |
84d396f6c4 | ||
![]() |
b2fb5b1664 | ||
![]() |
3477469b66 | ||
![]() |
bed95b1757 | ||
![]() |
f83761d95f | ||
![]() |
84cb60d882 | ||
![]() |
313764b533 | ||
![]() |
44b5251045 | ||
![]() |
743e63edbf | ||
![]() |
74e20dcb3e | ||
![]() |
9a971860e0 | ||
![]() |
b1a1bf05d2 | ||
![]() |
06c712cb64 | ||
![]() |
84891fb2f2 | ||
![]() |
889026bece | ||
![]() |
2ebb210c57 | ||
![]() |
bfb0e5bd29 | ||
![]() |
61528de505 | ||
![]() |
f62a82364c | ||
![]() |
f461c706d1 | ||
![]() |
898c82ec8f | ||
![]() |
f5b69b73cf | ||
![]() |
5a01b4bb35 | ||
![]() |
918aa15e74 | ||
![]() |
522b37425f | ||
![]() |
a04968913c | ||
![]() |
3b755287e7 | ||
![]() |
25b556ae14 | ||
![]() |
daa2fe1785 | ||
![]() |
30712745bc | ||
![]() |
15d14359d7 | ||
![]() |
75f7250ed1 | ||
![]() |
853e9c08e0 | ||
![]() |
2f6afb2f97 | ||
![]() |
cbd3956cdc | ||
![]() |
4ab2033a81 | ||
![]() |
e8fe0726ff | ||
![]() |
f773bc0348 | ||
![]() |
d208d4f9a7 | ||
![]() |
a5f6d5a142 | ||
![]() |
cfce10b0ca | ||
![]() |
2ccfb5ca9f | ||
![]() |
c7f471cb8f | ||
![]() |
c255cd54ed | ||
![]() |
075380749c | ||
![]() |
f1a03554f0 | ||
![]() |
9353c9ef40 | ||
![]() |
d664c5a1c6 | ||
![]() |
d499b0d7be | ||
![]() |
f764fec458 | ||
![]() |
0cb502520f | ||
![]() |
b4e38409a9 | ||
![]() |
03ffb12ff1 | ||
![]() |
31d4ad151e | ||
![]() |
5229be4687 | ||
![]() |
e76c6829f7 | ||
![]() |
e7a7895c6e | ||
![]() |
7f2cfe4f52 | ||
![]() |
7f27745303 | ||
![]() |
4002cbca1b | ||
![]() |
f2c7abcc6f | ||
![]() |
e47b813b69 | ||
![]() |
0f635fba7d | ||
![]() |
9a10b210ec | ||
![]() |
038de48d54 | ||
![]() |
89cd40d0cf | ||
![]() |
3d77c29393 | ||
![]() |
aea0da5570 | ||
![]() |
7a88d1ef99 | ||
![]() |
ee2dc9ccc5 | ||
![]() |
73bb88e61f | ||
![]() |
2846e590d5 | ||
![]() |
cdf7091ae1 | ||
![]() |
bed49cf038 | ||
![]() |
4120ea2601 | ||
![]() |
0e9b6894c7 | ||
![]() |
ff6031209f | ||
![]() |
7e5ea84f37 | ||
![]() |
e87be24e5d | ||
![]() |
8141d58652 | ||
![]() |
d6631280e5 | ||
![]() |
0da7200898 | ||
![]() |
ed87ea3df1 | ||
![]() |
749c4006a2 | ||
![]() |
66ed2cdda1 | ||
![]() |
3739cfd0ef | ||
![]() |
815ef927cb | ||
![]() |
1d94617837 | ||
![]() |
a25b75f828 | ||
![]() |
e92ea5061a | ||
![]() |
d9f009953f | ||
![]() |
08fe335a80 | ||
![]() |
73ebcaeb90 | ||
![]() |
6de3663269 | ||
![]() |
12302d375d | ||
![]() |
490634b85a | ||
![]() |
cc0689d946 | ||
![]() |
fe4b6ca72e | ||
![]() |
791a5da245 | ||
![]() |
2a91577521 | ||
![]() |
08c597513c | ||
![]() |
3c64b86297 | ||
![]() |
a37d03fd02 | ||
![]() |
12eda471fc | ||
![]() |
5877366b77 | ||
![]() |
9b78d38726 | ||
![]() |
b78bd5abef | ||
![]() |
5865519402 | ||
![]() |
4f1959501d | ||
![]() |
12e18934df | ||
![]() |
05e8648d25 | ||
![]() |
e9c8225255 | ||
![]() |
14475330da | ||
![]() |
53e2b3bfa8 | ||
![]() |
8197012bcb | ||
![]() |
719c7339cf | ||
![]() |
21893fdff8 | ||
![]() |
9a3c69870c | ||
![]() |
30f73cb004 | ||
![]() |
3025e8e01c | ||
![]() |
e5f7a23157 | ||
![]() |
8c0c056c47 | ||
![]() |
17af3b8dc0 | ||
![]() |
82ec6beeb5 | ||
![]() |
1318427bb7 | ||
![]() |
29b2093ef0 | ||
![]() |
c08296bc3b | ||
![]() |
cd53eedc7f | ||
![]() |
e0b07b8aba | ||
![]() |
8678468998 | ||
![]() |
d33b539659 | ||
![]() |
09776f07cd | ||
![]() |
f762204512 | ||
![]() |
06b9269b84 | ||
![]() |
243a03e142 | ||
![]() |
dfa4e59737 | ||
![]() |
cf0146050e | ||
![]() |
18080d174c | ||
![]() |
34f3bb7a08 | ||
![]() |
09789590a2 | ||
![]() |
0cadea231a | ||
![]() |
bbab5cc223 | ||
![]() |
fe3280e02e | ||
![]() |
a31a7a32a5 | ||
![]() |
b13771e34f | ||
![]() |
cc8ee46efe | ||
![]() |
1ca899d8ab | ||
![]() |
8a1bd930eb | ||
![]() |
ecce8d13c1 | ||
![]() |
5a8eb1e7aa | ||
![]() |
cadbab25bb | ||
![]() |
dba9fb30e8 | ||
![]() |
2908148c00 | ||
![]() |
8be34ade30 | ||
![]() |
52d389a5e7 | ||
![]() |
f9767bf7f7 | ||
![]() |
d25c142bfa | ||
![]() |
bdd935d9c2 | ||
![]() |
eab367cf6f | ||
![]() |
486950c1aa | ||
![]() |
0e4442f513 | ||
![]() |
401b1934e2 | ||
![]() |
6ea5995c12 | ||
![]() |
b3a385693c | ||
![]() |
737f9e51d8 | ||
![]() |
ef7b28b6b3 | ||
![]() |
993d522e15 | ||
![]() |
969db5c3db | ||
![]() |
8b0210eb5d | ||
![]() |
5da6a81d4b | ||
![]() |
36d4248a32 | ||
![]() |
b1dc1eefe6 | ||
![]() |
2630999acf | ||
![]() |
a4a5dea3d7 | ||
![]() |
09dba18994 | ||
![]() |
a5671e20e5 | ||
![]() |
5ba1ba5b97 | ||
![]() |
eff1a81125 | ||
![]() |
727fade948 | ||
![]() |
126091c080 | ||
![]() |
7a017e30ea | ||
![]() |
293d04e2c3 | ||
![]() |
70c984353c | ||
![]() |
87ed9250ef | ||
![]() |
ba9a0ba459 | ||
![]() |
f50a834ae7 | ||
![]() |
301dace730 | ||
![]() |
b369612070 | ||
![]() |
911392deab | ||
![]() |
fa238b3e22 | ||
![]() |
956842f102 | ||
![]() |
04a93de5a5 | ||
![]() |
04451257d2 | ||
![]() |
2d4d4609da | ||
![]() |
ff7cf0f24e | ||
![]() |
54576543e9 | ||
![]() |
14c54ab275 | ||
![]() |
ecf1f8dbbe | ||
![]() |
6884e1ff6a | ||
![]() |
258adf10da | ||
![]() |
3a4334ffd2 | ||
![]() |
4d41421fb8 | ||
![]() |
e2fda18dbd | ||
![]() |
6b1f00880e | ||
![]() |
86df5c39a2 | ||
![]() |
47a49b7bb2 | ||
![]() |
0b58669e39 | ||
![]() |
9fca1cad12 | ||
![]() |
077cd6562e | ||
![]() |
d7bfb956ec | ||
![]() |
dc0a9b1a7d | ||
![]() |
0b624eeefd | ||
![]() |
8de8b0dda8 | ||
![]() |
964dfbb085 | ||
![]() |
c362facdd7 | ||
![]() |
2b5076584d | ||
![]() |
79993814a8 | ||
![]() |
1802b00525 | ||
![]() |
5848b5e737 | ||
![]() |
313d362ed3 | ||
![]() |
9e9a6bd584 | ||
![]() |
810438b5e5 | ||
![]() |
5bc48be5d0 | ||
![]() |
0a2bdc7033 | ||
![]() |
3b03fd2189 | ||
![]() |
b8dd91e353 | ||
![]() |
6689e8c84c | ||
![]() |
bb1598dde2 | ||
![]() |
2740983308 | ||
![]() |
2436adc257 | ||
![]() |
e4355eeb48 | ||
![]() |
606dcef16f | ||
![]() |
dc0c0ca849 | ||
![]() |
8973f40020 | ||
![]() |
d8635e957c | ||
![]() |
e4edee269b | ||
![]() |
8391014b38 | ||
![]() |
54a71ae977 | ||
![]() |
5c2a14e6a7 | ||
![]() |
2bb475a0fd | ||
![]() |
0d8bb7eebd | ||
![]() |
ed8cd503b5 | ||
![]() |
8326d3c702 | ||
![]() |
c9be7a7a7f | ||
![]() |
fa7dd8c541 | ||
![]() |
0f1be2883a | ||
![]() |
bcec79fe17 | ||
![]() |
e017c0f475 | ||
![]() |
6109737b9d | ||
![]() |
7cc31a5d6e | ||
![]() |
f4aabc1f2d | ||
![]() |
280144f4eb | ||
![]() |
a9005bef23 | ||
![]() |
0530422a9b | ||
![]() |
aaee9d00e4 | ||
![]() |
721e821ca5 | ||
![]() |
e9799990f0 | ||
![]() |
a0594dcc2b | ||
![]() |
0cf0da06f8 | ||
![]() |
c03884c429 | ||
![]() |
f1d931c276 | ||
![]() |
30a9d0ecc7 | ||
![]() |
0784fd43f3 | ||
![]() |
4defcc7aea | ||
![]() |
500eba29fa | ||
![]() |
9cf015a676 | ||
![]() |
5ba425ae95 | ||
![]() |
516aaa95ca | ||
![]() |
a453d69296 | ||
![]() |
ceeeea6ef9 | ||
![]() |
87932751b4 | ||
![]() |
7fc7481cfb | ||
![]() |
f92e1a9791 | ||
![]() |
cf988e6fa6 | ||
![]() |
ef69ee435f | ||
![]() |
edfdd68c36 | ||
![]() |
91527aed58 | ||
![]() |
3d7cd68707 | ||
![]() |
2e9c727248 | ||
![]() |
361bbc50b8 | ||
![]() |
c13d1803ce | ||
![]() |
6b10a5f63d | ||
![]() |
21edc0f20d | ||
![]() |
35920bffe9 | ||
![]() |
bdf922443d | ||
![]() |
19b5163d0b | ||
![]() |
4e7cac6aef | ||
![]() |
58e8ea5ee8 | ||
![]() |
d1d8fabb60 | ||
![]() |
ebd65b26be | ||
![]() |
30e3b5721e | ||
![]() |
36dd070d05 | ||
![]() |
af85dc5aed | ||
![]() |
88a3ee183f | ||
![]() |
c50f76c40a | ||
![]() |
4348112b04 | ||
![]() |
ff79533fa0 | ||
![]() |
b04b23d04b | ||
![]() |
7001976252 | ||
![]() |
ed4e3c3d74 | ||
![]() |
7c768c446b | ||
![]() |
f80fe2629a | ||
![]() |
1f3b00ee44 | ||
![]() |
79abddd802 | ||
![]() |
1d4e2b14b6 | ||
![]() |
9ada45ea4b | ||
![]() |
b9ac16d165 | ||
![]() |
14a3270184 | ||
![]() |
1843ca5bfd | ||
![]() |
6cd666552d | ||
![]() |
58a7745b0e | ||
![]() |
f56fe42c6c | ||
![]() |
cd0abc5323 | ||
![]() |
d3c1163632 | ||
![]() |
6dbc688773 | ||
![]() |
8955afae66 | ||
![]() |
c8f2ba00ed | ||
![]() |
1d908b8147 | ||
![]() |
fb15ed871b | ||
![]() |
59e8163f27 | ||
![]() |
a40c2174a9 | ||
![]() |
5c78eac179 | ||
![]() |
0e41597798 | ||
![]() |
fe827e74f0 | ||
![]() |
372f092919 | ||
![]() |
c442892b59 | ||
![]() |
9c9983411f | ||
![]() |
a2d180ea12 | ||
![]() |
c506b3e1e7 | ||
![]() |
2bad915583 | ||
![]() |
df33ee6770 | ||
![]() |
24131ffa77 | ||
![]() |
9895207dd4 | ||
![]() |
aa00164dff | ||
![]() |
319da24989 | ||
![]() |
1b8eb77eab | ||
![]() |
877001587b | ||
![]() |
c7c6d41eff | ||
![]() |
f51a6510aa | ||
![]() |
551b7d45f4 | ||
![]() |
6b53c13492 | ||
![]() |
517d977266 | ||
![]() |
d8371a9b45 | ||
![]() |
41bb9c0676 | ||
![]() |
04a57f4f8d | ||
![]() |
7595b03639 | ||
![]() |
508610d304 | ||
![]() |
9d76d1f06b | ||
![]() |
9e20f1b0a6 | ||
![]() |
a43bd84570 | ||
![]() |
b4818e617f | ||
![]() |
00b8995fc8 | ||
![]() |
bb1e23a2dd | ||
![]() |
e9e24d5e0f | ||
![]() |
a3a1a307fd | ||
![]() |
f2bfcd25d1 | ||
![]() |
75dc7c6f28 | ||
![]() |
6503b433e1 | ||
![]() |
9dd83a6f2f | ||
![]() |
db341b5574 | ||
![]() |
774930c950 | ||
![]() |
7692f9f82a | ||
![]() |
aaa8fe85e8 | ||
![]() |
3b046ab0ee | ||
![]() |
220fba09a9 | ||
![]() |
8a1558f4da | ||
![]() |
d376d1125e | ||
![]() |
bc11a8d0af | ||
![]() |
759c562eb8 | ||
![]() |
88df448177 | ||
![]() |
2600d12fc2 | ||
![]() |
40a3df305b | ||
![]() |
4636771081 | ||
![]() |
1f7acf2bc5 | ||
![]() |
69170a88fc | ||
![]() |
a0481f2e5b | ||
![]() |
99207f570e | ||
![]() |
334a3ae0a5 | ||
![]() |
d40248bb06 | ||
![]() |
0735764a34 | ||
![]() |
09bb1566b1 | ||
![]() |
03806337e7 | ||
![]() |
6dce8e65a7 | ||
![]() |
06ee73dcd5 | ||
![]() |
c2e10f5783 | ||
![]() |
d51e486a84 | ||
![]() |
3cc882829a | ||
![]() |
cb14461f58 | ||
![]() |
44a11ce5bb | ||
![]() |
6aa0e98993 | ||
![]() |
dd935b5f90 | ||
![]() |
e454ea6e61 | ||
![]() |
2369f6c4c8 | ||
![]() |
66554819a6 | ||
![]() |
5d9103b933 | ||
![]() |
4496c441fe | ||
![]() |
f3b3fb4acd | ||
![]() |
e55434965b | ||
![]() |
bb3f03fb17 | ||
![]() |
1a63c7cf6d | ||
![]() |
868636deb9 | ||
![]() |
f68c3c2722 | ||
![]() |
db3139e97d | ||
![]() |
c95e850bb1 | ||
![]() |
847e3d621d | ||
![]() |
3d7406ff24 | ||
![]() |
0b5a77dc3d | ||
![]() |
24182ab12c | ||
![]() |
f2a734f20c | ||
![]() |
aced51baff | ||
![]() |
52de2eee6c | ||
![]() |
6858544197 | ||
![]() |
86a730853a | ||
![]() |
ba205d3648 | ||
![]() |
13af4b2ed1 | ||
![]() |
d4e0763705 | ||
![]() |
78d58b1cff | ||
![]() |
766e91dae4 | ||
![]() |
5d15232260 | ||
![]() |
fb9962d013 | ||
![]() |
9a5e8693f4 | ||
![]() |
f8dd55aead | ||
![]() |
315d543399 | ||
![]() |
82cfa67e31 | ||
![]() |
52702a32e9 | ||
![]() |
05d89745c1 | ||
![]() |
44e33b540e | ||
![]() |
de753706d1 | ||
![]() |
6084ce23ed | ||
![]() |
36e335bd72 | ||
![]() |
d3e1e560c4 | ||
![]() |
1fb6e777a3 | ||
![]() |
fafd78af94 | ||
![]() |
8a549ea323 | ||
![]() |
8f62f9902d | ||
![]() |
fa1d63b5a2 | ||
![]() |
2217f82d32 | ||
![]() |
3b34d9f832 | ||
![]() |
66ece0b9a6 | ||
![]() |
becda2e494 | ||
![]() |
67fd713820 | ||
![]() |
49e7ca0fa0 | ||
![]() |
42d7ae0f9a | ||
![]() |
90513a1f30 | ||
![]() |
c59e6f3307 | ||
![]() |
9835e8bbb2 | ||
![]() |
8c8640f4db | ||
![]() |
fd5ff336b4 | ||
![]() |
7e4bd6b6aa | ||
![]() |
3495a059a1 | ||
![]() |
7d3732c58f | ||
![]() |
5df695c1ea | ||
![]() |
615826323a | ||
![]() |
8e75c40c86 | ||
![]() |
a7450bc32d | ||
![]() |
cb41c64aeb | ||
![]() |
35080bd175 | ||
![]() |
da2d41309a | ||
![]() |
6167a91090 | ||
![]() |
cd0f2b1869 | ||
![]() |
1d3b8f70b2 | ||
![]() |
f0b54bc52a | ||
![]() |
8a0dc85296 | ||
![]() |
be229bed63 | ||
![]() |
1f154c08c5 | ||
![]() |
b46afb551c | ||
![]() |
61541c47e1 | ||
![]() |
f06e2b168c | ||
![]() |
28d62d2400 | ||
![]() |
babcaac97f | ||
![]() |
2b6493c4e5 | ||
![]() |
a2841c399b | ||
![]() |
6ff3d37790 | ||
![]() |
ae141da578 | ||
![]() |
add2e47f91 | ||
![]() |
073431cb20 | ||
![]() |
8660668a94 | ||
![]() |
b97b908e0b | ||
![]() |
eeb1d59e36 | ||
![]() |
dba0f27aae | ||
![]() |
fbdc5a5406 | ||
![]() |
55c1174ae1 | ||
![]() |
a85c39aa26 | ||
![]() |
c828ef00c4 | ||
![]() |
fccf6863d7 | ||
![]() |
f61e2b9596 | ||
![]() |
1ab16db175 | ||
![]() |
782ee5995d | ||
![]() |
4c3b0c96c7 | ||
![]() |
9037257e7c |
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. Windows 10]
|
||||||
|
- Version [e.g. 3.0.0]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
169
.github/workflows/ci-linux.yml
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
name: CI-Linux
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
VNOTE_VER: 3.19.2
|
||||||
|
CMAKE_VER: 3.24.3
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
name: Build On Ubuntu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 120
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE.
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Init Submodules
|
||||||
|
run: |
|
||||||
|
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||||
|
git submodule sync --recursive
|
||||||
|
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||||
|
|
||||||
|
- name: Install a Fresh CMake
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh
|
||||||
|
chmod +x cmake-${CMAKE_VER}-Linux-x86_64.sh
|
||||||
|
mkdir ${{runner.workspace}}/cmake
|
||||||
|
sudo ./cmake-${CMAKE_VER}-Linux-x86_64.sh --skip-license --prefix=${{runner.workspace}}/cmake
|
||||||
|
sudo rm -f /usr/local/bin/cmake /usr/local/bin/cpack
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake/bin/cmake /usr/local/bin/cmake
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake/bin/cpack /usr/local/bin/cpack
|
||||||
|
|
||||||
|
- name: Install linuxdeploy
|
||||||
|
uses: miurahr/install-linuxdeploy-action@v1
|
||||||
|
with:
|
||||||
|
plugins: qt appimage
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libfcitx5-qt-dev fcitx-libs-dev extra-cmake-modules libxkbcommon-dev
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tree
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y fuse libxcb-cursor-dev
|
||||||
|
python3 -m pip config set global.break-system-packages true
|
||||||
|
|
||||||
|
- name: Cache Qt
|
||||||
|
id: cache-qt
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{runner.workspace}}/Qt
|
||||||
|
key: ${{ runner.os }}-QtCache-6.8
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
version: 6.8.3
|
||||||
|
target: desktop
|
||||||
|
modules: 'qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat qtserialport'
|
||||||
|
tools: 'tools_opensslv3_src'
|
||||||
|
cache: 'true'
|
||||||
|
|
||||||
|
- name: Compile OpenSSLV3
|
||||||
|
run: |
|
||||||
|
cd ${Qt6_DIR}/../../Tools/OpenSSLv3/src
|
||||||
|
./Configure
|
||||||
|
make -j2
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
- name: Create Build Dir
|
||||||
|
run: mkdir build
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Compile fcitxqt5
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/fcitx/fcitx-qt5
|
||||||
|
cd fcitx-qt5
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake -DENABLE_QT5=OFF -DENABLE_QT6=ON ..
|
||||||
|
make -j2
|
||||||
|
sudo make install
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Compile qt6ct
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/trialuser02/qt6ct qt6ct.git
|
||||||
|
cd qt6ct.git
|
||||||
|
qmake
|
||||||
|
make -j$(nproc) && sudo make install
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Configure Project
|
||||||
|
run: |
|
||||||
|
qmake -v
|
||||||
|
cmake --version
|
||||||
|
cmake ${GITHUB_WORKSPACE}
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Build Project
|
||||||
|
run: |
|
||||||
|
# Remove the libqsqlmimer.so as libmimerapi.so is not deployed with Qt6
|
||||||
|
rm ${{runner.workspace}}/Qt/6.*/gcc_64/plugins/sqldrivers/libqsqlmimer.so
|
||||||
|
cmake --build . --target pack
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Fix Package
|
||||||
|
run: |
|
||||||
|
mkdir fixpackage
|
||||||
|
mv VNote*.AppImage ./fixpackage
|
||||||
|
pushd fixpackage
|
||||||
|
# Extract the AppImage
|
||||||
|
./VNote*.AppImage --appimage-extract
|
||||||
|
# Remove libnss3.so and libnssutil3.so
|
||||||
|
rm ./squashfs-root/usr/lib/libnss*.so
|
||||||
|
# Re-package
|
||||||
|
rm VNote*.AppImage
|
||||||
|
linuxdeploy-plugin-appimage-x86_64.AppImage --appdir=./squashfs-root
|
||||||
|
mv VNote*.AppImage ../
|
||||||
|
popd
|
||||||
|
mv VNote*.AppImage VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Archive Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
|
||||||
|
- name: Update Tag
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
git tag --force continuous-build ${GITHUB_SHA}
|
||||||
|
git push --force --tags
|
||||||
|
|
||||||
|
- name: Update Continuous Build Release
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
release: Continuous Build
|
||||||
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
235
.github/workflows/ci-macos.yml
vendored
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
name: CI-MacOS
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
VNOTE_VER: 3.19.2
|
||||||
|
CMAKE_VER: 3.24.3
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
environment: Mac-code-sign
|
||||||
|
name: Build On MacOS
|
||||||
|
timeout-minutes: 120
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- name: "Build on Arm64"
|
||||||
|
os: macos-latest
|
||||||
|
arch: universal
|
||||||
|
qt: 6.8.3
|
||||||
|
|
||||||
|
runs-on: ${{matrix.config.os}}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE.
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Init Submodules
|
||||||
|
run: |
|
||||||
|
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||||
|
git submodule sync --recursive
|
||||||
|
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
brew install tree libiodbc libpq
|
||||||
|
|
||||||
|
- name: Fix SQL
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /usr/local/opt/libiodbc/lib
|
||||||
|
sudo ln -s /opt/homebrew/opt/libiodbc/lib/libiodbc.2.dylib /usr/local/opt/libiodbc/lib/libiodbc.2.dylib
|
||||||
|
sudo mkdir -p /Applications/Postgres.app/Contents/Versions/14/lib
|
||||||
|
sudo ln -s /opt/homebrew/Cellar/libpq/16.3/lib/libpq.5.dylib /Applications/Postgres.app/Contents/Versions/14/lib/libpq.5.dylib
|
||||||
|
|
||||||
|
- name: Install a fresh CMake
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-macos-universal.tar.gz
|
||||||
|
tar xzf cmake-${CMAKE_VER}-macos-universal.tar.gz
|
||||||
|
sudo rm -f /usr/local/bin/cmake /usr/local/bin/cpack
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cmake /usr/local/bin/cmake
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cpack /usr/local/bin/cpack
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Install macdeployqtfix
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/tamlok/macdeployqtfix.git macdeployqtfix --depth=1
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Install optool
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/alexzielenski/optool/releases/download/0.1/optool.zip
|
||||||
|
unzip ./optool.zip
|
||||||
|
sudo ln -s ./optool /usr/local/bin/optool
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Cache Qt
|
||||||
|
id: cache-qt
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{runner.workspace}}/Qt
|
||||||
|
key: ${{ runner.os }}-QtCache-6.8
|
||||||
|
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
version: ${{matrix.config.qt}}
|
||||||
|
target: desktop
|
||||||
|
modules: 'qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat qtserialport'
|
||||||
|
cache: 'true'
|
||||||
|
|
||||||
|
- name: Create Build Dir
|
||||||
|
run: mkdir build
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Configure Project
|
||||||
|
run: |
|
||||||
|
qmake -v
|
||||||
|
cmake --version
|
||||||
|
cmake -DMACDEPLOYQTFIX_EXECUTABLE=${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" ${GITHUB_WORKSPACE}
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Build Project
|
||||||
|
run: |
|
||||||
|
# Keep only required SQL drivers
|
||||||
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlmimer.dylib
|
||||||
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlodbc.dylib
|
||||||
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlpsql.dylib
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
cmake --build . --target pack
|
||||||
|
|
||||||
|
# Fix Qt frameworks
|
||||||
|
python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..
|
||||||
|
|
||||||
|
# Only delete rpaths that exist to avoid errors
|
||||||
|
for rpath in $(otool -l ./src/VNote.app/Contents/MacOS/VNote | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
|
||||||
|
echo "Checking rpath: $rpath"
|
||||||
|
if otool -l ./src/VNote.app/Contents/MacOS/VNote | grep -q "$rpath"; then
|
||||||
|
echo "Deleting rpath: $rpath"
|
||||||
|
install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/MacOS/VNote
|
||||||
|
else
|
||||||
|
echo "Rpath not found: $rpath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for rpath in $(otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
|
||||||
|
echo "Checking rpath: $rpath"
|
||||||
|
if otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | grep -q "$rpath"; then
|
||||||
|
echo "Deleting rpath: $rpath"
|
||||||
|
install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib
|
||||||
|
else
|
||||||
|
echo "Rpath not found: $rpath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run macdeployqtfix again to ensure all dependencies are properly fixed
|
||||||
|
python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Codesign Bundle
|
||||||
|
# Extract the secrets we defined earlier as environment variables
|
||||||
|
env:
|
||||||
|
MACOS_CERTIFICATE: ${{ secrets.CLI_MACOS_CERTIFICATE }}
|
||||||
|
MACOS_CERTIFICATE_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE_PWD }}
|
||||||
|
MACOS_CERTIFICATE_NAME: ${{ secrets.CLI_MACOS_CERTIFICATE_NAME }}
|
||||||
|
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE }}
|
||||||
|
run: |
|
||||||
|
# Turn our base64-encoded certificate back to a regular .p12 file
|
||||||
|
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
||||||
|
|
||||||
|
# We need to create a new keychain, otherwise using the certificate will prompt
|
||||||
|
# with a UI dialog asking for the certificate password, which we can't
|
||||||
|
# use in a headless CI environment
|
||||||
|
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
security default-keychain -s build.keychain
|
||||||
|
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
||||||
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
|
||||||
|
echo "Codesigning main app bundle"
|
||||||
|
codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./src/VNote.app
|
||||||
|
codesign -v -vvv ./src/VNote.app
|
||||||
|
|
||||||
|
hdiutil create -volname "VNote" -srcfolder ./src/VNote.app -ov -format UDZO VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
codesign -v -vvv ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: "Notarize Bundle"
|
||||||
|
# Extract the secrets we defined earlier as environment variables
|
||||||
|
env:
|
||||||
|
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.CLI_MACOS_NOTARY_USER }}
|
||||||
|
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.CLI_MACOS_TEAM_ID }}
|
||||||
|
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.CLI_MACOS_NOTARY_PWD }}
|
||||||
|
run: |
|
||||||
|
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||||
|
# from blocking the CI
|
||||||
|
echo "Create keychain profile"
|
||||||
|
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||||
|
|
||||||
|
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||||
|
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||||
|
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
|
||||||
|
# you're curious
|
||||||
|
echo "Notarize app"
|
||||||
|
xcrun notarytool submit "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg" --keychain-profile "notarytool-profile" --wait
|
||||||
|
|
||||||
|
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
|
||||||
|
# validated by macOS even when an internet connection is not available.
|
||||||
|
echo "Attach staple"
|
||||||
|
xcrun stapler staple "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg"
|
||||||
|
|
||||||
|
# Enable tmate debugging of manually-triggered workflows if the input option was provided
|
||||||
|
- name: Setup tmate session
|
||||||
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
|
||||||
|
|
||||||
|
- name: Archive DMG
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}
|
||||||
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
|
||||||
|
- name: Update Tag
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
git tag --force continuous-build ${GITHUB_SHA}
|
||||||
|
git push --force --tags
|
||||||
|
|
||||||
|
- name: Update Continuous Build Release
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
release: Continuous Build
|
||||||
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
157
.github/workflows/ci-win.yml
vendored
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
name: CI-Windows
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
VNOTE_VER: 3.19.2
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: ${{ matrix.config.name }}
|
||||||
|
runs-on: windows-${{ matrix.config.vs_version }}
|
||||||
|
timeout-minutes: 120
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- name: "Build on Win64 Qt 5.15"
|
||||||
|
arch: win64_msvc2019_64
|
||||||
|
vs_version: 2019
|
||||||
|
vs_cmd: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||||
|
qt: 5.15.2
|
||||||
|
qt_modules: qtwebengine
|
||||||
|
qt_tools: tools_opensslv3_x64
|
||||||
|
qt_major: 5
|
||||||
|
suffix: "-windows7"
|
||||||
|
- name: "Build on Win64 Qt 6"
|
||||||
|
arch: win64_msvc2022_64
|
||||||
|
vs_version: 2022
|
||||||
|
vs_cmd: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||||
|
qt: 6.8.3
|
||||||
|
qt_modules: "qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat"
|
||||||
|
qt_tools: tools_opensslv3_x64
|
||||||
|
qt_major: 6
|
||||||
|
suffix: ""
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE.
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Init Submodules
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||||
|
git submodule sync --recursive
|
||||||
|
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||||
|
|
||||||
|
- name: Cache Qt
|
||||||
|
id: cache-qt
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{runner.workspace}}/Qt
|
||||||
|
key: ${{runner.os}}-${{matrix.config.arch}}-QtCache-${{matrix.config.qt}}
|
||||||
|
|
||||||
|
- name: Install Qt Official Build
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
version: ${{matrix.config.qt}}
|
||||||
|
target: desktop
|
||||||
|
arch: ${{matrix.config.arch}}
|
||||||
|
modules: ${{matrix.config.qt_modules}}
|
||||||
|
tools: ${{matrix.config.qt_tools}}
|
||||||
|
cache: 'true'
|
||||||
|
|
||||||
|
- name: Create Build Dir
|
||||||
|
shell: bash
|
||||||
|
run: mkdir build
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Clone OpenSSL on 5.15
|
||||||
|
shell: bash
|
||||||
|
if: ${{startsWith(matrix.config.qt, '5.15')}}
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/tamlok/openssl-utils.git openssl-utils.git --depth=1
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
# Enable tmate debugging of manually-triggered workflows if the input option was provided
|
||||||
|
- name: Setup tmate session
|
||||||
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
|
||||||
|
|
||||||
|
- name: Configure and Build Project
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
cmake --version
|
||||||
|
call "${{matrix.config.vs_cmd}}"
|
||||||
|
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DQT_DEFAULT_MAJOR_VERSION=${{matrix.config.qt_major}} -DOPENSSL_EXTRA_LIB_DIR=${{runner.workspace}}\build\openssl-utils.git\1.1.1j\Win_x64 %GITHUB_WORKSPACE%
|
||||||
|
cmake --build .
|
||||||
|
cmake --build . --target=pack
|
||||||
|
7z x VNote*.zip -o*
|
||||||
|
dir
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Rename on 5.15
|
||||||
|
shell: bash
|
||||||
|
if: ${{startsWith(matrix.config.qt, '5.15')}}
|
||||||
|
run: |
|
||||||
|
mv VNote-${{env.VNOTE_VER}}-win64 VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
|
mv VNote-${{env.VNOTE_VER}}-win64.zip VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.zip
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Archive Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
|
|
||||||
|
- name: Archive Installer
|
||||||
|
if: ${{!startsWith(matrix.config.qt, '5.15')}}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.msi
|
||||||
|
path: ${{runner.workspace}}/build/VNote*.msi
|
||||||
|
|
||||||
|
- name: Update Tag
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git tag --force continuous-build ${GITHUB_SHA}
|
||||||
|
git push --force --tags
|
||||||
|
|
||||||
|
- name: Update Continuous Build Release
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# glob not supported
|
||||||
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.zip
|
||||||
|
release: Continuous Build
|
||||||
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# glob not supported
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
17
.gitignore
vendored
@ -1,2 +1,17 @@
|
|||||||
VNote.pro.user*
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
.ccls
|
||||||
|
compile_commands.json
|
||||||
|
compile_commands.json.*
|
||||||
|
compile_flags.txt
|
||||||
|
.cache
|
||||||
|
.tasks
|
||||||
|
.vimspector.json
|
||||||
|
GPATH
|
||||||
|
GRTAGS
|
||||||
|
GTAGS
|
||||||
|
aqtinstall.log
|
||||||
|
tags
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
|
build
|
||||||
|
.DS_Store
|
||||||
|
12
.gitmodules
vendored
@ -1,6 +1,6 @@
|
|||||||
[submodule "src/utils/marked"]
|
[submodule "libs/vtextedit"]
|
||||||
path = src/utils/marked
|
path = libs/vtextedit
|
||||||
url = https://github.com/chjj/marked.git
|
url = https://github.com/vnotex/vtextedit.git
|
||||||
[submodule "hoedown"]
|
[submodule "libs/QHotkey"]
|
||||||
path = hoedown
|
path = libs/QHotkey
|
||||||
url = https://github.com/tamlok/hoedown.git
|
url = https://github.com/vnotex/QHotkey.git
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"package": {
|
|
||||||
"name": "vnote",
|
|
||||||
"repo": "vnote",
|
|
||||||
"subject": "tamlok",
|
|
||||||
"desc": "Continuous deployment by Travis-CI",
|
|
||||||
"website_url": "https://github.com/tamlok/vnote",
|
|
||||||
"issue_tracker_url": "https://github.com/tamlok/vnote/issues",
|
|
||||||
"vcs_url": "https://github.com/tamlok/vnote.git",
|
|
||||||
"github_use_tag_release_notes": false,
|
|
||||||
"github_release_notes_file": "",
|
|
||||||
"licenses": ["MIT"],
|
|
||||||
"labels": ["Markdown", "Note-Taking", "Office", "Utils", "Efficiency"],
|
|
||||||
"public_download_numbers": true,
|
|
||||||
"public_stats": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"version": {
|
|
||||||
"name": "2.7.1",
|
|
||||||
"desc": "VNote Releases",
|
|
||||||
"released": "2019-06-25",
|
|
||||||
"vcs_tag": "2.7.1",
|
|
||||||
"gpgSign": false
|
|
||||||
},
|
|
||||||
|
|
||||||
"files":
|
|
||||||
[{"includePattern": "build/(VNote-.*\\.AppImage)", "uploadPattern": "$1",
|
|
||||||
"matrixParams": {"override": 1 }}],
|
|
||||||
|
|
||||||
"publish": true
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"package": {
|
|
||||||
"name": "vnote",
|
|
||||||
"repo": "vnote",
|
|
||||||
"subject": "tamlok",
|
|
||||||
"desc": "Continuous deployment by Travis-CI",
|
|
||||||
"website_url": "https://github.com/tamlok/vnote",
|
|
||||||
"issue_tracker_url": "https://github.com/tamlok/vnote/issues",
|
|
||||||
"vcs_url": "https://github.com/tamlok/vnote.git",
|
|
||||||
"github_use_tag_release_notes": false,
|
|
||||||
"github_release_notes_file": "",
|
|
||||||
"licenses": ["MIT"],
|
|
||||||
"labels": ["Markdown", "Note-Taking", "Office", "Utils", "Efficiency"],
|
|
||||||
"public_download_numbers": true,
|
|
||||||
"public_stats": true
|
|
||||||
},
|
|
||||||
|
|
||||||
"version": {
|
|
||||||
"name": "2.7.1",
|
|
||||||
"desc": "VNote Releases",
|
|
||||||
"released": "2019-06-25",
|
|
||||||
"vcs_tag": "2.7.1",
|
|
||||||
"gpgSign": false
|
|
||||||
},
|
|
||||||
|
|
||||||
"files":
|
|
||||||
[{"includePattern": "build/distrib/(VNote-.*\\.dmg)", "uploadPattern": "$1",
|
|
||||||
"matrixParams": {"override": 1 }}],
|
|
||||||
|
|
||||||
"publish": true
|
|
||||||
}
|
|
61
.travis.yml
@ -1,61 +0,0 @@
|
|||||||
dist: trusty
|
|
||||||
sudo: required
|
|
||||||
git:
|
|
||||||
depth: 1
|
|
||||||
language: cpp
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: osx
|
|
||||||
compiler: clang
|
|
||||||
osx_image: xcode9.4
|
|
||||||
- os: linux
|
|
||||||
compiler: g++
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo apt-get -qq update ; fi
|
|
||||||
- export version="2.7.1"
|
|
||||||
|
|
||||||
install:
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install p7zip-full ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install chrpath ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install openssl libssl-dev ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install libgl1-mesa-dev ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install tree ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo apt-get install -qq gcc-6; sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 100 ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then sudo apt-get install -qq g++-6; sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-6 100 ; fi
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then chmod +x .travis_linux.sh ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then chmod +x .travis_macos.sh ; fi
|
|
||||||
|
|
||||||
script:
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then CXX="g++-6" CC="gcc-6" ./.travis_linux.sh ; fi
|
|
||||||
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then ./.travis_macos.sh ; fi
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
- provider: bintray
|
|
||||||
skip_cleanup: true
|
|
||||||
file: "./.linux_bintray.json"
|
|
||||||
user: tamlok
|
|
||||||
key:
|
|
||||||
secure: vADlrYSusARnHxK3NTT3r1r6I/lrxyEuFKLOO73KXl6rvDywrrDDi6YsFekL14/o3clZKLOC8LbvA+4BKPVSoGTO4Dpx/i51fXphf+mMFB3QXSGnbqHm4+2ZnhCl62vfVlFeOPBLDO0KUBI8DCP0I+QogOUickXv3zYx69z6AudSxgjY7nPoN5jGSPgyId4r3o8Shrj1Fk1WtN6qciKyPne57v+jmvRlJTkoEfYkvwTRNMBlmaKy8Vj/CSoIvB8TH8bv3rhHLrN4o1QCwePdaX9G7xlImSpXqgRgzQVU3SRFN2bYTj5DZc1aFyA7iNOhmwgCLAN6OrqXyyJCbyywNhylfgad2rQANcfXiZw9ywooKEYafLDRuiK2G6Pk8m+R6Ded9JBoX9MSz/ZDxxfk4NmLO991wS7IK5aFTQfHZz5W8Tmh1rCphFwlDI/Rxs7ExbXu7INA8IhoLpOSmLIA5lfdC4fD8rv8mjy5gfpMkWlP8XATfi2eMH9uGj89aJa6xp7Bc2mfW3M71YHtYP/pyE/7Bk5vVonP8Cq9rK6OruMIUYtNmXoJnpte20ecSXj9yw7oTR27dhSx3XuAKOXiNpIau0CPxtXA5cSm5X0OS1Lt8RWrms0jp9Ch2dgxlNMpr0soF9DmwekhfHnVoOLyFBWBMDwvkx5TWij9FNAAJb4=
|
|
||||||
dry-run: false
|
|
||||||
on:
|
|
||||||
condition: $TRAVIS_OS_NAME = linux
|
|
||||||
branch: master
|
|
||||||
- provider: bintray
|
|
||||||
skip_cleanup: true
|
|
||||||
file: "./.macos_bintray.json"
|
|
||||||
user: tamlok
|
|
||||||
key:
|
|
||||||
secure: vADlrYSusARnHxK3NTT3r1r6I/lrxyEuFKLOO73KXl6rvDywrrDDi6YsFekL14/o3clZKLOC8LbvA+4BKPVSoGTO4Dpx/i51fXphf+mMFB3QXSGnbqHm4+2ZnhCl62vfVlFeOPBLDO0KUBI8DCP0I+QogOUickXv3zYx69z6AudSxgjY7nPoN5jGSPgyId4r3o8Shrj1Fk1WtN6qciKyPne57v+jmvRlJTkoEfYkvwTRNMBlmaKy8Vj/CSoIvB8TH8bv3rhHLrN4o1QCwePdaX9G7xlImSpXqgRgzQVU3SRFN2bYTj5DZc1aFyA7iNOhmwgCLAN6OrqXyyJCbyywNhylfgad2rQANcfXiZw9ywooKEYafLDRuiK2G6Pk8m+R6Ded9JBoX9MSz/ZDxxfk4NmLO991wS7IK5aFTQfHZz5W8Tmh1rCphFwlDI/Rxs7ExbXu7INA8IhoLpOSmLIA5lfdC4fD8rv8mjy5gfpMkWlP8XATfi2eMH9uGj89aJa6xp7Bc2mfW3M71YHtYP/pyE/7Bk5vVonP8Cq9rK6OruMIUYtNmXoJnpte20ecSXj9yw7oTR27dhSx3XuAKOXiNpIau0CPxtXA5cSm5X0OS1Lt8RWrms0jp9Ch2dgxlNMpr0soF9DmwekhfHnVoOLyFBWBMDwvkx5TWij9FNAAJb4=
|
|
||||||
dry-run: false
|
|
||||||
on:
|
|
||||||
condition: $TRAVIS_OS_NAME = osx
|
|
||||||
branch: master
|
|
102
.travis_linux.sh
@ -1,102 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
project_dir=$(pwd)
|
|
||||||
|
|
||||||
# Complain when not in Travis environment
|
|
||||||
if [ -z ${TRAVIS_COMMIT+x} ]; then
|
|
||||||
echo "This script is intended to be used only in Travis CI environment."
|
|
||||||
echo "To build VNote from source, please see the [documentation](https://tamlok.github.io/vnote/en_us/#!docs/Developers/Build%20VNote.md)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install qt5.9
|
|
||||||
sudo add-apt-repository ppa:george-edison55/cmake-3.x -y
|
|
||||||
sudo add-apt-repository ppa:beineri/opt-qt597-trusty -y
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get -y install qt59base qt59webengine qt59webchannel qt59svg qt59location qt59tools qt59translations
|
|
||||||
source /opt/qt*/bin/qt*-env.sh
|
|
||||||
|
|
||||||
# Compile qt5ct
|
|
||||||
wget -c https://excellmedia.dl.sourceforge.net/project/qt5ct/qt5ct-0.37.tar.bz2
|
|
||||||
tar xf qt5ct-0.*.tar.bz2
|
|
||||||
cd qt5ct-0.*/
|
|
||||||
QT_SELECT=5 qmake
|
|
||||||
make -j$(nproc) && sudo make install
|
|
||||||
|
|
||||||
# Compile newer version fcitx-qt5
|
|
||||||
sudo apt-get -y install fcitx-libs-dev libgl1-mesa-dev bison
|
|
||||||
sudo apt-get -y install cmake
|
|
||||||
|
|
||||||
wget http://xkbcommon.org/download/libxkbcommon-0.5.0.tar.xz
|
|
||||||
tar xf libxkbcommon-0.5.0.tar.xz
|
|
||||||
cd libxkbcommon-0.5.0
|
|
||||||
./configure -prefix=/usr -libdir=/usr/lib/x86_64-linux-gnu -disable-x11
|
|
||||||
make -j$(nproc) && sudo make install
|
|
||||||
|
|
||||||
git clone git://anongit.kde.org/extra-cmake-modules
|
|
||||||
cd extra-cmake-modules
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake ..
|
|
||||||
make -j$(nproc) && sudo make install
|
|
||||||
|
|
||||||
git clone https://github.com/fcitx/fcitx-qt5
|
|
||||||
cd fcitx-qt5
|
|
||||||
git checkout 1.0.5
|
|
||||||
cmake .
|
|
||||||
make -j$(nproc) && sudo make install
|
|
||||||
|
|
||||||
# Copy fcitx-qt5 files to qt
|
|
||||||
sudo cp /usr/local/lib/libFcitxQt5DBusAddons.so* /opt/qt*/lib/
|
|
||||||
sudo cp /usr/local/lib/libFcitxQt5WidgetsAddons.so* /opt/qt*/lib/
|
|
||||||
|
|
||||||
tree /opt/qt59/lib/
|
|
||||||
|
|
||||||
cd ${project_dir}
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
qmake -v
|
|
||||||
qmake CONFIG+=release -spec linux-g++-64 ../VNote.pro
|
|
||||||
make -j$(nproc)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Pack AppImage using linuxdeployqt
|
|
||||||
#
|
|
||||||
mkdir dist
|
|
||||||
INSTALL_ROOT=${project_dir}/build/dist make install ; tree dist/
|
|
||||||
|
|
||||||
# Copy SVG module
|
|
||||||
mkdir -p ./dist/usr/plugins/iconengines
|
|
||||||
mkdir -p ./dist/usr/plugins/imageformats
|
|
||||||
mkdir -p ./dist/usr/plugins/platforminputcontexts
|
|
||||||
cp /opt/qt59/plugins/iconengines/* ./dist/usr/plugins/iconengines/
|
|
||||||
cp /opt/qt59/plugins/imageformats/* ./dist/usr/plugins/imageformats/
|
|
||||||
cp /opt/qt59/plugins/platforminputcontexts/* ./dist/usr/plugins/platforminputcontexts/
|
|
||||||
|
|
||||||
# Copy other project files
|
|
||||||
cp "${project_dir}/README.md" "dist/README.md"
|
|
||||||
cp "${project_dir}/LICENSE" "dist/LICENSE"
|
|
||||||
echo ${version} > ./dist/version
|
|
||||||
echo "${TRAVIS_COMMIT}" >> ./dist/version
|
|
||||||
|
|
||||||
# Get linuxdeployqt tool
|
|
||||||
git clone https://github.com/tamlok/vnote-utils.git vnote-utils.git
|
|
||||||
cp vnote-utils.git/linuxdeployqt-continuous-x86_64.AppImage ./linuxdeployqt-continuous-x86_64.AppImage
|
|
||||||
# wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
|
||||||
chmod a+x linuxdeployqt*.AppImage
|
|
||||||
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
|
||||||
./linuxdeployqt*.AppImage ./dist/usr/share/applications/*.desktop -bundle-non-qt-libs -exclude-libs=libnss3,libnssutil3 -extra-plugins=platformthemes/libqt5ct.so,styles/libqt5ct-style.so
|
|
||||||
|
|
||||||
# Copy translations
|
|
||||||
cp /opt/qt59/translations/*_zh_CN.qm ./dist/usr/translations/
|
|
||||||
|
|
||||||
# Package it for the second time.
|
|
||||||
./linuxdeployqt*.AppImage ./dist/usr/share/applications/*.desktop -appimage -exclude-libs=libnss3,libnssutil3 -extra-plugins=platformthemes/libqt5ct.so,styles/libqt5ct-style.so
|
|
||||||
|
|
||||||
tree dist/
|
|
||||||
|
|
||||||
ls -l *.AppImage
|
|
||||||
|
|
||||||
mv VNote-*.AppImage VNote-${version}-x86_64.AppImage
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
exit 0
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
project_dir=$(pwd)
|
|
||||||
|
|
||||||
# Complain when not in Travis environment
|
|
||||||
if [ -z ${TRAVIS_COMMIT+x} ]; then
|
|
||||||
echo "This script is intended to be used only in Travis CI environment."
|
|
||||||
echo "To build VNote from source, please see the [documentation](https://tamlok.github.io/vnote/en_us/#!docs/Developers/Build%20VNote.md)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
brew update > /dev/null
|
|
||||||
|
|
||||||
brew install gnu-getopt
|
|
||||||
export PATH="/usr/local/opt/gnu-getopt/bin:$PATH"
|
|
||||||
|
|
||||||
# Download Qt from Qt Installer
|
|
||||||
cd ${project_dir}
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
export VERBOSE=1
|
|
||||||
export QT_CI_PACKAGES="qt.qt5.5120.clang_64,qt.qt5.5120.qtwebengine"
|
|
||||||
|
|
||||||
git clone https://github.com/tamlok/qtci.git
|
|
||||||
source qtci/path.env
|
|
||||||
|
|
||||||
install-qt 5.12.0
|
|
||||||
source qt-5.12.0.env
|
|
||||||
|
|
||||||
echo $PATH
|
|
||||||
|
|
||||||
QTDIR="${project_dir}/build/Qt/5.12.0/clang_64"
|
|
||||||
LDFLAGS=-L$QTDIR/lib
|
|
||||||
CPPFLAGS=-I$QTDIR/include
|
|
||||||
|
|
||||||
# Build your app
|
|
||||||
cd ${project_dir}/build
|
|
||||||
qmake -v
|
|
||||||
qmake CONFIG-=debug CONFIG+=release ../VNote.pro
|
|
||||||
make -j2
|
|
||||||
|
|
||||||
git clone https://github.com/aurelien-rainone/macdeployqtfix.git
|
|
||||||
|
|
||||||
# Package DMG from build/src/VNote.app directory
|
|
||||||
cd src/
|
|
||||||
|
|
||||||
sed -i -e 's/com.yourcompany.VNote/com.tamlok.VNote/g' VNote.app/Contents/Info.plist
|
|
||||||
$QTDIR/bin/macdeployqt VNote.app
|
|
||||||
python ../macdeployqtfix/macdeployqtfix.py VNote.app/Contents/MacOS/VNote $QTDIR
|
|
||||||
|
|
||||||
# Fix Helpers/QtWebEngineProcess.app
|
|
||||||
cd VNote.app/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers
|
|
||||||
$QTDIR/bin/macdeployqt QtWebEngineProcess.app
|
|
||||||
python ${project_dir}/build/macdeployqtfix/macdeployqtfix.py QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess $QTDIR
|
|
||||||
|
|
||||||
cd ${project_dir}/build
|
|
||||||
mkdir -p distrib/VNote
|
|
||||||
cd distrib/VNote
|
|
||||||
mv ../../src/VNote.app ./
|
|
||||||
cp "${project_dir}/LICENSE" "LICENSE"
|
|
||||||
cp "${project_dir}/README.md" "README.md"
|
|
||||||
echo "${version}" > version
|
|
||||||
echo "${TRAVIS_COMMIT}" >> version
|
|
||||||
|
|
||||||
ln -s /Applications ./Applications
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
hdiutil create -srcfolder ./VNote -format UDBZ ./VNote.dmg
|
|
||||||
mv VNote.dmg VNote-${version}-x64.dmg
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
exit 0
|
|
@ -1,90 +1,26 @@
|
|||||||
cmake_minimum_required (VERSION 3.12)
|
cmake_minimum_required (VERSION 3.20)
|
||||||
|
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.1" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
project(VNote
|
project(VNote
|
||||||
VERSION 2.2.0
|
VERSION 3.19.2
|
||||||
DESCRIPTION "VNote is a markdown note taking application"
|
DESCRIPTION "A pleasant note-taking platform"
|
||||||
HOMEPAGE_URL "https://tamlok.github.io/vnote"
|
HOMEPAGE_URL "https://app.vnote.fun"
|
||||||
LANGUAGES C CXX)
|
LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type, defaults to Release")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
## Qt5 configurations
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
## Default Qt5 path
|
set(QHOTKEY_INSTALL OFF CACHE BOOL "Disable installing QHotKey" FORCE)
|
||||||
if(WIN32)
|
add_subdirectory(libs)
|
||||||
set(Qt5_DIR "c:/Qt/Qt5.9.7/5.9.7/msvc2017_64/lib/cmake/Qt5/" CACHE PATH "directory where Qt5Config.cmake exists.")
|
|
||||||
elseif(APPLE)
|
|
||||||
set(Qt5_DIR "/usr/local/Cellar/qt/5.9.7/clang_64/lib/cmake/Qt5/" CACHE PATH "directory where Qt5Config.cmake exists.")
|
|
||||||
else()
|
|
||||||
set(Qt5_DIR "" CACHE PATH "directory where Qt5Config.cmake exists.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Core Gui Network PrintSupport WebChannel WebEngine
|
|
||||||
WebEngineWidgets Positioning Svg Widgets LinguistTools
|
|
||||||
REQUIRED NO_DEFAULT_PATH)
|
|
||||||
## hoedown library
|
|
||||||
add_library(hoedown STATIC
|
|
||||||
hoedown/src/autolink.c hoedown/src/document.c hoedown/src/html.c hoedown/src/html_smartypants.c
|
|
||||||
hoedown/src/version.c hoedown/src/buffer.c hoedown/src/escape.c hoedown/src/html_blocks.c
|
|
||||||
hoedown/src/stack.c )
|
|
||||||
target_link_libraries(hoedown PRIVATE Qt5::Core Qt5::Gui)
|
|
||||||
## peg-highlight library
|
|
||||||
add_library(peg-highlight STATIC peg-highlight/pmh_parser.c peg-highlight/pmh_styleparser.c)
|
|
||||||
target_link_libraries(peg-highlight PRIVATE Qt5::Core Qt5::Gui)
|
|
||||||
|
|
||||||
## project sources
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
option(CMake_RUN_CLANG_TIDY "Run clang-tidy with the compiler." OFF)
|
# TODO: find a better way to organize tests
|
||||||
if(CMake_RUN_CLANG_TIDY)
|
# add_subdirectory(tests)
|
||||||
if(CMake_SOURCE_DIR STREQUAL CMake_BINARY_DIR)
|
|
||||||
message(FATAL_ERROR "CMake_RUN_CLANG_TIDY requires an out-of-source build!")
|
|
||||||
endif()
|
|
||||||
find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)
|
|
||||||
if(NOT CLANG_TIDY_COMMAND)
|
|
||||||
message(WARNING "CMake_RUN_CLANG_TIDY is ON but clang-tidy is not found!")
|
|
||||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE)
|
|
||||||
else()
|
|
||||||
set(CLANG_TIDY_CHECKS "-*,modernize-*")
|
|
||||||
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};-checks=${CLANG_TIDY_CHECKS};-header-filter='${CMAKE_SOURCE_DIR}/src/*'")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Create a preprocessor definition that depends on .clang-tidy content so
|
|
||||||
# the compile command will change when .clang-tidy changes. This ensures
|
|
||||||
# that a subsequent build re-runs clang-tidy on all sources even if they
|
|
||||||
# do not otherwise need to be recompiled. Nothing actually uses this
|
|
||||||
# definition. We add it to targets on which we run clang-tidy just to
|
|
||||||
# get the build dependency on the .clang-tidy file.
|
|
||||||
file(SHA1 ${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1)
|
|
||||||
set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}")
|
|
||||||
unset(clang_tidy_sha1)
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(CMake_RUN_IWYU "Run include-what-you-use with the compiler." OFF)
|
|
||||||
if(CMake_RUN_IWYU)
|
|
||||||
find_program(IWYU_COMMAND NAMES include-what-you-use iwyu)
|
|
||||||
if(NOT IWYU_COMMAND)
|
|
||||||
message(WARNING "CMake_RUN_IWYU is ON but include-what-you-use is not found!")
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
|
|
||||||
"${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w")
|
|
||||||
list(APPEND CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${CMake_IWYU_OPTIONS})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Clazy is a Qt oriented code checker based on clang framework. Krazy's little brother.
|
|
||||||
set(CMake_RUN_CLAZY OFF CACHE BOOL "Add clazy check for builds")
|
|
||||||
if(ENABLE_CLAZY)
|
|
||||||
find_program(CLAZY_EXECUTABLE NAMES clazy PATHS /usr/local/llvm/bin /usr/local/bin /opt/clazy/bin)
|
|
||||||
if(CLAZY_EXECUTABLE)
|
|
||||||
message(STATUS "clazy found: ${CLAZY_EXECUTABLE}")
|
|
||||||
else()
|
|
||||||
message(AUTHOR_WARNING "clazy not found.")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
# vim: ts=2 sw=2 sts=2 et
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "x64-Debug",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"configurationType": "RelWithDebInfo",
|
|
||||||
"inheritEnvironments": [
|
|
||||||
"msvc_x64_x64"
|
|
||||||
],
|
|
||||||
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
|
|
||||||
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
|
||||||
"cmakeCommandArgs": "-DQt5_DIR=c:\\Qt\\Qt5.9.7\\5.9.7\\msvc2017_64\\lib\\cmake\\Qt5\\",
|
|
||||||
"buildCommandArgs": "-v",
|
|
||||||
"ctestCommandArgs": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
165
COPYING.LESSER
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
@ -1,9 +0,0 @@
|
|||||||
OS Version (操作系统): Windows, Linux, macOS
|
|
||||||
|
|
||||||
VNote Version (Help - About VNote - Version: )(VNote版本): 2.2, d78e892d5cc etc..
|
|
||||||
|
|
||||||
Symptoms (表现):
|
|
||||||
|
|
||||||
|
|
||||||
How to Repro (如何复现):
|
|
||||||
|
|
21
LICENSE
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2016 Le Tan
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
229
README.md
@ -1,223 +1,42 @@
|
|||||||
# VNote
|
# VNote
|
||||||
[中文 Chinese](./README_zh.md) | [日本語 Japanese](./README_ja.md)
|
  
|
||||||
|
|
||||||
**VNote is a note-taking application that knows programmers and Markdown better.**
|
[简体中文](README_zh_CN.md)
|
||||||
|
|
||||||
For more information, please visit [**VNote's Homepage**](https://tamlok.github.io/vnote).
|
[Project on Gitee](https://gitee.com/vnotex/vnote)
|
||||||
|
|
||||||

|
A pleasant note-taking platform.
|
||||||
|
|
||||||
# Downloads
|
For more information, please visit [**VNote's Home Page**](https://vnotex.github.io/vnote).
|
||||||
Users from China can download the latest release of VNote from [Baidu Netdisk](http://pan.baidu.com/s/1jI5HROq).
|
|
||||||
|
|
||||||
## Windows
|

|
||||||
### Official Zip
|
|
||||||

|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
## Description
|
||||||
- Latest builds on master: [  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
**VNote** is a Qt-based, free and open source note-taking application, focusing on Markdown now. VNote is designed to provide a pleasant note-taking platform with excellent editing experience.
|
||||||
|
|
||||||
**NOT** supported in XP since QtWebEngineProcess used by VNote could not work in XP.
|
VNote is **NOT** just a simple editor for Markdown. By providing notes management, VNote makes taking notes in Markdown simpler. In the future, VNote will support more formats besides Markdown.
|
||||||
|
|
||||||
### Scoop
|
|
||||||
VNote can be installed from `extras` bucket of Scoop.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
scoop bucket add extras
|
|
||||||
scoop install vnote
|
|
||||||
scoop update vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux
|
|
||||||
### AppImage
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
There is an AppImage format standalone executable of VNote for major Linux distributions. **Any help for packaging and distribution on Linux is appreciated!**
|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
|
||||||
- Latest builds on master: [  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
### openSUSE
|
|
||||||
Currently `vnote` on openSUSE Tumbleweed can be installed from `home:opensuse_zh` project on OBS. You can execute the following command directly:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo zypper ar https://download.opensuse.org/repositories/home:/opensuse_zh/openSUSE_Tumbleweed/ home:opensuse_zh
|
|
||||||
sudo zypper ref
|
|
||||||
sudo zypper in vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
For other architectures, please search for `vnote` at [software.opensuse.org](https://software.opensuse.org).
|
|
||||||
|
|
||||||
We don't support Leap 42 and below due to the Qt version. Please use AppImage or build it yourself.
|
|
||||||
|
|
||||||
### Arch Linux
|
|
||||||
VNote on Arch Linux can be installed from the AUR as [vnote](https://aur.archlinux.org/packages/vnote-bin/):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone https://aur.archlinux.org/vnote-bin.git
|
|
||||||
cd vnote-bin
|
|
||||||
makepkg -sic
|
|
||||||
```
|
|
||||||
|
|
||||||
There is also a development version that tracks the latest master [vnote-git](https://aur.archlinux.org/packages/vnote-git/).
|
|
||||||
|
|
||||||
### NixOS
|
|
||||||
Thank @kuznero for packaging VNote in NixOS. It should be available in `unstable` and `unstable-small` channels.
|
|
||||||
|
|
||||||
## MacOS
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
|
||||||
- Latest builds on master: [  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
You can also install VNote using homebrew, through the cask tap:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
brew cask install vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
# Description
|
|
||||||
**VNote** is a Qt-based, free and open source note-taking application, focusing on Markdown. VNote is designed to provide comfortable edit experience, especially for programmers.
|
|
||||||
|
|
||||||
VNote is **NOT** just a simple editor for Markdown. By providing notes management, VNote makes taking notes in Markdown simpler and more pleasant.
|
|
||||||
|
|
||||||
Utilizing Qt, VNote could run on **Linux**, **Windows**, and **macOS**.
|
Utilizing Qt, VNote could run on **Linux**, **Windows**, and **macOS**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
# Supports
|

|
||||||
- [Github issues](https://github.com/tamlok/vnote/issues);
|
|
||||||
- Email: `tamlokveer at gmail.com`;
|
|
||||||
- [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTQ1Yzk1YjA5MjAyYTU0MjJkMTUxNmRiYWQ2YjlkOWU0ZGZlMTFlZTAxNzg0ZGUyNzI0ZGY2NDg4MmU1M2FkMDg);
|
|
||||||
- WeChat Public Account: VNote笔记 (vnote_md);
|
|
||||||

|
|
||||||
|
|
||||||
# Highlights
|
## Downloads
|
||||||
- Powerful **full-text search**;
|
Continuous builds on `master` branch could be found at the [Continuous Build](https://github.com/vnotex/vnote/releases/tag/continuous-build) release.
|
||||||
- **Universal Entry** to reach anything just by typing;
|
|
||||||
- Inserting images directly from clipboard;
|
|
||||||
- Syntax highlights of fenced code blocks in both **edit** and **read** mode;
|
|
||||||
- Powerful **In-Place Preview** for images, diagrams, and formulas;
|
|
||||||
- Side-by-side live preview for diagrams;
|
|
||||||
- Outline in both edit and read mode;
|
|
||||||
- Custom styles in both edit and read mode;
|
|
||||||
- **Vim** mode and a set of powerful shortcuts;
|
|
||||||
- Infinite levels of folders;
|
|
||||||
- Multiple tabs and splitting windows;
|
|
||||||
- [Mermaid](http://knsv.github.io/mermaid/), [Flowchart.js](http://flowchart.js.org/), [MathJax](https://www.mathjax.org/), [PlantUML](http://plantuml.com/), and [Graphviz](http://www.graphviz.org/);
|
|
||||||
- Supports HiDPI;
|
|
||||||
- Attachments of notes;
|
|
||||||
- Themes and dark mode;
|
|
||||||
- Rich and extensible export, such as HTML, PDF, PDF (All In One), and images;
|
|
||||||
|
|
||||||
# Donate
|
Latest stable builds could be found at the [latest release](https://github.com/vnotex/vnote/releases/latest). Alternative download services are available:
|
||||||
You could help VNote's development in many ways.
|
|
||||||
|
|
||||||
- Keep monitoring VNote and sending feedback for improvement.
|
* [Tianyi Netdisk](https://cloud.189.cn/t/Av67NvmEJVBv)
|
||||||
- Spread and promote VNote to your friends. Popularity is a strong power to drive developers.
|
* [Baidu Netdisk](https://pan.baidu.com/s/1lX69oMBw8XuJshQDN3HiHw?pwd=f8fk)
|
||||||
- Participate in the development of VNote and send PullRequest to make VNote perfect.
|
|
||||||
- Last, really appreciate your donate to VNote if you think VNote really helps you and you want to help VNote.
|
|
||||||
|
|
||||||
**PayPal**: [PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
|
## Supports
|
||||||
|
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
||||||
|
* Email: `tamlokveer at gmail.com`;
|
||||||
|
* [Telegram](https://t.me/vnotex);
|
||||||
|
* WeChat Public Account: vnotex;
|
||||||
|
|
||||||
**Alipay**: `tamlokveer@gmail.com`
|
Thank [users who donated to VNote](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
||||||
|
|
||||||
<img src="screenshots/alipay.png" width="256px" height="256px" />
|
## License
|
||||||
|
VNote is licensed under [GNU LGPLv3](https://opensource.org/licenses/LGPL-3.0). Code base of VNote could be used freely by VNoteX.
|
||||||
**WeChat**
|
|
||||||
|
|
||||||
<img src="screenshots/wechat_pay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
Thank [users who donated to VNote](https://github.com/tamlok/vnote/wiki/Donate-List)!
|
|
||||||
|
|
||||||
# Why VNote
|
|
||||||
## Markdown Editor & Notes Management
|
|
||||||
VNote tries to be a powerful Markdown editor with notes management, or a note-taking application with pleasant Markdown support. If you are a fan of Markdown and enjoy writing Markdown notes for study, work, and life, VNote is the right tool for you.
|
|
||||||
|
|
||||||
## Pleasant Markdown Experience
|
|
||||||
### Insights About Markdown
|
|
||||||
Markdown, as a simple mark language, unlike rich text, was born with a **gap between edit and read**. There are about three ways to handle this gap:
|
|
||||||
|
|
||||||
1. As one extreme, some editors just treat Markdown as **plain text**. Users may lose themselves in the messy black characters. It is hard to keep track of the information of the note.
|
|
||||||
2. Most Markdown editors use two panels to **edit and preview Markdown notes simultaneously**. It makes things easier since users could see a pleasant typesetting and layout while editing the text. However, two panels may occupy the whole screen and users keep moving eyes left and right which will be a big distraction.
|
|
||||||
3. As another extreme, some editors convert the Markdown elements in place immediately after the typing, which makes editing Markdown just like editing rich text document in Word.
|
|
||||||
|
|
||||||
Since most editors choose the second way to handle the gap, people always think of preview when it comes to Markdown. It may be a misunderstanding about Markdown. Designed as a simple mark language, Markdown is intended to help to keep track of the information of the text when editing and provide a beautiful typesetting when reading after being converted to HTML.
|
|
||||||
|
|
||||||
### Tradeoff: VNote's Way
|
|
||||||
VNote tries to minimize the gap and provide the best-effort *WYSIWYG* for Markdown via tuned **syntax highlights** and some other features. By helping to keep track of the content, there is no need to preview or alter the text immediately after being typed.
|
|
||||||
|
|
||||||
# Features
|
|
||||||
## Notebook-Based Notes Management
|
|
||||||
VNote uses **notebooks** to hold your notes. Like OneNote, a notebook can be hosted on any location on your system. A notebook is designed to represent one account. For example, you could have one notebook hosted on local file system and another notebook hosted on an OwnCloud server. This is really useful when notes require different levels of security.
|
|
||||||
|
|
||||||
A notebook corresponds to a self-contained folder (called the *Root Folder* of the notebook) in the file system. You could copy the folder to another location (or on another computer) and import it into VNote.
|
|
||||||
|
|
||||||
A notebook could have infinite levels of folders. VNote supports copying or moving folders or notes within or between notebooks.
|
|
||||||
|
|
||||||
## Simple Notes Management
|
|
||||||
All your notes are managed by some plaintext configuration files and stored as plaintext files. You could access your notes without VNote. You could use external file synchronization services to synchronize your notes and import them on another machine.
|
|
||||||
|
|
||||||
VNote supports both Markdown (suffix `md`) and rich text notes.
|
|
||||||
|
|
||||||
## Syntax Highlight
|
|
||||||
VNote supports accurate syntax highlight for Markdown. Tuning the style of the highlight, VNote enables you to keep track of your document easily.
|
|
||||||
|
|
||||||
VNote also supports **syntax highlight for fenced code blocks** in edit mode in Markdown, which is **superior** than almost all current Markdown editors.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## In-Place Preview
|
|
||||||
VNote supports powerful **in-place preview** for images, diagrams, and formulas in edit mode.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Pleasant Image Experience
|
|
||||||
Just paste your image into the Markdown note, VNote will manage all other stuffs. VNote stores images in a specified folder in the same folder with the note. VNote will pop up a window to preview the image when you insert an image. Furthermore, VNote will delete the useless image files automatically after you remove the image links.
|
|
||||||
|
|
||||||
## Universal Entry & Full-Text Search
|
|
||||||
VNote has powerful built-in full-text search with **Regular Expression** and **Fuzzy Search** support. The search could be executed within all notebooks, current notebook, or current folder, targeted at name or content.
|
|
||||||
|
|
||||||
Like the `CtrlP` in Vim, VNote supports **Universal Entry** to reach anything by typing in a simple input.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Interactive Outline Viewer In Read & Edit Mode
|
|
||||||
VNote provides a user-friendly outline viewer for both edit and view mode. The outline viewer is a responsive item tree instead of a segment of HTML.
|
|
||||||
|
|
||||||
## Powerful Shortcuts
|
|
||||||
VNote supports many pleasant and powerful shortcuts which facilitate your editing, including **Vim Mode**, **Captain Mode**, and **Navigation Mode** which enable you to work without the mouse.
|
|
||||||
|
|
||||||
Please refer to the [shortcuts help](src/resources/docs/shortcuts_en.md) in the help menu for more details.
|
|
||||||
|
|
||||||
## Highly Configurable
|
|
||||||
In VNote, almost everything is configurable, such as background color, font, and Markdown style. VNote uses a plaintext file to record all your configuration, so you could just copy that file to initialize a new VNote on another computer.
|
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
- [Qt 5.9](http://qt-project.org) (L-GPL v3)
|
|
||||||
- [PEG Markdown Highlight](http://hasseg.org/peg-markdown-highlight/) (MIT License)
|
|
||||||
- [Hoedown 3.0.7](https://github.com/hoedown/hoedown/) (ISC License)
|
|
||||||
- [Marked 0.5.1](https://github.com/markedjs/marked) (MIT License)
|
|
||||||
- [Highlight.js](https://github.com/isagalaev/highlight.js/) (BSD License)
|
|
||||||
- [Ionicons 2.0.1](https://github.com/driftyco/ionicons/) (MIT License)
|
|
||||||
- [markdown-it 8.3.1](https://github.com/markdown-it/markdown-it) (MIT License)
|
|
||||||
- [markdown-it-headinganchor 1.3.0](https://github.com/adam-p/markdown-it-headinganchor) (MIT License)
|
|
||||||
- [markdown-it-task-lists 1.4.0](https://github.com/revin/markdown-it-task-lists) (ISC License)
|
|
||||||
- [markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote) (MIT License)
|
|
||||||
- [markdown-it-sub](https://github.com/markdown-it/markdown-it-sub) (MIT License)
|
|
||||||
- [markdown-it-sup](https://github.com/markdown-it/markdown-it-sup) (MIT License)
|
|
||||||
- [markdown-it-front-matter](https://github.com/craigdmckenna/markdown-it-front-matter) (MIT License)
|
|
||||||
- [markdown-it-imsize](https://github.com/tatsy/markdown-it-imsize) (Unknown) (Thanks @Kinka for help)
|
|
||||||
- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) (MIT License)
|
|
||||||
- [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath) (MIT License)
|
|
||||||
- [markdown-it-container 2.0.0](https://github.com/markdown-it/markdown-it-container) (MIT License)
|
|
||||||
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
|
|
||||||
- [MathJax](https://www.mathjax.org/) (Apache-2.0)
|
|
||||||
- [showdown](https://github.com/showdownjs/showdown) (Unknown)
|
|
||||||
- [flowchart.js](https://github.com/adrai/flowchart.js) (MIT License)
|
|
||||||
- [PlantUML](http://plantuml.com/) (MIT License)
|
|
||||||
- [dom-to-image](https://github.com/tsayen/dom-to-image) (MIT License)
|
|
||||||
- [turndown](https://github.com/domchristie/turndown) (MIT License)
|
|
||||||
|
|
||||||
# License
|
|
||||||
VNote is licensed under the [MIT license](http://opensource.org/licenses/MIT).
|
|
||||||
|
221
README_ja.md
@ -1,221 +0,0 @@
|
|||||||
# VNote
|
|
||||||
[中文 Chinese](./README_zh.md) | [英語 English](./README.md)
|
|
||||||
|
|
||||||
**VNote は、プログラマとMarkdownをよく理解するノート作成アプリケーションです。**
|
|
||||||
|
|
||||||
詳細情報は、[**VNoteのホームページ**](https://tamlok.github.io/vnote)に訪問してください。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# ダウンロード
|
|
||||||
中国のユーザは、VNoteを[バイヅゥ(Baidu Netdisk)](http://pan.baidu.com/s/1jI5HROq)から入手できます。
|
|
||||||
|
|
||||||
## Windows
|
|
||||||
### Zipアーカイブ
|
|
||||||

|
|
||||||
|
|
||||||
- [Githubリリース](https://github.com/tamlok/vnote/releases)
|
|
||||||
- 開発中の最新ビルド: [](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
Windows XPはサポート**されません。**
|
|
||||||
|
|
||||||
### Scoop
|
|
||||||
VNote can be installed from `extras` bucket of Scoop.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
scoop bucket add extras
|
|
||||||
scoop install vnote
|
|
||||||
scoop update vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux
|
|
||||||
### AppImage
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
主要Linuxディストリビューションむけには、AppImageのVNoteスタンドアロン実行ファイルがあります。**Linuxのパッケージングと配布の支援を歓迎します!**
|
|
||||||
|
|
||||||
- [Githubリリース](https://github.com/tamlok/vnote/releases)
|
|
||||||
- 開発中の最新ビルド: [](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
### openSUSE
|
|
||||||
現在、OpenSUSE Tumbleweedの`vnote`は、OBS上の`home:openuse_zh`プロジェクトからインストールすることができます。次のコマンドを直接実行できます。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo zypper ar https://download.opensuse.org/repositories/home:/opensuse_zh/openSUSE_Tumbleweed/ home:opensuse_zh
|
|
||||||
sudo zypper ref
|
|
||||||
sudo zypper in vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
その他のアーキテクチャについては、[software.opensuse.org](https://software.opensuse.org)で`vnote`を検索してください。
|
|
||||||
|
|
||||||
Qtバージョンの関係で、Leap 42およびそれ以下のバージョンをサポートしていません。AppImageを使ったり、自分でビルドしてください。
|
|
||||||
|
|
||||||
### Arch Linux
|
|
||||||
Arch Linux上のVNoteは、AURから[vnote](https://aur.archlinux.org/packages/vnote-bin/)のインストールができます。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone https://aur.archlinux.org/vnote-bin.git
|
|
||||||
cd vnote-bin
|
|
||||||
makepkg -sic
|
|
||||||
```
|
|
||||||
|
|
||||||
また、最新のマスター[vnote git](https://aur.archlinux.org/packages/vnote-git/)を追跡する開発バージョンもあります。
|
|
||||||
|
|
||||||
### NixOS
|
|
||||||
Thank @kuznero for packaging VNote in NixOS. It should be available in `unstable` and `unstable-small` channels.
|
|
||||||
|
|
||||||
## MacOS
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
- [Githubリリース](https://github.com/tamlok/vnote/releases)
|
|
||||||
- 開発中の最新ビルド: [](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
cask tapを通じ、homebrewをつかってVNoteをインストールすることもできます。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
brew cask install vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
# 説明
|
|
||||||
**VNote**は、Qtベースの無料のオープンソースのノート作成アプリケーションで、Markdownに焦点を当てています。VNoteは、特にプログラマーにとって快適な編集エクスペリエンスを提供するように設計されています。
|
|
||||||
|
|
||||||
VNoteは、Markdownの単純なエディタ**ではありません**。ノート管理を提供することで、VNoteはマークダウンのノート作成をより簡単に、より楽しくすることができます。
|
|
||||||
|
|
||||||
Qtを使用し、VNoteは、**Linux**, **Windows**そして、**macOS**で利用できます。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# サポート
|
|
||||||
- [Github issues](https://github.com/tamlok/vnote/issues);
|
|
||||||
- Email: `tamlokveer at gmail.com`;
|
|
||||||
- [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTQ1Yzk1YjA5MjAyYTU0MjJkMTUxNmRiYWQ2YjlkOWU0ZGZlMTFlZTAxNzg0ZGUyNzI0ZGY2NDg4MmU1M2FkMDg);
|
|
||||||
|
|
||||||
# ハイライト
|
|
||||||
- 強力な**全文検索**;
|
|
||||||
- **ユニバーサルエントリ**は、入力するだけで何かに到達することができます。
|
|
||||||
- 直接クリップボードから画像を挿入;
|
|
||||||
- **編集**と**読み込み**の両方で、フェンシングされたコードブロックの構文のハイライト表示;
|
|
||||||
- 編集モードでの画像、図、数式の強力な**その場プレビュー**;
|
|
||||||
- 図の横並びのライブプレビュー;
|
|
||||||
- 編集モードと読み込みモードの両方でアウトラインを作成;
|
|
||||||
- 編集モードと読み込みモードの両方でカスタムスタイル;
|
|
||||||
- **Vim**モードと協力なショートカットキー;
|
|
||||||
- 無限レベルのフォルダ;
|
|
||||||
- 複数のタブとウィンドウ分割;
|
|
||||||
- [Mermaid](http://knsv.github.io/mermaid/), [Flowchart.js](http://flowchart.js.org/), [MathJax](https://www.mathjax.org/), [PlantUML](http://plantuml.com/), and [Graphviz](http://www.graphviz.org/);
|
|
||||||
- HiDPIのサポート;
|
|
||||||
- ノートの添付ファイル;
|
|
||||||
- テーマとダーク・モード;
|
|
||||||
- HTML、PDF、PDF(All In One)、イメージなど、拡張性と拡張性に優れたエクスポート
|
|
||||||
|
|
||||||
# 寄付
|
|
||||||
VNoteの開発に、さまざまな方法で支援できます。
|
|
||||||
|
|
||||||
- VNoteの開発に注目し、改善のためにフィードバックを送信する
|
|
||||||
- VNoteを友達に広める。人気がひろまることは、開発者にとって大きなエネルギーになります。
|
|
||||||
- VNoteの開発に参加し、VNoteを完全にするためにPullRequestを送信します。
|
|
||||||
- VNoteが本当に役に立ち、VNoteを助けたいと思ったら、VNoteへの寄付を本当に感謝します。
|
|
||||||
|
|
||||||
**PayPal**: [PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
|
|
||||||
|
|
||||||
**Alipay**: `tamlokveer@gmail.com`
|
|
||||||
|
|
||||||
<img src="screenshots/alipay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
**WeChat**
|
|
||||||
|
|
||||||
<img src="screenshots/wechat_pay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
[VNoteヘ寄付されたユーザ](https://github.com/tamlok/vnote/wiki/Donate-List)に感謝いたします!
|
|
||||||
|
|
||||||
# VNoteのわけ
|
|
||||||
## Markdown編集とノート管理
|
|
||||||
VNoteは、ノート管理機能のついた協力なMarkdownエディタ、あるいは快適なMarkdownサポートつきのノート作成アプリケーションを目指しています。もしMarkdownのファンで、勉強や仕事、人生のためにMarkdownのノートを書くのなら、VNoteはあなたにとって正しいツールです。
|
|
||||||
|
|
||||||
## 快適なマークダウン体験
|
|
||||||
### Markdownについての洞察
|
|
||||||
Markdownは、リッチテキストとは異なり、編集と読み取りの間にある**ギャップ**を持って生まれた、シンプルなマークアップ言語です。このギャップを扱うには、3つの方法があります。
|
|
||||||
|
|
||||||
1. 一つの極端な例として、エディタの中には、Markdownを**プレーンテキスト**として扱うだけのものもある。ユーザーは、ごちゃごちゃした黒い文字で自分を失うことがあります。メモの情報を追跡するのは難しくなる。
|
|
||||||
2. ほとんどのMarkdownエディターは、**編集とプレビューを同時に行うために、2つのパネルを使用します**。ユーザーはテキストの編集中に、楽しいタイプの設定とレイアウトを見ることができるので、より簡単になります。しかし、2つのパネルが画面全体を占め、ユーザは目を左右に動かすことになり、大きな混乱を招くことになりかねません。
|
|
||||||
3. もう一つの極端な点として、編集の直後にMarkdown要素を変換するエディタもあり、Wordのリッチテキスト文書を編集するのと同じように、Markdownを編集することができます。
|
|
||||||
|
|
||||||
ほとんどのエディタは、ギャップを処理するための2番目の方法を選んでいるので、Markdownをつかうときは、常にプレビューを考えていることになります。これは、Markdownの誤解かもしれません。シンプルなマーク言語として設計されたMarkdownは、編集時にテキストの情報を記録し、HTMLに変換された後に美しいタイプの設定を提供することを目的としています。
|
|
||||||
|
|
||||||
### トレードオフ:VNoteの方法
|
|
||||||
VNoteは、チューニングされた**構文ハイライト**とその他の機能によって、ギャップを最小限に抑えて、Markdownのためにベストエフォート*WYSIWYG*を提供します。コンテンツを追跡することを助けることにより、テキストを入力した直後にテキストをプレビューしたり変更する必要がなくなります。
|
|
||||||
|
|
||||||
# 機能
|
|
||||||
## ノートブック・ベースのノート管理
|
|
||||||
VNoteは、**ノートブック**を使用してノートを管理することができます。OneNoteと同様に、ノートブックはシステム上の任意の場所にホストすることができます。ノートブックは1つのアカウントを表すように設計されています。たとえば、ローカル・ファイルシステムで管理されているノートブックと、OwnCloudサーバ上に保存されている別のノートブックをもつことができます。これは、メモが異なるレベルのセキュリティを必要とする場合に、実際に役立ちます。
|
|
||||||
|
|
||||||
ノートブックは、ファイルシステム内の自己完結型フォルダ(ノートブックの*Rootフォルダ*と呼ばれます)に対応しています。フォルダを別の場所(または別のコンピュータ)にコピーして、VNoteにインポートすることができます。
|
|
||||||
|
|
||||||
ノートブックは、無限レベルのフォルダを持つことができます。VNoteでは、ノートブック内またはノートブック間でフォルダやノートをコピーまたは移動することができます。
|
|
||||||
|
|
||||||
## シンプルなノート管理
|
|
||||||
すべてのメモは、平文の設定ファイルによって管理され、平文ファイルとして格納されます。ノートは、VNOTEなしでアクセスできます。外部のファイル同期サービスを使用して、ノートを同期させたり、別のマシンにインポートすることができます。
|
|
||||||
|
|
||||||
VNoteは、Markdown(拡張子`md`)とリッチテキストノートの両方をサポートしています。
|
|
||||||
|
|
||||||
## 構文ハイライト
|
|
||||||
VNoteでは、Markdownの正確な構文強調表示をサポートしています。ハイライトのスタイルを調整することで、VNoteを使用してドキュメントを簡単に追跡することができます。
|
|
||||||
|
|
||||||
また、VNoteは、**Fenceされたコードブロックに対する**構文ハイライトをサポートしています。これは、現在のあらゆるMarkdownエディタよりも**優れています**。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## インプレイスプレビュー
|
|
||||||
VNoteは、編集モードでのイメージ、図、数式の強力な**その場プレビュー**をサポートしています。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 快適なイメージ体験
|
|
||||||
画像をMarkdownに貼り付けするだけで、VNoteは他のすべてのものを管理することになります。VNoteは、同じフォルダ内の指定されたフォルダに、ノートとともに画像を格納します。VNoteは、画像を挿入するときに画像プレビューするウィンドウをポップアップ表示させます。また、VNoteは、画像リンクを削除した後に、自動的に画像ファイルを削除します。
|
|
||||||
|
|
||||||
## ユニバーサルエントリと全文検索
|
|
||||||
VNote には、**正規表現**と**ファジー検索**サポートのある、強力な全文検索が組み込まれています。検索は、すべてのノートブック、現在のノートブック、または現在のフォルダ、名前またはコンテンツを対象に実行することができます。
|
|
||||||
|
|
||||||
VNoteは、Vimでの`Ctrl+P`のように、**ユニバーサルエントリ**機能をサポートし、シンプルな入力であらゆる機能へ到達できます。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 読み込み&編集モードのインタラクティブなアウトライン表示
|
|
||||||
VNoteでは、編集モードと閲覧モードの両方でユーザフレンドリなアウトラインビューアが提供されています。アウトライン・ビューアは、HTMLのセグメントではなく、応答するアイテム・ツリーです。
|
|
||||||
|
|
||||||
## 強力なショートカット
|
|
||||||
VNoteは、<x/>Vim Mode**、**キャプテンモード**、<x/>、**ナビゲーションモード**など、編集を容易にする強力なショートカットをサポートしています。これにより、マウスを使用せずに作業を行うことができます。
|
|
||||||
|
|
||||||
詳細については、ヘルプメニューの[ショートカットヘルプ](src/resources/docs/shortcuts_en.md)を参照してください。
|
|
||||||
|
|
||||||
## 柔軟に調整可能
|
|
||||||
VNoteでは、背景色、フォント、マークダウンなど、ほとんどすべてのものが調整可能です。VNoteは平文ファイルを使ってすべての構成を記録しますので、そのファイルをコピーすれば、別のコンピュータで新しいVNoteを初期化することができます。
|
|
||||||
|
|
||||||
# 依存関係
|
|
||||||
- [Qt 5.9](http://qt-project.org) (L-GPL v3)
|
|
||||||
- [PEG Markdown Highlight](http://hasseg.org/peg-markdown-highlight/) (MIT License)
|
|
||||||
- [Hoedown 3.0.7](https://github.com/hoedown/hoedown/) (ISC License)
|
|
||||||
- [Marked 0.5.1](https://github.com/markedjs/marked) (MIT License)
|
|
||||||
- [Highlight.js](https://github.com/isagalaev/highlight.js/) (BSD License)
|
|
||||||
- [Ionicons 2.0.1](https://github.com/driftyco/ionicons/) (MIT License)
|
|
||||||
- [markdown-it 8.3.1](https://github.com/markdown-it/markdown-it) (MIT License)
|
|
||||||
- [markdown-it-headinganchor 1.3.0](https://github.com/adam-p/markdown-it-headinganchor) (MIT License)
|
|
||||||
- [markdown-it-task-lists 1.4.0](https://github.com/revin/markdown-it-task-lists) (ISC License)
|
|
||||||
- [markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote) (MIT License)
|
|
||||||
- [markdown-it-sub](https://github.com/markdown-it/markdown-it-sub) (MIT License)
|
|
||||||
- [markdown-it-sup](https://github.com/markdown-it/markdown-it-sup) (MIT License)
|
|
||||||
- [markdown-it-front-matter](https://github.com/craigdmckenna/markdown-it-front-matter) (MIT License)
|
|
||||||
- [markdown-it-imsize](https://github.com/tatsy/markdown-it-imsize) (Unknown) (Thanks @Kinka for help)
|
|
||||||
- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) (MIT License)
|
|
||||||
- [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath) (MIT License)
|
|
||||||
- [markdown-it-container 2.0.0](https://github.com/markdown-it/markdown-it-container) (MIT License)
|
|
||||||
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
|
|
||||||
- [MathJax](https://www.mathjax.org/) (Apache-2.0)
|
|
||||||
- [showdown](https://github.com/showdownjs/showdown) (Unknown)
|
|
||||||
- [flowchart.js](https://github.com/adrai/flowchart.js) (MIT License)
|
|
||||||
- [PlantUML](http://plantuml.com/) (MIT License)
|
|
||||||
- [dom-to-image](https://github.com/tsayen/dom-to-image) (MIT License)
|
|
||||||
- [turndown](https://github.com/domchristie/turndown) (MIT License)
|
|
||||||
|
|
||||||
# ライセンス
|
|
||||||
VNoteは、[MITライセンス](http://opensource.org/licenses/MIT)の下でライセンスされています。
|
|
226
README_zh.md
@ -1,226 +0,0 @@
|
|||||||
# VNote
|
|
||||||
[英文 English](./README.md) | [日本語 Japanese](./README_ja.md)
|
|
||||||
|
|
||||||
**VNote是一个更懂程序员和Markdown的笔记!**
|
|
||||||
|
|
||||||
更多信息,请访问 [**VNote主页**](https://tamlok.github.io/vnote) 。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# 下载
|
|
||||||
国内的用户可以尝试在[百度云盘](http://pan.baidu.com/s/1jI5HROq)下载VNote的最新发行版本。
|
|
||||||
|
|
||||||
## Windows
|
|
||||||
### 官方压缩包
|
|
||||||

|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
|
||||||
- master分支的最新构建:[  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
VNote不支持**XP**,因为QtWebEngineProcess无法在XP上运行。
|
|
||||||
|
|
||||||
### Scoop
|
|
||||||
VNote也可以通过Scoop的`extras`仓库进行安装。
|
|
||||||
|
|
||||||
```shell
|
|
||||||
scoop bucket add extras
|
|
||||||
scoop install vnote
|
|
||||||
scoop update vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux
|
|
||||||
### AppImage
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
VNote当前为主要Linux发行版提供了一个AppImage格式的独立可执行文件。希望了解Linux系统下打包发布的开发人员能提供这方面进一步的帮助!
|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
|
||||||
- master分支的最新构建:[  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
### openSUSE
|
|
||||||
目前 openSUSE Tumbleweed 可以通过 OBS 上的 `home:opensuse_zh` 源直接安装。您可以直接执行以下命令:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo zypper ar https://download.opensuse.org/repositories/home:/opensuse_zh/openSUSE_Tumbleweed/ home:opensuse_zh
|
|
||||||
sudo zypper ref
|
|
||||||
sudo zypper in vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
其他架构请直接在 [software.opensuse.org](https://software.opensuse.org) 搜索 `vnote`。
|
|
||||||
|
|
||||||
由于 Leap 42 及以下版本的 Qt 版本过低,我们无法在 OBS 上进行打包。请使用 AppImage 或自行构建。
|
|
||||||
|
|
||||||
### Arch Linux
|
|
||||||
Arch Linux可以通过AUR中的 [vnote-bin](https://aur.archlinux.org/packages/vnote-bin/) 进行安装:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git clone https://aur.archlinux.org/vnote-bin.git
|
|
||||||
cd vnote-bin
|
|
||||||
makepkg -sic
|
|
||||||
```
|
|
||||||
|
|
||||||
AUR也提供一个和最新master分支同步的开发版本 [vnote-git](https://aur.archlinux.org/packages/vnote-git/) 。
|
|
||||||
|
|
||||||
## MacOS
|
|
||||||
[](https://travis-ci.org/tamlok/vnote)
|
|
||||||
|
|
||||||
- [Github releases](https://github.com/tamlok/vnote/releases)
|
|
||||||
- master分支的最新构建:[  ](https://bintray.com/tamlok/vnote/vnote/_latestVersion)
|
|
||||||
|
|
||||||
也可以通过 homebrew cask 进行安装:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
brew cask install vnote
|
|
||||||
```
|
|
||||||
|
|
||||||
### NixOS
|
|
||||||
@kuznero packaged VNote in NixOS. It should be available in `unstable` and `unstable-small` channels.
|
|
||||||
|
|
||||||
感谢 @kuznero 在NixOS上打包VNote。可以在`unstable`和`unstable-small`频道中找到VNote。
|
|
||||||
|
|
||||||
# 简介
|
|
||||||
|
|
||||||
**VNote**是一个基于Qt框架的、免费的开源笔记软件。VNote专注于Markdown的编辑与阅读,以提供舒适的编辑体验为设计目标。
|
|
||||||
|
|
||||||
VNote不是一个简单的Markdown编辑器。通过提供笔记管理功能,VNote使得编写Markdown笔记更简单和舒适!
|
|
||||||
|
|
||||||
基于Qt框架,VNote能够在主流操作系统上运行,包括 **Linux**, **Windows** 以及 **macOS** 。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# 支持
|
|
||||||
- [Github issues](https://github.com/tamlok/vnote/issues);
|
|
||||||
- 邮箱: `tamlokveer at gmail.com` ;
|
|
||||||
- [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTQ1Yzk1YjA5MjAyYTU0MjJkMTUxNmRiYWQ2YjlkOWU0ZGZlMTFlZTAxNzg0ZGUyNzI0ZGY2NDg4MmU1M2FkMDg);
|
|
||||||
- 微信公众号: VNote笔记(vnote_md);
|
|
||||||

|
|
||||||
|
|
||||||
# 亮点
|
|
||||||
- 强大的**全文搜索**;
|
|
||||||
- **通用入口**,通过按键操控一切;
|
|
||||||
- 直接从剪切板插入图片;
|
|
||||||
- 编辑和阅读模式下代码块的语法高亮;
|
|
||||||
- 强大的**原地预览**,包括图片、图表和公式;
|
|
||||||
- 针对图表的两边实时预览;
|
|
||||||
- 编辑和阅读模式下的大纲;
|
|
||||||
- 自定义编辑和阅读模式的样式;
|
|
||||||
- **Vim** 模式以及一系列强大的快捷键;
|
|
||||||
- 无限层级的文件夹;
|
|
||||||
- 多个标签页和窗口分割;
|
|
||||||
- [Mermaid](http://knsv.github.io/mermaid/)、 [Flowchart.js](http://flowchart.js.org/)、 [MathJax](https://www.mathjax.org/)、 [PlantUML](http://plantuml.com/) 和 [Graphviz](http://www.graphviz.org/);
|
|
||||||
- 支持高分辨率;
|
|
||||||
- 笔记附件;
|
|
||||||
- 主题以及深色模式;
|
|
||||||
- 丰富、可扩展的导出,包括HTML、PDF、PDF(多合一)和图片;
|
|
||||||
|
|
||||||
# 捐赠
|
|
||||||
您可以通过很多途径帮助VNote的开发。
|
|
||||||
|
|
||||||
- 持续关注VNote并反馈。
|
|
||||||
- 向您的朋友们推广和传播VNote。普及度是驱动开发者的一股强大力量。
|
|
||||||
- 参与到VNote的开发中,发送PullRequest来帮助VNote变得更完美。
|
|
||||||
- 最后,如果您觉得VNote真的帮助到您并且想回馈VNote,非常感谢您的捐赠。
|
|
||||||
|
|
||||||
**PayPal**: [PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
|
|
||||||
|
|
||||||
**支付宝**: `tamlokveer@gmail.com`
|
|
||||||
|
|
||||||
<img src="screenshots/alipay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
**微信**
|
|
||||||
|
|
||||||
<img src="screenshots/wechat_pay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
非常感谢[这些用户](https://github.com/tamlok/vnote/wiki/Donate-List)对VNote的捐赠!
|
|
||||||
|
|
||||||
# 开发VNote的动机
|
|
||||||
## Markdown编辑器与笔记管理
|
|
||||||
VNote设计为带有笔记管理功能的Markdown编辑器,或者有良好Markdown支持的笔记软件。如果您喜欢Markdown并经常在学习、工作和生活中使用Markdown记录笔记,那么VNote就是一个适合您的工具。
|
|
||||||
|
|
||||||
## 舒适的Markdown体验
|
|
||||||
### Markdown的本质
|
|
||||||
Markdown作为一个简单标记语言,不像富文本,它的编辑和阅读有着与生俱来的隔阂。一般目前大概有三类方法来处理这个隔阂:
|
|
||||||
|
|
||||||
1. 作为一个极端,一些编辑器只是将Markdown作为无格式的纯文本处理。用户很容易在密密麻麻的黑漆漆的一片文字中找不着方向。
|
|
||||||
2. 大部分编辑器使用两个面板来同时编辑和预览Markdown笔记。从而,用户可以在编辑的同时看到优美的排版和布局。但是,两个面板基本会占据了整个屏幕,而用户的目光焦点左右频繁移动,往往也会使得用户无法专注编辑。
|
|
||||||
3. 作为另一个极端,一些编辑器在用户输入文本后立即将Markdown的标记转换为HTML元素,使得编写Markdown如同在Word文档里面编写富文本一样。
|
|
||||||
|
|
||||||
由于几乎所有的编辑器都选择第二种方法来处理隔阂,一提到Markdown人们往往会想起预览。这可能是对Markdown的一个最大的误解了。设计为一个简单的标记语言,Markdown的设计初衷就是为了在编辑的时候方便帮助跟踪文本的信息,而又能在阅读的时候被转换为HTML为发布提供美观的排版输出。所以,Markdown本身就应该在编辑的时候能够方便地跟踪和掌控文本的信息和脉络,而不需要通过预览这种接近饮鸩止渴的方法来方便编辑。
|
|
||||||
|
|
||||||
### 折中:VNote的方案
|
|
||||||
VNote尝试通过精心调配的**语法高亮**和其他一些特性,来最大程度地减小Markdown的这种割裂感,尽可能地提供一个*所见即所得*的编辑体验。用户在编辑的时候就能有效第把握内容脉络,也就没有必要进行预览或者强制更改文本为HTML元素了。
|
|
||||||
|
|
||||||
# 功能
|
|
||||||
## 基于笔记本的管理
|
|
||||||
VNote使用 **笔记本** 来管理笔记。类似于OneNote,一个笔记本可以保存在系统上的任意位置。一个笔记本对应于一个账户的概念。例如,您可以在本地文件系统上有一个笔记本,另外在某台OwnCloud服务器上保存另一个笔记本。当不同的笔记有不同的保密要求时,独立的笔记本就非常适用了。
|
|
||||||
|
|
||||||
一个笔记本对应于文件系统上的一个独立完整的文件夹(称为笔记本的 **根目录** )。您可以将该文件夹拷贝到其他位置(或者另一台计算机上),然后将其导入到VNote中。
|
|
||||||
|
|
||||||
VNote支持一个笔记本中包含无限层级的文件夹。VNote支持在笔记本内或笔记本间拷贝或剪切文件夹和笔记。
|
|
||||||
|
|
||||||
## 直观的笔记管理
|
|
||||||
所有笔记被保存为纯文本而且通过纯文本的配置文件进行管理。即使没有VNote,您也能方便访问您的数据。这样,您也可以使用第三方的文件同步服务来同步您的笔记,并在另一台计算机上导入到VNote中。
|
|
||||||
|
|
||||||
VNote支持Markdown和富文本笔记,其中Markdown笔记必须以`md`为后缀名。
|
|
||||||
|
|
||||||
## 语法高亮
|
|
||||||
VNote支持精确的Markdown语法高亮。通过精心调试的高亮样式,VNote使得您能够轻松跟踪和阅读您的文档。
|
|
||||||
|
|
||||||
VNote还支持Markdown编辑模式中代码块的语法高亮。目前的Markdown编辑器中绝大部分都尚不支持该特性。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 原地预览
|
|
||||||
VNote支持在编辑时原地预览图片、图表和公式。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 良好的图片体验
|
|
||||||
编辑时,支持像其他富文本编辑器一样直接粘贴插入图片,VNote会帮您管理所插入的图片。VNote将这些图片保存在和笔记同一目录下的一个指定目录中。插入图片时,VNote会弹出一个窗口预览即将要插入的图片。另外,当您移除笔记中的图片链接时,VNote会自动删除对应的图片文件。
|
|
||||||
|
|
||||||
## 通用入口和全文搜索
|
|
||||||
VNote内置强大的全文搜索,支持**正则表达式**和**模糊搜索**。搜索可以指定范围,包括全部笔记本、当前笔记本和当前文件夹,也可以指定目标,如名字或内容。
|
|
||||||
|
|
||||||
类似于Vim中的`CtrlP`,VNote支持**通用入口**,可以在一个输入框中进行搜索或跳转。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 编辑和阅读模式中的交互式大纲视图
|
|
||||||
VNote为编辑和预览模式都提供了一个用户友好的大纲视图。该大纲视图是一个项目树,而不是简单地插入一段HTML。
|
|
||||||
|
|
||||||
## 强大的快捷键
|
|
||||||
VNote提供很多快捷键,从而提供一个愉悦的编辑体验。其中包括 **Vim模式**、**舰长模式** 和 **导航模式**,它们能让您完全摆脱鼠标进行操作。
|
|
||||||
|
|
||||||
更多细节请参考帮助菜单中的[快捷键帮助](src/resources/docs/shortcuts_zh.md)。
|
|
||||||
|
|
||||||
## 高度可定制
|
|
||||||
VNote中,几乎一切都是可以定制的,例如背景颜色、字体以及Markdown样式等。VNote使用一个纯文本文件来记录您的所有配置,因此通过拷贝该文件就能够很快地在另一台电脑上初始化一个新的VNote。
|
|
||||||
|
|
||||||
# 依赖
|
|
||||||
- [Qt 5.9](http://qt-project.org) (L-GPL v3)
|
|
||||||
- [PEG Markdown Highlight](http://hasseg.org/peg-markdown-highlight/) (MIT License)
|
|
||||||
- [Hoedown 3.0.7](https://github.com/hoedown/hoedown/) (ISC License)
|
|
||||||
- [Marked 0.5.1](https://github.com/markedjs/marked) (MIT License)
|
|
||||||
- [Highlight.js](https://github.com/isagalaev/highlight.js/) (BSD License)
|
|
||||||
- [Ionicons 2.0.1](https://github.com/driftyco/ionicons/) (MIT License)
|
|
||||||
- [markdown-it 8.3.1](https://github.com/markdown-it/markdown-it) (MIT License)
|
|
||||||
- [markdown-it-headinganchor 1.3.0](https://github.com/adam-p/markdown-it-headinganchor) (MIT License)
|
|
||||||
- [markdown-it-task-lists 1.4.0](https://github.com/revin/markdown-it-task-lists) (ISC License)
|
|
||||||
- [markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote) (MIT License)
|
|
||||||
- [markdown-it-sub](https://github.com/markdown-it/markdown-it-sub) (MIT License)
|
|
||||||
- [markdown-it-sup](https://github.com/markdown-it/markdown-it-sup) (MIT License)
|
|
||||||
- [markdown-it-front-matter](https://github.com/craigdmckenna/markdown-it-front-matter) (MIT License)
|
|
||||||
- [markdown-it-imsize](https://github.com/tatsy/markdown-it-imsize) (Unknown) (Thanks @Kinka for help)
|
|
||||||
- [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) (MIT License)
|
|
||||||
- [markdown-it-texmath](https://github.com/goessner/markdown-it-texmath) (MIT License)
|
|
||||||
- [markdown-it-container 2.0.0](https://github.com/markdown-it/markdown-it-container) (MIT License)
|
|
||||||
- [mermaid 7.0.0](https://github.com/knsv/mermaid) (MIT License)
|
|
||||||
- [MathJax](https://www.mathjax.org/) (Apache-2.0)
|
|
||||||
- [showdown](https://github.com/showdownjs/showdown) (Unknown)
|
|
||||||
- [flowchart.js](https://github.com/adrai/flowchart.js) (MIT License)
|
|
||||||
- [PlantUML](http://plantuml.com/) (MIT License)
|
|
||||||
- [dom-to-image](https://github.com/tsayen/dom-to-image) (MIT License)
|
|
||||||
- [turndown](https://github.com/domchristie/turndown) (MIT License)
|
|
||||||
|
|
||||||
# 代码许可
|
|
||||||
VNote使用[MIT许可](http://opensource.org/licenses/MIT)。
|
|
42
README_zh_CN.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# VNote
|
||||||
|
  
|
||||||
|
|
||||||
|
[English](README.md)
|
||||||
|
|
||||||
|
[Gitee托管项目](https://gitee.com/vnotex/vnote)
|
||||||
|
|
||||||
|
一个舒适的笔记平台!
|
||||||
|
|
||||||
|
更多信息,请访问[VNote主页](https://vnotex.github.io/vnote)。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 简介
|
||||||
|
**VNote**是一个专注于Markdown的基于Qt的开源免费的笔记应用。VNote希望能提供一个拥有完美编辑体验的舒适的笔记平台。
|
||||||
|
|
||||||
|
VNote不是一个简单的Markdown编辑器。通过提供强大的笔记管理,VNote使得使用Markdown记笔记更轻松简单。将来,VNote会支持更多的文档格式。
|
||||||
|
|
||||||
|
得益于Qt,VNote当前可以高效地运行在**Linux**,**Windows**,以及**macOS**平台上。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 下载
|
||||||
|
基于`master`分支的[持续构建版本发布](https://github.com/vnotex/vnote/releases/tag/continuous-build)。
|
||||||
|
|
||||||
|
最新的[稳定版本发布](https://github.com/vnotex/vnote/releases/latest)。其他下载选项:
|
||||||
|
|
||||||
|
* [天翼云盘](https://cloud.189.cn/t/Av67NvmEJVBv)
|
||||||
|
* [百度云盘](https://pan.baidu.com/s/1lX69oMBw8XuJshQDN3HiHw?pwd=f8fk)
|
||||||
|
|
||||||
|
## 支持
|
||||||
|
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
||||||
|
* 邮件:`tamlokveer at gmail.com`;
|
||||||
|
* [Telegram](https://t.me/vnotex);
|
||||||
|
* 微信公众号:`vnotex`;
|
||||||
|
|
||||||
|
感谢这些[捐赠用户](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
||||||
|
|
||||||
|
## 许可
|
||||||
|
VNote遵循[GNU LGPLv3](https://opensource.org/licenses/LGPL-3.0)许可。VNote项目的代码可以自由给VNoteX项目使用。
|
15
SECURITY.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Only the latest version is supported with security updates.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please [contact support](mailto:tamlokveer@gmail.com) **with a proof of concept** that shows the security vulnerability. Please do not contact us without this proof of concept, as we cannot fix anything without this.
|
||||||
|
|
||||||
|
For general opinions on what makes an app more or less secure, please use the forum.
|
||||||
|
|
||||||
|
## Bounty
|
||||||
|
|
||||||
|
We **do not** offer a bounty for discovering vulnerabilities, please do not ask. We can however credit you and link to your website/profile in the changelog and release announcement.
|
15
VNote.pro
@ -1,15 +0,0 @@
|
|||||||
#-------------------------------------------------
|
|
||||||
#
|
|
||||||
# Project created by QtCreator 2016-10-01T11:03:59
|
|
||||||
#
|
|
||||||
#-------------------------------------------------
|
|
||||||
|
|
||||||
TEMPLATE = subdirs
|
|
||||||
|
|
||||||
CONFIG += c++11
|
|
||||||
|
|
||||||
SUBDIRS = hoedown \
|
|
||||||
peg-highlight \
|
|
||||||
src
|
|
||||||
|
|
||||||
src.depends = hoedown peg-highlight
|
|
78
appveyor.yml
@ -1,78 +0,0 @@
|
|||||||
image: Visual Studio 2015
|
|
||||||
|
|
||||||
version: 2.7.1.{build}
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
environment:
|
|
||||||
COMPILER: msvc
|
|
||||||
VSVER: 14
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
- QT: C:\Qt\5.9\msvc2015_64
|
|
||||||
PLATFORM: amd64
|
|
||||||
- QT: C:\Qt\5.9\msvc2015
|
|
||||||
PLATFORM: x86
|
|
||||||
|
|
||||||
clone_depth: 1
|
|
||||||
|
|
||||||
# scripts that run after cloning repository
|
|
||||||
install:
|
|
||||||
- set PATH=%QT%\bin\;C:\Qt\Tools\QtCreator\bin\;C:\Qt\QtIFW2.0.1\bin\;%PATH%
|
|
||||||
- git submodule update --init --recursive
|
|
||||||
|
|
||||||
# scripts that run before build
|
|
||||||
before_build:
|
|
||||||
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %PLATFORM%
|
|
||||||
# After calling vcvarsall.bat, %PLATFORM% will be X64 or x86
|
|
||||||
- qmake --version
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- if "%PLATFORM%" EQU "X64" (qmake -r -spec win32-msvc CONFIG+=x86_64 CONFIG-=debug CONFIG+=release ../VNote.pro)
|
|
||||||
- if "%PLATFORM%" EQU "x86" (qmake -r -spec win32-msvc CONFIG+=Win32 CONFIG-=debug CONFIG+=release ../VNote.pro)
|
|
||||||
|
|
||||||
# custom build scripts
|
|
||||||
build_script:
|
|
||||||
- nmake
|
|
||||||
|
|
||||||
# scripts that run after build
|
|
||||||
after_build:
|
|
||||||
- set vnote_version=2.7.1
|
|
||||||
# Clone OpenSSL DLLs
|
|
||||||
- git clone https://github.com/tamlok/openssl-utils.git openssl-utils.git
|
|
||||||
- mkdir distrib\VNote
|
|
||||||
- windeployqt.exe --dir .\distrib\VNote %APPVEYOR_BUILD_FOLDER%\build\src\release\VNote.exe
|
|
||||||
- copy "%APPVEYOR_BUILD_FOLDER%\build\src\release\VNote.exe" "distrib\VNote\VNote.exe"
|
|
||||||
- copy "%APPVEYOR_BUILD_FOLDER%\README.md" "distrib\VNote\README.md"
|
|
||||||
- copy "%APPVEYOR_BUILD_FOLDER%\LICENSE" "distrib\VNote\LICENSE.txt"
|
|
||||||
- echo %vnote_version% > "distrib\VNote\version.txt"
|
|
||||||
- echo %APPVEYOR_REPO_COMMIT% >> "distrib\VNote\version.txt"
|
|
||||||
- copy "distrib\VNote\VNote.exe" "distrib\VNote_win_%PLATFORM%.exe"
|
|
||||||
# Delete translations\qt_*.qm
|
|
||||||
- del /F /Q "distrib\VNote\translations\qt_*.qm"
|
|
||||||
# Copy OpenSSL DLLs
|
|
||||||
- if "%PLATFORM%" EQU "X64" (xcopy "openssl-utils.git\win64\*.dll" "distrib\VNote")
|
|
||||||
- if "%PLATFORM%" EQU "x86" (xcopy "openssl-utils.git\win32\*.dll" "distrib\VNote")
|
|
||||||
- cd distrib
|
|
||||||
- 7z a VNote_win_%PLATFORM%_portable_%vnote_version%.zip VNote
|
|
||||||
|
|
||||||
artifacts:
|
|
||||||
- path: build\distrib\VNote_win_%PLATFORM%_portable_%vnote_version%.zip
|
|
||||||
name: portable
|
|
||||||
- path: build\distrib\VNote_win_%PLATFORM%.exe
|
|
||||||
name: exe_only
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
- provider: BinTray
|
|
||||||
username: tamlok
|
|
||||||
api_key:
|
|
||||||
secure: YJqzsVDlC2NYH2RgzbUMtjZWbSXOdWUiiENOIqImo31hOfeiB0MiVGmBLmKPAHEg
|
|
||||||
subject: tamlok
|
|
||||||
repo: vnote
|
|
||||||
package: vnote
|
|
||||||
version: 2.7.1
|
|
||||||
publish: true
|
|
||||||
override: true
|
|
||||||
artifact: portable
|
|
569
changes.md
@ -1,375 +1,256 @@
|
|||||||
# Changes History
|
# Changes
|
||||||
## v2.7.1
|
## v3.19.2
|
||||||
- Fix PlantUML command;
|
* Codesign MacOS Bundle
|
||||||
- Use 5.12.0 on macOS;
|
* Fix toolbar expansion button style
|
||||||
- Add config [web]/enable_code_block_copy_button for copy button in code block in read mode;
|
* Support hot-reloading of theme via --watch-themes option
|
||||||
|
|
||||||
## v2.7
|
## v3.19.1
|
||||||
- Editor
|
* Fix toolbar button in Qt 6.8
|
||||||
- Fix smart table bugs;
|
|
||||||
- Fix improper leading line space on macOS;
|
|
||||||
- Fix bug which will open two tabs for the same file;
|
|
||||||
- Add copy button to copy code block in read mode;
|
|
||||||
- PluatUML: use shell to launch Java;
|
|
||||||
- Use qt 5.12.1 on macOS for better performance;
|
|
||||||
- Add theme `v_simple` provided by user LuoshuiTianyi;
|
|
||||||
- Support adding sibling folder in context menu;
|
|
||||||
|
|
||||||
## v2.6
|
## v3.19.0
|
||||||
- Version-specific user track;
|
* Add VSCode-sytle editor shortcuts
|
||||||
|
|
||||||
## v2.5
|
## v3.18.1
|
||||||
- Do not open unknown type file when creating a new note;
|
* Fix crash caused by Qt6 change
|
||||||
- Support Right-To-Left text in edit mode (with Vim mode disabled);
|
* Fix XSS protection exemption
|
||||||
- Remove credict information in export template;
|
* Check link before open
|
||||||
|
|
||||||
## v2.4
|
## v3.18.0
|
||||||
- Bundle qt5ct in Linux for native look support;
|
* Upgrade to Qt6
|
||||||
- Use `Return` or `Enter` to confirm selection in macOS (besides `Cmd+O`);
|
* Support MacOS universal build
|
||||||
- Support sync note list to current note automatically via config `global/sync_note_list_to_current_tab`;
|
* Upgrade Mermaid, Flowchart.js, and markdown-it
|
||||||
- Add `Ctrl+E N` to view and edit current note's information;
|
* Markdown-it
|
||||||
- Fix Markdown highlighter to handle fenced code block without a leading empty line;
|
* Fix XSS protection and turn it on by default
|
||||||
- Prompt for restart after changing theme;
|
* Support mark by `==xx==`
|
||||||
|
|
||||||
## v2.3
|
## v3.17.0
|
||||||
- Add Japanese translations (thanks to @miurahr);
|
* Quick note: create note in given scheme (@feloxx)
|
||||||
- Editor
|
* MarkdownEditor: support inserting multiple images (@feloxx)
|
||||||
- Bug fix of smart table;
|
* Mermaid: upgrade and fix preview issue (@ygcaicn)
|
||||||
- Allow to disable smart table;
|
* Flowchart.js: upgrade
|
||||||
- Update to Qt 5.9.7 in CI in Linux;
|
|
||||||
- Add user track logics for users counting;
|
|
||||||
- Add CMake build system;
|
|
||||||
- Support multiple packaging genration;
|
|
||||||
- QtIFW GUI installer
|
|
||||||
- Debian package
|
|
||||||
- RPM package
|
|
||||||
- AppImage
|
|
||||||
- Tar.gz package
|
|
||||||
- ZIP package
|
|
||||||
- Windows Nullsoft installer
|
|
||||||
- Windows NuGet package
|
|
||||||
- Mac OS X dmg package
|
|
||||||
- Support staic code checkers;
|
|
||||||
- clang-tidy
|
|
||||||
- crazy
|
|
||||||
- include-what-you-see
|
|
||||||
- Support modern IDEs;
|
|
||||||
- Microsoft Visual Studio 2017
|
|
||||||
- JetBrains CLion
|
|
||||||
- QtCreator
|
|
||||||
- XCode
|
|
||||||
- VSCode
|
|
||||||
|
|
||||||
## v2.2
|
## v3.16.0
|
||||||
- Editor
|
* Support reading PDF format
|
||||||
- Support smart GFM table;
|
* Support Ming Map editor in suffix `*.emind`
|
||||||
- support auto scrolling cursor into center;
|
* Support "View By" for notebooks selector
|
||||||
- Support specifying font via settings to override style config;
|
* ViewWindow: add shortcut Ctrl+G,V to alternate among view modes
|
||||||
- Guess image title from the file name;
|
* Bug fixes
|
||||||
- Support ~~~ as fenced code block marker;
|
|
||||||
- MathJax
|
|
||||||
- Support equation number;
|
|
||||||
- Support \begin and \end directly;
|
|
||||||
- Support $..$ in \text{} within $$...$$;
|
|
||||||
- NotebookPanel: support spliting file list out;
|
|
||||||
- Add openGL option in settings on Windows;
|
|
||||||
- Markdown-it
|
|
||||||
- Support alert text via markdown-it-container plugin;
|
|
||||||
- Support WaveDrom for digital timing diagram;
|
|
||||||
|
|
||||||
## v2.1
|
## v3.15.1
|
||||||
- UniversalEntry/Searcher: `Ctrl+B` to expand/collapse all items;
|
* Add two themes
|
||||||
- Captain mode: support specifying keyboard layout mappings, such as Russian or French;
|
* Bug fixes
|
||||||
- Editor
|
|
||||||
- Support downloading images to local when Parse&Paste;
|
|
||||||
- Support scaling image when inserting image;
|
|
||||||
- Support Parse&Paste as table from Microsoft Excel;
|
|
||||||
- Support attach a file as attachment and insert as link by Drag&Drop;
|
|
||||||
- Support `Ctrl+Sfhit+V` to paste as plain text;
|
|
||||||
- Fix Unicode issue;
|
|
||||||
- Attachment
|
|
||||||
- Support copying file path;
|
|
||||||
- Support Drag&Drop to copy/move notes;
|
|
||||||
- Support MathJax euqation number in read mode;
|
|
||||||
- Fix blurry toolbar icon on macOS;
|
|
||||||
- Fix blurry renderring in read mode on Windows;
|
|
||||||
|
|
||||||
## v2.0
|
## v3.15.0
|
||||||
- Vim: support specifying leader key via "[editor]/vim_leader_key";
|
* Editor supports Word Count
|
||||||
- LivePreview
|
* Add Open Windows panel
|
||||||
- Smart live preview for PlantUML (Live Preview Tunnel);
|
* Theme: add Vue-light theme
|
||||||
- Expand live preview area via `Ctrl+E U`;
|
* Support default open mode
|
||||||
- In-Place Preview: support in-place preview for online PlantUML;
|
* NotebookSelector: support dynamic icons for notebooks
|
||||||
- Captain: fix captain mode shortcuts in different keyboard layout (Windows only);
|
|
||||||
- Quick Access: specify a note for quick access via `Ctrl+Alt+I`;
|
|
||||||
- Magic Word: support `%att%` as the relative path of the attachment folder;
|
|
||||||
- Search: highlight matches of full-text search results in page in edit mode;
|
|
||||||
- Editor
|
|
||||||
- Allow inserting link or content when dropping files in;
|
|
||||||
- Support highlighting tabs;
|
|
||||||
- Support parsing HTML tables without head;
|
|
||||||
- Export: support outline panel in exported HTML files;
|
|
||||||
|
|
||||||
## v1.22
|
## v3.14.0
|
||||||
- Editor
|
* Theme: support custom icons
|
||||||
- Support parsting HTML as converted Markdown text;
|
* Theme: refine icons
|
||||||
- Improve performance of in-place preview;
|
* NavigationMode: fix issue for input method
|
||||||
- Be aware of links, images, and in-place preview in edit mode (visit or copy);
|
|
||||||
- Support exporting and copying PlantUML and Graphviz diagram in edit mode;
|
|
||||||
- Support middle click to close a tab;
|
|
||||||
- Support searching files via multiple tags, such as "vnote && markdown";
|
|
||||||
|
|
||||||
## v1.21
|
## v3.13.1
|
||||||
- Improve performance of editor (now could process 10K lines);
|
* Shortcuts for Copy/Paste/Properties in node explorer
|
||||||
- Support `<mark>vnote</mark>` highlight in edit mode;
|
* Global shortcut to call out main window
|
||||||
- Support **completion** in edit mode by `Ctrl+N/P`;
|
* UnitedEntry: bug fix for macOS
|
||||||
- Support building a notebook from external directory recursively;
|
|
||||||
- Update Flowchart.js to 1.11.3;
|
|
||||||
|
|
||||||
## v1.20
|
## v3.13.0
|
||||||
- More efficient and accurate Markdown parser and highlighter;
|
* United Entry: migration of Universal Entry
|
||||||
- MathJax: get rid of escaping;
|
|
||||||
- Draw background for **hrule** in edit mode;
|
|
||||||
- Support specifying the expanded level of outline;
|
|
||||||
- Support drag&drop a directory to Explorer to open it;
|
|
||||||
- `Ctrl+;` to insert inline code and `Ctrl+J/K` to scroll page in edit mode;
|
|
||||||
- Support YAML front matter in edit mode;
|
|
||||||
- Support searching Explorer root directory;
|
|
||||||
|
|
||||||
## v1.19
|
## v3.12.888
|
||||||
- Support tags for notes;
|
* Fix shortcuts in key sequence with input method (like `Ctrl+G, E`)
|
||||||
- UniversalEntry: support searching tags;
|
* Add line ending settings for config files
|
||||||
- WebView: click an image or diagram to view it in read mode;
|
* FindAndReplace: fix zero-length search
|
||||||
- Add test buttons for PlantUML and Graphviz in settings dialog;
|
* QuickAccess: support folders
|
||||||
- CaptainMode: Y to focus to the edit area;
|
* Upgrade to Qt 5.15.2
|
||||||
|
* Support file associations
|
||||||
|
* NewNoteDialog: remember default file type
|
||||||
|
|
||||||
## v1.18
|
## v3.12.0
|
||||||
- Explorer: fix the crash when no root entry is set;
|
* NotebookExplorer: support separate node explorer
|
||||||
- New dark theme **v_detorte** from a Vim *detorte* theme;
|
* Theme: add user-provided VSCode-Dark theme
|
||||||
- Support maximizing split or distributing splits;
|
* MarkdownEditor: use web to highlight code blocks
|
||||||
- Refine styles and HiDPI support;
|
* MarkdownViewWindow
|
||||||
|
* Add switch for code block line number
|
||||||
|
* Fix ParseToMarkdown `<style>` issue
|
||||||
|
* Add config for overridding MathJax script
|
||||||
|
* SortDialog: fix sorting issue of date
|
||||||
|
* FramelessMainWindow: fix StayOnTop issue
|
||||||
|
|
||||||
## v1.17
|
## v3.11.0
|
||||||
- Add **History** to browse history;
|
* Task: support a simple task system (@tootal)
|
||||||
- Add **Explorer** to browse external files;
|
* Theme: add user-provided Solarized-Dark and Solarized-Light themes
|
||||||
- Support view order in note list;
|
* Export: fix wkhtmltopdf table-of-contents translation
|
||||||
- Support relative path for notebook;
|
* Support equation begin in MathJax
|
||||||
- UniversalEntry
|
* MainWindow: decide DPI on the screen vnote starts
|
||||||
- Fix input method issue on macOS;
|
* Settings: support searching
|
||||||
- Add `j` for listing and searching History;
|
* Fix crash caused by Youdao Dict
|
||||||
- Support customized zoom delta of editor;
|
|
||||||
- Add cache for in-place preview;
|
|
||||||
- Better support for hiDPI;
|
|
||||||
- Lazy initialization;
|
|
||||||
- Support stay-on-top;
|
|
||||||
|
|
||||||
## v1.16
|
## v3.10.1
|
||||||
- Markdown-it: supports specifying image size, emoji, and YAML metadata;
|
* MarkdownEditor: fix view mode issue
|
||||||
- Bug fixes;
|
* Support print
|
||||||
|
* Refine icons
|
||||||
|
|
||||||
## v1.15
|
## v3.10.0
|
||||||
- Support **PlantUML** and **Graphviz**;
|
* MarkdownEditor
|
||||||
- **In-Place Preview** for MathJax, PlantUML, Graphviz, and Flowchart.js;
|
* Support side-by-side edit with preview
|
||||||
- **Live Preview** for diagrams via `Ctrl+E I`;
|
* Support config for highlighting whitespace
|
||||||
- Restore cursor position when recovering pages at startup;
|
* Tag: fix input method issue on macOS
|
||||||
- UniversalEntry
|
|
||||||
- Ctrl+I to expand/collapse current item;
|
|
||||||
- Ctrl+L to go to current item's parent item;
|
|
||||||
- Markdown-it: aware of YAML format metadata in notes;
|
|
||||||
- Show hovered link in status line in read mode;
|
|
||||||
- Export: support embedding images as data URI into HTML pages;
|
|
||||||
|
|
||||||
## v1.14
|
## v3.9.0
|
||||||
- Support **Universal Entry** by `Ctrl+G`;
|
* Remove recycle bin node (now recycle bin is just a simple folder)
|
||||||
- Single click a note in note list to open it in a new tab by default;
|
* Quick Access: support removing items directly
|
||||||
- Translate `Ctrl` in default shortcuts to `Meta` on macOS;
|
* MarkdownEditor
|
||||||
- Do not copy files when import if they locate in current folder;
|
* Support centering images in read mode
|
||||||
|
* Add user.css for user styles in read mode
|
||||||
|
* Add debugger by F12
|
||||||
|
* Support context-sensitive context menu for images and links
|
||||||
|
|
||||||
## v1.13
|
## v3.8.0
|
||||||
- Replace **v_white** theme with **v_native**, which behaves more like native applications;
|
* Support tags
|
||||||
- Support **full-text search**;
|
* Introduce notebook database using SQLITE
|
||||||
- Support `&&` and `||` logics (space-separated keywords are treated as AND);
|
* A perfect frameless main window on Windows
|
||||||
- Enhanced export;
|
* Add switch to control whether store history in notebook
|
||||||
- Support MHTML format;
|
* Refine dock widgets of main window
|
||||||
- Support All-In-One PDF via tool *wkhtmltopdf*;
|
* NotebookExplorer: support scan notebook and import external files
|
||||||
- Support *pandoc* and random tool for custom export;
|
|
||||||
- Support **Word Count** information in both read and edit mode;
|
|
||||||
- Support SavePage action in read mode;
|
|
||||||
- Support *back reference* in replace text via `\1`, `\2`, and so on;
|
|
||||||
- Support sorting in Cart;
|
|
||||||
- Support sorting notes and folders via name or modification date;
|
|
||||||
- Support both `flow` and `flowchart` as the language of *flowchart.js* diagram;
|
|
||||||
- Add PasteAsBlockQuote menu action to paste text as block quote from clipboard;
|
|
||||||
- Add options for Markdown-it to support subscript and superscript;
|
|
||||||
- Better support for 4K display;
|
|
||||||
|
|
||||||
## v1.12
|
## v3.7.0
|
||||||
- Combine `EditNote` and `SaveExitNote` as `EditReadNote` (`Ctrl+T`);
|
* PlantUml/Graphviz: support relative path executable
|
||||||
- Support exporting notes as Markdown, HTML, and PDF;
|
* macOS: support opening file with VNote in Finder
|
||||||
- Support simple search in directory tree, file list, and outline;
|
* Sort notes by name case-insensitively
|
||||||
- Support copying selected text as HTML in edit mode;
|
* Export
|
||||||
- Support copying text to Evernote, OneNote, Word, WeChat Public Account editor and so on;
|
* Support All-in-One in PDF format
|
||||||
- Support auto-save;
|
* Support Custom export format (like Pandoc)
|
||||||
- Support fullscreen mode and hiding menu bar;
|
* Allow minimizing the export dialog and doing export at background
|
||||||
- Support `Ctrl+H/W/U` to delete text in most line edits;
|
* MainWindow: use icon-only bar for docks
|
||||||
- Support zooming in/out in edit mode;
|
* Support update check
|
||||||
- Support MathJax in fenced code block with language `mathjax` specified;
|
* Add shortcuts for CloseOtherTabs and CloseTabsToTheRight
|
||||||
- More shortcuts;
|
* Search: highlight matched items in opened files
|
||||||
- Add **Cart** to collect notes for further processing;
|
* Editor: support specifying line ending
|
||||||
- Output built-in themes on start of VNote;
|
|
||||||
- `Esc` to exit edit mode when Vim mode is disabled;
|
|
||||||
- Support Vim command line for search in read mode;
|
|
||||||
- Support printing;
|
|
||||||
- Single click in file list to open file in current tab, double clicks to open in a new tab;
|
|
||||||
|
|
||||||
## v1.11.1
|
## v3.6.0
|
||||||
- Refine copy function in read mode. Better support for copying and pasting into OneNote or WeChat editor;
|
* Support **Image Host**: GitHub and Gitee
|
||||||
- Do not highlight code blocks without language specified by default;
|
* Add config page for Vi
|
||||||
- Refine themes and styles;
|
|
||||||
- Support foreground for selected/searched word in MDHL style;
|
|
||||||
- Support shortcuts for external programs;
|
|
||||||
- Support resetting VNote;
|
|
||||||
- Cover more scenarios for Chinese translations;
|
|
||||||
|
|
||||||
## v1.11
|
## v3.5.1
|
||||||
- Support themes;
|
* LocationList: fix recently introduced regression when highlighting segments of text
|
||||||
- Three built-in mordern themes;
|
|
||||||
- One dark mode theme;
|
|
||||||
- Vim mode
|
|
||||||
- Support block cursor in Normal/Visual mode;
|
|
||||||
- `=` to auto-indent selected lines as the first line;
|
|
||||||
- Support custom external editors to open notes;
|
|
||||||
- Enable `Ctrl+C`/`Ctrl+V` in Vim mode to copy/paste;
|
|
||||||
- Support Flash Page to record ideas quickly;
|
|
||||||
- Support previewing inline images;
|
|
||||||
|
|
||||||
## v1.10
|
## v3.5.0
|
||||||
- Migrate to Qt 5.9.1;
|
* Support History
|
||||||
- Support Compact mode in main window;
|
* ViewArea
|
||||||
- Update icons;
|
* `Ctrl+G, H/J/K/L` to navigate through ViewSplits
|
||||||
- Support custom startup pages;
|
* `Ctrl+G, Shift+H/J/K/L` to move ViewWindow across ViewSplits
|
||||||
- Remove obsolete title marker when inserting new one;
|
* MarkdownEditor
|
||||||
- Support Magic Words;
|
* Add configs for in-place preview sources
|
||||||
- Vim mode
|
* Add a tool button to disable in-place preview
|
||||||
- Share registers among all tabs;
|
* Vi: support align and indent commands `=` and `>`
|
||||||
- Support `Ctrl+O` in Insert mode;
|
* LocationList: highlight matched text segments
|
||||||
- Add "Code Block", "Insert Link", and "Insert Image" tool bar buttons;
|
* SelectDialog: support shortcuts (such as Rich Paste)
|
||||||
- Support `Ctrl+Shift+T` to recover last closed tabs;
|
|
||||||
- Support view read-only files in edit mode;
|
|
||||||
- Refactor editor for speed;
|
|
||||||
- Support templates when creating notes;
|
|
||||||
- Support snippets;
|
|
||||||
- Support file change check;
|
|
||||||
- Support backup file (save changes automatically);
|
|
||||||
|
|
||||||
## v1.9
|
## v3.4.0
|
||||||
- Support attachments of notes.
|
* Support Snippet
|
||||||
- Add recycle bin to notebook to hold deleted files.
|
* `Ctrl+G S` to insert a snippet
|
||||||
- Refine Vim mode:
|
* `%snippet_name%` to insert a snippet (the legacy Magic Word)
|
||||||
- Support J and gJ to join line;
|
* Snippet is supported in some dialogs (such as creating a new note)
|
||||||
- Support S, {, and };
|
* Support note template (snippet is supported)
|
||||||
- <leader>w to save note;
|
* Remove `'` and `"` from auot-brackets
|
||||||
- Fix Y and D actions in Visual mode.
|
|
||||||
- Support AppImage package for Linux.
|
|
||||||
- More responsive and efficient syntax highlight and image preview.
|
|
||||||
- More pleasant line distance.
|
|
||||||
- More natural interaction of folder and note management.
|
|
||||||
- Support inserting note name as title.
|
|
||||||
- Support custom default mode to open a note.
|
|
||||||
- Support auto heading sequence.
|
|
||||||
- Support color column in fenced code block in edit mode.
|
|
||||||
- Support line number in code block in both read and edit mode.
|
|
||||||
- Support created time and modified time of notes, folders, and notebooks.
|
|
||||||
- Support custom Markdown-it options, such as auto line break.
|
|
||||||
- Confirm when cleaning up unused images.
|
|
||||||
- Support custom Mathjax location.
|
|
||||||
- Support custom style for code block highlights in read mode.
|
|
||||||
- Double click on a tab to close it.
|
|
||||||
|
|
||||||
## v1.8
|
## v3.3.0
|
||||||
- Support editing external files. VNote could open files from command line.
|
* Editor: support auto indent, auto list
|
||||||
- Support drag-and-drop to open external files.
|
* Support opening notes with external programs
|
||||||
- Refine tab context menu.
|
* Add a delay after code/math blocks update before preview
|
||||||
- Support system tray icon.
|
|
||||||
- Refine Vim mode.
|
|
||||||
- Make all tool buttons always visible and smaller.
|
|
||||||
- Support custom file type suffix.
|
|
||||||
- Make the name of notebook/folder/note case-insensitive.
|
|
||||||
- Support links to internal notes in notes.
|
|
||||||
|
|
||||||
## v1.7
|
## v3.2.0
|
||||||
- ATTENTION: please add font-size option to the "editor" section of your custom MDHL style.
|
* Support local PlantUml and Graphviz rendering
|
||||||
- Refine Vim mode (more functions, please refer to the shortcuts help).
|
* Add shortcuts to tab navigation in ViewSplit
|
||||||
- Support Find in Vim mode.
|
* Editor: support auto bracket and overridding font family
|
||||||
- Refine tab context menu.
|
|
||||||
- Support Flowchart.js for flowchart.
|
|
||||||
- Add toolbar for common text edit functions.
|
|
||||||
- Support line number (both absolute and relative) in edit mode.
|
|
||||||
- Support custom shortcuts.
|
|
||||||
- Support [[, ]], [], ][, [{, ]} to navigate through titles in both edit and read mode.
|
|
||||||
- Many minor bug fixes.
|
|
||||||
|
|
||||||
## v1.6
|
## v3.1.0
|
||||||
- Support simple but powerful **Vim mode**.
|
* Support Japanese translation (Thanks @miurahr)
|
||||||
- Change the shortcut of ExitAndRead from `Ctrl+R` to `Ctrl+T`.
|
* MarkdownEditor: guess image suffix when fetching to local
|
||||||
- Add a edit status indicator in the status bar.
|
* Refine read mode styles (Thanks @heartnn)
|
||||||
- Dragging mouse with Ctrl and left button pressed to scroll in read and edit mode.
|
* Support recovering edit session on start
|
||||||
- Refine highlighting cursor line.
|
* Support recovering notebook explorer session on start
|
||||||
- Support subscript, superscript and footnote in markdown-it renderer.
|
* Support Flash Page
|
||||||
- Refactor outline logics to not show extra [EMPTY] headers.
|
* Support Quick Access
|
||||||
- Handle HTML comments correctly.
|
* Allow to keep docks (like Outline) when expanding content area
|
||||||
- Provide a default root folder when adding notebooks.
|
|
||||||
- Support check for updates.
|
|
||||||
- Redraw app icons.
|
|
||||||
- Many minor bug fixes.
|
|
||||||
|
|
||||||
## v1.5
|
## v3.0.1
|
||||||
- Support logging in release mode.
|
* Support spell check via Hunspell
|
||||||
- Fix Chinese font matching in mdhl.
|
* `Ctrl+Alt+F` to trigger full-text search
|
||||||
- Fix VimagePreviewer to support optional title.
|
* Auto focus to the input widget when activating full-text search
|
||||||
- Refactor local image folder logics.
|
* Fix Expand Content Area with panels
|
||||||
- Support custom local image folder for both notebook scope and global scope.
|
|
||||||
- Support constraining the width of images in read mode.
|
|
||||||
- Fix and refine default style.
|
|
||||||
- Centering the images and display the alt text as caption in read mode.
|
|
||||||
- Support exporting a single note as PDF file.
|
|
||||||
- Add "Open File Location" menu item in folder tree and note list.
|
|
||||||
- Support highlighting trailing space.
|
|
||||||
|
|
||||||
## v1.4
|
## v3.0.0-beta.11
|
||||||
- Use `_vnote.json` as the config file.
|
* Full-text search
|
||||||
- More user friendly messages.
|
|
||||||
- Delete notebook by deleting root directories one by one.
|
|
||||||
- Refactor image preview logics to support previewing all images in edit mode.
|
|
||||||
- Support constraining the width of previewed images to the edit window.
|
|
||||||
- bugfix.
|
|
||||||
|
|
||||||
## v1.3
|
## v3.0.0-beta.10
|
||||||
- Support code block syntax highlight in edit mode.
|
* Show more tips
|
||||||
- A more pleasant AutoIndent and AutoList.
|
* Add exclude patterns for external nodes
|
||||||
- `Ctrl+<Num>` instead of `Ctrl+Alt+<Num>` to insert title.
|
* Add command line parser and support opening files from command line
|
||||||
- Support custom Markdown CSS styles and editor styles.
|
* Update Mermaid.js to 8.9.1
|
||||||
|
* Support exporting current note
|
||||||
|
* Add ExpandAll to node explorer
|
||||||
|
|
||||||
## v1.2
|
## v3.0.0-beta.9
|
||||||
- Support **MathJax**.
|
* Fix crash when exporting external files
|
||||||
- Fix a crash on macOS.
|
* Support manual sorting folders and notes
|
||||||
- Change default font family.
|
* Support showing external files in notebook
|
||||||
- Refine tab order.
|
|
||||||
- Better support for HiDPI.
|
|
||||||
- Support zoom in/out page when reading.
|
|
||||||
- Introduce **Captain Mode** and **Navigation Mode**.
|
|
||||||
- A more user friendly popup opened notes list.
|
|
||||||
- Support jumping to specified tab efficiently by num keys.
|
|
||||||
- Add shortcuts documentation.
|
|
||||||
- AutoList and AutoIndent.
|
|
||||||
|
|
||||||
## v1.1
|
## v3.0.0-beta.8
|
||||||
- Refine messages and dialogs. Add Chinese translations.
|
* Note explorer supports different view orders
|
||||||
- A new application icon.
|
* Fix `Ctrl+V` paste in editor
|
||||||
- Support install target for Linux.
|
* Fix Linux HTTPS crash bug
|
||||||
- Continuous build and deployment for Linux, macOS, and Windows.
|
* Add button to show/hide recycle bin node
|
||||||
- Support both X64 and x86 version of Windows.
|
* Other small fixes
|
||||||
- Add `.md` suffix automatically when creating a note.
|
|
||||||
- A more user friendly insert dialog.
|
## v3.0.0-beta.7
|
||||||
- Support **Mermaid** diagram.
|
* Support export to Markdown/HTML/PDF
|
||||||
- Add **markdown-it** as the default renderer. Support task list.
|
* Support base level 1/2/3 for section number in read mode
|
||||||
|
* Support opening link to folder in read mode
|
||||||
|
|
||||||
|
## v3.0.0-beta.6
|
||||||
|
* Add theme **pure** for light mode
|
||||||
|
* Small fixes
|
||||||
|
|
||||||
|
## v3.0.0-beta.5
|
||||||
|
* Refine themes
|
||||||
|
* Add section number style "1.1" and "1.1.", and use the later as default
|
||||||
|
* Support indentation of first line of paragraph in read mode
|
||||||
|
* Add file type combo box in NewNoteDialog
|
||||||
|
* Add "Insert Mark" in tool bar
|
||||||
|
* Support **Smart Table**
|
||||||
|
* Support `*.rmd` as Markdown suffix
|
||||||
|
* Turn on system title bar by default
|
||||||
|
* Enable AutoBreak by default
|
||||||
|
|
||||||
|
## v3.0.0-beta.4
|
||||||
|
* Add theme **moonlight** for dark mode
|
||||||
|
* Add shortcuts for split and workspace
|
||||||
|
* Bug fix
|
||||||
|
* More configs in Settings dialog for Markdown viewer
|
||||||
|
* Support section number in edit mode (without the dot suffix)
|
||||||
|
* Support link jump in Markdown viewer
|
||||||
|
* Use socket for single instance guard
|
||||||
|
|
||||||
|
## v3.0.0-beta.3
|
||||||
|
* Support `[TOC]`
|
||||||
|
* Fix MathJax
|
||||||
|
* Add shortcut for StayOnTop
|
||||||
|
* Add Markdown guide and shortcuts guide
|
||||||
|
* Show hovered link in read mode
|
||||||
|
* Smart Input Method in Vi mode
|
||||||
|
* Bug fix in Markdown editor when finding current heading index
|
||||||
|
* Add custom Info.plist on macOS
|
||||||
|
* Support minimizing to system tray
|
||||||
|
* Support restart
|
||||||
|
* Add read and edit in Markdown ViewWindow
|
||||||
|
* Add Chinese translations
|
||||||
|
|
||||||
|
## v3.0.0-beta.2
|
||||||
|
* Fix Import Legacy Notebook
|
||||||
|
* Refine toolbar
|
||||||
|
* Fix Outline viewer
|
||||||
|
6
debian/changelog
vendored
@ -1,6 +0,0 @@
|
|||||||
vnote (1.8-0ubuntu1) zesty; urgency=medium
|
|
||||||
|
|
||||||
* Initial release
|
|
||||||
* Adjusted the Makefile to fix $(DESTDIR) problems.
|
|
||||||
|
|
||||||
-- Le Tan <tamlokveer@gmail.com> Sun, 20 Aug 2017 09:32:22 +0800
|
|
1
debian/compat
vendored
@ -1 +0,0 @@
|
|||||||
9
|
|
17
debian/control
vendored
@ -1,17 +0,0 @@
|
|||||||
Source: vnote
|
|
||||||
Section: editors
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: Le Tan <tamlokveer@gmail.com>
|
|
||||||
Build-Depends: debhelper (>=9), qt5-default (>= 5.7.1), libqt5svg5-dev, qtwebengine5-dev, libqt5webchannel5-dev, qtpositioning5-dev
|
|
||||||
Standards-Version: 3.9.6
|
|
||||||
Homepage: https://tamlok.github.io/vnote
|
|
||||||
Vcs-Browser: https://github.com/tamlok/vnote.git
|
|
||||||
|
|
||||||
Package: vnote
|
|
||||||
Architecture: any
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libQt5WebEngineWidgets (>= 5.7.1), libQt5WebEngineCore, libQt5PrintSupport, libQt5Widgets, libQt5Gui, libQt5WebChannel, libQt5Network, libQt5Core
|
|
||||||
Suggests: libssl
|
|
||||||
Description: A Vim-inspired note-taking application for Markdown.
|
|
||||||
VNote is a cross-platform, free note-taking application, designed especially
|
|
||||||
for Markdown. VNote provides both simple note management and pleasant Markdown
|
|
||||||
edit experience.
|
|
7
debian/copyright
vendored
@ -1,7 +0,0 @@
|
|||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Upstream-Name: vnote
|
|
||||||
Source: https://tamlok.github.io/vnote
|
|
||||||
|
|
||||||
Files: *
|
|
||||||
Copyright: 2017 Le Tan <tamlokveer@gmail.com>
|
|
||||||
License: MIT License
|
|
28
debian/rules
vendored
@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
# See debhelper(7) (uncomment to enable)
|
|
||||||
# output every command that modifies files on the build system.
|
|
||||||
#export DH_VERBOSE = 1
|
|
||||||
|
|
||||||
|
|
||||||
# see FEATURE AREAS in dpkg-buildflags(1)
|
|
||||||
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
|
||||||
|
|
||||||
# see ENVIRONMENT in dpkg-buildflags(1)
|
|
||||||
# package maintainers to append CFLAGS
|
|
||||||
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
|
||||||
# package maintainers to append LDFLAGS
|
|
||||||
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
|
||||||
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@
|
|
||||||
|
|
||||||
|
|
||||||
# dh_make generated override targets
|
|
||||||
# This is example for Cmake (See https://bugs.debian.org/641051 )
|
|
||||||
#override_dh_auto_configure:
|
|
||||||
# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
|
|
||||||
override_dh_shlibdeps:
|
|
||||||
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
|
|
||||||
|
|
||||||
export QT_SELECT=qt5
|
|
1
debian/source/format
vendored
@ -1 +0,0 @@
|
|||||||
3.0 (quilt)
|
|
@ -1 +0,0 @@
|
|||||||
|
|
1
hoedown
@ -1 +0,0 @@
|
|||||||
Subproject commit e63d2160a7d9895defc253d933b58a83ac54f81a
|
|
2
libs/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
add_subdirectory(QHotkey)
|
||||||
|
add_subdirectory(vtextedit)
|
1
libs/QHotkey
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 8abe0b2280533af57f423f5785acc4d9d4d73ab8
|
1
libs/vtextedit
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 50b1421793af3882ddc62ad4e6cf5537e1d7906f
|
24
package/QtWebEngineProcess.entitlements.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.debugger</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.inherit</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
package/banner_text.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
24
package/entitlements.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.debugger</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.inherit</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
110
package/lgpl-3.0.rtf
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
{\rtf1\ansi\deff3\adeflang1025
|
||||||
|
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq0\fcharset128 Helvetica{\*\falt Arial};}{\f6\fnil\fprq2\fcharset0 Droid Sans Fallback;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
|
||||||
|
{\colortbl;\red0\green0\blue0;\red0\green0\blue128;\red128\green128\blue128;}
|
||||||
|
{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033 Normal;}
|
||||||
|
{\*\cs15\snext15\cf2\ul\ulc0\langfe255\alang255\lang255 Internet Link;}
|
||||||
|
{\s16\sbasedon0\snext17\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f4\fs28 Heading;}
|
||||||
|
{\s17\sbasedon0\snext17\sl288\slmult1\sb0\sa140 Text Body;}
|
||||||
|
{\s18\sbasedon17\snext18\sl288\slmult1\sb0\sa140\dbch\af8 List;}
|
||||||
|
{\s19\sbasedon0\snext19\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;}
|
||||||
|
{\s20\sbasedon0\snext20\noline\dbch\af8 Index;}
|
||||||
|
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67241986}}\deftab720
|
||||||
|
\viewscale100
|
||||||
|
{\*\pgdsctbl
|
||||||
|
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
|
||||||
|
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
|
||||||
|
\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs28\loch\f5
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Version 3, 29 June 2007}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Copyright \u169\'3f 2007 Free Software Foundation, Inc. <}{{\field{\*\fldinst HYPERLINK "https://fsf.org/" }{\fldrslt {\cf2\ul\ulc0\langfe255\alang255\lang255\ul\ulc0\rtlch \ltrch\loch\loch\f5
|
||||||
|
https://fsf.org/}{}}}\rtlch \ltrch\loch\loch\f5
|
||||||
|
>}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
0. Additional Definitions.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
As used herein, \uc2 \u8220\'81\'67this License\u8221\'81\'68 refers to version 3 of the GNU Lesser General Public License, and the \u8220\'81\'67GNU GPL\u8221\'81\'68 refers to version 3 of the GNU General Public License.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\f5
|
||||||
|
\uc2 \u8220\'81\'67\uc1 }{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The Library\uc2 \u8221\'81\'68 refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
An \uc2 \u8220\'81\'67Application\u8221\'81\'68 is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
A \uc2 \u8220\'81\'67Combined Work\u8221\'81\'68 is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the \u8220\'81\'67Linked Version\u8221\'81\'68.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The \uc2 \u8220\'81\'67Minimal Corresponding Source\u8221\'81\'68 for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The \uc2 \u8220\'81\'67Corresponding Application Code\u8221\'81\'68 for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
1. Exception to Section 3 of the GNU GPL.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
2. Conveying Modified Versions.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Accompany the object code with a copy of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
4. Combined Works.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Accompany the Combined Work with a copy of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab d) Do one of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li720\ri0\lin720\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8211\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li720\ri0\lin720\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8211\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
5. Combined Libraries.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License \uc2 \u8220\'81\'67or any later version\u8221\'81\'68 applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.}
|
||||||
|
\par }
|
2
package/qt.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[Platforms]
|
||||||
|
WindowsArguments = fontengine=freetype
|
BIN
package/wix_banner.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
package/wix_dialog.png
Normal file
After Width: | Height: | Size: 12 KiB |
@ -1,18 +0,0 @@
|
|||||||
# PEG-Markdown-Highlight
|
|
||||||
# Github: https://github.com/ali-rantakari/peg-markdown-highlight
|
|
||||||
|
|
||||||
QT -= core gui
|
|
||||||
|
|
||||||
TARGET = peg-highlight
|
|
||||||
|
|
||||||
TEMPLATE = lib
|
|
||||||
|
|
||||||
CONFIG += warn_off
|
|
||||||
CONFIG += staticlib
|
|
||||||
|
|
||||||
SOURCES += pmh_parser.c \
|
|
||||||
pmh_styleparser.c
|
|
||||||
|
|
||||||
HEADERS += pmh_parser.h \
|
|
||||||
pmh_styleparser.h \
|
|
||||||
pmh_definitions.h
|
|
@ -1,138 +0,0 @@
|
|||||||
/* PEG Markdown Highlight
|
|
||||||
* Copyright 2011-2016 Ali Rantakari -- http://hasseg.org
|
|
||||||
* Licensed under the GPL2+ and MIT licenses (see LICENSE for more info).
|
|
||||||
*
|
|
||||||
* pmh_definitions.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef pmh_MARKDOWN_DEFINITIONS
|
|
||||||
#define pmh_MARKDOWN_DEFINITIONS
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Global definitions for the parser.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Element types.
|
|
||||||
*
|
|
||||||
* The first (documented) ones are language element types.
|
|
||||||
*
|
|
||||||
* The last (non-documented) ones are utility types used
|
|
||||||
* by the parser itself.
|
|
||||||
*
|
|
||||||
* \sa pmh_element
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
pmh_LINK, /**< Explicit link */
|
|
||||||
pmh_AUTO_LINK_URL, /**< Implicit URL link */
|
|
||||||
pmh_AUTO_LINK_EMAIL, /**< Implicit email link */
|
|
||||||
pmh_IMAGE, /**< Image definition */
|
|
||||||
pmh_CODE, /**< Code (inline) */
|
|
||||||
pmh_HTML, /**< HTML */
|
|
||||||
pmh_HTML_ENTITY, /**< HTML special entity definition */
|
|
||||||
pmh_EMPH, /**< Emphasized text */
|
|
||||||
pmh_STRONG, /**< Strong text */
|
|
||||||
pmh_LIST_BULLET, /**< Bullet for an unordered list item */
|
|
||||||
pmh_LIST_ENUMERATOR, /**< Enumerator for an ordered list item */
|
|
||||||
pmh_COMMENT, /**< (HTML) Comment */
|
|
||||||
|
|
||||||
// Code assumes that pmh_H1-6 are in order.
|
|
||||||
pmh_H1, /**< Header, level 1 */
|
|
||||||
pmh_H2, /**< Header, level 2 */
|
|
||||||
pmh_H3, /**< Header, level 3 */
|
|
||||||
pmh_H4, /**< Header, level 4 */
|
|
||||||
pmh_H5, /**< Header, level 5 */
|
|
||||||
pmh_H6, /**< Header, level 6 */
|
|
||||||
|
|
||||||
pmh_BLOCKQUOTE, /**< Blockquote */
|
|
||||||
pmh_VERBATIM, /**< Verbatim (e.g. block of code) */
|
|
||||||
pmh_HTMLBLOCK, /**< Block of HTML */
|
|
||||||
pmh_HRULE, /**< Horizontal rule */
|
|
||||||
pmh_REFERENCE, /**< Reference */
|
|
||||||
pmh_FENCEDCODEBLOCK, /**< Fenced code block */
|
|
||||||
pmh_NOTE, /**< Note */
|
|
||||||
pmh_STRIKE, /**< Strike-through */
|
|
||||||
pmh_FRONTMATTER, /**< Front matter */
|
|
||||||
pmh_DISPLAYFORMULA, /**< Math display formula */
|
|
||||||
pmh_INLINEEQUATION, /**< Math inline equation */
|
|
||||||
pmh_MARK, /**< HTML <mark> tag content */
|
|
||||||
pmh_TABLE, /**< GFM table */
|
|
||||||
pmh_TABLEHEADER, /**< GFM table header */
|
|
||||||
pmh_TABLEBORDER, /**< GFM table border | */
|
|
||||||
|
|
||||||
// Utility types used by the parser itself:
|
|
||||||
|
|
||||||
// List of pmh_RAW element lists, each to be processed separately from
|
|
||||||
// others (for each element in linked lists of this type, `children` points
|
|
||||||
// to a linked list of pmh_RAW elements):
|
|
||||||
pmh_RAW_LIST, /**< Internal to parser. Please ignore. */
|
|
||||||
|
|
||||||
// Span marker for positions in original input to be post-processed
|
|
||||||
// in a second parsing step:
|
|
||||||
pmh_RAW, /**< Internal to parser. Please ignore. */
|
|
||||||
|
|
||||||
// Additional text to be parsed along with spans in the original input
|
|
||||||
// (these may be added to linked lists of pmh_RAW elements):
|
|
||||||
pmh_EXTRA_TEXT, /**< Internal to parser. Please ignore. */
|
|
||||||
|
|
||||||
// Separates linked lists of pmh_RAW elements into parts to be processed
|
|
||||||
// separate from each other:
|
|
||||||
pmh_SEPARATOR, /**< Internal to parser. Please ignore. */
|
|
||||||
|
|
||||||
// Placeholder element used while parsing:
|
|
||||||
pmh_NO_TYPE, /**< Internal to parser. Please ignore. */
|
|
||||||
|
|
||||||
// Linked list of *all* elements created while parsing:
|
|
||||||
pmh_ALL /**< Internal to parser. Please ignore. */
|
|
||||||
} pmh_element_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Number of types in pmh_element_type.
|
|
||||||
* \sa pmh_element_type
|
|
||||||
*/
|
|
||||||
#define pmh_NUM_TYPES 39
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Number of *language element* types in pmh_element_type.
|
|
||||||
* \sa pmh_element_type
|
|
||||||
*/
|
|
||||||
#define pmh_NUM_LANG_TYPES (pmh_NUM_TYPES - 6)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A Language element occurrence.
|
|
||||||
*/
|
|
||||||
struct pmh_Element
|
|
||||||
{
|
|
||||||
pmh_element_type type; /**< \brief Type of element */
|
|
||||||
unsigned long pos; /**< \brief Unicode code point offset marking the
|
|
||||||
beginning of this element in the
|
|
||||||
input. */
|
|
||||||
unsigned long end; /**< \brief Unicode code point offset marking the
|
|
||||||
end of this element in the input. */
|
|
||||||
struct pmh_Element *next; /**< \brief Next element in list */
|
|
||||||
char *label; /**< \brief Label (for links and references) */
|
|
||||||
char *address; /**< \brief Address (for links and references) */
|
|
||||||
};
|
|
||||||
typedef struct pmh_Element pmh_element;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Bitfield enumeration of supported Markdown extensions.
|
|
||||||
*/
|
|
||||||
enum pmh_extensions
|
|
||||||
{
|
|
||||||
pmh_EXT_NONE = 0, /**< No extensions */
|
|
||||||
pmh_EXT_NOTES = (1 << 0), /**< Footnote syntax:
|
|
||||||
http://pandoc.org/README.html#footnotes */
|
|
||||||
pmh_EXT_STRIKE = (1 << 1), /**< Strike-through syntax:
|
|
||||||
http://pandoc.org/README.html#strikeout */
|
|
||||||
pmh_EXT_FRONTMATTER = (1 << 2), /**< YAML meta data */
|
|
||||||
pmh_EXT_MATH = (1 << 3), /**< Math */
|
|
||||||
pmh_EXT_MARK = (1 << 4), /**< HTML <mark> tag content */
|
|
||||||
pmh_EXT_MATH_RAW = (1 << 5), /**< Math in format \begin and \end */
|
|
||||||
pmh_EXT_TABLE = (1 << 6), /** GFM Table */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,91 +0,0 @@
|
|||||||
/* PEG Markdown Highlight
|
|
||||||
* Copyright 2011-2016 Ali Rantakari -- http://hasseg.org
|
|
||||||
* Licensed under the GPL2+ and MIT licenses (see LICENSE for more info).
|
|
||||||
*
|
|
||||||
* pmh_parser.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef Q_CC_GNU
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Parser public interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#include <stdbool.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "pmh_definitions.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Parse Markdown text, return elements
|
|
||||||
*
|
|
||||||
* Parses the given Markdown text and returns the results as an
|
|
||||||
* array of linked lists of elements, indexed by type.
|
|
||||||
*
|
|
||||||
* \param[in] text The Markdown text to parse for highlighting.
|
|
||||||
* \param[in] extensions The extensions to use in parsing (a bitfield
|
|
||||||
* of pmh_extensions values).
|
|
||||||
* \param[out] out_result A pmh_element array, indexed by type, containing
|
|
||||||
* the results of the parsing (linked lists of elements).
|
|
||||||
* You must pass this to pmh_free_elements() when it's
|
|
||||||
* not needed anymore.
|
|
||||||
*
|
|
||||||
* \sa pmh_element_type
|
|
||||||
*/
|
|
||||||
void pmh_markdown_to_elements(char *text, int extensions,
|
|
||||||
pmh_element **out_result[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Sort elements in list by start offset.
|
|
||||||
*
|
|
||||||
* Sorts the linked lists of elements in the list returned by
|
|
||||||
* pmh_markdown_to_elements() by their start offsets (pos).
|
|
||||||
*
|
|
||||||
* \param[in] element_lists Array of linked lists of elements (output
|
|
||||||
* from pmh_markdown_to_elements()).
|
|
||||||
*
|
|
||||||
* \sa pmh_markdown_to_elements
|
|
||||||
* \sa pmh_element::pos
|
|
||||||
*/
|
|
||||||
void pmh_sort_elements_by_pos(pmh_element *element_lists[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Free pmh_element array
|
|
||||||
*
|
|
||||||
* Frees an pmh_element array returned by pmh_markdown_to_elements().
|
|
||||||
*
|
|
||||||
* \param[in] elems The pmh_element array resulting from calling
|
|
||||||
* pmh_markdown_to_elements().
|
|
||||||
*
|
|
||||||
* \sa pmh_markdown_to_elements
|
|
||||||
*/
|
|
||||||
void pmh_free_elements(pmh_element **elems);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Get element type name
|
|
||||||
*
|
|
||||||
* \param[in] type The type value to get the name for.
|
|
||||||
*
|
|
||||||
* \return The name of the given type as a null-terminated string.
|
|
||||||
*
|
|
||||||
* \sa pmh_element_type
|
|
||||||
*/
|
|
||||||
char *pmh_element_name_from_type(pmh_element_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Get element type from a name
|
|
||||||
*
|
|
||||||
* \param[in] name The name of the type.
|
|
||||||
*
|
|
||||||
* \return The element type corresponding to the given name.
|
|
||||||
*
|
|
||||||
* \sa pmh_element_type
|
|
||||||
*/
|
|
||||||
pmh_element_type pmh_element_type_from_name(char *name);
|
|
||||||
|
|
@ -1,937 +0,0 @@
|
|||||||
/* PEG Markdown Highlight
|
|
||||||
* Copyright 2011-2016 Ali Rantakari -- http://hasseg.org
|
|
||||||
* Licensed under the GPL2+ and MIT licenses (see LICENSE for more info).
|
|
||||||
*
|
|
||||||
* styleparser.c
|
|
||||||
*
|
|
||||||
* Parser for custom syntax highlighting stylesheets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "pmh_styleparser.h"
|
|
||||||
#include "pmh_parser.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if pmh_DEBUG_OUTPUT
|
|
||||||
#define pmhsp_PRINTF(x, ...) fprintf(stderr, x, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define pmhsp_PRINTF(x, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// vasprintf is not in the C standard nor in POSIX so we provide our own
|
|
||||||
static int our_vasprintf(char **strptr, const char *fmt, va_list argptr)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
va_list argptr2;
|
|
||||||
*strptr = NULL;
|
|
||||||
|
|
||||||
va_copy(argptr2, argptr);
|
|
||||||
ret = vsnprintf(NULL, 0, fmt, argptr2);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
*strptr = (char *)malloc(ret+1);
|
|
||||||
if (*strptr == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
va_copy(argptr2, argptr);
|
|
||||||
ret = vsnprintf(*strptr, ret+1, fmt, argptr2);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing context data
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *input;
|
|
||||||
void (*error_callback)(char*,int,void*);
|
|
||||||
void *error_callback_context;
|
|
||||||
int styles_pos;
|
|
||||||
pmh_style_collection *styles;
|
|
||||||
} style_parser_data;
|
|
||||||
|
|
||||||
typedef struct raw_attribute
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
char *value;
|
|
||||||
int line_number;
|
|
||||||
struct raw_attribute *next;
|
|
||||||
} raw_attribute;
|
|
||||||
|
|
||||||
static raw_attribute *new_raw_attribute(char *name, char *value,
|
|
||||||
int line_number)
|
|
||||||
{
|
|
||||||
raw_attribute *v = (raw_attribute *)malloc(sizeof(raw_attribute));
|
|
||||||
v->name = name;
|
|
||||||
v->value = value;
|
|
||||||
v->line_number = line_number;
|
|
||||||
v->next = NULL;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_raw_attributes(raw_attribute *list)
|
|
||||||
{
|
|
||||||
raw_attribute *cur = list;
|
|
||||||
while (cur != NULL)
|
|
||||||
{
|
|
||||||
raw_attribute *pattr = NULL;
|
|
||||||
if (cur->name != NULL) free(cur->name);
|
|
||||||
if (cur->value != NULL) free(cur->value);
|
|
||||||
pattr = cur;
|
|
||||||
cur = cur->next;
|
|
||||||
free(pattr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void report_error(style_parser_data *p_data,
|
|
||||||
int line_number, char *str, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
if (p_data->error_callback == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(argptr, str);
|
|
||||||
char *errmsg;
|
|
||||||
our_vasprintf(&errmsg, str, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
p_data->error_callback(errmsg, line_number,
|
|
||||||
p_data->error_callback_context);
|
|
||||||
free(errmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *trim_str(char *str)
|
|
||||||
{
|
|
||||||
while (isspace(*str))
|
|
||||||
str++;
|
|
||||||
if (*str == '\0')
|
|
||||||
return str;
|
|
||||||
char *end = str + strlen(str) - 1;
|
|
||||||
while (end > str && isspace(*end))
|
|
||||||
end--;
|
|
||||||
*(end+1) = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *trim_str_dup(char *str)
|
|
||||||
{
|
|
||||||
size_t start = 0;
|
|
||||||
while (isspace(*(str + start)))
|
|
||||||
start++;
|
|
||||||
size_t end = strlen(str) - 1;
|
|
||||||
while (start < end && isspace(*(str + end)))
|
|
||||||
end--;
|
|
||||||
|
|
||||||
size_t len = end - start + 1;
|
|
||||||
char *ret = (char *)malloc(sizeof(char)*len + 1);
|
|
||||||
*ret = '\0';
|
|
||||||
strncat(ret, (str + start), len);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *strcpy_lower(char *str)
|
|
||||||
{
|
|
||||||
char *low = strdup(str);
|
|
||||||
int i;
|
|
||||||
int len = strlen(str);
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
*(low+i) = tolower(*(low+i));
|
|
||||||
return low;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *standardize_str(char *str)
|
|
||||||
{
|
|
||||||
return strcpy_lower(trim_str(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static pmh_attr_argb_color *new_argb_color(int r, int g, int b, int a)
|
|
||||||
{
|
|
||||||
pmh_attr_argb_color *c = (pmh_attr_argb_color *)
|
|
||||||
malloc(sizeof(pmh_attr_argb_color));
|
|
||||||
c->red = r; c->green = g; c->blue = b; c->alpha = a;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
static pmh_attr_argb_color *new_argb_from_hex(long long hex, bool has_alpha)
|
|
||||||
{
|
|
||||||
// 0xaarrggbb
|
|
||||||
int a = has_alpha ? ((hex >> 24) & 0xFF) : 255;
|
|
||||||
int r = ((hex >> 16) & 0xFF);
|
|
||||||
int g = ((hex >> 8) & 0xFF);
|
|
||||||
int b = (hex & 0xFF);
|
|
||||||
return new_argb_color(r,g,b,a);
|
|
||||||
}
|
|
||||||
static pmh_attr_argb_color *new_argb_from_hex_str(style_parser_data *p_data,
|
|
||||||
int attr_line_number,
|
|
||||||
char *str)
|
|
||||||
{
|
|
||||||
// "aarrggbb"
|
|
||||||
int len = strlen(str);
|
|
||||||
if (len != 6 && len != 8) {
|
|
||||||
report_error(p_data, attr_line_number,
|
|
||||||
"Value '%s' is not a valid color value: it should be a "
|
|
||||||
"hexadecimal number, 6 or 8 characters long.",
|
|
||||||
str);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
char *endptr = NULL;
|
|
||||||
long long num = strtoll(str, &endptr, 16);
|
|
||||||
if (*endptr != '\0') {
|
|
||||||
report_error(p_data, attr_line_number,
|
|
||||||
"Value '%s' is not a valid color value: the character "
|
|
||||||
"'%c' is invalid. The color value should be a hexadecimal "
|
|
||||||
"number, 6 or 8 characters long.",
|
|
||||||
str, *endptr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return new_argb_from_hex(num, (len == 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
static pmh_attr_value *new_attr_value()
|
|
||||||
{
|
|
||||||
return (pmh_attr_value *)malloc(sizeof(pmh_attr_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
static pmh_attr_font_styles *new_font_styles()
|
|
||||||
{
|
|
||||||
pmh_attr_font_styles *ret = (pmh_attr_font_styles *)
|
|
||||||
malloc(sizeof(pmh_attr_font_styles));
|
|
||||||
ret->italic = false;
|
|
||||||
ret->bold = false;
|
|
||||||
ret->underlined = false;
|
|
||||||
ret->strikeout = false;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pmh_attr_font_size *new_font_size()
|
|
||||||
{
|
|
||||||
pmh_attr_font_size *ret = (pmh_attr_font_size *)
|
|
||||||
malloc(sizeof(pmh_attr_font_size));
|
|
||||||
ret->is_relative = false;
|
|
||||||
ret->size_pt = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pmh_style_attribute *new_attr(char *name, pmh_attr_type type)
|
|
||||||
{
|
|
||||||
pmh_style_attribute *attr = (pmh_style_attribute *)malloc(sizeof(pmh_style_attribute));
|
|
||||||
attr->name = strdup(name);
|
|
||||||
attr->type = type;
|
|
||||||
attr->next = NULL;
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_style_attributes(pmh_style_attribute *list)
|
|
||||||
{
|
|
||||||
pmh_style_attribute *cur = list;
|
|
||||||
while (cur != NULL)
|
|
||||||
{
|
|
||||||
if (cur->name != NULL)
|
|
||||||
free(cur->name);
|
|
||||||
if (cur->value != NULL)
|
|
||||||
{
|
|
||||||
if (cur->type == pmh_attr_type_foreground_color
|
|
||||||
|| cur->type == pmh_attr_type_background_color
|
|
||||||
|| cur->type == pmh_attr_type_caret_color
|
|
||||||
|| cur->type == pmh_attr_type_strike_color)
|
|
||||||
free(cur->value->argb_color);
|
|
||||||
else if (cur->type == pmh_attr_type_font_family)
|
|
||||||
free(cur->value->font_family);
|
|
||||||
else if (cur->type == pmh_attr_type_font_style)
|
|
||||||
free(cur->value->font_styles);
|
|
||||||
else if (cur->type == pmh_attr_type_font_size_pt)
|
|
||||||
free(cur->value->font_size);
|
|
||||||
else if (cur->type == pmh_attr_type_other)
|
|
||||||
free(cur->value->string);
|
|
||||||
free(cur->value);
|
|
||||||
}
|
|
||||||
pmh_style_attribute *pattr = cur;
|
|
||||||
cur = cur->next;
|
|
||||||
free(pattr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define IF_ATTR_NAME(x) if (strcmp(x, name) == 0)
|
|
||||||
pmh_attr_type pmh_attr_type_from_name(char *name)
|
|
||||||
{
|
|
||||||
IF_ATTR_NAME("color") return pmh_attr_type_foreground_color;
|
|
||||||
else IF_ATTR_NAME("foreground") return pmh_attr_type_foreground_color;
|
|
||||||
else IF_ATTR_NAME("foreground-color") return pmh_attr_type_foreground_color;
|
|
||||||
else IF_ATTR_NAME("background") return pmh_attr_type_background_color;
|
|
||||||
else IF_ATTR_NAME("background-color") return pmh_attr_type_background_color;
|
|
||||||
else IF_ATTR_NAME("caret") return pmh_attr_type_caret_color;
|
|
||||||
else IF_ATTR_NAME("caret-color") return pmh_attr_type_caret_color;
|
|
||||||
else IF_ATTR_NAME("strike") return pmh_attr_type_strike_color;
|
|
||||||
else IF_ATTR_NAME("strike-color") return pmh_attr_type_strike_color;
|
|
||||||
else IF_ATTR_NAME("font-size") return pmh_attr_type_font_size_pt;
|
|
||||||
else IF_ATTR_NAME("font-family") return pmh_attr_type_font_family;
|
|
||||||
else IF_ATTR_NAME("font-style") return pmh_attr_type_font_style;
|
|
||||||
return pmh_attr_type_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *pmh_attr_name_from_type(pmh_attr_type type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case pmh_attr_type_foreground_color:
|
|
||||||
return "foreground-color"; break;
|
|
||||||
case pmh_attr_type_background_color:
|
|
||||||
return "background-color"; break;
|
|
||||||
case pmh_attr_type_caret_color:
|
|
||||||
return "caret-color"; break;
|
|
||||||
case pmh_attr_type_strike_color:
|
|
||||||
return "strike-color"; break;
|
|
||||||
case pmh_attr_type_font_size_pt:
|
|
||||||
return "font-size"; break;
|
|
||||||
case pmh_attr_type_font_family:
|
|
||||||
return "font-family"; break;
|
|
||||||
case pmh_attr_type_font_style:
|
|
||||||
return "font-style"; break;
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct multi_value
|
|
||||||
{
|
|
||||||
char *value;
|
|
||||||
size_t length;
|
|
||||||
int line_number;
|
|
||||||
struct multi_value *next;
|
|
||||||
} multi_value;
|
|
||||||
|
|
||||||
static multi_value *split_multi_value(char *input, char separator)
|
|
||||||
{
|
|
||||||
multi_value *head = NULL;
|
|
||||||
multi_value *tail = NULL;
|
|
||||||
|
|
||||||
char *c = input;
|
|
||||||
while (*c != '\0')
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; (*(c+i) != '\0' && *(c+i) != separator); i++);
|
|
||||||
|
|
||||||
multi_value *mv = (multi_value *)malloc(sizeof(multi_value));
|
|
||||||
mv->value = (char *)malloc(sizeof(char)*i + 1);
|
|
||||||
mv->length = i;
|
|
||||||
mv->line_number = 0;
|
|
||||||
mv->next = NULL;
|
|
||||||
*mv->value = '\0';
|
|
||||||
strncat(mv->value, c, i);
|
|
||||||
|
|
||||||
if (head == NULL) {
|
|
||||||
head = mv;
|
|
||||||
tail = mv;
|
|
||||||
} else {
|
|
||||||
tail->next = mv;
|
|
||||||
tail = mv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*(c+i) == separator)
|
|
||||||
i++;
|
|
||||||
c += i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_multi_value(multi_value *val)
|
|
||||||
{
|
|
||||||
multi_value *cur = val;
|
|
||||||
while (cur != NULL)
|
|
||||||
{
|
|
||||||
multi_value *pvalue = cur;
|
|
||||||
multi_value *next_cur = cur->next;
|
|
||||||
free(pvalue->value);
|
|
||||||
free(pvalue);
|
|
||||||
cur = next_cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define EQUALS(a,b) (strcmp(a, b) == 0)
|
|
||||||
|
|
||||||
static pmh_style_attribute *interpret_attributes(style_parser_data *p_data,
|
|
||||||
pmh_element_type lang_element_type,
|
|
||||||
raw_attribute *raw_attributes)
|
|
||||||
{
|
|
||||||
pmh_style_attribute *attrs = NULL;
|
|
||||||
|
|
||||||
raw_attribute *cur = raw_attributes;
|
|
||||||
while (cur != NULL)
|
|
||||||
{
|
|
||||||
pmh_attr_type atype = pmh_attr_type_from_name(cur->name);
|
|
||||||
pmh_style_attribute *attr = new_attr(cur->name, atype);
|
|
||||||
attr->lang_element_type = lang_element_type;
|
|
||||||
attr->value = new_attr_value();
|
|
||||||
|
|
||||||
if (atype == pmh_attr_type_foreground_color
|
|
||||||
|| atype == pmh_attr_type_background_color
|
|
||||||
|| atype == pmh_attr_type_caret_color
|
|
||||||
|| atype == pmh_attr_type_strike_color)
|
|
||||||
{
|
|
||||||
char *hexstr = trim_str(cur->value);
|
|
||||||
// new_argb_from_hex_str() reports conversion errors
|
|
||||||
attr->value->argb_color =
|
|
||||||
new_argb_from_hex_str(p_data, cur->line_number, hexstr);
|
|
||||||
if (attr->value->argb_color == NULL) {
|
|
||||||
free_style_attributes(attr);
|
|
||||||
attr = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (atype == pmh_attr_type_font_size_pt)
|
|
||||||
{
|
|
||||||
pmh_attr_font_size *fs = new_font_size();
|
|
||||||
attr->value->font_size = fs;
|
|
||||||
|
|
||||||
char *trimmed_value = trim_str_dup(cur->value);
|
|
||||||
|
|
||||||
fs->is_relative = (*trimmed_value == '+' || *trimmed_value == '-');
|
|
||||||
char *endptr = NULL;
|
|
||||||
fs->size_pt = (int)strtol(cur->value, &endptr, 10);
|
|
||||||
if (endptr == cur->value) {
|
|
||||||
report_error(p_data, cur->line_number,
|
|
||||||
"Value '%s' is invalid for attribute '%s'",
|
|
||||||
cur->value, cur->name);
|
|
||||||
free_style_attributes(attr);
|
|
||||||
attr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(trimmed_value);
|
|
||||||
}
|
|
||||||
else if (atype == pmh_attr_type_font_family)
|
|
||||||
{
|
|
||||||
attr->value->font_family = trim_str_dup(cur->value);
|
|
||||||
}
|
|
||||||
else if (atype == pmh_attr_type_font_style)
|
|
||||||
{
|
|
||||||
attr->value->font_styles = new_font_styles();
|
|
||||||
multi_value *values = split_multi_value(cur->value, ',');
|
|
||||||
multi_value *value_cur = values;
|
|
||||||
while (value_cur != NULL)
|
|
||||||
{
|
|
||||||
char *standardized_value = standardize_str(value_cur->value);
|
|
||||||
|
|
||||||
if (EQUALS(standardized_value, "italic"))
|
|
||||||
attr->value->font_styles->italic = true;
|
|
||||||
else if (EQUALS(standardized_value, "bold"))
|
|
||||||
attr->value->font_styles->bold = true;
|
|
||||||
else if (EQUALS(standardized_value, "underlined"))
|
|
||||||
attr->value->font_styles->underlined = true;
|
|
||||||
else if (EQUALS(standardized_value, "strikeout"))
|
|
||||||
attr->value->font_styles->strikeout = true;
|
|
||||||
else {
|
|
||||||
report_error(p_data, cur->line_number,
|
|
||||||
"Value '%s' is invalid for attribute '%s'",
|
|
||||||
standardized_value, cur->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(standardized_value);
|
|
||||||
value_cur = value_cur->next;
|
|
||||||
}
|
|
||||||
free_multi_value(values);
|
|
||||||
}
|
|
||||||
else if (atype == pmh_attr_type_other)
|
|
||||||
{
|
|
||||||
attr->value->string = trim_str_dup(cur->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr != NULL) {
|
|
||||||
// add to linked list
|
|
||||||
attr->next = attrs;
|
|
||||||
attrs = attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = cur->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void interpret_and_add_style(style_parser_data *p_data,
|
|
||||||
char *style_rule_name,
|
|
||||||
int style_rule_line_number,
|
|
||||||
raw_attribute *raw_attributes)
|
|
||||||
{
|
|
||||||
bool isEditorType = false;
|
|
||||||
bool isCurrentLineType = false;
|
|
||||||
bool isSelectionType = false;
|
|
||||||
pmh_element_type type = pmh_element_type_from_name(style_rule_name);
|
|
||||||
if (type == pmh_NO_TYPE)
|
|
||||||
{
|
|
||||||
if (EQUALS(style_rule_name, "editor"))
|
|
||||||
isEditorType = true, type = pmh_NO_TYPE;
|
|
||||||
else if (EQUALS(style_rule_name, "editor-current-line"))
|
|
||||||
isCurrentLineType = true, type = pmh_NO_TYPE;
|
|
||||||
else if (EQUALS(style_rule_name, "editor-selection"))
|
|
||||||
isSelectionType = true, type = pmh_NO_TYPE;
|
|
||||||
else {
|
|
||||||
report_error(p_data, style_rule_line_number,
|
|
||||||
"Style rule '%s' is not a language element type name or "
|
|
||||||
"one of the following: 'editor', 'editor-current-line', "
|
|
||||||
"'editor-selection'",
|
|
||||||
style_rule_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pmh_style_attribute *attrs = interpret_attributes(p_data, type, raw_attributes);
|
|
||||||
if (isEditorType)
|
|
||||||
p_data->styles->editor_styles = attrs;
|
|
||||||
else if (isCurrentLineType)
|
|
||||||
p_data->styles->editor_current_line_styles = attrs;
|
|
||||||
else if (isSelectionType)
|
|
||||||
p_data->styles->editor_selection_styles = attrs;
|
|
||||||
else
|
|
||||||
p_data->styles->element_styles[(p_data->styles_pos)++] = attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool char_is_whitespace(char c)
|
|
||||||
{
|
|
||||||
return (c == ' ' || c == '\t');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool char_begins_linecomment(char c)
|
|
||||||
{
|
|
||||||
return (c == '#');
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool line_is_comment(multi_value *line)
|
|
||||||
{
|
|
||||||
char *c;
|
|
||||||
for (c = line->value; *c != '\0'; c++)
|
|
||||||
{
|
|
||||||
if (!char_is_whitespace(*c))
|
|
||||||
return char_begins_linecomment(*c);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool line_is_empty(multi_value *line)
|
|
||||||
{
|
|
||||||
char *c;
|
|
||||||
for (c = line->value; *c != '\0'; c++)
|
|
||||||
{
|
|
||||||
if (!char_is_whitespace(*c))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct block
|
|
||||||
{
|
|
||||||
multi_value *lines;
|
|
||||||
struct block *next;
|
|
||||||
} block;
|
|
||||||
|
|
||||||
static block *new_block()
|
|
||||||
{
|
|
||||||
block *ret = (block *)malloc(sizeof(block));
|
|
||||||
ret->next = NULL;
|
|
||||||
ret->lines = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_blocks(block *val)
|
|
||||||
{
|
|
||||||
block *cur = val;
|
|
||||||
while (cur != NULL)
|
|
||||||
{
|
|
||||||
block *pblock = cur;
|
|
||||||
block *next = pblock->next;
|
|
||||||
free_multi_value(pblock->lines);
|
|
||||||
free(pblock);
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static block *get_blocks(char *input)
|
|
||||||
{
|
|
||||||
block *head = NULL;
|
|
||||||
block *tail = NULL;
|
|
||||||
block *current_block = NULL;
|
|
||||||
|
|
||||||
multi_value *discarded_lines = NULL;
|
|
||||||
|
|
||||||
int line_number_counter = 1;
|
|
||||||
|
|
||||||
multi_value *lines = split_multi_value(input, '\n');
|
|
||||||
multi_value *previous_line = NULL;
|
|
||||||
multi_value *line_cur = lines;
|
|
||||||
while (line_cur != NULL)
|
|
||||||
{
|
|
||||||
bool discard_line = false;
|
|
||||||
|
|
||||||
line_cur->line_number = line_number_counter++;
|
|
||||||
|
|
||||||
if (line_is_empty(line_cur))
|
|
||||||
{
|
|
||||||
discard_line = true;
|
|
||||||
|
|
||||||
if (current_block != NULL)
|
|
||||||
{
|
|
||||||
// terminate block
|
|
||||||
if (tail != current_block)
|
|
||||||
tail->next = current_block;
|
|
||||||
tail = current_block;
|
|
||||||
current_block = NULL;
|
|
||||||
previous_line->next = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (line_is_comment(line_cur))
|
|
||||||
{
|
|
||||||
// Do not discard (i.e. free()) comment lines within blocks:
|
|
||||||
if (current_block == NULL)
|
|
||||||
discard_line = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (current_block == NULL)
|
|
||||||
{
|
|
||||||
// start block
|
|
||||||
current_block = new_block();
|
|
||||||
current_block->lines = line_cur;
|
|
||||||
if (previous_line != NULL)
|
|
||||||
previous_line->next = NULL;
|
|
||||||
}
|
|
||||||
if (head == NULL) {
|
|
||||||
head = current_block;
|
|
||||||
tail = current_block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_value *next_cur = line_cur->next;
|
|
||||||
previous_line = (discard_line) ? NULL : line_cur;
|
|
||||||
|
|
||||||
if (discard_line) {
|
|
||||||
line_cur->next = discarded_lines;
|
|
||||||
discarded_lines = line_cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
line_cur = next_cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_block != NULL && tail != current_block)
|
|
||||||
tail->next = current_block;
|
|
||||||
|
|
||||||
free_multi_value(discarded_lines);
|
|
||||||
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define ASSIGNMENT_OP_UITEXT "':' or '='"
|
|
||||||
#define IS_ASSIGNMENT_OP(c) ((c) == ':' || (c) == '=')
|
|
||||||
#define IS_STYLE_RULE_NAME_CHAR(c) \
|
|
||||||
( (c) != '\0' && !isspace(c) \
|
|
||||||
&& !char_begins_linecomment(c) && !IS_ASSIGNMENT_OP(c) )
|
|
||||||
#define IS_ATTRIBUTE_NAME_CHAR(c) \
|
|
||||||
( (c) != '\0' && !char_begins_linecomment(c) && !IS_ASSIGNMENT_OP(c) )
|
|
||||||
#define IS_ATTRIBUTE_VALUE_CHAR(c) \
|
|
||||||
( (c) != '\0' && !char_begins_linecomment(c) )
|
|
||||||
|
|
||||||
static char *get_style_rule_name(multi_value *line)
|
|
||||||
{
|
|
||||||
char *str = line->value;
|
|
||||||
|
|
||||||
// Scan past leading whitespace:
|
|
||||||
size_t start_index;
|
|
||||||
for (start_index = 0;
|
|
||||||
(*(str+start_index) != '\0' && isspace(*(str+start_index)));
|
|
||||||
start_index++);
|
|
||||||
|
|
||||||
// Scan until style rule name characters end:
|
|
||||||
size_t value_end_index;
|
|
||||||
for (value_end_index = start_index;
|
|
||||||
IS_STYLE_RULE_NAME_CHAR(*(str + value_end_index));
|
|
||||||
value_end_index++);
|
|
||||||
|
|
||||||
// Copy style rule name:
|
|
||||||
size_t value_len = value_end_index - start_index;
|
|
||||||
char *value = (char *)malloc(sizeof(char)*value_len + 1);
|
|
||||||
*value = '\0';
|
|
||||||
strncat(value, (str + start_index), value_len);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parse_attribute_line(style_parser_data *p_data, multi_value *line,
|
|
||||||
char **out_attr_name, char **out_attr_value)
|
|
||||||
{
|
|
||||||
char *str = line->value;
|
|
||||||
|
|
||||||
// Scan past leading whitespace:
|
|
||||||
size_t name_start_index;
|
|
||||||
for (name_start_index = 0;
|
|
||||||
( *(str+name_start_index) != '\0' &&
|
|
||||||
isspace(*(str+name_start_index)) );
|
|
||||||
name_start_index++);
|
|
||||||
|
|
||||||
// Scan until attribute name characters end:
|
|
||||||
size_t name_end_index;
|
|
||||||
for (name_end_index = name_start_index;
|
|
||||||
IS_ATTRIBUTE_NAME_CHAR(*(str + name_end_index));
|
|
||||||
name_end_index++);
|
|
||||||
// Scan backwards to trim trailing whitespace off:
|
|
||||||
while (name_start_index < name_end_index
|
|
||||||
&& isspace(*(str + name_end_index - 1)))
|
|
||||||
name_end_index--;
|
|
||||||
|
|
||||||
// Scan until just after the first assignment operator:
|
|
||||||
size_t assignment_end_index;
|
|
||||||
for (assignment_end_index = name_end_index;
|
|
||||||
( *(str + assignment_end_index) != '\0' &&
|
|
||||||
!IS_ASSIGNMENT_OP(*(str + assignment_end_index)) );
|
|
||||||
assignment_end_index++);
|
|
||||||
|
|
||||||
// Scan over the found assignment operator, or report error:
|
|
||||||
if (IS_ASSIGNMENT_OP(*(str + assignment_end_index)))
|
|
||||||
assignment_end_index++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
report_error(p_data, line->line_number,
|
|
||||||
"Invalid attribute definition: str does not contain "
|
|
||||||
"an assignment operator (%s): '%s'",
|
|
||||||
ASSIGNMENT_OP_UITEXT, str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t value_start_index = assignment_end_index;
|
|
||||||
// Scan until attribute value characters end:
|
|
||||||
size_t value_end_index;
|
|
||||||
for (value_end_index = value_start_index;
|
|
||||||
IS_ATTRIBUTE_VALUE_CHAR(*(str + value_end_index));
|
|
||||||
value_end_index++);
|
|
||||||
|
|
||||||
// Copy attribute name:
|
|
||||||
size_t name_len = name_end_index - name_start_index;
|
|
||||||
char *attr_name = (char *)malloc(sizeof(char)*name_len + 1);
|
|
||||||
*attr_name = '\0';
|
|
||||||
strncat(attr_name, (str + name_start_index), name_len);
|
|
||||||
*out_attr_name = attr_name;
|
|
||||||
|
|
||||||
// Copy attribute value:
|
|
||||||
size_t attr_value_len = value_end_index - assignment_end_index;
|
|
||||||
char *attr_value_str = (char *)malloc(sizeof(char)*attr_value_len + 1);
|
|
||||||
*attr_value_str = '\0';
|
|
||||||
strncat(attr_value_str, (str + assignment_end_index), attr_value_len);
|
|
||||||
*out_attr_value = attr_value_str;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define HAS_UTF8_BOM(x) ( ((*x & 0xFF) == 0xEF)\
|
|
||||||
&& ((*(x+1) & 0xFF) == 0xBB)\
|
|
||||||
&& ((*(x+2) & 0xFF) == 0xBF) )
|
|
||||||
|
|
||||||
// - Removes UTF-8 BOM
|
|
||||||
// - Standardizes line endings to \n
|
|
||||||
static char *strcpy_preformat_style(char *str)
|
|
||||||
{
|
|
||||||
char *new_str = (char *)malloc(sizeof(char) * strlen(str) + 1);
|
|
||||||
|
|
||||||
char *c = str;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (HAS_UTF8_BOM(c))
|
|
||||||
c += 3;
|
|
||||||
|
|
||||||
while (*c != '\0')
|
|
||||||
{
|
|
||||||
if (*c == '\r' && *(c+1) == '\n')
|
|
||||||
{
|
|
||||||
*(new_str+i) = '\n';
|
|
||||||
i++;
|
|
||||||
c += 2;
|
|
||||||
}
|
|
||||||
else if (*c == '\r')
|
|
||||||
{
|
|
||||||
*(new_str+i) = '\n';
|
|
||||||
i++;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(new_str+i) = *c;
|
|
||||||
i++;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*(new_str+i) = '\0';
|
|
||||||
|
|
||||||
return new_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void _sty_parse(style_parser_data *p_data)
|
|
||||||
{
|
|
||||||
// We don't have to worry about leaking the original p_data->input;
|
|
||||||
// the user of the library is responsible for that:
|
|
||||||
p_data->input = strcpy_preformat_style(p_data->input);
|
|
||||||
|
|
||||||
block *blocks = get_blocks(p_data->input);
|
|
||||||
|
|
||||||
block *block_cur = blocks;
|
|
||||||
while (block_cur != NULL)
|
|
||||||
{
|
|
||||||
raw_attribute *attributes_head = NULL;
|
|
||||||
raw_attribute *attributes_tail = NULL;
|
|
||||||
|
|
||||||
pmhsp_PRINTF("Block:\n");
|
|
||||||
multi_value *header_line = block_cur->lines;
|
|
||||||
if (header_line == NULL) {
|
|
||||||
block_cur = block_cur->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmhsp_PRINTF(" Head line (len %ld): '%s'\n",
|
|
||||||
header_line->length, header_line->value);
|
|
||||||
char *style_rule_name = get_style_rule_name(header_line);
|
|
||||||
pmhsp_PRINTF(" Style rule name: '%s'\n", style_rule_name);
|
|
||||||
|
|
||||||
multi_value *attr_line_cur = header_line->next;
|
|
||||||
if (attr_line_cur == NULL)
|
|
||||||
report_error(p_data, header_line->line_number,
|
|
||||||
"No style attributes defined for style rule '%s'",
|
|
||||||
style_rule_name);
|
|
||||||
|
|
||||||
while (attr_line_cur != NULL)
|
|
||||||
{
|
|
||||||
if (line_is_comment(attr_line_cur))
|
|
||||||
{
|
|
||||||
attr_line_cur = attr_line_cur->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmhsp_PRINTF(" Attr line (len %ld): '%s'\n",
|
|
||||||
attr_line_cur->length, attr_line_cur->value);
|
|
||||||
char *attr_name_str;
|
|
||||||
char *attr_value_str;
|
|
||||||
bool success = parse_attribute_line(p_data,
|
|
||||||
attr_line_cur,
|
|
||||||
&attr_name_str,
|
|
||||||
&attr_value_str);
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
pmhsp_PRINTF(" Attr: '%s' Value: '%s'\n",
|
|
||||||
attr_name_str, attr_value_str);
|
|
||||||
raw_attribute *attribute =
|
|
||||||
new_raw_attribute(attr_name_str, attr_value_str,
|
|
||||||
attr_line_cur->line_number);
|
|
||||||
if (attributes_head == NULL) {
|
|
||||||
attributes_head = attribute;
|
|
||||||
attributes_tail = attribute;
|
|
||||||
} else {
|
|
||||||
attributes_tail->next = attribute;
|
|
||||||
attributes_tail = attribute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attr_line_cur = attr_line_cur->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes_head != NULL)
|
|
||||||
{
|
|
||||||
interpret_and_add_style(p_data, style_rule_name,
|
|
||||||
header_line->line_number, attributes_head);
|
|
||||||
free_raw_attributes(attributes_head);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(style_rule_name);
|
|
||||||
|
|
||||||
block_cur = block_cur->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_blocks(blocks);
|
|
||||||
free(p_data->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static pmh_style_collection *new_style_collection()
|
|
||||||
{
|
|
||||||
pmh_style_collection *sc = (pmh_style_collection *)
|
|
||||||
malloc(sizeof(pmh_style_collection));
|
|
||||||
|
|
||||||
sc->element_styles = (pmh_style_attribute**)
|
|
||||||
malloc(sizeof(pmh_style_attribute*)
|
|
||||||
* pmh_NUM_LANG_TYPES);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < pmh_NUM_LANG_TYPES; i++)
|
|
||||||
sc->element_styles[i] = NULL;
|
|
||||||
|
|
||||||
sc->editor_styles = NULL;
|
|
||||||
sc->editor_current_line_styles = NULL;
|
|
||||||
sc->editor_selection_styles = NULL;
|
|
||||||
|
|
||||||
return sc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmh_free_style_collection(pmh_style_collection *coll)
|
|
||||||
{
|
|
||||||
free_style_attributes(coll->editor_styles);
|
|
||||||
free_style_attributes(coll->editor_current_line_styles);
|
|
||||||
free_style_attributes(coll->editor_selection_styles);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < pmh_NUM_LANG_TYPES; i++)
|
|
||||||
free_style_attributes(coll->element_styles[i]);
|
|
||||||
free(coll->element_styles);
|
|
||||||
free(coll);
|
|
||||||
}
|
|
||||||
|
|
||||||
static style_parser_data *new_style_parser_data(char *input)
|
|
||||||
{
|
|
||||||
style_parser_data *p_data = (style_parser_data*)
|
|
||||||
malloc(sizeof(style_parser_data));
|
|
||||||
p_data->input = input;
|
|
||||||
p_data->styles_pos = 0;
|
|
||||||
p_data->styles = new_style_collection();
|
|
||||||
return p_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmh_style_collection *pmh_parse_styles(char *input,
|
|
||||||
void(*error_callback)(char*,int,void*),
|
|
||||||
void *error_callback_context)
|
|
||||||
{
|
|
||||||
style_parser_data *p_data = new_style_parser_data(input);
|
|
||||||
p_data->error_callback = error_callback;
|
|
||||||
p_data->error_callback_context = error_callback_context;
|
|
||||||
|
|
||||||
_sty_parse(p_data);
|
|
||||||
|
|
||||||
pmh_style_collection *ret = p_data->styles;
|
|
||||||
free(p_data);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
|||||||
/* PEG Markdown Highlight
|
|
||||||
* Copyright 2011-2016 Ali Rantakari -- http://hasseg.org
|
|
||||||
* Licensed under the GPL2+ and MIT licenses (see LICENSE for more info).
|
|
||||||
*
|
|
||||||
* pmh_styleparser.h
|
|
||||||
*
|
|
||||||
* Public interface of a parser for custom syntax highlighting stylesheets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* \brief Style parser public interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "pmh_definitions.h"
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Color (ARGB) attribute value.
|
|
||||||
*
|
|
||||||
* All values are 0-255.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int red; /**< Red color component (0-255) */
|
|
||||||
int green; /**< Green color component (0-255) */
|
|
||||||
int blue; /**< Blue color component (0-255) */
|
|
||||||
int alpha; /**< Alpha (opacity) color component (0-255) */
|
|
||||||
} pmh_attr_argb_color;
|
|
||||||
|
|
||||||
/** \brief Font style attribute value. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
bool italic;
|
|
||||||
bool bold;
|
|
||||||
bool underlined;
|
|
||||||
bool strikeout;
|
|
||||||
} pmh_attr_font_styles;
|
|
||||||
|
|
||||||
/** \brief Font size attribute value. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int size_pt; /**< The font point size */
|
|
||||||
bool is_relative; /**< Whether the size is relative (i.e. size_pt points
|
|
||||||
larger than the default font) */
|
|
||||||
} pmh_attr_font_size;
|
|
||||||
|
|
||||||
/** \brief Style attribute types. */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
pmh_attr_type_foreground_color, /**< Foreground color */
|
|
||||||
pmh_attr_type_background_color, /**< Background color */
|
|
||||||
pmh_attr_type_caret_color, /**< Caret (insertion point) color */
|
|
||||||
pmh_attr_type_font_size_pt, /**< Font size (in points) */
|
|
||||||
pmh_attr_type_font_family, /**< Font family */
|
|
||||||
pmh_attr_type_font_style, /**< Font style */
|
|
||||||
pmh_attr_type_strike_color, /**< Strike-through color */
|
|
||||||
pmh_attr_type_other /**< Arbitrary custom attribute */
|
|
||||||
} pmh_attr_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Style attribute value.
|
|
||||||
*
|
|
||||||
* Determine which member to access in this union based on the
|
|
||||||
* 'type' value of the pmh_style_attribute.
|
|
||||||
*
|
|
||||||
* \sa pmh_style_attribute
|
|
||||||
*/
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
pmh_attr_argb_color *argb_color; /**< ARGB color */
|
|
||||||
pmh_attr_font_styles *font_styles; /**< Font styles */
|
|
||||||
pmh_attr_font_size *font_size; /**< Font size */
|
|
||||||
char *font_family; /**< Font family */
|
|
||||||
char *string; /**< Arbitrary custom string value
|
|
||||||
(use this if the attribute's type
|
|
||||||
is pmh_attr_type_other) */
|
|
||||||
} pmh_attr_value;
|
|
||||||
|
|
||||||
/** \brief Style attribute. */
|
|
||||||
typedef struct pmh_style_attribute
|
|
||||||
{
|
|
||||||
pmh_element_type lang_element_type; /**< The Markdown language element this
|
|
||||||
style applies to */
|
|
||||||
pmh_attr_type type; /**< The type of the attribute */
|
|
||||||
char *name; /**< The name of the attribute (if type
|
|
||||||
is pmh_attr_type_other, you can
|
|
||||||
use this value to determine what
|
|
||||||
the attribute is) */
|
|
||||||
pmh_attr_value *value; /**< The value of the attribute */
|
|
||||||
struct pmh_style_attribute *next; /**< Next attribute in linked list */
|
|
||||||
} pmh_style_attribute;
|
|
||||||
|
|
||||||
/** \brief Collection of styles. */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
/** Styles that apply to the editor in general */
|
|
||||||
pmh_style_attribute *editor_styles;
|
|
||||||
|
|
||||||
/** Styles that apply to the line in the editor where the caret (insertion
|
|
||||||
point) resides */
|
|
||||||
pmh_style_attribute *editor_current_line_styles;
|
|
||||||
|
|
||||||
/** Styles that apply to the range of selected text in the editor */
|
|
||||||
pmh_style_attribute *editor_selection_styles;
|
|
||||||
|
|
||||||
/** Styles that apply to specific Markdown language elements */
|
|
||||||
pmh_style_attribute **element_styles;
|
|
||||||
} pmh_style_collection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Parse stylesheet string, return style collection
|
|
||||||
*
|
|
||||||
* \param[in] input The stylesheet string to parse.
|
|
||||||
* \param[in] error_callback Callback function to be called when errors
|
|
||||||
* occur during parsing. The first argument
|
|
||||||
* to the callback function is the error
|
|
||||||
* message and the second one the line number
|
|
||||||
* in the original input where the error
|
|
||||||
* occurred. The last argument will always
|
|
||||||
* get the value you pass in for the
|
|
||||||
* error_callback_context argument to this
|
|
||||||
* function.
|
|
||||||
* Pass in NULL to suppress error reporting.
|
|
||||||
* \param[in] error_callback_context Arbitrary context pointer for the error
|
|
||||||
* callback function; will be passed in as
|
|
||||||
* the last argument to error_callback.
|
|
||||||
*
|
|
||||||
* \return A pmh_style_collection. You must pass this value to
|
|
||||||
* pmh_free_style_collection() when it's not needed anymore.
|
|
||||||
*/
|
|
||||||
pmh_style_collection *pmh_parse_styles(char *input,
|
|
||||||
void(*error_callback)(char*,int,void*),
|
|
||||||
void *error_callback_context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Free a pmh_style_collection.
|
|
||||||
*
|
|
||||||
* Frees a pmh_style_collection value returned by pmh_parse_styles().
|
|
||||||
*
|
|
||||||
* \param[in] collection The collection to free.
|
|
||||||
*/
|
|
||||||
void pmh_free_style_collection(pmh_style_collection *collection);
|
|
||||||
|
|
||||||
|
|
||||||
char *pmh_attr_name_from_type(pmh_attr_type type);
|
|
||||||
|
|
||||||
pmh_attr_type pmh_attr_type_from_name(char *name);
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
NONEXISTENT_TYPE
|
|
||||||
x: 3
|
|
||||||
|
|
||||||
STRONG
|
|
||||||
font-style: funkadelic, bold, snazzy
|
|
||||||
foreground: 13bx12
|
|
||||||
background: 5
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
|||||||
# Styles using 'Solarized' color scheme
|
|
||||||
# by Ethan Schoonover: http://ethanschoonover.com/solarized
|
|
||||||
#
|
|
||||||
# (dark background version)
|
|
||||||
|
|
||||||
editor
|
|
||||||
foreground: 93a1a1 # base1
|
|
||||||
background: 002b36 # base03
|
|
||||||
caret: ffffff
|
|
||||||
font-size: 13
|
|
||||||
|
|
||||||
H1
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
font-size: +6
|
|
||||||
|
|
||||||
H2
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
font-size: +5
|
|
||||||
|
|
||||||
H3
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-size: +4
|
|
||||||
|
|
||||||
H4
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
font-size: +3
|
|
||||||
|
|
||||||
H5
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
font-size: +2
|
|
||||||
|
|
||||||
H6
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
font-size: +1
|
|
||||||
|
|
||||||
HRULE
|
|
||||||
foreground: 586e75 # base01
|
|
||||||
|
|
||||||
LIST_BULLET
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LIST_ENUMERATOR
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LINK
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_URL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_EMAIL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
IMAGE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
REFERENCE
|
|
||||||
foreground: 80b58900 # yellow, reduced alpha
|
|
||||||
font-size: -2
|
|
||||||
|
|
||||||
CODE
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
EMPH
|
|
||||||
foreground: cb4b16 # orange
|
|
||||||
font-style: italic
|
|
||||||
|
|
||||||
STRONG
|
|
||||||
foreground: dc322f # red
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
HTML_ENTITY
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
|
|
||||||
COMMENT
|
|
||||||
foreground: 93a1a1 # base1
|
|
||||||
|
|
||||||
VERBATIM
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
BLOCKQUOTE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
STRIKE
|
|
||||||
strike-color: 93a1a1 # base1
|
|
@ -1 +0,0 @@
|
|||||||
# linecomment
editor # comment
foreground : 13ff13
background : 000000 # comment
# linecomment
STRONG:
EMPH=
# comment
foreground: 00ff00
comment asd
background: AB0000ff
STRONG :
dog: 1 # something
cat: 4
font-style: underlined, Italic , BoLD #hi, hello
font-size: 14pt
font-family: Courier New, Times
# linecomment
BOO
x: 3
editor-selection:
foreground: abcdef
background: abcdef
editor-current-line:
background: ffffff
|
|
@ -1,22 +0,0 @@
|
|||||||
editor :
|
|
||||||
foreground : 13ff13
|
|
||||||
background : 000000
|
|
||||||
caret: ffffff
|
|
||||||
|
|
||||||
EMPH
|
|
||||||
font-style: italic
|
|
||||||
|
|
||||||
STRONG
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
LINK
|
|
||||||
font-style: underlined
|
|
||||||
|
|
||||||
editor-selection:
|
|
||||||
foreground: ff0000
|
|
||||||
background: eeeeee
|
|
||||||
font-style: underlined
|
|
||||||
|
|
||||||
editor-current-line:
|
|
||||||
background: ffffff
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
# Styles using 'Solarized' color scheme
|
|
||||||
# by Ethan Schoonover: http://ethanschoonover.com/solarized
|
|
||||||
#
|
|
||||||
# (dark background version)
|
|
||||||
|
|
||||||
editor
|
|
||||||
foreground: 93a1a1 # base1
|
|
||||||
background: 002b36 # base03
|
|
||||||
caret: ffffff
|
|
||||||
|
|
||||||
H1
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
H2
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
H3
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
|
|
||||||
H4
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
H5
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
H6
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
HRULE
|
|
||||||
foreground: 586e75 # base01
|
|
||||||
|
|
||||||
LIST_BULLET
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LIST_ENUMERATOR
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LINK
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_URL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_EMAIL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
IMAGE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
REFERENCE
|
|
||||||
foreground: 80b58900 # yellow, reduced alpha
|
|
||||||
|
|
||||||
CODE
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
EMPH
|
|
||||||
foreground: cb4b16 # orange
|
|
||||||
font-style: italic
|
|
||||||
|
|
||||||
STRONG
|
|
||||||
foreground: dc322f # red
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
HTML_ENTITY
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
|
|
||||||
COMMENT
|
|
||||||
foreground: 93a1a1 # base1
|
|
||||||
|
|
||||||
VERBATIM
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
BLOCKQUOTE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
STRIKE
|
|
||||||
strike-color: 93a1a1 # base1
|
|
@ -1,80 +0,0 @@
|
|||||||
# Styles using 'Solarized' color scheme
|
|
||||||
# by Ethan Schoonover: http://ethanschoonover.com/solarized
|
|
||||||
#
|
|
||||||
# (light background version)
|
|
||||||
|
|
||||||
editor
|
|
||||||
foreground: 586e75 # base01
|
|
||||||
background: fdf6e3 # base3
|
|
||||||
caret: 000000
|
|
||||||
|
|
||||||
H1
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
H2
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
H3
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
|
|
||||||
H4
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
H5
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
H6
|
|
||||||
foreground: 268bd2 # blue
|
|
||||||
|
|
||||||
HRULE
|
|
||||||
foreground: 586e75 # base01
|
|
||||||
|
|
||||||
LIST_BULLET
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LIST_ENUMERATOR
|
|
||||||
foreground: b58900 # yellow
|
|
||||||
|
|
||||||
LINK
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_URL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
AUTO_LINK_EMAIL
|
|
||||||
foreground: 2aa198 # cyan
|
|
||||||
|
|
||||||
IMAGE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
REFERENCE
|
|
||||||
foreground: 80b58900 # yellow, reduced alpha
|
|
||||||
|
|
||||||
CODE
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
EMPH
|
|
||||||
foreground: cb4b16 # orange
|
|
||||||
font-style: italic
|
|
||||||
|
|
||||||
STRONG
|
|
||||||
foreground: dc322f # red
|
|
||||||
font-style: bold
|
|
||||||
|
|
||||||
HTML_ENTITY
|
|
||||||
foreground: 6c71c4 # violet
|
|
||||||
|
|
||||||
COMMENT
|
|
||||||
foreground: 93a1a1 # base1
|
|
||||||
|
|
||||||
VERBATIM
|
|
||||||
foreground: 859900 # green
|
|
||||||
|
|
||||||
BLOCKQUOTE
|
|
||||||
foreground: d33682 # magenta
|
|
||||||
|
|
||||||
STRIKE
|
|
||||||
strike-color: 586e75 # base01
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
# linecomment
|
|
||||||
|
|
||||||
editor # comment
|
|
||||||
foreground : 13ff13
|
|
||||||
background : 000000 # comment
|
|
||||||
|
|
||||||
# linecomment
|
|
||||||
STRONG:
|
|
||||||
|
|
||||||
EMPH=
|
|
||||||
# comment
|
|
||||||
foreground: 00ff00
|
|
||||||
comment asd
|
|
||||||
background: AB0000ff
|
|
||||||
|
|
||||||
STRONG :
|
|
||||||
dog: 1 # something
|
|
||||||
cat: 4
|
|
||||||
font-style: underlined, Italic , BoLD #hi, hello
|
|
||||||
font-size: 14pt
|
|
||||||
font-family: Courier New, Times
|
|
||||||
|
|
||||||
# linecomment
|
|
||||||
BOO
|
|
||||||
x: 3
|
|
||||||
|
|
||||||
editor-selection:
|
|
||||||
foreground: abcdef
|
|
||||||
background: abcdef
|
|
||||||
|
|
||||||
editor-current-line:
|
|
||||||
background: ffffff
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
# linecomment
|
|
||||||
|
|
||||||
editor # comment
|
|
||||||
foreground : 13ff13
|
|
||||||
background : 000000 # comment
|
|
||||||
|
|
||||||
# linecomment
|
|
||||||
STRONG:
|
|
||||||
|
|
||||||
EMPH=
|
|
||||||
# comment
|
|
||||||
foreground: 00ff00
|
|
||||||
comment asd
|
|
||||||
background: AB0000ff
|
|
||||||
|
|
||||||
STRONG :
|
|
||||||
dog: 1 # something
|
|
||||||
cat: 4
|
|
||||||
font-style: underlined, Italic , BoLD #hi, hello
|
|
||||||
font-size: 14pt
|
|
||||||
font-family: Courier New, Times
|
|
||||||
|
|
||||||
# linecomment
|
|
||||||
BOO
|
|
||||||
x: 3
|
|
||||||
|
|
||||||
editor-selection:
|
|
||||||
foreground: abcdef
|
|
||||||
background: abcdef
|
|
||||||
|
|
||||||
editor-current-line:
|
|
||||||
background: ffffff
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
|||||||
|
|
||||||
The Syntax of PEG Markdown Highlight Stylesheets
|
|
||||||
================================================
|
|
||||||
|
|
||||||
[PEG Markdown Highlight][pmh] includes a parser for stylesheets that define how different Markdown language elements are to be highlighted. This document describes the syntax of these stylesheets.
|
|
||||||
|
|
||||||
[pmh]: http://hasseg.org/peg-markdown-highlight/
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
|
||||||
|
|
||||||
Here is a quick, simple example of a stylesheet:
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.codetable { border-collapse: collapse; }
|
|
||||||
.codetable .left { text-align: right; padding-right: 10px; }
|
|
||||||
.codetable .right { text-align: left; padding-left: 10px; }
|
|
||||||
.codetable .content { font-family: monospace; background: #eee; padding: 0 5px; }
|
|
||||||
.codetable .comment { color: #174EB3; }
|
|
||||||
.codetable .rule { color: #491B8F; }
|
|
||||||
.codetable .attrname { color: #48B317; }
|
|
||||||
.codetable .attrvalue { color: #A65C1F; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<table class="codetable">
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"># The first comment lines</td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"># describe the stylesheet.</td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"> </td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><span class="rule">Style rule →</span></td>
|
|
||||||
<td class="content"><span class="rule">editor:</span></td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"> foreground: ff0000 <span class="comment"># red text</span></td>
|
|
||||||
<td class="right"><span class="comment">← Comment</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"><span class="attrname">Attribute name →</span></td>
|
|
||||||
<td class="content"> <span class="attrname">font-family</span>: <span class="attrvalue">Consolas</span></td>
|
|
||||||
<td class="right"><span class="attrvalue">← Attribute value</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"> </td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content">EMPH:</td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"> font-size: 14</td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="left"></td>
|
|
||||||
<td class="content"> font-style: bold, underlined</td>
|
|
||||||
<td class="right"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
Style Rules
|
|
||||||
-----------
|
|
||||||
|
|
||||||
A stylesheet is composed of one or more *rules*. Rules are separated from each other by **empty lines** like so:
|
|
||||||
|
|
||||||
H2:
|
|
||||||
foreground: ff0000
|
|
||||||
|
|
||||||
H3:
|
|
||||||
foreground: 00ff00
|
|
||||||
|
|
||||||
Each begins with the ***name* of the rule**, which is always on its own line, and may be one of the following:
|
|
||||||
|
|
||||||
- **`editor`**: Styles that apply to the whole document/editor
|
|
||||||
- **`editor-current-line`**: Styles that apply to the current line in the editor (i.e. the line where the caret is)
|
|
||||||
- **`editor-selection`**: Styles that apply to the selected range in the editor when the user makes a selection in the text
|
|
||||||
- A Markdown element type (like `EMPH`, `REFERENCE` or `H1`): Styles that apply to occurrences of that particular element. The supported element types are:
|
|
||||||
- **`LINK`:** Explicit link (like `[click here][ref]`)
|
|
||||||
- **`AUTO_LINK_URL`:** Implicit URL link (like `<http://google.com>`)
|
|
||||||
- **`AUTO_LINK_EMAIL`:** Implicit email link (like `<first.last@google.com>`)
|
|
||||||
- **`IMAGE`:** Image definition
|
|
||||||
- **`REFERENCE`:** Reference (like `[id]: http://www.google.com`)
|
|
||||||
- **`CODE`:** Inline code
|
|
||||||
- **`EMPH`:** Emphasized text
|
|
||||||
- **`STRONG`:** Strong text
|
|
||||||
- **`LIST_BULLET`:** Bullet for an unordered list item
|
|
||||||
- **`LIST_ENUMERATOR`:** Enumerator for an ordered list item
|
|
||||||
- **`H1`:** Header, level 1
|
|
||||||
- **`H2`:** Header, level 2
|
|
||||||
- **`H3`:** Header, level 3
|
|
||||||
- **`H4`:** Header, level 4
|
|
||||||
- **`H5`:** Header, level 5
|
|
||||||
- **`H6`:** Header, level 6
|
|
||||||
- **`BLOCKQUOTE`:** Blockquote marker
|
|
||||||
- **`VERBATIM`:** Block of code
|
|
||||||
- **`HRULE`:** Horizontal rule
|
|
||||||
- **`HTML`:** HTML tag
|
|
||||||
- **`HTML_ENTITY`:** HTML special entity definition (like `…`)
|
|
||||||
- **`HTMLBLOCK`:** Block of HTML
|
|
||||||
- **`COMMENT`:** (HTML) Comment
|
|
||||||
- **`NOTE`:** Note
|
|
||||||
- **`STRIKE`:** Strike-through
|
|
||||||
|
|
||||||
The name may be optionally followed by an assignment operator (either `:` or `=`):
|
|
||||||
|
|
||||||
H1:
|
|
||||||
foreground: ff00ff
|
|
||||||
|
|
||||||
H2 =
|
|
||||||
foreground: ff0000
|
|
||||||
|
|
||||||
H3
|
|
||||||
foreground: 00ff00
|
|
||||||
|
|
||||||
The **order of style rules is significant**; it defines the order in which different language elements should be highlighted. *(Of course applications that use PEG Markdown Highlight and the style parser may disregard this and highlight elements in whatever order they desire.)*
|
|
||||||
|
|
||||||
After the name of the rule, there can be one or more *attributes*.
|
|
||||||
|
|
||||||
|
|
||||||
Style Attributes
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Attribute assignments are each on their own line, and they consist of the *name* of the attribute as well as the *value* assigned to it. An assignment operator (either `:` or `=`) separates the name from the value:
|
|
||||||
|
|
||||||
attribute-name: value
|
|
||||||
attribute-name= value
|
|
||||||
|
|
||||||
Attribute assignment lines **may be indented**.
|
|
||||||
|
|
||||||
### Attribute Names and Types
|
|
||||||
|
|
||||||
The following is a list of the names of predefined attributes, and the values they may be assigned:
|
|
||||||
|
|
||||||
- `foreground-color` *(aliases: `foreground` and `color`)*
|
|
||||||
- See the *Color Attribute Values* subsection for information about valid values for this attribute.
|
|
||||||
- `background-color` *(alias: `background`)*
|
|
||||||
- See the *Color Attribute Values* subsection for information about valid values for this attribute.
|
|
||||||
- `caret-color` *(alias: `caret`)*
|
|
||||||
- See the *Color Attribute Values* subsection for information about valid values for this attribute.
|
|
||||||
- `strike-color` *(alias: `strike`)*
|
|
||||||
- See the *Color Attribute Values* subsection for information about valid values for this attribute.
|
|
||||||
- `font-size`
|
|
||||||
- An integer value for the font size, *in points* (i.e. not in pixels). The number may have a textual suffix such as `pt`.
|
|
||||||
- If the value begins with `+` or `-`, it is considered *relative* to some base font size (as defined by the host application). For example, the value `3` defines the font size as 3 (absolute) while `+3` defines it as +3 (relative), i.e. 3 point sizes larger than the base font size.
|
|
||||||
- `font-family`
|
|
||||||
- A comma-separated list of one or more arbitrary font family names. *(It is up to the application that uses the PEG Markdown Highlight library to resolve this string to actual fonts on the system.)*
|
|
||||||
- `font-style`
|
|
||||||
- A comma-separated list of one or more of the following:
|
|
||||||
- `italic`
|
|
||||||
- `bold`
|
|
||||||
- `underlined`
|
|
||||||
|
|
||||||
Applications may also include support for any **custom attribute names and values** they desire — attributes other than the ones listed above will be included in the style parser results, with their values stored as strings.
|
|
||||||
|
|
||||||
|
|
||||||
## Color Attribute Values
|
|
||||||
|
|
||||||
Colors can be specified either in **RGB** (red, green, blue) or **ARGB** (alpha, red, green, blue) formats. In both, each component is a two-character hexadecimal value (from `00` to `FF`):
|
|
||||||
|
|
||||||
foreground: ff00ee # red = ff, green = 00, blue = ee (and implicitly, alpha = ff)
|
|
||||||
background: 99ff00ee # alpha = 99, red = ff, green = 00, blue = ee
|
|
||||||
|
|
||||||
|
|
||||||
Comments
|
|
||||||
--------
|
|
||||||
|
|
||||||
Each line in a stylesheet may have a comment. The `#` character begins a line comment that continues until the end of the line:
|
|
||||||
|
|
||||||
# this line has only this comment
|
|
||||||
H1: # this line has a style rule name and then a comment
|
|
||||||
foreground: ff0000 # this line has an attribute and then a comment
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
BIN
pics/main.png
Normal file
After Width: | Height: | Size: 269 KiB |
BIN
pics/main2.png
Normal file
After Width: | Height: | Size: 218 KiB |
BIN
pics/vnote.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
26
privacy_policy.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Privacy Policy
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Welcome to VNote! We value your privacy and are committed to protecting your personal information. This Privacy Policy explains how we handle your information when you use our application.
|
||||||
|
|
||||||
|
## Information We Collect
|
||||||
|
VNote does not collect any personal or usage data from its users. Your interactions with the app remain private and are not stored or shared.
|
||||||
|
|
||||||
|
## How We Use Your Information
|
||||||
|
Since VNote does not collect any user data, we do not use, store, or process any personal information.
|
||||||
|
|
||||||
|
## Sharing Your Information
|
||||||
|
As VNote does not collect any user data, we do not share any personal information with third parties.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
While VNote does not collect any user data, we still implement security measures to ensure the integrity and safety of the application itself.
|
||||||
|
|
||||||
|
## Your Choices
|
||||||
|
Since no data is collected, there are no choices or actions required from users regarding their personal information.
|
||||||
|
|
||||||
|
## Children's Privacy
|
||||||
|
Our services are not intended for children under the age of 13. We do not knowingly collect personal information from children under 13.
|
||||||
|
|
||||||
|
## Changes to This Privacy Policy
|
||||||
|
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on our app. You are advised to review this Privacy Policy periodically for any changes.
|
||||||
|
|
Before Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 570 KiB |
Before Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 351 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 83 KiB |
39
scripts/update_version.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import fileinput
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Please provide a new version string!")
|
||||||
|
exit
|
||||||
|
|
||||||
|
newVersion = sys.argv[1]
|
||||||
|
shortVersion = re.match('^(\\d+\\.\\d+).', newVersion).group(1)
|
||||||
|
print("New version: {0}".format(newVersion))
|
||||||
|
|
||||||
|
# CMakeList
|
||||||
|
regExp = re.compile('(\\s+)VERSION \\S+')
|
||||||
|
for line in fileinput.input(['CMakeLists.txt'], inplace = True):
|
||||||
|
print(regExp.sub('\\1VERSION ' + newVersion, line), end='')
|
||||||
|
|
||||||
|
# vnotex.json
|
||||||
|
regExp = re.compile('(\\s+)"version" : "\\S+"')
|
||||||
|
for line in fileinput.input(['src/data/core/vnotex.json'], inplace = True):
|
||||||
|
print(regExp.sub('\\1"version" : "' + newVersion + '"', line), end='')
|
||||||
|
|
||||||
|
# ci-xxx.yml
|
||||||
|
regExp = re.compile('(\\s+)VNOTE_VER: \\S+')
|
||||||
|
for line in fileinput.input(['.github/workflows/ci-win.yml', '.github/workflows/ci-linux.yml', '.github/workflows/ci-macos.yml'], inplace = True):
|
||||||
|
print(regExp.sub('\\1VNOTE_VER: ' + newVersion, line), end='')
|
||||||
|
|
||||||
|
# Info.plist
|
||||||
|
regExp = re.compile('(\\s+)<string>(?!10\\.15)\\d+\\.\\d+</string>')
|
||||||
|
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
||||||
|
print(regExp.sub('\\1<string>' + shortVersion + '</string>', line), end='')
|
||||||
|
|
||||||
|
regExp = re.compile('(\\s+)<string>\\d+\\.\\d+\\.\\d+</string>')
|
||||||
|
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
||||||
|
print(regExp.sub('\\1<string>' + newVersion + '</string>', line), end='')
|
||||||
|
|
||||||
|
regExp = re.compile('(\\s+)<string>\\d+\\.\\d+\\.\\d+\\.\\d+</string>')
|
||||||
|
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
||||||
|
print(regExp.sub('\\1<string>' + newVersion + '.1</string>', line), end='')
|
@ -1,57 +0,0 @@
|
|||||||
name: vnote
|
|
||||||
version: "2.3"
|
|
||||||
summary: Markdown note-taking app
|
|
||||||
description: |
|
|
||||||
VNote is a note-taking application that
|
|
||||||
knows programmers and Markdown better.
|
|
||||||
It's designed to provide both powerful
|
|
||||||
note management and pleasant Markdown
|
|
||||||
experience.
|
|
||||||
|
|
||||||
confinement: devmode
|
|
||||||
|
|
||||||
apps:
|
|
||||||
vnote:
|
|
||||||
command: desktop-launch VNote
|
|
||||||
|
|
||||||
parts:
|
|
||||||
vnote:
|
|
||||||
source: https://github.com/tamlok/vnote.git
|
|
||||||
plugin: qmake
|
|
||||||
qt-version: qt5
|
|
||||||
options:
|
|
||||||
- CONFIG+=release
|
|
||||||
- CONFIG+=c++11
|
|
||||||
- CONFIG+=c99
|
|
||||||
- QMAKE_CXX=g++-6
|
|
||||||
- QMAKE_CC=gcc-6
|
|
||||||
- QMAKE_CFLAGS+=-std=c99
|
|
||||||
- ./VNote.pro
|
|
||||||
build-packages:
|
|
||||||
- build-essential
|
|
||||||
- g++-6
|
|
||||||
- gcc-6
|
|
||||||
- qtbase5-dev
|
|
||||||
- libqt5svg5-dev
|
|
||||||
- libqt5webchannel5-dev
|
|
||||||
- qt5-default
|
|
||||||
- qtpositioning5-dev
|
|
||||||
- qtwebengine5-dev
|
|
||||||
- libxcb1-dev
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libssl-dev
|
|
||||||
- libgl1-mesa-dev
|
|
||||||
stage-packages:
|
|
||||||
- libqt5gui5
|
|
||||||
- libqt5core5a
|
|
||||||
- libqt5network5
|
|
||||||
- libqt5printsupport5
|
|
||||||
- libqt5webchannel5
|
|
||||||
- libqt5webenginecore5
|
|
||||||
- libqt5webenginewidgets5
|
|
||||||
- libqt5widgets5
|
|
||||||
- libqt5svg5
|
|
||||||
- libxcb1
|
|
||||||
- libxcb-xkb1
|
|
||||||
- openssl
|
|
||||||
after: [desktop-qt5]
|
|
@ -1,209 +1,179 @@
|
|||||||
add_executable(VNote main.cpp
|
cmake_minimum_required(VERSION 3.20)
|
||||||
vmainwindow.cpp
|
|
||||||
vdirectorytree.cpp
|
|
||||||
vnote.cpp
|
|
||||||
vnotebook.cpp
|
|
||||||
dialog/vnewdirdialog.cpp
|
|
||||||
vconfigmanager.cpp
|
|
||||||
vfilelist.cpp
|
|
||||||
dialog/vnewfiledialog.cpp
|
|
||||||
vedit.cpp
|
|
||||||
vdocument.cpp
|
|
||||||
utils/vutils.cpp
|
|
||||||
vpreviewpage.cpp
|
|
||||||
vstyleparser.cpp
|
|
||||||
dialog/vnewnotebookdialog.cpp
|
|
||||||
vmarkdownconverter.cpp
|
|
||||||
dialog/vnotebookinfodialog.cpp
|
|
||||||
dialog/vdirinfodialog.cpp
|
|
||||||
dialog/vfileinfodialog.cpp
|
|
||||||
veditoperations.cpp
|
|
||||||
vmdeditoperations.cpp
|
|
||||||
dialog/vinsertimagedialog.cpp
|
|
||||||
vdownloader.cpp
|
|
||||||
veditarea.cpp
|
|
||||||
veditwindow.cpp
|
|
||||||
vedittab.cpp
|
|
||||||
voutline.cpp
|
|
||||||
vsingleinstanceguard.cpp
|
|
||||||
vdirectory.cpp
|
|
||||||
vfile.cpp
|
|
||||||
vnotebookselector.cpp
|
|
||||||
vnofocusitemdelegate.cpp
|
|
||||||
vmdedit.cpp
|
|
||||||
dialog/vfindreplacedialog.cpp
|
|
||||||
dialog/vsettingsdialog.cpp
|
|
||||||
dialog/vdeletenotebookdialog.cpp
|
|
||||||
dialog/vselectdialog.cpp
|
|
||||||
vcaptain.cpp
|
|
||||||
vopenedlistmenu.cpp
|
|
||||||
vnavigationmode.cpp
|
|
||||||
vorphanfile.cpp
|
|
||||||
vcodeblockhighlighthelper.cpp
|
|
||||||
vwebview.cpp
|
|
||||||
vmdtab.cpp
|
|
||||||
vhtmltab.cpp
|
|
||||||
utils/vvim.cpp
|
|
||||||
utils/veditutils.cpp
|
|
||||||
vvimindicator.cpp
|
|
||||||
vbuttonwithwidget.cpp
|
|
||||||
vtabindicator.cpp
|
|
||||||
dialog/vupdater.cpp
|
|
||||||
dialog/vorphanfileinfodialog.cpp
|
|
||||||
vtextblockdata.cpp
|
|
||||||
utils/vpreviewutils.cpp
|
|
||||||
dialog/vconfirmdeletiondialog.cpp
|
|
||||||
vnotefile.cpp
|
|
||||||
vattachmentlist.cpp
|
|
||||||
dialog/vsortdialog.cpp
|
|
||||||
vfilesessioninfo.cpp
|
|
||||||
vtableofcontent.cpp
|
|
||||||
utils/vmetawordmanager.cpp
|
|
||||||
vmetawordlineedit.cpp
|
|
||||||
dialog/vinsertlinkdialog.cpp
|
|
||||||
vplaintextedit.cpp
|
|
||||||
vimageresourcemanager.cpp
|
|
||||||
vlinenumberarea.cpp
|
|
||||||
veditor.cpp
|
|
||||||
vmdeditor.cpp
|
|
||||||
veditconfig.cpp
|
|
||||||
vpreviewmanager.cpp
|
|
||||||
vimageresourcemanager2.cpp
|
|
||||||
vtextdocumentlayout.cpp
|
|
||||||
vtextedit.cpp
|
|
||||||
vsnippetlist.cpp
|
|
||||||
vsnippet.cpp
|
|
||||||
dialog/veditsnippetdialog.cpp
|
|
||||||
utils/vimnavigationforwidget.cpp
|
|
||||||
vtoolbox.cpp
|
|
||||||
vinsertselector.cpp
|
|
||||||
utils/vclipboardutils.cpp
|
|
||||||
vpalette.cpp
|
|
||||||
vbuttonmenuitem.cpp
|
|
||||||
utils/viconutils.cpp
|
|
||||||
lineeditdelegate.cpp
|
|
||||||
dialog/vtipsdialog.cpp
|
|
||||||
dialog/vcopytextashtmldialog.cpp
|
|
||||||
vwaitingwidget.cpp
|
|
||||||
utils/vwebutils.cpp
|
|
||||||
vlineedit.cpp
|
|
||||||
vcart.cpp
|
|
||||||
vvimcmdlineedit.cpp
|
|
||||||
vlistwidget.cpp
|
|
||||||
vsimplesearchinput.cpp
|
|
||||||
vstyleditemdelegate.cpp
|
|
||||||
vtreewidget.cpp
|
|
||||||
dialog/vexportdialog.cpp
|
|
||||||
vexporter.cpp
|
|
||||||
vsearcher.cpp
|
|
||||||
vsearch.cpp
|
|
||||||
vsearchresulttree.cpp
|
|
||||||
vsearchengine.cpp
|
|
||||||
vuniversalentry.cpp
|
|
||||||
vlistwidgetdoublerows.cpp
|
|
||||||
vdoublerowitemwidget.cpp
|
|
||||||
vsearchue.cpp
|
|
||||||
voutlineue.cpp
|
|
||||||
vhelpue.cpp
|
|
||||||
vlistfolderue.cpp
|
|
||||||
dialog/vfixnotebookdialog.cpp
|
|
||||||
vplantumlhelper.cpp
|
|
||||||
vgraphvizhelper.cpp
|
|
||||||
vlivepreviewhelper.cpp
|
|
||||||
vmathjaxpreviewhelper.cpp
|
|
||||||
vmathjaxwebdocument.cpp
|
|
||||||
vmathjaxinplacepreviewhelper.cpp
|
|
||||||
vhistorylist.cpp
|
|
||||||
vexplorer.cpp
|
|
||||||
vlistue.cpp
|
|
||||||
vuetitlecontentpanel.cpp
|
|
||||||
utils/vprocessutils.cpp
|
|
||||||
vtagpanel.cpp
|
|
||||||
valltagspanel.cpp
|
|
||||||
vtaglabel.cpp
|
|
||||||
vtagexplorer.cpp
|
|
||||||
pegmarkdownhighlighter.cpp
|
|
||||||
pegparser.cpp
|
|
||||||
peghighlighterresult.cpp
|
|
||||||
vtexteditcompleter.cpp
|
|
||||||
utils/vkeyboardlayoutmanager.cpp
|
|
||||||
dialog/vkeyboardlayoutmappingdialog.cpp
|
|
||||||
vfilelistwidget.cpp
|
|
||||||
widgets/vcombobox.cpp
|
|
||||||
vtablehelper.cpp
|
|
||||||
vtable.cpp
|
|
||||||
dialog/vinserttabledialog.cpp
|
|
||||||
isearchengine.cpp
|
|
||||||
iuniversalentry.cpp
|
|
||||||
vnote.qrc translations.qrc)
|
|
||||||
|
|
||||||
# Qt5 libraries
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
target_link_libraries(VNote PRIVATE Qt5::Core Qt5::WebEngine Qt5::WebEngineWidgets
|
|
||||||
Qt5::Network Qt5::PrintSupport Qt5::WebChannel Qt5::Widgets
|
|
||||||
Qt5::PrintSupport Qt5::Svg)
|
|
||||||
set_property(TARGET VNote PROPERTY AUTORCC_OPTIONS "--compress;9")
|
|
||||||
|
|
||||||
# Thirdparty libraries
|
set(CMAKE_INSTALL_BINDIR "." CACHE STRING "Binary dir for install")
|
||||||
target_include_directories(VNote PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/peg-highlight ${CMAKE_SOURCE_DIR}/hoedown)
|
|
||||||
target_link_libraries(VNote PRIVATE peg-highlight hoedown)
|
|
||||||
|
|
||||||
# Compile options
|
set(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use (5 or 6), defaults to 6")
|
||||||
if(GCC_VERSION VERSION_GREATER_EQUAL 8.0)
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} REQUIRED COMPONENTS Core Gui Network PrintSupport Sql Svg Widgets WebChannel WebEngineWidgets LinguistTools)
|
||||||
target_compile_options(VNote PRIVATE "-Wno-class-memaccess")
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} OPTIONAL_COMPONENTS Core5Compat)
|
||||||
|
|
||||||
|
if ((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
|
qt_standard_project_setup()
|
||||||
|
else()
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
## INSTALLS
|
# Application icon on Windows
|
||||||
install(TARGETS VNote RUNTIME DESTINATION bin)
|
set(VX_APP_ICON_RC_WIN data/core/icons/vnote.rc)
|
||||||
install(FILES translations/vnote_zh_CN.qm translations/vnote_ja.qm DESTINATION translations )
|
|
||||||
|
# The MACOSX_BUNDLE_ICON_FILE variable is added to the Info.plist
|
||||||
|
# generated by CMake. This variable contains the .icns file name,
|
||||||
|
# without the path.
|
||||||
|
set(MACOSX_BUNDLE_ICON_FILE vnote.icns)
|
||||||
|
# And the following tells CMake where to find and install the file itself.
|
||||||
|
set(VX_APP_ICON_MACOS data/core/icons/vnote.icns)
|
||||||
|
set_source_files_properties(${VX_APP_ICON_MACOS} PROPERTIES
|
||||||
|
MACOSX_PACKAGE_LOCATION "Resources")
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
set(VX_TS_FILES data/core/translations/vnote_zh_CN.ts
|
||||||
|
data/core/translations/vnote_ja.ts)
|
||||||
|
if((QT_DEFAULT_MAJOR_VERSION EQUAL 6))
|
||||||
|
if((Qt6Widgets_VERSION VERSION_GREATER_EQUAL 6.7.0))
|
||||||
|
qt_add_lupdate(TS_FILES ${VX_TS_FILES}
|
||||||
|
SOURCE_TARGETS vnote)
|
||||||
|
else()
|
||||||
|
qt_add_lupdate(vnote TS_FILES ${VX_TS_FILES})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
# Generate .qm files from .ts files (lrelease)
|
||||||
|
set_source_files_properties(${VX_TS_FILES} PROPERTIES
|
||||||
|
OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
|
||||||
|
qt_add_translation(VX_QM_FILES ${VX_TS_FILES})
|
||||||
|
add_custom_target(lrelease DEPENDS ${VX_QM_FILES})
|
||||||
|
|
||||||
|
# TODO: VTextEdit translations
|
||||||
|
list(APPEND VX_QM_FILES
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qdialogbuttonbox_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtbase_ja.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtbase_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtv_ja.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtv_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qwebengine_zh_CN.qm
|
||||||
|
)
|
||||||
|
|
||||||
|
# Resources
|
||||||
|
set(VX_RESOURCE_FILES data/core/core.qrc)
|
||||||
|
set(VX_EXTRA_RESOURCE_FILES_RCC ${CMAKE_CURRENT_BINARY_DIR}/vnote_extra.rcc)
|
||||||
|
qt_add_binary_resources(VX_EXTRA_RESOURCE data/extra/extra.qrc DESTINATION ${VX_EXTRA_RESOURCE_FILES_RCC} OPTIONS -compress 9)
|
||||||
|
|
||||||
|
add_executable(vnote WIN32 MACOSX_BUNDLE
|
||||||
|
application.cpp application.h
|
||||||
|
commandlineoptions.cpp commandlineoptions.h
|
||||||
|
fakeaccessible.cpp fakeaccessible.h
|
||||||
|
main.cpp
|
||||||
|
${VX_APP_ICON_RC_WIN} ${VX_APP_ICON_MACOS} ${VX_RESOURCE_FILES}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_dependencies(vnote VX_EXTRA_RESOURCE)
|
||||||
|
|
||||||
|
set(VX_LIBS_FOLDER ../libs)
|
||||||
|
target_include_directories(vnote PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program(GOLD_LINKER "ld.gold")
|
||||||
|
if (NOT ${GOLD_LINKER} STREQUAL GOLD_LINKER-NOTFOUND)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(vnote PRIVATE
|
||||||
|
QT_MESSAGELOGCONTEXT
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(core)
|
||||||
|
add_subdirectory(export)
|
||||||
|
add_subdirectory(imagehost)
|
||||||
|
add_subdirectory(search)
|
||||||
|
add_subdirectory(snippet)
|
||||||
|
add_subdirectory(task)
|
||||||
|
add_subdirectory(unitedentry)
|
||||||
|
add_subdirectory(utils)
|
||||||
|
add_subdirectory(widgets)
|
||||||
|
|
||||||
|
target_link_libraries(vnote PRIVATE
|
||||||
|
Qt::Core
|
||||||
|
Qt::Gui
|
||||||
|
Qt::Network
|
||||||
|
Qt::PrintSupport
|
||||||
|
Qt::Sql
|
||||||
|
Qt::Svg
|
||||||
|
Qt::WebChannel
|
||||||
|
Qt::WebEngineWidgets
|
||||||
|
Qt::Widgets
|
||||||
|
VTextEdit
|
||||||
|
qhotkey
|
||||||
|
)
|
||||||
|
|
||||||
|
if((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
|
target_link_libraries(vnote PRIVATE
|
||||||
|
Qt::Core5Compat
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Copy the qt.conf on Windows
|
||||||
|
if(WIN32)
|
||||||
|
add_custom_command(TARGET vnote POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${PROJECT_SOURCE_DIR}/package/qt.conf" $<TARGET_FILE_DIR:vnote>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
if (WIN32)
|
||||||
|
install(TARGETS vnote RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES "${PROJECT_SOURCE_DIR}/package/qt.conf" DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES ${VX_EXTRA_RESOURCE_FILES_RCC} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES ${VX_QM_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}/translations" OPTIONAL)
|
||||||
|
elseif(APPLE)
|
||||||
|
set(CMAKE_MACOSX_RPATH ON)
|
||||||
|
|
||||||
|
# TODO: declare install for macOS if necessary. For packing, we will manually copy files into
|
||||||
|
# the src/vnote.app bundle.
|
||||||
|
|
||||||
|
# The generated Info.plist will be overridden.
|
||||||
|
set_target_properties(vnote
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME "${PROJECT_NAME}"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}"
|
||||||
|
MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}"
|
||||||
|
MACOSX_BUNDLE_GUI_IDENTIFIER "fun.vnote.vnote"
|
||||||
|
MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}"
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
|
||||||
|
MACOSX_BUNDLE_COPYRIGHT "Distributed under LGPL-3.0 license. Copyright (c) 2024 app.vnote.fun"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install(TARGETS vnote
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
install(FILES ${VX_EXTRA_RESOURCE_FILES_RCC} DESTINATION ${CMAKE_INSTALL_DATADIR})
|
||||||
|
install(FILES ${VX_QM_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/translations" OPTIONAL)
|
||||||
|
|
||||||
if(UNIX AND NOT DARWIN)
|
|
||||||
set(desktop.path applications)
|
set(desktop.path applications)
|
||||||
set(desktop.files vnote.desktop)
|
set(desktop.files data/core/vnote.desktop)
|
||||||
|
|
||||||
set(icon16.path icons/hicolor/16x16/apps)
|
set(icon16.path icons/hicolor/16x16/apps)
|
||||||
set(icon16.files resources/icons/16x16/vnote.png)
|
set(icon16.files data/core/logo/16x16/vnote.png)
|
||||||
|
|
||||||
set(icon32.path icons/hicolor/32x32/apps)
|
set(icon32.path icons/hicolor/32x32/apps)
|
||||||
set(icon32.files resources/icons/32x32/vnote.png)
|
set(icon32.files data/core/logo/32x32/vnote.png)
|
||||||
|
|
||||||
set(icon48.path icons/hicolor/48x48/apps)
|
set(icon48.path icons/hicolor/48x48/apps)
|
||||||
set(icon48.files resources/icons/48x48/vnote.png)
|
set(icon48.files data/core/logo/48x48/vnote.png)
|
||||||
|
|
||||||
set(icon64.path icons/hicolor/64x64/apps)
|
set(icon64.path icons/hicolor/64x64/apps)
|
||||||
set(icon64.files resources/icons/64x64/vnote.png)
|
set(icon64.files data/core/logo/64x64/vnote.png)
|
||||||
|
|
||||||
set(icon128.path icons/hicolor/128x128/apps)
|
set(icon128.path icons/hicolor/128x128/apps)
|
||||||
set(icon128.files resources/icons/128x128/vnote.png)
|
set(icon128.files data/core/logo/128x128/vnote.png)
|
||||||
|
|
||||||
set(icon256.path icons/hicolor/256x256/apps)
|
set(icon256.path icons/hicolor/256x256/apps)
|
||||||
set(icon256.files resources/icons/256x256/vnote.png)
|
set(icon256.files data/core/logo/256x256/vnote.png)
|
||||||
|
|
||||||
set(iconsvg.path icons/hicolor/scalable/apps)
|
set(iconsvg.path icons/hicolor/scalable/apps)
|
||||||
set(iconsvg.files resources/icons/vnote.svg)
|
set(iconsvg.files data/core/logo/vnote.svg)
|
||||||
|
foreach(item IN ITEMS desktop icon16 icon32 icon48 icon64 icon128 icon256 iconsvg)
|
||||||
foreach(items IN ITEMS desktop icon16 icon32 icon48 icon64 icon128 icon256 iconsvg)
|
install(FILES ${CMAKE_CURRENT_LIST_DIR}/${${item}.files}
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${${items}.files}
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/${${item}.path}
|
||||||
DESTINATION share/${${items}.path}
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
|
||||||
endforeach()
|
endforeach()
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE
|
|
||||||
DESTINATION share/doc/vnote/
|
|
||||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
|
|
||||||
RENAME copyright)
|
|
||||||
elseif(DARWIN)
|
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME "VNote")
|
|
||||||
set(MACOSX_BUNDLE_BUNDLE_GUI_IDENTIFIER "com.tamlok.VNote")
|
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.icns)
|
|
||||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
|
||||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING ${MACOSX_BUNDLE_BUNDLE_VERSION})
|
|
||||||
# Set short version independent with project version to be able to increment independendently.
|
|
||||||
math(EXPR SHORT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR} * 100 + ${PROJECT_VERSION_MINOR}")
|
|
||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${SHORT_VERSION_MAJOR}.${PROJECT_VERSION_PATCH}.0")
|
|
||||||
set(MACOSX_BUNDLE_EXECUTABLE_NAME "VNote")
|
|
||||||
set(MACOSX_BUNDLE_COPYRIGHT "Distributed under MIT license. Copyright 2016-2019 Le Tan")
|
|
||||||
set(MACOSX_BUNDLE_INFO_STRING "VNote is a note-taking application that knows programmers and Markdown better. Distributed under MIT license. Copyright 2017 Le Tan")
|
|
||||||
|
|
||||||
set_source_files_properties(${MACOSX_BUNDLE_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/Packaging.cmake)
|
include(${CMAKE_CURRENT_LIST_DIR}/Packaging.cmake)
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} DESTDIR=${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage install
|
message(STATUS "VX_APPIMAGE_DEST_DIR ${VX_APPIMAGE_DEST_DIR}")
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
message(STATUS "VX_APPIMAGE_DESKTOP_FILE ${VX_APPIMAGE_DESKTOP_FILE}")
|
||||||
execute_process(COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop -bundle-non-qt-libs -qmake=${_qmake_executable}
|
|
||||||
# hot fix for a known issue for libnss3 and libnssutils3.
|
execute_process(
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${NSS3_PLUGIN_PATH} ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/lib/
|
COMMAND ${CMAKE_MAKE_PROGRAM} DESTDIR=${VX_APPIMAGE_DEST_DIR} install
|
||||||
COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop -appimage -qmake=${_qmake_executable}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
execute_process(
|
||||||
)
|
COMMAND env QMAKE=${QMAKE_EXECUTABLE} LD_LIBRARY_PATH=/usr/local/lib64:$ENV{LD_LIBRARY_PATH} "${LINUXDEPLOY_EXECUTABLE}" --plugin=qt --output=appimage
|
||||||
|
--appdir=${VX_APPIMAGE_DEST_DIR} -e ${CMAKE_CURRENT_BINARY_DIR}/vnote -d ${VX_APPIMAGE_DESKTOP_FILE}
|
||||||
|
-i ${CMAKE_CURRENT_LIST_DIR}/data/core/logo/64x64/vnote.png
|
||||||
|
-l ${QT_PLUGINS_DIR}/platformthemes/libqgtk3.so
|
||||||
|
-l /usr/local/lib64/libcrypto.so.3
|
||||||
|
-l /usr/local/lib64/libssl.so.3
|
||||||
|
# --exclude-library option does not work as expected
|
||||||
|
# --exclude-library=libssl.so.1.1,libcrypto.so.1.1,libnss3.so,libnssutil3.so
|
||||||
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY})
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app -dmg
|
execute_process(COMMAND "optool" strip -t ${CMAKE_CURRENT_BINARY_DIR}/VNote.app
|
||||||
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
||||||
)
|
)
|
||||||
|
execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_CURRENT_BINARY_DIR}/VNote.app -always-overwrite -verbose=1
|
||||||
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
||||||
|
)
|
||||||
|
@ -1,233 +1,165 @@
|
|||||||
|
# from: https://github.com/miurahr/cmake-qt-packaging-example
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} REQUIRED COMPONENTS Core)
|
||||||
|
|
||||||
find_package(Qt5Core REQUIRED)
|
get_target_property(QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||||
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
|
get_filename_component(QT_BIN_DIR "${QMAKE_EXECUTABLE}" DIRECTORY)
|
||||||
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
|
execute_process(COMMAND ${QMAKE_EXECUTABLE} -query QT_VERSION OUTPUT_VARIABLE QT_VERSION)
|
||||||
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}")
|
|
||||||
find_program(LINUXDEPLOYQT_EXECUTABLE linuxdeployqt linuxdeployqt-continuous-x86_64.AppImage HINTS "${_qt_bin_dir}")
|
set(QT_TOOLS_DIR "${QT_BIN_DIR}/../../../Tools")
|
||||||
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}")
|
cmake_path(NORMAL_PATH QT_TOOLS_DIR OUTPUT_VARIABLE QT_TOOLS_DIR)
|
||||||
find_program(MACDEPLOYQTFIX_EXECUTABLE macdeployqtfix.py HINTS "${_qt_bin_dir}")
|
|
||||||
|
set(QT_PLUGINS_DIR "${QT_BIN_DIR}/../plugins")
|
||||||
|
cmake_path(NORMAL_PATH QT_PLUGINS_DIR OUTPUT_VARIABLE QT_PLUGINS_DIR)
|
||||||
|
|
||||||
|
# To use the specific version of Qt
|
||||||
|
set(WINDEPLOYQT_EXECUTABLE "${QT_BIN_DIR}/windeployqt.exe")
|
||||||
|
|
||||||
|
find_program(LINUXDEPLOY_EXECUTABLE linuxdeploy linuxdeploy-x86_64.AppImage HINTS "${QT_BIN_DIR}")
|
||||||
|
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${QT_BIN_DIR}")
|
||||||
|
find_program(MACDEPLOYQTFIX_EXECUTABLE macdeployqtfix.py HINTS "${QT_BIN_DIR}")
|
||||||
find_package(Python)
|
find_package(Python)
|
||||||
|
|
||||||
set(CPACK_IFW_ROOT $ENV{HOME}/Qt/QtIFW-3.0.6/ CACHE PATH "Qt Installer Framework installation base path")
|
|
||||||
find_program(BINARYCREATOR_EXECUTABLE binarycreator HINTS "${_qt_bin_dir}" ${CPACK_IFW_ROOT}/bin)
|
|
||||||
|
|
||||||
mark_as_advanced(WINDEPLOYQT_EXECUTABLE LINUXDEPLOYQT_EXECUTABLE)
|
|
||||||
mark_as_advanced(MACDEPLOYQT_EXECUTABLE MACDEPLOYQTFIX_EXECUTABLE)
|
|
||||||
|
|
||||||
function(linuxdeployqt destdir desktopfile)
|
|
||||||
# creating AppDir
|
|
||||||
add_custom_command(TARGET bundle PRE_BUILD
|
|
||||||
COMMAND "${CMAKE_MAKE_PROGRAM}" DESTDIR=${destdir} install
|
|
||||||
COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${destdir}/${CMAKE_INSTALL_PREFIX}/${desktopfile} -bundle-non-qt-libs
|
|
||||||
-qmake=${_qmake_executable}
|
|
||||||
# hot fix for a known issue for libnss3 and libnssutils3.
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${NSS3_PLUGIN_PATH}
|
|
||||||
${destdir}/${CMAKE_INSTALL_PREFIX}/lib/
|
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
||||||
# packaging AppImage
|
|
||||||
add_custom_command(TARGET bundle POST_BUILD
|
|
||||||
COMMAND "${LINUXDEPLOYQT_EXECUTABLE}" ${destdir}/${CMAKE_INSTALL_PREFIX}/${desktopfile}
|
|
||||||
-appimage -qmake=${_qmake_executable}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/packaging)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(windeployqt target)
|
function(windeployqt target)
|
||||||
|
|
||||||
# Bundle Library Files
|
# Bundle Library Files
|
||||||
if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
|
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
|
||||||
set(WINDEPLOYQT_ARGS --debug)
|
|
||||||
else()
|
if ((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
set(WINDEPLOYQT_ARGS --release)
|
if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
|
||||||
|
set(WINDEPLOYQT_ARGS --debug)
|
||||||
|
else()
|
||||||
|
set(WINDEPLOYQT_ARGS --release)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_command(TARGET ${target} POST_BUILD
|
add_custom_target(deploy
|
||||||
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
||||||
COMMAND "${CMAKE_COMMAND}" -E
|
COMMAND "${CMAKE_COMMAND}" -E
|
||||||
env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}"
|
env PATH="${QT_BIN_DIR}" "${WINDEPLOYQT_EXECUTABLE}"
|
||||||
${WINDEPLOYQT_ARGS}
|
${WINDEPLOYQT_ARGS}
|
||||||
--verbose 0
|
--no-quick-import
|
||||||
--no-compiler-runtime
|
--no-opengl-sw
|
||||||
--no-angle
|
--no-compiler-runtime
|
||||||
--no-opengl-sw
|
--translations zh_CN,ja
|
||||||
--dir "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
--dir "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
||||||
$<TARGET_FILE:${target}>
|
$<TARGET_FILE:${target}>
|
||||||
COMMENT "Deploying Qt..."
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/generic/"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/styles/"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/qmltooling/"
|
||||||
|
COMMENT "Deploying Qt..."
|
||||||
|
DEPENDS vnote lrelease
|
||||||
)
|
)
|
||||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/winqt/" DESTINATION bin)
|
|
||||||
|
add_dependencies(pack deploy)
|
||||||
|
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/winqt/" DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
|
set(OPENSSL_ROOT_DIR "${QT_TOOLS_DIR}/OpenSSL/Win_x64" CACHE STRING "OpenSSL dir")
|
||||||
|
file(GLOB OPENSSL_LIBS_FILES "${OPENSSL_ROOT_DIR}/bin/lib*.dll")
|
||||||
|
cmake_path(NORMAL_PATH OPENSSL_LIBS_FILES OUTPUT_VARIABLE OPENSSL_LIBS_FILES)
|
||||||
|
install(FILES ${OPENSSL_LIBS_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
|
message(STATUS "OpenSSLExtraLIBDIR:${OPENSSL_EXTRA_LIB_DIR}")
|
||||||
|
file(GLOB OPENSSL_EXTRA_LIB_FILES "${OPENSSL_EXTRA_LIB_DIR}/lib*.dll")
|
||||||
|
cmake_path(NORMAL_PATH OPENSSL_EXTRA_LIB_FILES OUTPUT_VARIABLE OPENSSL_EXTRA_LIB_FILES)
|
||||||
|
message(STATUS "OpenSSLExtraLibFiles:${OPENSSL_EXTRA_LIB_FILES}")
|
||||||
|
install(FILES ${OPENSSL_EXTRA_LIB_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
||||||
include(InstallRequiredSystemLibraries)
|
include(InstallRequiredSystemLibraries)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(macdeployqt bundle targetdir _PACKAGER)
|
set(CPACK_PACKAGE_VENDOR "VNoteX")
|
||||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/CPackMacDeployQt-${_PACKAGER}.cmake
|
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||||
CONTENT "set(APP_BUNDLE_DIR \"${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Darwin/${_PACKAGER}/${targetdir}/${bundle}\")
|
|
||||||
execute_process(
|
|
||||||
COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE_DIR}}\" -always-overwrite
|
|
||||||
COMMAND ${Python_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE_DIR}/Contents/MacOS/VNote\" ${qt_bin_dir}/../
|
|
||||||
COMMAND \"${MACDEPLOYQT_EXECUTABLE}\" \"${APP_BUNDLE_DIR}>/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app
|
|
||||||
COMMAND ${Python_EXECUTABLE} \"${MACDEPLOYQTFIX_EXECUTABLE}\" \"${APP_BUNDLE_DIR}>/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers/QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess\" ${qt_bin_dir}/../
|
|
||||||
)"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(SCRIPT ${CMAKE_BINARY_DIR}/CPackMacDeployQt-${_PACKAGER}.cmake COMPONENT Runtime)
|
|
||||||
include(InstallRequiredSystemLibraries)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VENDOR "Le Tan")
|
|
||||||
set(CPACK_PACKAGE_NAME "vnote")
|
|
||||||
set(CPACK_PACKAGE_CONTACT "Le Tan <tamlokveer@gmail.com>")
|
set(CPACK_PACKAGE_CONTACT "Le Tan <tamlokveer@gmail.com>")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING.LESSER")
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||||
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "vnote")
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
|
||||||
set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/packaging")
|
set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
|
|
||||||
|
# Start menu entry on Windows
|
||||||
|
set(CPACK_PACKAGE_EXECUTABLES "vnote" "VNote")
|
||||||
|
# Desktop link on Windows
|
||||||
|
set(CPACK_CREATE_DESKTOP_LINKS "vnote")
|
||||||
|
|
||||||
# set human names to exetuables
|
|
||||||
set(CPACK_PACKAGE_EXECUTABLES "VNote" "VNote")
|
|
||||||
set(CPACK_CREATE_DESKTOP_LINKS "VNote")
|
|
||||||
set(CPACK_STRIP_FILES TRUE)
|
set(CPACK_STRIP_FILES TRUE)
|
||||||
|
|
||||||
|
# WIX generator
|
||||||
|
set(CPACK_WIX_UPGRADE_GUID BA25F337-991A-4893-9D8A-AD5E89BAF5C4)
|
||||||
|
set(CPACK_WIX_PRODUCT_GUID BA25F337-991A-4893-9D8A-AD5E89BAF5C4)
|
||||||
|
set(CPACK_WIX_LICENSE_RTF "${PROJECT_SOURCE_DIR}/package/lgpl-3.0.rtf")
|
||||||
|
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_LIST_DIR}/data/core/icons/vnote.ico")
|
||||||
|
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/package/wix_banner.png")
|
||||||
|
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/package/wix_dialog.png")
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# include CPack, so we get target for packages
|
# include CPack, so we get target for packages
|
||||||
set(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
|
set(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
|
||||||
|
|
||||||
add_custom_target(bundle
|
add_custom_target(pack
|
||||||
COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake"
|
COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake" "--verbose"
|
||||||
COMMENT "Running CPACK. Please wait..."
|
COMMENT "Running CPACK. Please wait..."
|
||||||
DEPENDS VNote)
|
DEPENDS vnote)
|
||||||
|
add_dependencies(pack lrelease)
|
||||||
|
|
||||||
set(CPACK_GENERATOR)
|
set(CPACK_GENERATOR)
|
||||||
|
|
||||||
# Qt IFW packaging framework
|
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_LIST_DIR}/data/core/logo/64x64/vnote.png")
|
||||||
if(BINARYCREATOR_EXECUTABLE)
|
|
||||||
list(APPEND CPACK_GENERATOR IFW)
|
if(WIN32)
|
||||||
message(STATUS " + Qt Installer Framework YES ")
|
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_BIN_DIR}" DOC "Path to the windeployqt utility")
|
||||||
else()
|
|
||||||
message(STATUS " + Qt Installer Framework NO ")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX)
|
|
||||||
#--------------------------------------------------------------------------
|
|
||||||
# Windows specific
|
|
||||||
list(APPEND CPACK_GENERATOR ZIP)
|
list(APPEND CPACK_GENERATOR ZIP)
|
||||||
message(STATUS "Package generation - Windows")
|
message(STATUS "Package generation - Windows - Zip")
|
||||||
message(STATUS " + ZIP YES ")
|
|
||||||
|
|
||||||
set(PACKAGE_ICON "${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.ico")
|
find_program(WIX_EXECUTABLE wix HINTS "${QT_BIN_DIR}" DOC "Path to the WiX utility")
|
||||||
|
|
||||||
# NSIS windows installer
|
if (NOT WIX_EXECUTABLE-NOTFOUND)
|
||||||
find_program(NSIS_PATH nsis PATH_SUFFIXES nsis)
|
list(APPEND CPACK_GENERATOR WIX)
|
||||||
if(NSIS_PATH)
|
message(STATUS "Package generation - Windows - WiX")
|
||||||
list(APPEND CPACK_GENERATOR NSIS)
|
|
||||||
message(STATUS " + NSIS YES ")
|
|
||||||
|
|
||||||
set(CPACK_NSIS_DISPLAY_NAME ${CPACK_PACKAGE_NAME})
|
|
||||||
# Icon of the installer
|
|
||||||
file(TO_NATIVE_PATH "${PACKAGE_ICON}" CPACK_NSIS_MUI_ICON)
|
|
||||||
file(TO_NATIVE_PATH "${PACKAGE_ICON}" CPACK_NSIS_MUI_HEADERIMAGE_BITMAP)
|
|
||||||
set(CPACK_NSIS_CONTACT "${CPACK_PACKAGE_CONTACT}")
|
|
||||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
|
||||||
else()
|
|
||||||
message(STATUS " + NSIS NO ")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# NuGet package
|
windeployqt(vnote)
|
||||||
find_program(NUGET_EXECUTABLE nuget)
|
|
||||||
if(NUGET_EXECUTABLE)
|
|
||||||
list(APPEND CPACK_GENERATOR NuGET)
|
|
||||||
message(STATUS " + NuGET YES ")
|
|
||||||
set(CPACK_NUGET_PACKAGE_NAME "VNote")
|
|
||||||
else()
|
|
||||||
message(STATUS " + NuGET NO ")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
windeployqt(VNote)
|
|
||||||
|
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
#--------------------------------------------------------------------------
|
# Manually copy resources.
|
||||||
# Apple specific
|
set(VX_BUNDLE_CONTENTS_DIR $<TARGET_FILE_DIR:vnote>/..)
|
||||||
message(STATUS "Package generation - Mac OS X")
|
add_custom_target(deploy
|
||||||
message(STATUS " + TBZ2 YES ")
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/data/core/Info.plist" ${VX_BUNDLE_CONTENTS_DIR}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${VX_EXTRA_RESOURCE_FILES_RCC} ${VX_BUNDLE_CONTENTS_DIR}/Resources
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${VX_BUNDLE_CONTENTS_DIR}/Resources/translations
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${VX_QM_FILES} ${VX_BUNDLE_CONTENTS_DIR}/Resources/translations
|
||||||
|
COMMENT "Copying resources into bundle Contents ${VX_BUNDLE_CONTENTS_DIR}"
|
||||||
|
DEPENDS vnote lrelease
|
||||||
|
)
|
||||||
|
add_dependencies(pack deploy)
|
||||||
|
|
||||||
list(APPEND CPACK_GENERATOR TBZ2)
|
message(STATUS "MACDeployQtExecutable: ${MACDEPLOYQT_EXECUTABLE}")
|
||||||
set(CPACK_PACKAGE_ICON ${CMAKE_SOURCE_DIR}/resources/Icon.icns)
|
if (MACDEPLOYQT_EXECUTABLE)
|
||||||
set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks")
|
message(STATUS "Package generation - MacOS - DMG")
|
||||||
macdeployqt("${PROJECT_NAME}.app" "${PROJECT_NAME}-${PROJECT_VERSION}-Darwin" "TBZ")
|
|
||||||
|
|
||||||
# XXX: not working settings for bundle and dragndrop generator
|
|
||||||
set(CPACK_BUNDLE_NAME "${PROJECT_NAME}" )
|
|
||||||
set(CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/Info.plist")
|
|
||||||
set(CPACK_BUNDLE_ICON ${CMAKE_PACKAGE_ICON})
|
|
||||||
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
|
||||||
set(CPACK_DMG_FORMAT "UDBZ")
|
|
||||||
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.png")
|
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
|
|
||||||
list(APPEND CPACK_GENERATOR External)
|
list(APPEND CPACK_GENERATOR External)
|
||||||
message(STATUS " + macdeployqt -dmg YES ")
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CPackMacDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CPackMacDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
|
include(InstallRequiredSystemLibraries)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
#-----------------------------------------------------------------------------
|
message(STATUS "LinuxDeployExecutable: ${LINUXDEPLOY_EXECUTABLE}")
|
||||||
# Linux specific
|
if(LINUXDEPLOY_EXECUTABLE)
|
||||||
list(APPEND CPACK_GENERATOR TBZ2 TXZ)
|
message(STATUS "Package generation - Linux - AppImage")
|
||||||
message(STATUS "Package generation - UNIX")
|
|
||||||
message(STATUS " + TBZ2 YES ")
|
|
||||||
message(STATUS " + TXZ YES ")
|
|
||||||
|
|
||||||
find_program(RPMBUILD_PATH rpmbuild)
|
list(APPEND CPACK_GENERATOR External)
|
||||||
if(RPMBUILD_PATH)
|
set(VX_APPIMAGE_DEST_DIR "${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage")
|
||||||
message(STATUS " + RPM YES ")
|
set(VX_APPIMAGE_DESKTOP_FILE "${VX_APPIMAGE_DEST_DIR}${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop")
|
||||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/CPackLinuxDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
else()
|
|
||||||
message(STATUS " + RPM NO ")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND CPACK_GENERATOR DEB)
|
|
||||||
message(STATUS " + DEB YES ")
|
|
||||||
# use default, that is an output of `dpkg --print-architecture`
|
|
||||||
#set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://tamlok.github.io/vnote")
|
|
||||||
# check if dependencies exist in standard path, i.e standard package
|
|
||||||
# ubuntu bionic or later has it.
|
|
||||||
find_path(QT5WEBENGINEWIDGET_PATH
|
|
||||||
NAMES libQt5WebEngineWidgets.so
|
|
||||||
PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/lib
|
|
||||||
NO_DEFAULT_PATH)
|
|
||||||
if(QT5WEBENGINEWIDGET_PATH)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
|
||||||
else()
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a, libqt5gui5, libqt5positioning5, libqt5webenginewidgets5")
|
|
||||||
endif()
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "graphviz")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SUGGESTS "libjs-mathjax")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
|
|
||||||
|
|
||||||
if(LINUXDEPLOYQT_EXECUTABLE)
|
|
||||||
message(STATUS " + AppImage YES ")
|
|
||||||
find_path(NSS3_PLUGIN_PATH NAMES libsoftokn3.so PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/lib /usr/local/lib
|
|
||||||
PATH_SUFFIXES nss NO_DEFAULT_PATH)
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 3.13)
|
|
||||||
linuxdeployqt("${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/AppImage" "share/applications/vnote.desktop")
|
|
||||||
else()
|
|
||||||
set(CPACK_GENERATOR "External;${CPACK_GENERATOR}")
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CPackLinuxDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
|
||||||
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(STATUS " + AppImage NO ")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# set package icon
|
|
||||||
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/src/resources/icons/vnote.png")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
75
src/application.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "application.h"
|
||||||
|
|
||||||
|
#include <QFileOpenEvent>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
Application::Application(int &p_argc, char **p_argv)
|
||||||
|
: QApplication(p_argc, p_argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::watchThemeFolder(const QString &p_themeFolderPath)
|
||||||
|
{
|
||||||
|
if (p_themeFolderPath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize watchers only when needed
|
||||||
|
if (!m_styleWatcher) {
|
||||||
|
m_styleWatcher = new QFileSystemWatcher(this);
|
||||||
|
}
|
||||||
|
if (!m_reloadTimer) {
|
||||||
|
m_reloadTimer = new QTimer(this);
|
||||||
|
m_reloadTimer->setSingleShot(true);
|
||||||
|
m_reloadTimer->setInterval(500); // 500ms debounce delay
|
||||||
|
connect(m_reloadTimer, &QTimer::timeout,
|
||||||
|
this, &Application::reloadThemeResources);
|
||||||
|
|
||||||
|
// Connect file watcher to timer
|
||||||
|
connect(m_styleWatcher, &QFileSystemWatcher::directoryChanged,
|
||||||
|
m_reloadTimer, qOverload<>(&QTimer::start));
|
||||||
|
connect(m_styleWatcher, &QFileSystemWatcher::fileChanged,
|
||||||
|
m_reloadTimer, qOverload<>(&QTimer::start));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch the theme folder and its files
|
||||||
|
m_styleWatcher->addPath(p_themeFolderPath);
|
||||||
|
|
||||||
|
// Also watch individual files in the theme folder
|
||||||
|
QDir themeDir(p_themeFolderPath);
|
||||||
|
QStringList files = themeDir.entryList(QDir::Files);
|
||||||
|
for (const QString &file : files) {
|
||||||
|
m_styleWatcher->addPath(themeDir.filePath(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::reloadThemeResources()
|
||||||
|
{
|
||||||
|
VNoteX::getInst().getThemeMgr().refreshCurrentTheme();
|
||||||
|
|
||||||
|
auto stylesheet = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet();
|
||||||
|
if (!stylesheet.isEmpty()) {
|
||||||
|
setStyleSheet(stylesheet);
|
||||||
|
style()->unpolish(this);
|
||||||
|
style()->polish(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::event(QEvent *p_event)
|
||||||
|
{
|
||||||
|
// On macOS, we need this to open file from Finder.
|
||||||
|
if (p_event->type() == QEvent::FileOpen) {
|
||||||
|
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(p_event);
|
||||||
|
qDebug() << "request to open file" << openEvent->file();
|
||||||
|
emit openFileRequested(openEvent->file());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QApplication::event(p_event);
|
||||||
|
}
|
34
src/application.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef APPLICATION_H
|
||||||
|
#define APPLICATION_H
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
class QFileSystemWatcher;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Application : public QApplication
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Application(int &p_argc, char **p_argv);
|
||||||
|
|
||||||
|
// Set up theme folder watcher for hot-reload
|
||||||
|
void watchThemeFolder(const QString &p_themeFolderPath);
|
||||||
|
|
||||||
|
// Reload the theme resources (stylesheet, icons, etc)
|
||||||
|
void reloadThemeResources();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void openFileRequested(const QString &p_filePath);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool event(QEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFileSystemWatcher *m_styleWatcher = nullptr;
|
||||||
|
QTimer *m_reloadTimer = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // APPLICATION_H
|
81
src/commandlineoptions.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "commandlineoptions.h"
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCommandLineOption>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <widgets/mainwindow.h>
|
||||||
|
|
||||||
|
using vnotex::MainWindow;
|
||||||
|
|
||||||
|
CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_arguments)
|
||||||
|
{
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(MainWindow::tr("A pleasant note-taking platform."));
|
||||||
|
const auto helpOpt = parser.addHelpOption();
|
||||||
|
const auto versionOpt = parser.addVersionOption();
|
||||||
|
|
||||||
|
// Positional arguments.
|
||||||
|
parser.addPositionalArgument("paths", MainWindow::tr("Files or folders to open."));
|
||||||
|
|
||||||
|
const QCommandLineOption verboseOpt("verbose", MainWindow::tr("Print more logs."));
|
||||||
|
parser.addOption(verboseOpt);
|
||||||
|
|
||||||
|
const QCommandLineOption logStderrOpt("log-stderr", MainWindow::tr("Log to stderr."));
|
||||||
|
parser.addOption(logStderrOpt);
|
||||||
|
|
||||||
|
const QCommandLineOption watchThemesOpt("watch-themes", MainWindow::tr("Watch theme folder for changes."));
|
||||||
|
parser.addOption(watchThemesOpt);
|
||||||
|
|
||||||
|
// WebEngine options.
|
||||||
|
// No need to handle them. Just add them to the parser to avoid parse error.
|
||||||
|
{
|
||||||
|
QCommandLineOption webRemoteDebuggingPortOpt("remote-debugging-port",
|
||||||
|
MainWindow::tr("WebEngine remote debugging port."),
|
||||||
|
MainWindow::tr("port_number"));
|
||||||
|
webRemoteDebuggingPortOpt.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||||
|
parser.addOption(webRemoteDebuggingPortOpt);
|
||||||
|
|
||||||
|
QCommandLineOption webNoSandboxOpt("no-sandbox", MainWindow::tr("WebEngine without sandbox."));
|
||||||
|
webNoSandboxOpt.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||||
|
parser.addOption(webNoSandboxOpt);
|
||||||
|
|
||||||
|
QCommandLineOption webDisableGpu("disable-gpu", MainWindow::tr("WebEngine with GPU disabled."));
|
||||||
|
webDisableGpu.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||||
|
parser.addOption(webDisableGpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser.parse(p_arguments)) {
|
||||||
|
m_errorMsg = parser.errorText();
|
||||||
|
return ParseResult::Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle results.
|
||||||
|
m_helpText = parser.helpText();
|
||||||
|
if (parser.isSet(helpOpt)) {
|
||||||
|
return ParseResult::HelpRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(versionOpt)) {
|
||||||
|
return ParseResult::VersionRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position arguments.
|
||||||
|
const auto args = parser.positionalArguments();
|
||||||
|
m_pathsToOpen = args;
|
||||||
|
|
||||||
|
if (parser.isSet(verboseOpt)) {
|
||||||
|
m_verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(logStderrOpt)) {
|
||||||
|
m_logToStderr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(watchThemesOpt)) {
|
||||||
|
m_watchThemes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseResult::Ok;
|
||||||
|
}
|
35
src/commandlineoptions.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef COMMANDLINEOPTIONS_H
|
||||||
|
#define COMMANDLINEOPTIONS_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class CommandLineOptions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ParseResult
|
||||||
|
{
|
||||||
|
Ok,
|
||||||
|
Error,
|
||||||
|
VersionRequested,
|
||||||
|
HelpRequested
|
||||||
|
};
|
||||||
|
|
||||||
|
CommandLineOptions() = default;
|
||||||
|
|
||||||
|
ParseResult parse(const QStringList &p_arguments);
|
||||||
|
|
||||||
|
QString m_errorMsg;
|
||||||
|
|
||||||
|
QString m_helpText;
|
||||||
|
|
||||||
|
QStringList m_pathsToOpen;
|
||||||
|
|
||||||
|
bool m_verbose = false;
|
||||||
|
|
||||||
|
bool m_logToStderr = false;
|
||||||
|
|
||||||
|
// Whether to watch theme folder for changes
|
||||||
|
bool m_watchThemes = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMMANDLINEOPTIONS_H
|
87
src/core/CMakeLists.txt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
target_sources(vnote PRIVATE
|
||||||
|
buffer/buffer.cpp buffer/buffer.h
|
||||||
|
buffer/bufferprovider.cpp buffer/bufferprovider.h
|
||||||
|
buffer/filebufferprovider.cpp buffer/filebufferprovider.h
|
||||||
|
buffer/filetypehelper.cpp buffer/filetypehelper.h
|
||||||
|
buffer/ibufferfactory.h
|
||||||
|
buffer/markdownbuffer.cpp buffer/markdownbuffer.h
|
||||||
|
buffer/markdownbufferfactory.cpp buffer/markdownbufferfactory.h
|
||||||
|
buffer/mindmapbuffer.cpp buffer/mindmapbuffer.h
|
||||||
|
buffer/mindmapbufferfactory.cpp buffer/mindmapbufferfactory.h
|
||||||
|
buffer/nodebufferprovider.cpp buffer/nodebufferprovider.h
|
||||||
|
buffer/pdfbuffer.cpp buffer/pdfbuffer.h
|
||||||
|
buffer/pdfbufferfactory.cpp buffer/pdfbufferfactory.h
|
||||||
|
buffer/textbuffer.cpp buffer/textbuffer.h
|
||||||
|
buffer/textbufferfactory.cpp buffer/textbufferfactory.h
|
||||||
|
buffer/urlbasedbufferprovider.h
|
||||||
|
buffermgr.cpp buffermgr.h
|
||||||
|
clipboarddata.cpp clipboarddata.h
|
||||||
|
configmgr.cpp configmgr.h
|
||||||
|
coreconfig.cpp coreconfig.h
|
||||||
|
editorconfig.cpp editorconfig.h
|
||||||
|
events.h
|
||||||
|
exception.h
|
||||||
|
externalfile.cpp externalfile.h
|
||||||
|
file.cpp file.h
|
||||||
|
filelocator.h
|
||||||
|
fileopenparameters.h
|
||||||
|
global.cpp global.h
|
||||||
|
historyitem.cpp historyitem.h
|
||||||
|
historymgr.cpp historymgr.h
|
||||||
|
htmltemplatehelper.cpp htmltemplatehelper.h
|
||||||
|
iconfig.h
|
||||||
|
location.h
|
||||||
|
logger.cpp logger.h
|
||||||
|
mainconfig.cpp mainconfig.h
|
||||||
|
markdowneditorconfig.cpp markdowneditorconfig.h
|
||||||
|
mindmapeditorconfig.cpp mindmapeditorconfig.h
|
||||||
|
namebasedserver.h
|
||||||
|
noncopyable.h
|
||||||
|
notebook/bundlenotebook.cpp notebook/bundlenotebook.h
|
||||||
|
notebook/bundlenotebookfactory.cpp notebook/bundlenotebookfactory.h
|
||||||
|
notebook/externalnode.cpp notebook/externalnode.h
|
||||||
|
notebook/historyi.h
|
||||||
|
notebook/inotebookfactory.h
|
||||||
|
notebook/node.cpp notebook/node.h
|
||||||
|
notebook/nodeparameters.cpp notebook/nodeparameters.h
|
||||||
|
notebook/notebook.cpp notebook/notebook.h
|
||||||
|
notebook/notebookdatabaseaccess.cpp notebook/notebookdatabaseaccess.h
|
||||||
|
notebook/notebookparameters.cpp notebook/notebookparameters.h
|
||||||
|
notebook/notebooktagmgr.cpp notebook/notebooktagmgr.h
|
||||||
|
notebook/tag.cpp notebook/tag.h
|
||||||
|
notebook/tagi.h
|
||||||
|
notebook/vxnode.cpp notebook/vxnode.h
|
||||||
|
notebook/vxnodefile.cpp notebook/vxnodefile.h
|
||||||
|
notebookbackend/inotebookbackend.cpp notebookbackend/inotebookbackend.h
|
||||||
|
notebookbackend/inotebookbackendfactory.h
|
||||||
|
notebookbackend/localnotebookbackend.cpp notebookbackend/localnotebookbackend.h
|
||||||
|
notebookbackend/localnotebookbackendfactory.cpp notebookbackend/localnotebookbackendfactory.h
|
||||||
|
notebookconfigmgr/bundlenotebookconfigmgr.cpp notebookconfigmgr/bundlenotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/inotebookconfigmgr.cpp notebookconfigmgr/inotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/inotebookconfigmgrfactory.h
|
||||||
|
notebookconfigmgr/notebookconfig.cpp notebookconfigmgr/notebookconfig.h
|
||||||
|
notebookconfigmgr/vxnodeconfig.cpp notebookconfigmgr/vxnodeconfig.h
|
||||||
|
notebookconfigmgr/vxnotebookconfigmgr.cpp notebookconfigmgr/vxnotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/vxnotebookconfigmgrfactory.cpp notebookconfigmgr/vxnotebookconfigmgrfactory.h
|
||||||
|
notebookmgr.cpp notebookmgr.h
|
||||||
|
pdfviewerconfig.cpp pdfviewerconfig.h
|
||||||
|
quickaccesshelper.cpp quickaccesshelper.h
|
||||||
|
sessionconfig.cpp sessionconfig.h
|
||||||
|
singleinstanceguard.cpp singleinstanceguard.h
|
||||||
|
templatemgr.cpp templatemgr.h
|
||||||
|
texteditorconfig.cpp texteditorconfig.h
|
||||||
|
theme.cpp theme.h
|
||||||
|
thememgr.cpp thememgr.h
|
||||||
|
versioncontroller/dummyversioncontroller.cpp versioncontroller/dummyversioncontroller.h
|
||||||
|
versioncontroller/dummyversioncontrollerfactory.cpp versioncontroller/dummyversioncontrollerfactory.h
|
||||||
|
versioncontroller/iversioncontroller.h
|
||||||
|
versioncontroller/iversioncontrollerfactory.h
|
||||||
|
versioncontroller/versioncontrollerserver.cpp versioncontroller/versioncontrollerserver.h
|
||||||
|
vnotex.cpp vnotex.h
|
||||||
|
webresource.h
|
||||||
|
widgetconfig.cpp widgetconfig.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(vnote PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
577
src/core/buffer/buffer.cpp
Normal file
@ -0,0 +1,577 @@
|
|||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <notebook/node.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <widgets/viewwindow.h>
|
||||||
|
#include <utils/pathutils.h>
|
||||||
|
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/editorconfig.h>
|
||||||
|
|
||||||
|
#include "bufferprovider.h"
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
static vnotex::ID generateBufferID()
|
||||||
|
{
|
||||||
|
static vnotex::ID id = 0;
|
||||||
|
return ++id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Buffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
: QObject(p_parent),
|
||||||
|
m_provider(p_parameters.m_provider),
|
||||||
|
m_id(generateBufferID()),
|
||||||
|
m_readOnly(m_provider->isReadOnly())
|
||||||
|
{
|
||||||
|
m_autoSaveTimer = new QTimer(this);
|
||||||
|
m_autoSaveTimer->setSingleShot(true);
|
||||||
|
m_autoSaveTimer->setInterval(1000);
|
||||||
|
connect(m_autoSaveTimer, &QTimer::timeout,
|
||||||
|
this, &Buffer::autoSave);
|
||||||
|
|
||||||
|
readContent();
|
||||||
|
|
||||||
|
checkBackupFileOfPreviousSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::~Buffer()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_attachedViewWindowCount == 0);
|
||||||
|
Q_ASSERT(!m_viewWindowToSync);
|
||||||
|
Q_ASSERT(!isModified());
|
||||||
|
Q_ASSERT(m_backupFilePath.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::getAttachViewWindowCount() const
|
||||||
|
{
|
||||||
|
return m_attachedViewWindowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::attachViewWindow(ViewWindow *p_win)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_win);
|
||||||
|
Q_ASSERT(!(m_state & StateFlag::Discarded));
|
||||||
|
++m_attachedViewWindowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::detachViewWindow(ViewWindow *p_win)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_win);
|
||||||
|
Q_ASSERT(p_win != m_viewWindowToSync);
|
||||||
|
|
||||||
|
--m_attachedViewWindowCount;
|
||||||
|
Q_ASSERT(m_attachedViewWindowCount >= 0);
|
||||||
|
|
||||||
|
if (m_attachedViewWindowCount == 0) {
|
||||||
|
emit attachedViewWindowEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindow *Buffer::createViewWindow(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
|
||||||
|
{
|
||||||
|
auto window = createViewWindowInternal(p_paras, p_parent);
|
||||||
|
Q_ASSERT(window);
|
||||||
|
window->attachToBuffer(this, p_paras);
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::match(const Node *p_node) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_node);
|
||||||
|
return m_provider->match(p_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::match(const QString &p_filePath) const
|
||||||
|
{
|
||||||
|
return m_provider->match(p_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getName() const
|
||||||
|
{
|
||||||
|
return m_provider->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getPath() const
|
||||||
|
{
|
||||||
|
return m_provider->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getContentPath() const
|
||||||
|
{
|
||||||
|
return m_provider->getContentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getResourcePath() const
|
||||||
|
{
|
||||||
|
return m_provider->getResourcePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
ID Buffer::getId() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &Buffer::getContent() const
|
||||||
|
{
|
||||||
|
const_cast<Buffer *>(this)->syncContent();
|
||||||
|
return m_content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::setContent(const QString &p_content, int &p_revision)
|
||||||
|
{
|
||||||
|
m_viewWindowToSync = nullptr;
|
||||||
|
m_content = p_content;
|
||||||
|
p_revision = ++m_revision;
|
||||||
|
setModified(true);
|
||||||
|
m_autoSaveTimer->start();
|
||||||
|
emit contentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::invalidateContent(const ViewWindow *p_win,
|
||||||
|
const std::function<void(int)> &p_setRevision)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_viewWindowToSync || m_viewWindowToSync == p_win);
|
||||||
|
++m_revision;
|
||||||
|
p_setRevision(m_revision);
|
||||||
|
m_viewWindowToSync = p_win;
|
||||||
|
m_autoSaveTimer->start();
|
||||||
|
emit contentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::getRevision() const
|
||||||
|
{
|
||||||
|
return m_revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::syncContent(const ViewWindow *p_win)
|
||||||
|
{
|
||||||
|
if (m_viewWindowToSync == p_win) {
|
||||||
|
syncContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::syncContent()
|
||||||
|
{
|
||||||
|
if (m_viewWindowToSync) {
|
||||||
|
// Need to sync content.
|
||||||
|
m_content = m_viewWindowToSync->getLatestContent();
|
||||||
|
m_viewWindowToSync = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isModified() const
|
||||||
|
{
|
||||||
|
return m_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::setModified(bool p_modified)
|
||||||
|
{
|
||||||
|
if (m_modified == p_modified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_modified = p_modified;
|
||||||
|
emit modified(m_modified);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isReadOnly() const
|
||||||
|
{
|
||||||
|
return m_readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::OperationCode Buffer::save(bool p_force)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_readOnly);
|
||||||
|
if (m_readOnly) {
|
||||||
|
return OperationCode::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_modified
|
||||||
|
|| p_force
|
||||||
|
|| m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) {
|
||||||
|
syncContent();
|
||||||
|
|
||||||
|
// We do not involve user here to handle file missing and changed outside cases.
|
||||||
|
// The active ViewWindow will check this periodically.
|
||||||
|
// Check if file still exists.
|
||||||
|
if (!p_force && !checkFileExistsOnDisk()) {
|
||||||
|
qWarning() << "failed to save buffer due to file missing on disk" << getPath();
|
||||||
|
return OperationCode::FileMissingOnDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file is modified outside.
|
||||||
|
if (!p_force && checkFileChangedOutside()) {
|
||||||
|
qWarning() << "failed to save buffer due to file changed from outside" << getPath();
|
||||||
|
return OperationCode::FileChangedOutside;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_provider->write(m_content);
|
||||||
|
} catch (Exception &p_e) {
|
||||||
|
qWarning() << "failed to write the buffer content" << getPath() << p_e.what();
|
||||||
|
return OperationCode::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
setModified(false);
|
||||||
|
m_state &= ~(StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside);
|
||||||
|
}
|
||||||
|
return OperationCode::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::OperationCode Buffer::reload()
|
||||||
|
{
|
||||||
|
// Check if file is missing.
|
||||||
|
if (!checkFileExistsOnDisk()) {
|
||||||
|
qWarning() << "failed to save buffer due to file missing on disk" << getPath();
|
||||||
|
return OperationCode::FileMissingOnDisk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_modified
|
||||||
|
|| m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) {
|
||||||
|
readContent();
|
||||||
|
|
||||||
|
emit modified(m_modified);
|
||||||
|
emit contentsChanged();
|
||||||
|
}
|
||||||
|
return OperationCode::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::readContent()
|
||||||
|
{
|
||||||
|
m_content = m_provider->read();
|
||||||
|
++m_revision;
|
||||||
|
|
||||||
|
// Reset state.
|
||||||
|
m_viewWindowToSync = nullptr;
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::discard()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!(m_state & StateFlag::Discarded));
|
||||||
|
Q_ASSERT(m_attachedViewWindowCount == 1);
|
||||||
|
m_autoSaveTimer->stop();
|
||||||
|
m_content.clear();
|
||||||
|
m_state |= StateFlag::Discarded;
|
||||||
|
++m_revision;
|
||||||
|
|
||||||
|
m_viewWindowToSync = nullptr;
|
||||||
|
m_modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::close()
|
||||||
|
{
|
||||||
|
// Delete the backup file if exists.
|
||||||
|
m_autoSaveTimer->stop();
|
||||||
|
if (!m_backupFilePath.isEmpty()) {
|
||||||
|
FileUtils::removeFile(m_backupFilePath);
|
||||||
|
m_backupFilePath.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getImageFolderPath() const
|
||||||
|
{
|
||||||
|
return const_cast<Buffer *>(this)->m_provider->fetchImageFolderPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_srcImagePath);
|
||||||
|
Q_UNUSED(p_imageFileName);
|
||||||
|
Q_ASSERT_X(false, "insertImage", "image insert is not supported");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::insertImage(const QImage &p_image, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_image);
|
||||||
|
Q_UNUSED(p_imageFileName);
|
||||||
|
Q_ASSERT_X(false, "insertImage", "image insert is not supported");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::removeImage(const QString &p_imagePath)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_imagePath);
|
||||||
|
Q_ASSERT_X(false, "removeImage", "image remove is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::autoSave()
|
||||||
|
{
|
||||||
|
if (m_readOnly) {
|
||||||
|
m_autoSaveTimer->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state & (StateFlag::FileMissingOnDisk | StateFlag::FileChangedOutside)) {
|
||||||
|
qDebug() << "disable AutoSave due to file missing on disk or changed outside";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Q_ASSERT(!(m_state & StateFlag::Discarded));
|
||||||
|
auto policy = ConfigMgr::getInst().getEditorConfig().getAutoSavePolicy();
|
||||||
|
switch (policy) {
|
||||||
|
case EditorConfig::AutoSavePolicy::None:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case EditorConfig::AutoSavePolicy::AutoSave:
|
||||||
|
if (save(false) != OperationCode::Success) {
|
||||||
|
qWarning() << "AutoSave failed to save buffer, retry later";
|
||||||
|
} else {
|
||||||
|
emit autoSaved();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EditorConfig::AutoSavePolicy::BackupFile:
|
||||||
|
try {
|
||||||
|
writeBackupFile();
|
||||||
|
} catch (Exception &p_e) {
|
||||||
|
qWarning() << "AutoSave failed to write backup file, retry later" << p_e.what();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::writeBackupFile()
|
||||||
|
{
|
||||||
|
if (m_backupFilePath.isEmpty()) {
|
||||||
|
const auto &config = ConfigMgr::getInst().getEditorConfig();
|
||||||
|
QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory()));
|
||||||
|
backupDirPath = QDir::cleanPath(backupDirPath);
|
||||||
|
auto backupFileName = FileUtils::generateFileNameWithSequence(backupDirPath,
|
||||||
|
getName(),
|
||||||
|
config.getBackupFileExtension());
|
||||||
|
QDir backupDir(backupDirPath);
|
||||||
|
backupDir.mkpath(backupDirPath);
|
||||||
|
m_backupFilePath = backupDir.filePath(backupFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(m_backupFilePathOfPreviousSession.isEmpty());
|
||||||
|
|
||||||
|
// Just use FileUtils instead of notebook backend.
|
||||||
|
FileUtils::writeFile(m_backupFilePath, generateBackupFileHead() + getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::generateBackupFileHead() const
|
||||||
|
{
|
||||||
|
return QStringLiteral("vnotex_backup_file %1|").arg(getContentPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::checkBackupFileOfPreviousSession()
|
||||||
|
{
|
||||||
|
const auto &config = ConfigMgr::getInst().getEditorConfig();
|
||||||
|
if (config.getAutoSavePolicy() != EditorConfig::AutoSavePolicy::BackupFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory()));
|
||||||
|
backupDirPath = QDir::cleanPath(backupDirPath);
|
||||||
|
QDir backupDir(backupDirPath);
|
||||||
|
QStringList backupFiles;
|
||||||
|
{
|
||||||
|
const QString nameFilter = QStringLiteral("%1*%2").arg(getName(), config.getBackupFileExtension());
|
||||||
|
backupFiles = backupDir.entryList(QStringList(nameFilter),
|
||||||
|
QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backupFiles.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &file : backupFiles) {
|
||||||
|
const auto filePath = backupDir.filePath(file);
|
||||||
|
if (isBackupFileOfBuffer(filePath)) {
|
||||||
|
const auto backupContent = readBackupFile(filePath);
|
||||||
|
if (backupContent == getContent()) {
|
||||||
|
// Found backup file with identical content.
|
||||||
|
// Just discard the backup file.
|
||||||
|
FileUtils::removeFile(filePath);
|
||||||
|
qInfo() << "delete identical backup file of previous session" << filePath;
|
||||||
|
} else {
|
||||||
|
m_backupFilePathOfPreviousSession = filePath;
|
||||||
|
qInfo() << "found backup file of previous session" << filePath;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isBackupFileOfBuffer(const QString &p_file) const
|
||||||
|
{
|
||||||
|
QFile file(p_file);
|
||||||
|
if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream st(&file);
|
||||||
|
const auto head = st.readLine();
|
||||||
|
return head.startsWith(generateBackupFileHead());
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &Buffer::getBackupFileOfPreviousSession() const
|
||||||
|
{
|
||||||
|
return m_backupFilePathOfPreviousSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::readBackupFile(const QString &p_filePath)
|
||||||
|
{
|
||||||
|
auto content = FileUtils::readTextFile(p_filePath);
|
||||||
|
return content.mid(content.indexOf(QLatin1Char('|')) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::discardBackupFileOfPreviousSession()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty());
|
||||||
|
|
||||||
|
FileUtils::removeFile(m_backupFilePathOfPreviousSession);
|
||||||
|
qInfo() << "discard backup file of previous session" << m_backupFilePathOfPreviousSession;
|
||||||
|
m_backupFilePathOfPreviousSession.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::recoverFromBackupFileOfPreviousSession()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_backupFilePathOfPreviousSession.isEmpty());
|
||||||
|
|
||||||
|
m_content = readBackupFile(m_backupFilePathOfPreviousSession);
|
||||||
|
m_provider->write(m_content);
|
||||||
|
++m_revision;
|
||||||
|
|
||||||
|
FileUtils::removeFile(m_backupFilePathOfPreviousSession);
|
||||||
|
qInfo() << "recover from backup file of previous session" << m_backupFilePathOfPreviousSession;
|
||||||
|
m_backupFilePathOfPreviousSession.clear();
|
||||||
|
|
||||||
|
// Reset state.
|
||||||
|
m_viewWindowToSync = nullptr;
|
||||||
|
m_modified = false;
|
||||||
|
|
||||||
|
emit modified(m_modified);
|
||||||
|
emit contentsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isChildOf(const Node *p_node) const
|
||||||
|
{
|
||||||
|
return m_provider->isChildOf(p_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isAttachmentSupported() const
|
||||||
|
{
|
||||||
|
return !m_readOnly && m_provider->isAttachmentSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::hasAttachment() const
|
||||||
|
{
|
||||||
|
if (!isAttachmentSupported()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_provider->getAttachmentFolder().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir dir(getAttachmentFolderPath());
|
||||||
|
return !dir.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::getAttachmentFolderPath() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(isAttachmentSupported());
|
||||||
|
return const_cast<Buffer *>(this)->m_provider->fetchAttachmentFolderPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Buffer::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
|
||||||
|
{
|
||||||
|
if (p_files.isEmpty()) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
auto destFolderPath = p_destFolderPath.isEmpty() ? getAttachmentFolderPath() : p_destFolderPath;
|
||||||
|
Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), destFolderPath));
|
||||||
|
auto files = m_provider->addAttachment(destFolderPath, p_files);
|
||||||
|
if (!files.isEmpty()) {
|
||||||
|
emit attachmentChanged();
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath));
|
||||||
|
auto filePath = m_provider->newAttachmentFile(p_destFolderPath, p_name);
|
||||||
|
emit attachmentChanged();
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_destFolderPath));
|
||||||
|
auto folderPath = m_provider->newAttachmentFolder(p_destFolderPath, p_name);
|
||||||
|
emit attachmentChanged();
|
||||||
|
return folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Buffer::renameAttachment(const QString &p_path, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_ASSERT(PathUtils::pathContains(getAttachmentFolderPath(), p_path));
|
||||||
|
return m_provider->renameAttachment(p_path, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Buffer::removeAttachment(const QStringList &p_paths)
|
||||||
|
{
|
||||||
|
m_provider->removeAttachment(p_paths);
|
||||||
|
emit attachmentChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isAttachment(const QString &p_path) const
|
||||||
|
{
|
||||||
|
return PathUtils::pathContains(getAttachmentFolderPath(), p_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isTagSupported() const
|
||||||
|
{
|
||||||
|
return m_provider->isTagSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::ProviderType Buffer::getProviderType() const
|
||||||
|
{
|
||||||
|
return m_provider->getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *Buffer::getNode() const
|
||||||
|
{
|
||||||
|
return m_provider->getNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::checkFileExistsOnDisk()
|
||||||
|
{
|
||||||
|
if (m_provider->checkFileExistsOnDisk()) {
|
||||||
|
m_state &= ~StateFlag::FileMissingOnDisk;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
m_state |= StateFlag::FileMissingOnDisk;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::checkFileChangedOutside()
|
||||||
|
{
|
||||||
|
if (m_provider->checkFileChangedOutside()) {
|
||||||
|
m_state |= StateFlag::FileChangedOutside;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
m_state &= ~StateFlag::FileChangedOutside;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::StateFlags Buffer::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<File> Buffer::getFile() const
|
||||||
|
{
|
||||||
|
return m_provider->getFile();
|
||||||
|
}
|
250
src/core/buffer/buffer.h
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
#ifndef BUFFER_H
|
||||||
|
#define BUFFER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <global.h>
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
class Buffer;
|
||||||
|
class ViewWindow;
|
||||||
|
struct FileOpenParameters;
|
||||||
|
class BufferProvider;
|
||||||
|
class File;
|
||||||
|
|
||||||
|
struct BufferParameters
|
||||||
|
{
|
||||||
|
QSharedPointer<BufferProvider> m_provider;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Buffer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class ProviderType
|
||||||
|
{
|
||||||
|
Internal,
|
||||||
|
External
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class OperationCode
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
FileMissingOnDisk,
|
||||||
|
FileChangedOutside,
|
||||||
|
Failed
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StateFlag
|
||||||
|
{
|
||||||
|
Normal = 0,
|
||||||
|
FileMissingOnDisk = 0x1,
|
||||||
|
FileChangedOutside = 0x2,
|
||||||
|
Discarded = 0x4
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(StateFlags, StateFlag);
|
||||||
|
|
||||||
|
Buffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
virtual ~Buffer();
|
||||||
|
|
||||||
|
int getAttachViewWindowCount() const;
|
||||||
|
|
||||||
|
void attachViewWindow(ViewWindow *p_win);
|
||||||
|
void detachViewWindow(ViewWindow *p_win);
|
||||||
|
|
||||||
|
// Create a view window to show the content of this buffer.
|
||||||
|
// Attach the created view window to this buffer.
|
||||||
|
ViewWindow *createViewWindow(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent);
|
||||||
|
|
||||||
|
// Whether this buffer matches @p_node.
|
||||||
|
bool match(const Node *p_node) const;
|
||||||
|
|
||||||
|
// Whether this buffer matches @p_filePath.
|
||||||
|
bool match(const QString &p_filePath) const;
|
||||||
|
|
||||||
|
// Buffer name.
|
||||||
|
QString getName() const;
|
||||||
|
|
||||||
|
QString getPath() const;
|
||||||
|
|
||||||
|
// In some cases, getPath() may point to a container containting all the stuffs.
|
||||||
|
// getContentPath() will return the real path to the file providing the content.
|
||||||
|
QString getContentPath() const;
|
||||||
|
|
||||||
|
// Get the base path to resolve resources.
|
||||||
|
QString getResourcePath() const;
|
||||||
|
|
||||||
|
// Return nullptr if not available.
|
||||||
|
QSharedPointer<File> getFile() const;
|
||||||
|
|
||||||
|
ID getId() const;
|
||||||
|
|
||||||
|
// Get buffer content.
|
||||||
|
// It may differ from the content on disk.
|
||||||
|
// For performance, we need to sync the content with ViewWindow before returning
|
||||||
|
// the latest content.
|
||||||
|
const QString &getContent() const;
|
||||||
|
|
||||||
|
// @p_revision will be set before contentsChanged is emitted.
|
||||||
|
void setContent(const QString &p_content, int &p_revision);
|
||||||
|
|
||||||
|
// Invalidate the content of buffer.
|
||||||
|
// Need to sync with @p_win to get the latest content.
|
||||||
|
// @p_setRevision will be called to set revision before contentsChanged is emitted.
|
||||||
|
void invalidateContent(const ViewWindow *p_win,
|
||||||
|
const std::function<void(int)> &p_setRevision);
|
||||||
|
|
||||||
|
// Sync content with @p_win if @p_win is the window needed to sync.
|
||||||
|
void syncContent(const ViewWindow *p_win);
|
||||||
|
|
||||||
|
int getRevision() const;
|
||||||
|
|
||||||
|
bool isModified() const;
|
||||||
|
void setModified(bool p_modified);
|
||||||
|
|
||||||
|
bool isReadOnly() const;
|
||||||
|
|
||||||
|
// Save buffer content to file.
|
||||||
|
OperationCode save(bool p_force);
|
||||||
|
|
||||||
|
// Discard changes and reload file.
|
||||||
|
OperationCode reload();
|
||||||
|
|
||||||
|
// Discard the buffer which will invalidate the buffer.
|
||||||
|
void discard();
|
||||||
|
|
||||||
|
// Buffer is about to be deleted.
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// Insert image from @p_srcImagePath.
|
||||||
|
// Return inserted image file path.
|
||||||
|
virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName);
|
||||||
|
|
||||||
|
virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName);
|
||||||
|
|
||||||
|
virtual void removeImage(const QString &p_imagePath);
|
||||||
|
|
||||||
|
const QString &getBackupFileOfPreviousSession() const;
|
||||||
|
|
||||||
|
void discardBackupFileOfPreviousSession();
|
||||||
|
|
||||||
|
void recoverFromBackupFileOfPreviousSession();
|
||||||
|
|
||||||
|
// Whether this buffer's provider is a child of @p_node or an attachment of @p_node.
|
||||||
|
bool isChildOf(const Node *p_node) const;
|
||||||
|
|
||||||
|
Node *getNode() const;
|
||||||
|
|
||||||
|
bool isAttachmentSupported() const;
|
||||||
|
|
||||||
|
bool hasAttachment() const;
|
||||||
|
|
||||||
|
QString getAttachmentFolderPath() const;
|
||||||
|
|
||||||
|
// @p_destFolderPath: folder path locating in attachment folder. Use the root folder if empty.
|
||||||
|
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files);
|
||||||
|
|
||||||
|
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name);
|
||||||
|
|
||||||
|
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name);
|
||||||
|
|
||||||
|
QString renameAttachment(const QString &p_path, const QString &p_name);
|
||||||
|
|
||||||
|
void removeAttachment(const QStringList &p_paths);
|
||||||
|
|
||||||
|
// Judge whether file @p_path is attachment.
|
||||||
|
bool isAttachment(const QString &p_path) const;
|
||||||
|
|
||||||
|
bool isTagSupported() const;
|
||||||
|
|
||||||
|
ProviderType getProviderType() const;
|
||||||
|
|
||||||
|
bool checkFileExistsOnDisk();
|
||||||
|
|
||||||
|
bool checkFileChangedOutside();
|
||||||
|
|
||||||
|
StateFlags state() const;
|
||||||
|
|
||||||
|
static QString readBackupFile(const QString &p_filePath);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void attachedViewWindowEmpty();
|
||||||
|
|
||||||
|
void modified(bool p_modified);
|
||||||
|
|
||||||
|
void contentsChanged();
|
||||||
|
|
||||||
|
void nameChanged();
|
||||||
|
|
||||||
|
void attachmentChanged();
|
||||||
|
|
||||||
|
// This buffer is AutoSavePolicy::AutoSave.
|
||||||
|
void autoSaved();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent) = 0;
|
||||||
|
|
||||||
|
QSharedPointer<BufferProvider> m_provider;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void autoSave();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void syncContent();
|
||||||
|
|
||||||
|
void readContent();
|
||||||
|
|
||||||
|
// Get the path of the image folder.
|
||||||
|
QString getImageFolderPath() const;
|
||||||
|
|
||||||
|
void writeBackupFile();
|
||||||
|
|
||||||
|
// Generate backup file head.
|
||||||
|
QString generateBackupFileHead() const;
|
||||||
|
|
||||||
|
void checkBackupFileOfPreviousSession();
|
||||||
|
|
||||||
|
bool isBackupFileOfBuffer(const QString &p_file) const;
|
||||||
|
|
||||||
|
// Will be assigned uniquely once created.
|
||||||
|
const ID m_id = 0;
|
||||||
|
|
||||||
|
// Revision of contents.
|
||||||
|
int m_revision = 0;
|
||||||
|
|
||||||
|
// If the buffer is modified, m_content reflect the latest changes instead
|
||||||
|
// of the file content.
|
||||||
|
QString m_content;
|
||||||
|
|
||||||
|
bool m_readOnly = false;
|
||||||
|
|
||||||
|
bool m_modified = false;
|
||||||
|
|
||||||
|
int m_attachedViewWindowCount = 0;
|
||||||
|
|
||||||
|
const ViewWindow *m_viewWindowToSync = nullptr;
|
||||||
|
|
||||||
|
// Managed by QObject.
|
||||||
|
QTimer *m_autoSaveTimer = nullptr;
|
||||||
|
|
||||||
|
QString m_backupFilePath;
|
||||||
|
|
||||||
|
QString m_backupFilePathOfPreviousSession;
|
||||||
|
|
||||||
|
StateFlags m_state = StateFlag::Normal;
|
||||||
|
};
|
||||||
|
} // ns vnotex
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::Buffer::StateFlags)
|
||||||
|
|
||||||
|
#endif // BUFFER_H
|
25
src/core/buffer/bufferprovider.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "bufferprovider.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
bool BufferProvider::checkFileExistsOnDisk() const
|
||||||
|
{
|
||||||
|
return QFileInfo::exists(getContentPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime BufferProvider::getLastModifiedFromFile() const
|
||||||
|
{
|
||||||
|
return QFileInfo(getContentPath()).lastModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BufferProvider::checkFileChangedOutside() const
|
||||||
|
{
|
||||||
|
// TODO: support non-local URLs.
|
||||||
|
QFileInfo info(getContentPath());
|
||||||
|
if (!info.exists() || m_lastModified != info.lastModified()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
89
src/core/buffer/bufferprovider.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#ifndef BUFFERPROVIDER_H
|
||||||
|
#define BUFFERPROVIDER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
// Content provider for Buffer.
|
||||||
|
class BufferProvider : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
BufferProvider(QObject *p_parent = nullptr)
|
||||||
|
: QObject(p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~BufferProvider() {}
|
||||||
|
|
||||||
|
virtual Buffer::ProviderType getType() const = 0;
|
||||||
|
|
||||||
|
virtual bool match(const Node *p_node) const = 0;
|
||||||
|
|
||||||
|
virtual bool match(const QString &p_filePath) const = 0;
|
||||||
|
|
||||||
|
virtual QString getName() const = 0;
|
||||||
|
|
||||||
|
virtual QString getPath() const = 0;
|
||||||
|
|
||||||
|
virtual QString getContentPath() const = 0;
|
||||||
|
|
||||||
|
virtual QString getResourcePath() const = 0;
|
||||||
|
|
||||||
|
virtual void write(const QString &p_content) = 0;
|
||||||
|
|
||||||
|
virtual QString read() const = 0;
|
||||||
|
|
||||||
|
virtual QString fetchImageFolderPath() = 0;
|
||||||
|
|
||||||
|
virtual bool isChildOf(const Node *p_node) const = 0;
|
||||||
|
|
||||||
|
virtual Node *getNode() const = 0;
|
||||||
|
|
||||||
|
virtual QString getAttachmentFolder() const = 0;
|
||||||
|
|
||||||
|
virtual QString fetchAttachmentFolderPath() = 0;
|
||||||
|
|
||||||
|
virtual QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) = 0;
|
||||||
|
|
||||||
|
virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0;
|
||||||
|
|
||||||
|
virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0;
|
||||||
|
|
||||||
|
virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0;
|
||||||
|
|
||||||
|
virtual void removeAttachment(const QStringList &p_paths) = 0;
|
||||||
|
|
||||||
|
virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0;
|
||||||
|
|
||||||
|
virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0;
|
||||||
|
|
||||||
|
virtual void removeImage(const QString &p_imagePath) = 0;
|
||||||
|
|
||||||
|
virtual bool isAttachmentSupported() const = 0;
|
||||||
|
|
||||||
|
virtual bool isTagSupported() const = 0;
|
||||||
|
|
||||||
|
virtual bool checkFileExistsOnDisk() const;
|
||||||
|
|
||||||
|
virtual bool checkFileChangedOutside() const;
|
||||||
|
|
||||||
|
virtual bool isReadOnly() const = 0;
|
||||||
|
|
||||||
|
// Return nullptr if not available.
|
||||||
|
virtual QSharedPointer<File> getFile() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QDateTime getLastModifiedFromFile() const;
|
||||||
|
|
||||||
|
QDateTime m_lastModified;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUFFERPROVIDER_H
|
195
src/core/buffer/filebufferprovider.cpp
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
#include "filebufferprovider.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
#include <utils/pathutils.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <notebook/node.h>
|
||||||
|
#include <core/file.h>
|
||||||
|
#include <core/exception.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
FileBufferProvider::FileBufferProvider(const QSharedPointer<File> &p_file,
|
||||||
|
Node *p_nodeAttachedTo,
|
||||||
|
bool p_readOnly,
|
||||||
|
QObject *p_parent)
|
||||||
|
: BufferProvider(p_parent),
|
||||||
|
m_file(p_file),
|
||||||
|
c_nodeAttachedTo(p_nodeAttachedTo),
|
||||||
|
m_readOnly(p_readOnly)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::ProviderType FileBufferProvider::getType() const
|
||||||
|
{
|
||||||
|
return Buffer::ProviderType::External;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::match(const Node *p_node) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::match(const QString &p_filePath) const
|
||||||
|
{
|
||||||
|
return PathUtils::areSamePaths(m_file->getFilePath(), p_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::getName() const
|
||||||
|
{
|
||||||
|
return m_file->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::getPath() const
|
||||||
|
{
|
||||||
|
return m_file->getFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::getContentPath() const
|
||||||
|
{
|
||||||
|
return m_file->getContentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::getResourcePath() const
|
||||||
|
{
|
||||||
|
return m_file->getResourcePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferProvider::write(const QString &p_content)
|
||||||
|
{
|
||||||
|
m_file->write(p_content);
|
||||||
|
m_lastModified = getLastModifiedFromFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::read() const
|
||||||
|
{
|
||||||
|
const_cast<FileBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
|
||||||
|
return m_file->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::fetchImageFolderPath()
|
||||||
|
{
|
||||||
|
auto file = m_file->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->fetchImageFolderPath();
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::isChildOf(const Node *p_node) const
|
||||||
|
{
|
||||||
|
if (c_nodeAttachedTo) {
|
||||||
|
return c_nodeAttachedTo == p_node || Node::isAncestor(p_node, c_nodeAttachedTo);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::getAttachmentFolder() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::fetchAttachmentFolderPath()
|
||||||
|
{
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FileBufferProvider::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_destFolderPath);
|
||||||
|
Q_UNUSED(p_files);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_destFolderPath);
|
||||||
|
Q_UNUSED(p_name);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_destFolderPath);
|
||||||
|
Q_UNUSED(p_name);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::renameAttachment(const QString &p_path, const QString &p_name)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_path);
|
||||||
|
Q_UNUSED(p_name);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferProvider::removeAttachment(const QStringList &p_paths)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_paths);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
auto file = m_file->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->insertImage(p_srcImagePath, p_imageFileName);
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
auto file = m_file->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->insertImage(p_image, p_imageFileName);
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileBufferProvider::removeImage(const QString &p_imagePath)
|
||||||
|
{
|
||||||
|
auto file = m_file->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
file->removeImage(p_imagePath);
|
||||||
|
} catch (Exception &e) {
|
||||||
|
qWarning() << "failed to remove image" << p_imagePath << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::isAttachmentSupported() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::isTagSupported() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *FileBufferProvider::getNode() const
|
||||||
|
{
|
||||||
|
return c_nodeAttachedTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileBufferProvider::isReadOnly() const
|
||||||
|
{
|
||||||
|
return m_readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<File> FileBufferProvider::getFile() const
|
||||||
|
{
|
||||||
|
return m_file;
|
||||||
|
}
|
81
src/core/buffer/filebufferprovider.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FILEBUFFERPROVIDER_H
|
||||||
|
#define FILEBUFFERPROVIDER_H
|
||||||
|
|
||||||
|
#include "bufferprovider.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class File;
|
||||||
|
|
||||||
|
// Buffer provider based on external file.
|
||||||
|
class FileBufferProvider : public BufferProvider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FileBufferProvider(const QSharedPointer<File> &m_file,
|
||||||
|
Node *p_nodeAttachedTo,
|
||||||
|
bool p_readOnly,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
Buffer::ProviderType getType() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool match(const Node *p_node) const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool match(const QString &p_filePath) const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString getName() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString getPath() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString getContentPath() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString getResourcePath() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void write(const QString &p_content) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString read() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString fetchImageFolderPath() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
Node *getNode() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString getAttachmentFolder() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isAttachmentSupported() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isTagSupported() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isReadOnly() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QSharedPointer<File> getFile() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<File> m_file;
|
||||||
|
|
||||||
|
Node *c_nodeAttachedTo = nullptr;
|
||||||
|
|
||||||
|
bool m_readOnly = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FILEBUFFERPROVIDER_H
|
197
src/core/buffer/filetypehelper.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include "filetypehelper.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include "buffer.h"
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/coreconfig.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
QString FileType::preferredSuffix() const
|
||||||
|
{
|
||||||
|
return m_suffixes.isEmpty() ? QString() : m_suffixes.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileType::isMarkdown() const
|
||||||
|
{
|
||||||
|
return m_type == Type::Markdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileTypeHelper::s_systemDefaultProgram = QStringLiteral("System");
|
||||||
|
|
||||||
|
FileTypeHelper::FileTypeHelper()
|
||||||
|
{
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTypeHelper::reload()
|
||||||
|
{
|
||||||
|
setupBuiltInTypes();
|
||||||
|
|
||||||
|
setupSuffixTypeMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTypeHelper::setupBuiltInTypes()
|
||||||
|
{
|
||||||
|
m_fileTypes.clear();
|
||||||
|
|
||||||
|
const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::Markdown;
|
||||||
|
type.m_typeName = QStringLiteral("Markdown");
|
||||||
|
type.m_displayName = Buffer::tr("Markdown");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("md")
|
||||||
|
<< QStringLiteral("mkd")
|
||||||
|
<< QStringLiteral("rmd")
|
||||||
|
<< QStringLiteral("markdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::Text;
|
||||||
|
type.m_typeName = QStringLiteral("Text");
|
||||||
|
type.m_displayName = Buffer::tr("Text");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::Pdf;
|
||||||
|
type.m_typeName = QStringLiteral("PDF");
|
||||||
|
type.m_displayName = Buffer::tr("Portable Document Format");
|
||||||
|
type.m_isNewable = false;
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::MindMap;
|
||||||
|
type.m_typeName = QStringLiteral("MindMap");
|
||||||
|
type.m_displayName = Buffer::tr("Mind Map");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("emind");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::Others;
|
||||||
|
type.m_typeName = QStringLiteral("Others");
|
||||||
|
type.m_displayName = Buffer::tr("Others");
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileType &FileTypeHelper::getFileType(const QString &p_filePath) const
|
||||||
|
{
|
||||||
|
Q_ASSERT(!p_filePath.isEmpty());
|
||||||
|
|
||||||
|
QFileInfo fi(p_filePath);
|
||||||
|
auto suffix = fi.suffix().toLower();
|
||||||
|
auto it = m_suffixTypeMap.find(suffix);
|
||||||
|
if (it != m_suffixTypeMap.end()) {
|
||||||
|
return m_fileTypes.at(it.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Treat all unknown text files as plain text files.
|
||||||
|
if (FileUtils::isText(p_filePath)) {
|
||||||
|
return m_fileTypes[FileType::Text];
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_fileTypes[FileType::Others];
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileType &FileTypeHelper::getFileTypeBySuffix(const QString &p_suffix) const
|
||||||
|
{
|
||||||
|
auto it = m_suffixTypeMap.find(p_suffix.toLower());
|
||||||
|
if (it != m_suffixTypeMap.end()) {
|
||||||
|
return m_fileTypes.at(it.value());
|
||||||
|
} else {
|
||||||
|
return m_fileTypes[FileType::Others];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileTypeHelper::setupSuffixTypeMap()
|
||||||
|
{
|
||||||
|
m_suffixTypeMap.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < m_fileTypes.size(); ++i) {
|
||||||
|
for (const auto &suffix : m_fileTypes[i].m_suffixes) {
|
||||||
|
if (m_suffixTypeMap.contains(suffix)) {
|
||||||
|
qWarning() << "suffix conflicts detected" << suffix << m_fileTypes[i].m_type;
|
||||||
|
}
|
||||||
|
m_suffixTypeMap.insert(suffix, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<FileType> &FileTypeHelper::getAllFileTypes() const
|
||||||
|
{
|
||||||
|
return m_fileTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileType &FileTypeHelper::getFileType(int p_type) const
|
||||||
|
{
|
||||||
|
if (p_type >= m_fileTypes.size()) {
|
||||||
|
p_type = FileType::Others;
|
||||||
|
}
|
||||||
|
return m_fileTypes[p_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
FileTypeHelper &FileTypeHelper::getInst()
|
||||||
|
{
|
||||||
|
static FileTypeHelper helper;
|
||||||
|
return helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileTypeHelper::checkFileType(const QString &p_filePath, int p_type) const
|
||||||
|
{
|
||||||
|
return getFileType(p_filePath).m_type == p_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileType &FileTypeHelper::getFileTypeByName(const QString &p_typeName) const
|
||||||
|
{
|
||||||
|
for (const auto &ft : m_fileTypes) {
|
||||||
|
if (ft.m_typeName == p_typeName) {
|
||||||
|
return ft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return m_fileTypes[FileType::Others];
|
||||||
|
}
|
78
src/core/buffer/filetypehelper.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef FILETYPEHELPER_H
|
||||||
|
#define FILETYPEHELPER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class FileType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// There may be other types after Others.
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Markdown = 0,
|
||||||
|
Text,
|
||||||
|
Pdf,
|
||||||
|
MindMap,
|
||||||
|
Others
|
||||||
|
};
|
||||||
|
|
||||||
|
QString preferredSuffix() const;
|
||||||
|
|
||||||
|
bool isMarkdown() const;
|
||||||
|
|
||||||
|
// Type.
|
||||||
|
int m_type = -1;
|
||||||
|
|
||||||
|
QString m_typeName;
|
||||||
|
|
||||||
|
QString m_displayName;
|
||||||
|
|
||||||
|
QStringList m_suffixes;
|
||||||
|
|
||||||
|
// Whether we can new this type of file.
|
||||||
|
bool m_isNewable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only handle built-in editors.
|
||||||
|
class FileTypeHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const FileType &getFileType(const QString &p_filePath) const;
|
||||||
|
|
||||||
|
const FileType &getFileType(int p_type) const;
|
||||||
|
|
||||||
|
const FileType &getFileTypeByName(const QString &p_typeName) const;
|
||||||
|
|
||||||
|
const FileType &getFileTypeBySuffix(const QString &p_suffix) const;
|
||||||
|
|
||||||
|
const QVector<FileType> &getAllFileTypes() const;
|
||||||
|
|
||||||
|
bool checkFileType(const QString &p_filePath, int p_type) const;
|
||||||
|
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
static FileTypeHelper &getInst();
|
||||||
|
|
||||||
|
static QString s_systemDefaultProgram;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileTypeHelper();
|
||||||
|
|
||||||
|
void setupBuiltInTypes();
|
||||||
|
|
||||||
|
void setupSuffixTypeMap();
|
||||||
|
|
||||||
|
// Built-in Type could be accessed via enum Type.
|
||||||
|
QVector<FileType> m_fileTypes;
|
||||||
|
|
||||||
|
// suffix -> index of m_fileTypes.
|
||||||
|
// TODO: handle suffix conflicts.
|
||||||
|
QMap<QString, int> m_suffixTypeMap;
|
||||||
|
};
|
||||||
|
} // ns vnotex
|
||||||
|
|
||||||
|
#endif // FILETYPEHELPER_H
|
26
src/core/buffer/ibufferfactory.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef IBUFFERFACTORY_H
|
||||||
|
#define IBUFFERFACTORY_H
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Buffer;
|
||||||
|
struct BufferParameters;
|
||||||
|
|
||||||
|
// Abstract factory to create buffer.
|
||||||
|
class IBufferFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IBufferFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent) = 0;
|
||||||
|
|
||||||
|
virtual bool isBufferCreatedByFactory(const Buffer *p_buffer) const = 0;
|
||||||
|
};
|
||||||
|
} // ns vnotex
|
||||||
|
|
||||||
|
#endif // IBUFFERFACTORY_H
|
107
src/core/buffer/markdownbuffer.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "markdownbuffer.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <widgets/markdownviewwindow.h>
|
||||||
|
#include <notebook/node.h>
|
||||||
|
#include <utils/pathutils.h>
|
||||||
|
#include <buffer/bufferprovider.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
MarkdownBuffer::MarkdownBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
: Buffer(p_parameters, p_parent)
|
||||||
|
{
|
||||||
|
fetchInitialImages();
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindow *MarkdownBuffer::createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_paras);
|
||||||
|
return new MarkdownViewWindow(p_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MarkdownBuffer::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
return m_provider->insertImage(p_srcImagePath, p_imageFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MarkdownBuffer::insertImage(const QImage &p_image, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
return m_provider->insertImage(p_image, p_imageFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownBuffer::fetchInitialImages()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_initialImages.isEmpty());
|
||||||
|
// There is compilation error on Linux and macOS using TypeFlags directly.
|
||||||
|
int linkFlags = vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote;
|
||||||
|
m_initialImages = vte::MarkdownUtils::fetchImagesFromMarkdownText(getContent(),
|
||||||
|
getResourcePath(),
|
||||||
|
static_cast<vte::MarkdownLink::TypeFlags>(linkFlags));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownBuffer::addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink)
|
||||||
|
{
|
||||||
|
vte::MarkdownLink link;
|
||||||
|
link.m_path = p_imagePath;
|
||||||
|
link.m_urlInLink = p_urlInLink;
|
||||||
|
// There are two types: local internal and remote for image host.
|
||||||
|
link.m_type = PathUtils::isLocalFile(p_imagePath) ? vte::MarkdownLink::TypeFlag::LocalRelativeInternal : vte::MarkdownLink::TypeFlag::Remote;
|
||||||
|
m_insertedImages.append(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<QString, bool> MarkdownBuffer::clearObsoleteImages()
|
||||||
|
{
|
||||||
|
QHash<QString, bool> obsoleteImages;
|
||||||
|
|
||||||
|
Q_ASSERT(!isModified());
|
||||||
|
const bool discarded = state() & StateFlag::Discarded;
|
||||||
|
const int linkFlags = vte::MarkdownLink::TypeFlag::LocalRelativeInternal | vte::MarkdownLink::TypeFlag::Remote;
|
||||||
|
const auto latestImages =
|
||||||
|
vte::MarkdownUtils::fetchImagesFromMarkdownText(!discarded ? getContent() : m_provider->read(),
|
||||||
|
getResourcePath(),
|
||||||
|
static_cast<vte::MarkdownLink::TypeFlags>(linkFlags));
|
||||||
|
QSet<QString> latestImagesPath;
|
||||||
|
for (const auto &link : latestImages) {
|
||||||
|
if (link.m_type & vte::MarkdownLink::TypeFlag::Remote) {
|
||||||
|
latestImagesPath.insert(link.m_path);
|
||||||
|
} else {
|
||||||
|
latestImagesPath.insert(PathUtils::normalizePath(link.m_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &link : m_insertedImages) {
|
||||||
|
if (!(link.m_type & linkFlags)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote;
|
||||||
|
const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path);
|
||||||
|
if (!latestImagesPath.contains(linkPath)) {
|
||||||
|
obsoleteImages.insert(link.m_path, isRemote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_insertedImages.clear();
|
||||||
|
|
||||||
|
for (const auto &link : m_initialImages) {
|
||||||
|
Q_ASSERT(link.m_type & linkFlags);
|
||||||
|
const bool isRemote = link.m_type & vte::MarkdownLink::TypeFlag::Remote;
|
||||||
|
const auto linkPath = isRemote ? link.m_path : PathUtils::normalizePath(link.m_path);
|
||||||
|
if (!latestImagesPath.contains(linkPath)) {
|
||||||
|
obsoleteImages.insert(link.m_path, isRemote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_initialImages = latestImages;
|
||||||
|
|
||||||
|
return obsoleteImages;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownBuffer::removeImage(const QString &p_imagePath)
|
||||||
|
{
|
||||||
|
qDebug() << "remove obsolete image" << p_imagePath;
|
||||||
|
m_provider->removeImage(p_imagePath);
|
||||||
|
}
|
48
src/core/buffer/markdownbuffer.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef MARKDOWNBUFFER_H
|
||||||
|
#define MARKDOWNBUFFER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include <vtextedit/markdownutils.h>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class MarkdownBuffer : public Buffer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MarkdownBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void addInsertedImage(const QString &p_imagePath, const QString &p_urlInLink);
|
||||||
|
|
||||||
|
// Clear obsolete images.
|
||||||
|
// Won't delete images, just return a list of obsolete images path.
|
||||||
|
// Will re-init m_initialImages and clear m_insertedImages.
|
||||||
|
// Return [ImagePath] -> IsRemote.
|
||||||
|
QHash<QString, bool> clearObsoleteImages();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void fetchInitialImages();
|
||||||
|
|
||||||
|
// Images referenced in the file before opening this buffer.
|
||||||
|
QVector<vte::MarkdownLink> m_initialImages;
|
||||||
|
|
||||||
|
// Images newly inserted during this buffer's lifetime.
|
||||||
|
QVector<vte::MarkdownLink> m_insertedImages;
|
||||||
|
};
|
||||||
|
} // ns vnotex
|
||||||
|
|
||||||
|
#endif // MARKDOWNBUFFER_H
|
16
src/core/buffer/markdownbufferfactory.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "markdownbufferfactory.h"
|
||||||
|
|
||||||
|
#include "markdownbuffer.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
Buffer *MarkdownBufferFactory::createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
{
|
||||||
|
return new MarkdownBuffer(p_parameters, p_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MarkdownBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const MarkdownBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
19
src/core/buffer/markdownbufferfactory.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MARKDOWNBUFFERFACTORY_H
|
||||||
|
#define MARKDOWNBUFFERFACTORY_H
|
||||||
|
|
||||||
|
#include "ibufferfactory.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// Buffer factory for Markdown file.
|
||||||
|
class MarkdownBufferFactory : public IBufferFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
} // vnotex
|
||||||
|
|
||||||
|
#endif // MARKDOWNBUFFERFACTORY_H
|
17
src/core/buffer/mindmapbuffer.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "mindmapbuffer.h"
|
||||||
|
|
||||||
|
#include <widgets/mindmapviewwindow.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
MindMapBuffer::MindMapBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
: Buffer(p_parameters, p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindow *MindMapBuffer::createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_paras);
|
||||||
|
return new MindMapViewWindow(p_parent);
|
||||||
|
}
|
21
src/core/buffer/mindmapbuffer.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef MINDMAPBUFFER_H
|
||||||
|
#define MINDMAPBUFFER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class MindMapBuffer : public Buffer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MindMapBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras,
|
||||||
|
QWidget *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MINDMAPBUFFER_H
|
16
src/core/buffer/mindmapbufferfactory.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "mindmapbufferfactory.h"
|
||||||
|
|
||||||
|
#include "mindmapbuffer.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
Buffer *MindMapBufferFactory::createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
{
|
||||||
|
return new MindMapBuffer(p_parameters, p_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MindMapBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const MindMapBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
19
src/core/buffer/mindmapbufferfactory.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MINDMAPBUFFERFACTORY_H
|
||||||
|
#define MINDMAPBUFFERFACTORY_H
|
||||||
|
|
||||||
|
#include "ibufferfactory.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// Buffer factory for MindMap file.
|
||||||
|
class MindMapBufferFactory : public IBufferFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MINDMAPBUFFERFACTORY_H
|
175
src/core/buffer/nodebufferprovider.cpp
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#include "nodebufferprovider.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
#include <notebook/node.h>
|
||||||
|
#include <notebook/notebook.h>
|
||||||
|
#include <utils/pathutils.h>
|
||||||
|
#include <core/file.h>
|
||||||
|
#include <core/exception.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
NodeBufferProvider::NodeBufferProvider(const QSharedPointer<Node> &p_node,
|
||||||
|
const QSharedPointer<File> &p_file,
|
||||||
|
QObject *p_parent)
|
||||||
|
: BufferProvider(p_parent),
|
||||||
|
m_node(p_node),
|
||||||
|
m_nodeFile(p_file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::ProviderType NodeBufferProvider::getType() const
|
||||||
|
{
|
||||||
|
return Buffer::ProviderType::Internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::match(const Node *p_node) const
|
||||||
|
{
|
||||||
|
return m_node.data() == p_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::match(const QString &p_filePath) const
|
||||||
|
{
|
||||||
|
return PathUtils::areSamePaths(getPath(), p_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::getName() const
|
||||||
|
{
|
||||||
|
return m_node->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::getPath() const
|
||||||
|
{
|
||||||
|
return m_nodeFile->getFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::getContentPath() const
|
||||||
|
{
|
||||||
|
return m_nodeFile->getContentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::getResourcePath() const
|
||||||
|
{
|
||||||
|
return m_nodeFile->getResourcePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBufferProvider::write(const QString &p_content)
|
||||||
|
{
|
||||||
|
m_nodeFile->write(p_content);
|
||||||
|
m_lastModified = getLastModifiedFromFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::read() const
|
||||||
|
{
|
||||||
|
const_cast<NodeBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
|
||||||
|
return m_nodeFile->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::fetchImageFolderPath()
|
||||||
|
{
|
||||||
|
auto file = m_nodeFile->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->fetchImageFolderPath();
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return getContentPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::isChildOf(const Node *p_node) const
|
||||||
|
{
|
||||||
|
return Node::isAncestor(p_node, m_node.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::getAttachmentFolder() const
|
||||||
|
{
|
||||||
|
return m_node->getAttachmentFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::fetchAttachmentFolderPath()
|
||||||
|
{
|
||||||
|
return m_node->fetchAttachmentFolderPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList NodeBufferProvider::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
|
||||||
|
{
|
||||||
|
return m_node->addAttachment(p_destFolderPath, p_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
return m_node->newAttachmentFile(p_destFolderPath, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
|
||||||
|
{
|
||||||
|
return m_node->newAttachmentFolder(p_destFolderPath, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::renameAttachment(const QString &p_path, const QString &p_name)
|
||||||
|
{
|
||||||
|
return m_node->renameAttachment(p_path, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBufferProvider::removeAttachment(const QStringList &p_paths)
|
||||||
|
{
|
||||||
|
return m_node->removeAttachment(p_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
auto file = m_nodeFile->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->insertImage(p_srcImagePath, p_imageFileName);
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NodeBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName)
|
||||||
|
{
|
||||||
|
auto file = m_nodeFile->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
return file->insertImage(p_image, p_imageFileName);
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBufferProvider::removeImage(const QString &p_imagePath)
|
||||||
|
{
|
||||||
|
auto file = m_nodeFile->getImageInterface();
|
||||||
|
if (file) {
|
||||||
|
try {
|
||||||
|
file->removeImage(p_imagePath);
|
||||||
|
} catch (Exception &e) {
|
||||||
|
qWarning() << "failed to remove image" << p_imagePath << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::isAttachmentSupported() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::isTagSupported() const
|
||||||
|
{
|
||||||
|
return m_node->getNotebook()->tag() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *NodeBufferProvider::getNode() const
|
||||||
|
{
|
||||||
|
return m_node.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeBufferProvider::isReadOnly() const
|
||||||
|
{
|
||||||
|
return m_node->isReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<File> NodeBufferProvider::getFile() const
|
||||||
|
{
|
||||||
|
return m_nodeFile;
|
||||||
|
}
|