mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-21 06:42:41 -08:00
Compare commits
480 Commits
2019-03-04
...
2023-03-03
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a416ee8f2b | ||
|
|
c14936c63c | ||
|
|
42e7a8b423 | ||
|
|
4558b1c7ef | ||
|
|
f444ba9665 | ||
|
|
787c8d740b | ||
|
|
ef38a8bb2b | ||
|
|
b5d35d346a | ||
|
|
9a7b15d19b | ||
|
|
ba35a11e82 | ||
|
|
00c9efe541 | ||
|
|
44d1ab348b | ||
|
|
f25e4785ae | ||
|
|
4c290aec57 | ||
|
|
42d1d66d9b | ||
|
|
06c25301a5 | ||
|
|
43dbb45cc6 | ||
|
|
9fb62de5cb | ||
|
|
b282df2e27 | ||
|
|
da8f57f397 | ||
|
|
e9f1992c7f | ||
|
|
2c94a6a64e | ||
|
|
6a5e0a8501 | ||
|
|
26d7fe2ff0 | ||
|
|
5854a635ca | ||
|
|
3d4858b840 | ||
|
|
dec2a252fa | ||
|
|
f619ef23fd | ||
|
|
72743e834e | ||
|
|
8e4ddf366c | ||
|
|
b99bd0176a | ||
|
|
a68b98b245 | ||
|
|
a69d6ff1b4 | ||
|
|
ec679e95fd | ||
|
|
3f78235a74 | ||
|
|
c8a2fd78b0 | ||
|
|
45cf08111a | ||
|
|
527ac36129 | ||
|
|
a7232513a7 | ||
|
|
90f187e885 | ||
|
|
235adbbdf1 | ||
|
|
40c88fe385 | ||
|
|
54b7943d17 | ||
|
|
2f100f2ba3 | ||
|
|
b5305aa5e4 | ||
|
|
a2624e36f3 | ||
|
|
540511befd | ||
|
|
014e73d569 | ||
|
|
e2c256db5b | ||
|
|
28aa473362 | ||
|
|
b79506fbcf | ||
|
|
afbd7252ac | ||
|
|
3e5b7cd392 | ||
|
|
77622095d5 | ||
|
|
8ee71300a2 | ||
|
|
d79971edbc | ||
|
|
273ebb22e4 | ||
|
|
6b86e4d463 | ||
|
|
a8e1dc3b18 | ||
|
|
a95b338c80 | ||
|
|
3e90f109a2 | ||
|
|
b02adccf87 | ||
|
|
accd5e4df7 | ||
|
|
d007196059 | ||
|
|
79501a4af7 | ||
|
|
64c6611ea5 | ||
|
|
a532a63403 | ||
|
|
c10c69d0a9 | ||
|
|
191d5a83a9 | ||
|
|
de69e2c41f | ||
|
|
6d200d17b7 | ||
|
|
4899b6cfef | ||
|
|
0ff59e6d1e | ||
|
|
00a2a8ab71 | ||
|
|
2c702d3579 | ||
|
|
b464fa8d99 | ||
|
|
2b330940e1 | ||
|
|
0d0337f091 | ||
|
|
533045445a | ||
|
|
21f7dd5eba | ||
|
|
f5b973e15c | ||
|
|
baaf261116 | ||
|
|
92ed53e13a | ||
|
|
2a54e9d7d1 | ||
|
|
9577ada171 | ||
|
|
217dc09c0f | ||
|
|
7108eb42c8 | ||
|
|
eb3ce1fd7e | ||
|
|
c88d44e16c | ||
|
|
ec2ad4c713 | ||
|
|
4c04b4ef5a | ||
|
|
88b861d632 | ||
|
|
408a13c937 | ||
|
|
7d0a255a49 | ||
|
|
252883f67e | ||
|
|
bf08a04cda | ||
|
|
6928a2bd98 | ||
|
|
bb16ae09ef | ||
|
|
81d031ca0f | ||
|
|
8203a2fdeb | ||
|
|
75f0d60dff | ||
|
|
992e28797f | ||
|
|
92f941a54c | ||
|
|
4c31527832 | ||
|
|
febe029ed4 | ||
|
|
1d780058c8 | ||
|
|
513fcb0908 | ||
|
|
4bb13677c8 | ||
|
|
a5baf4303c | ||
|
|
7aba404f2e | ||
|
|
1b7e8f3a16 | ||
|
|
5cf93ad61c | ||
|
|
5a52e085a7 | ||
|
|
5d31b70406 | ||
|
|
2885f93fdf | ||
|
|
d225f55e5a | ||
|
|
69edc73585 | ||
|
|
ead1143f2e | ||
|
|
2fc85e0c08 | ||
|
|
fcafcb340a | ||
|
|
ae9b8b8f34 | ||
|
|
994704d353 | ||
|
|
d61c604bf4 | ||
|
|
baaf22d0c4 | ||
|
|
368ff1793f | ||
|
|
3253ad64fd | ||
|
|
1e70989f38 | ||
|
|
f6634de18d | ||
|
|
7903cd520a | ||
|
|
26d1fcc944 | ||
|
|
59d4e64a8d | ||
|
|
1347d88ddb | ||
|
|
6981cca2ae | ||
|
|
4d6c9ede8c | ||
|
|
e845c95816 | ||
|
|
a9f2fc427b | ||
|
|
07e6aadbbe | ||
|
|
86881bbbc3 | ||
|
|
1f15445c69 | ||
|
|
811ee54c76 | ||
|
|
d1a40fd36e | ||
|
|
a3d3aaaca8 | ||
|
|
c5aaa0bc2e | ||
|
|
6dc9f004ce | ||
|
|
6ce346af4a | ||
|
|
37879c4255 | ||
|
|
0683d1aced | ||
|
|
73c5956ece | ||
|
|
7c27e955d5 | ||
|
|
6ef394000b | ||
|
|
755a09bd83 | ||
|
|
8b1daa21ef | ||
|
|
691bcb9338 | ||
|
|
911a303326 | ||
|
|
5652b56b45 | ||
|
|
26acfd5102 | ||
|
|
f789e02096 | ||
|
|
43eee6b32e | ||
|
|
45d86e7ab7 | ||
|
|
b0845837c2 | ||
|
|
a10226d096 | ||
|
|
5e3a524401 | ||
|
|
b095d9b82f | ||
|
|
4cb7240f9a | ||
|
|
a87c66885c | ||
|
|
ac300b0b6d | ||
|
|
013bb8269f | ||
|
|
7712862036 | ||
|
|
656e3230de | ||
|
|
915c14f6cf | ||
|
|
ed32e72dc1 | ||
|
|
d684a9c5fc | ||
|
|
6f360374cc | ||
|
|
bbbf3e2a65 | ||
|
|
b1ef8220ee | ||
|
|
ebebb9c4bb | ||
|
|
586f23cfa9 | ||
|
|
f75ff2a7c8 | ||
|
|
e9ba195d7d | ||
|
|
19333c53f6 | ||
|
|
36e5a399d5 | ||
|
|
dde0f568d9 | ||
|
|
3bc90003b3 | ||
|
|
689f65b38a | ||
|
|
154e1084ba | ||
|
|
6df5cece04 | ||
|
|
c8bb8b0aae | ||
|
|
1e995cd97c | ||
|
|
c25bf491e4 | ||
|
|
affc288144 | ||
|
|
051be37419 | ||
|
|
c0bd49cf13 | ||
|
|
2fe572c398 | ||
|
|
904e740460 | ||
|
|
00add2a527 | ||
|
|
bbe43d4246 | ||
|
|
0280fea3e6 | ||
|
|
a65ce8694c | ||
|
|
c9ddd042fc | ||
|
|
da9222929b | ||
|
|
b858e36183 | ||
|
|
ebe2c494aa | ||
|
|
fac7bfaa92 | ||
|
|
0d05f9097d | ||
|
|
8db9475804 | ||
|
|
294229622d | ||
|
|
5cf9023a21 | ||
|
|
66d24f086e | ||
|
|
19a7c4092c | ||
|
|
b27cb58727 | ||
|
|
472f401590 | ||
|
|
744099277a | ||
|
|
dff25a175b | ||
|
|
61f1141fe8 | ||
|
|
0a73162bcf | ||
|
|
5f32892e75 | ||
|
|
ae7437750b | ||
|
|
046a3649ed | ||
|
|
890810f5b9 | ||
|
|
8fb561b4c4 | ||
|
|
b9c4b496e4 | ||
|
|
ff6f28390a | ||
|
|
e034de9083 | ||
|
|
ecf57b4226 | ||
|
|
63fe34437a | ||
|
|
1062894397 | ||
|
|
5969656429 | ||
|
|
ad0f313c9d | ||
|
|
6c004155ff | ||
|
|
88a8ee09bd | ||
|
|
7d1f082b27 | ||
|
|
1c48656623 | ||
|
|
b940e17fe7 | ||
|
|
8e954b10e6 | ||
|
|
1b4543aa11 | ||
|
|
406c0b17ae | ||
|
|
09de56ac87 | ||
|
|
07ea2d4334 | ||
|
|
c5fac2ee35 | ||
|
|
a5b8245227 | ||
|
|
073349fd05 | ||
|
|
00ed5c370c | ||
|
|
8e1d7d12e0 | ||
|
|
1811f7305e | ||
|
|
06bfc0291a | ||
|
|
b722864caf | ||
|
|
18e27ef932 | ||
|
|
7e3a669af0 | ||
|
|
aa6a0313e9 | ||
|
|
9bbe2f36bc | ||
|
|
0c7830b53c | ||
|
|
2b0a9975be | ||
|
|
df0b867d9e | ||
|
|
d27f108cbd | ||
|
|
fd0076e920 | ||
|
|
db5f6e01c9 | ||
|
|
f3255180ec | ||
|
|
039d058770 | ||
|
|
401fdcaf7a | ||
|
|
1bfcca91be | ||
|
|
3edb862561 | ||
|
|
00c0162da3 | ||
|
|
6fa5f4f9a5 | ||
|
|
db528c6762 | ||
|
|
0c54cdf6bc | ||
|
|
b63145c0a1 | ||
|
|
1ddc9cc929 | ||
|
|
a0deb73df6 | ||
|
|
0457e65751 | ||
|
|
d5b36e8b8a | ||
|
|
f595a61d50 | ||
|
|
dbf6cd745e | ||
|
|
0ce813b826 | ||
|
|
77be6a120c | ||
|
|
37053cc909 | ||
|
|
34e951298f | ||
|
|
8845a23d5d | ||
|
|
38606bdb87 | ||
|
|
56a51c7834 | ||
|
|
402c09e028 | ||
|
|
9e702ec358 | ||
|
|
c047a8ae3c | ||
|
|
b4740ad395 | ||
|
|
99b0abe7fe | ||
|
|
b0239c11ab | ||
|
|
46cf50d468 | ||
|
|
9f9581c2be | ||
|
|
f3cf1f0dde | ||
|
|
2f62671d8a | ||
|
|
589fbcdcd5 | ||
|
|
51b24bb92c | ||
|
|
6e00db4ef6 | ||
|
|
0d842b5a35 | ||
|
|
8441cb7ba9 | ||
|
|
4aaedf64d2 | ||
|
|
45d838a0b3 | ||
|
|
ca5f1dd434 | ||
|
|
d07bf1211a | ||
|
|
0966a8e90f | ||
|
|
68074b0f74 | ||
|
|
f11f072e0a | ||
|
|
3064621a7e | ||
|
|
0405c82cb2 | ||
|
|
8e9d4e3a67 | ||
|
|
ef78fdf342 | ||
|
|
a49c4865bb | ||
|
|
1a94261490 | ||
|
|
e10446f5b8 | ||
|
|
2081639970 | ||
|
|
8cbc4c91f6 | ||
|
|
b8cd3af21f | ||
|
|
1e8464c1d4 | ||
|
|
5df069ab19 | ||
|
|
752ba7d905 | ||
|
|
9cf7621102 | ||
|
|
9330774632 | ||
|
|
e33f802ae8 | ||
|
|
48c6458766 | ||
|
|
35fe6f624c | ||
|
|
e2251fe06b | ||
|
|
a5511190a3 | ||
|
|
eba9c097f6 | ||
|
|
58d024d067 | ||
|
|
be7b172e55 | ||
|
|
a8b79fd020 | ||
|
|
14fcb2e5d7 | ||
|
|
02935be14f | ||
|
|
bec02b4952 | ||
|
|
79f590c99a | ||
|
|
ade3e81682 | ||
|
|
45cbdad5fb | ||
|
|
3536fa8a75 | ||
|
|
b0c7b9078d | ||
|
|
964207d04f | ||
|
|
feee9cc328 | ||
|
|
4a563a131b | ||
|
|
69f035f017 | ||
|
|
daa89a9fb4 | ||
|
|
44297dcd1c | ||
|
|
80f613a77a | ||
|
|
776aa5c0ff | ||
|
|
446f9be24d | ||
|
|
5d9d91262b | ||
|
|
fe63dfa762 | ||
|
|
a76a3e5db6 | ||
|
|
faecfd65fe | ||
|
|
0063493066 | ||
|
|
2a7268c088 | ||
|
|
7fa1936d0f | ||
|
|
0f0e0193c1 | ||
|
|
0337f58088 | ||
|
|
53c6440cac | ||
|
|
28f3229a0e | ||
|
|
3dff63069e | ||
|
|
1eea8e9a37 | ||
|
|
2de863f645 | ||
|
|
dc8603596d | ||
|
|
fd0620445c | ||
|
|
04274d2497 | ||
|
|
c69e77f330 | ||
|
|
1988e4558f | ||
|
|
9246c190fa | ||
|
|
d30691559a | ||
|
|
46fe0cd725 | ||
|
|
45d62b6880 | ||
|
|
db85ec48c7 | ||
|
|
1976c4caed | ||
|
|
2c3eab9b0c | ||
|
|
27b7ebe208 | ||
|
|
a135ad064a | ||
|
|
e8d5715f7a | ||
|
|
9cec0852bb | ||
|
|
ca618c6cc1 | ||
|
|
c5e0b08800 | ||
|
|
568a4973fa | ||
|
|
5508699e92 | ||
|
|
71dd6b8a30 | ||
|
|
18a07274d4 | ||
|
|
1eb766b9d8 | ||
|
|
e84409c0cf | ||
|
|
91dc8b3b08 | ||
|
|
63b4f9b2f0 | ||
|
|
7285f24a29 | ||
|
|
17efe8c003 | ||
|
|
1815094249 | ||
|
|
a80c756dcb | ||
|
|
361833e023 | ||
|
|
632e44b0b7 | ||
|
|
8dd1e39ea9 | ||
|
|
0f18fa9546 | ||
|
|
7bfefee073 | ||
|
|
0ff7472ce5 | ||
|
|
8fb0baa449 | ||
|
|
57c02dcd5a | ||
|
|
b072b540a2 | ||
|
|
cd431594e2 | ||
|
|
e4c98e2ab8 | ||
|
|
32b557b862 | ||
|
|
e690b45f27 | ||
|
|
eadcdc6f7c | ||
|
|
b187fb52e0 | ||
|
|
7e89933552 | ||
|
|
096a472ed0 | ||
|
|
365b0a31ed | ||
|
|
e8fd2ce2aa | ||
|
|
a3fc9b6ee5 | ||
|
|
9eebc590c1 | ||
|
|
f840dcbd66 | ||
|
|
8879fc2e39 | ||
|
|
cd29e2f252 | ||
|
|
bcf505c98b | ||
|
|
933f3e1392 | ||
|
|
ba0462b24f | ||
|
|
7e8a63cd62 | ||
|
|
03e109ef12 | ||
|
|
257f2eb34c | ||
|
|
53728598fe | ||
|
|
3b98eb77f5 | ||
|
|
b6df5a4ac3 | ||
|
|
f54165025e | ||
|
|
013137c418 | ||
|
|
faf02100a5 | ||
|
|
a8b34d51a5 | ||
|
|
2ef3e6fc93 | ||
|
|
a3a1e20074 | ||
|
|
ce54aa6813 | ||
|
|
5139039402 | ||
|
|
f4adf79ad9 | ||
|
|
f10f9ada3a | ||
|
|
965a6cdde7 | ||
|
|
62c0825874 | ||
|
|
4e918f0f5d | ||
|
|
3e3154a58c | ||
|
|
22e2e442f5 | ||
|
|
c0c4a6df50 | ||
|
|
36ba9c2d94 | ||
|
|
1288795de9 | ||
|
|
0380de9571 | ||
|
|
6ac3852995 | ||
|
|
1d8fb79e11 | ||
|
|
e084bd18a9 | ||
|
|
7c3cc527f6 | ||
|
|
218aec07f8 | ||
|
|
ada13f6578 | ||
|
|
8682367b52 | ||
|
|
a80f3b77da | ||
|
|
fd8bf66acd | ||
|
|
115ed78059 | ||
|
|
00ca69fced | ||
|
|
6c21855f98 | ||
|
|
3830c85ce6 | ||
|
|
0dc4cc7e03 | ||
|
|
8f5bfd1f87 | ||
|
|
95d6efcdbf | ||
|
|
63cf0ae764 | ||
|
|
f1e79707e8 | ||
|
|
9073cb53a8 | ||
|
|
d018070891 | ||
|
|
837924b819 | ||
|
|
00cfb1347a | ||
|
|
0ce2e61db9 | ||
|
|
1854e3440b | ||
|
|
a0260eb0b2 | ||
|
|
c874f201c3 | ||
|
|
7072f24103 | ||
|
|
eb4914d36f | ||
|
|
6d27631764 | ||
|
|
a522255baf | ||
|
|
7eb2e36740 | ||
|
|
2d8f01b2e9 | ||
|
|
6f95556632 | ||
|
|
0326f0d4c9 | ||
|
|
389f7fdc25 | ||
|
|
11b2942d09 | ||
|
|
52cc725de4 | ||
|
|
a304d4235d | ||
|
|
4d7024e066 | ||
|
|
4ce928eb41 | ||
|
|
b172172be1 | ||
|
|
5fd86954d6 |
107
.appveyor.yml
107
.appveyor.yml
@@ -1,107 +0,0 @@
|
|||||||
version: build {build}
|
|
||||||
|
|
||||||
# Skipping commits affecting specific files (GitHub only).
|
|
||||||
# More details here: https://www.appveyor.com/docs/appveyor-yml and https://www.appveyor.com/docs/how-to/filtering-commits
|
|
||||||
skip_commits:
|
|
||||||
files:
|
|
||||||
- .ci/travis-*
|
|
||||||
- .github/
|
|
||||||
- .tx/
|
|
||||||
- webclient/
|
|
||||||
- .clang-format
|
|
||||||
- .*ignore
|
|
||||||
- .codacy.yml
|
|
||||||
- .gitlab-ci.yml
|
|
||||||
- .travis.yml
|
|
||||||
- '**/*.md'
|
|
||||||
- Dockerfile
|
|
||||||
- LICENSE
|
|
||||||
|
|
||||||
skip_branch_with_pr: true
|
|
||||||
|
|
||||||
clone_depth: 15
|
|
||||||
|
|
||||||
image: Visual Studio 2017
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- c:\Tools\vcpkg\installed
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- target_arch: win64
|
|
||||||
qt_ver: 5.9\msvc2017_64
|
|
||||||
cmake_generator: Visual Studio 15 2017 Win64
|
|
||||||
cmake_toolset: v141,host=x64
|
|
||||||
vcpkg_arch: x64
|
|
||||||
|
|
||||||
- target_arch: win32
|
|
||||||
qt_ver: 5.9\msvc2015 # Qt doesn't provide a msvc2017_32
|
|
||||||
cmake_generator: Visual Studio 15 2017
|
|
||||||
cmake_toolset: v141
|
|
||||||
vcpkg_arch: x86
|
|
||||||
|
|
||||||
install:
|
|
||||||
- vcpkg remove --outdated --recurse
|
|
||||||
- vcpkg install openssl protobuf liblzma zlib --triplet %vcpkg_arch%-windows
|
|
||||||
|
|
||||||
services:
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- ps: |
|
|
||||||
New-Item -ItemType directory -Path $env:APPVEYOR_BUILD_FOLDER\build
|
|
||||||
Set-Location -Path $env:APPVEYOR_BUILD_FOLDER\build
|
|
||||||
$vcpkgbindir = "C:\Tools\vcpkg\installed\$env:vcpkg_arch-windows\bin"
|
|
||||||
$mysqldll = "c:\Program Files\MySQL\MySQL Server 5.7\lib\libmysql.dll"
|
|
||||||
cmake --version
|
|
||||||
cmake .. -G "$env:cmake_generator" -T "$env:cmake_toolset" "-DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake" "-DCMAKE_PREFIX_PATH=c:/Qt/$env:qt_ver;$vcpkgbindir" "-DWITH_SERVER=1" "-DMYSQLCLIENT_LIBRARIES=$mysqldll"
|
|
||||||
- msbuild PACKAGE.vcxproj /p:Configuration=Release
|
|
||||||
- ps: |
|
|
||||||
$exe = dir -name *.exe
|
|
||||||
$new_name = $exe.Replace(".exe", "-${env:target_arch}.exe")
|
|
||||||
Push-AppveyorArtifact $exe -FileName $new_name
|
|
||||||
$cmake_name = $exe.Replace(".exe", "-${env:target_arch}.cmake.txt")
|
|
||||||
Push-AppveyorArtifact CMakeCache.txt -FileName $cmake_name
|
|
||||||
$json = New-Object PSObject
|
|
||||||
(New-Object PSObject | Add-Member -PassThru NoteProperty bin $new_name | Add-Member -PassThru NoteProperty cmake $cmake_name | Add-Member -PassThru NoteProperty commit $env:APPVEYOR_REPO_COMMIT) | ConvertTo-JSON | Out-File -FilePath "latest-$env:target_arch" -Encoding ASCII
|
|
||||||
Push-AppveyorArtifact "latest-$env:target_arch"
|
|
||||||
$version = $matches['content']
|
|
||||||
|
|
||||||
test: off
|
|
||||||
|
|
||||||
|
|
||||||
# Builds for pull requests skip the deployment step altogether
|
|
||||||
deploy:
|
|
||||||
# Deploy configuration for "beta" releases
|
|
||||||
- provider: GitHub
|
|
||||||
auth_token:
|
|
||||||
secure: z8Xh1lSCYtvs0SUfhOK6AijCFk0Rgf5jAxu7QvBByR42NG1SxFHPOmyrOllkfy1u
|
|
||||||
tag: "$(APPVEYOR_REPO_TAG_NAME)"
|
|
||||||
release: "Cockatrice $(APPVEYOR_REPO_TAG_NAME)"
|
|
||||||
description: "Beta release of Cockatrice"
|
|
||||||
artifact: /.*\.exe/
|
|
||||||
force_update: true
|
|
||||||
draft: false
|
|
||||||
prerelease: true
|
|
||||||
on:
|
|
||||||
APPVEYOR_REPO_TAG: true
|
|
||||||
APPVEYOR_REPO_TAG_NAME: /([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}-beta(\.([2-9]|[1-9][0-9]))?$/ # regex to match semver naming convention for beta pre-releases
|
|
||||||
|
|
||||||
# Deploy configuration for "stable" releases
|
|
||||||
- provider: GitHub
|
|
||||||
auth_token:
|
|
||||||
secure: z8Xh1lSCYtvs0SUfhOK6AijCFk0Rgf5jAxu7QvBByR42NG1SxFHPOmyrOllkfy1u
|
|
||||||
tag: "$(APPVEYOR_REPO_TAG_NAME)"
|
|
||||||
release: "Cockatrice $(APPVEYOR_REPO_TAG_NAME)"
|
|
||||||
artifact: /.*\.exe/
|
|
||||||
force_update: true
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
on:
|
|
||||||
APPVEYOR_REPO_TAG: true
|
|
||||||
APPVEYOR_REPO_TAG_NAME: /([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}$/ # regex to match semver naming convention for stable full releases
|
|
||||||
|
|
||||||
|
|
||||||
# Announcements of build image updates: https://www.appveyor.com/updates/
|
|
||||||
# Official validator for ".appveyor.yml" config file: https://ci.appveyor.com/tools/validate-yaml
|
|
||||||
# AppVeyor config documentation: https://www.appveyor.com/docs/build-configuration/
|
|
||||||
17
.ci/ArchLinux/Dockerfile
Normal file
17
.ci/ArchLinux/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from archlinux:latest
|
||||||
|
|
||||||
|
RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
|
||||||
|
base-devel \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
git \
|
||||||
|
gtest \
|
||||||
|
mariadb-libs \
|
||||||
|
protobuf \
|
||||||
|
qt6-base \
|
||||||
|
qt6-multimedia \
|
||||||
|
qt6-svg \
|
||||||
|
qt6-tools \
|
||||||
|
qt6-translations \
|
||||||
|
qt6-websockets \
|
||||||
|
&& pacman --sync --clean --clean --noconfirm
|
||||||
25
.ci/Debian10/Dockerfile
Normal file
25
.ci/Debian10/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM debian:10
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
ccache \
|
||||||
|
clang-format \
|
||||||
|
cmake \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt5multimedia5-plugins \
|
||||||
|
libqt5sql5-mysql \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5websockets5-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt5-default \
|
||||||
|
qtbase5-dev \
|
||||||
|
qtmultimedia5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
24
.ci/Debian11/Dockerfile
Normal file
24
.ci/Debian11/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
FROM debian:11
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
ccache \
|
||||||
|
clang-format \
|
||||||
|
cmake \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt5multimedia5-plugins \
|
||||||
|
libqt5sql5-mysql \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5websockets5-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qtmultimedia5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
FROM fedora:29
|
|
||||||
|
|
||||||
RUN dnf install -y \
|
|
||||||
@development-tools \
|
|
||||||
ccache \
|
|
||||||
cmake \
|
|
||||||
desktop-file-utils \
|
|
||||||
file \
|
|
||||||
gcc-c++ \
|
|
||||||
hicolor-icon-theme \
|
|
||||||
libappstream-glib \
|
|
||||||
protobuf-devel \
|
|
||||||
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel-5.11.1-2.fc29 \
|
|
||||||
rpm-build \
|
|
||||||
sqlite-devel \
|
|
||||||
wget \
|
|
||||||
zlib-devel \
|
|
||||||
xz-devel \
|
|
||||||
&& dnf clean all
|
|
||||||
14
.ci/Fedora36/Dockerfile
Normal file
14
.ci/Fedora36/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM fedora:36
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
gcc-c++ \
|
||||||
|
git \
|
||||||
|
mariadb-devel \
|
||||||
|
protobuf-devel \
|
||||||
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||||
|
rpm-build \
|
||||||
|
xz-devel \
|
||||||
|
zlib-devel \
|
||||||
|
&& dnf clean all
|
||||||
14
.ci/Fedora37/Dockerfile
Normal file
14
.ci/Fedora37/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM fedora:37
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
gcc-c++ \
|
||||||
|
git \
|
||||||
|
mariadb-devel \
|
||||||
|
protobuf-devel \
|
||||||
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||||
|
rpm-build \
|
||||||
|
xz-devel \
|
||||||
|
zlib-devel \
|
||||||
|
&& dnf clean all
|
||||||
@@ -2,21 +2,23 @@ FROM ubuntu:bionic
|
|||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
|
ccache \
|
||||||
clang-format \
|
clang-format \
|
||||||
|
cmake \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
git \
|
git \
|
||||||
ccache \
|
|
||||||
cmake \
|
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
libprotobuf-dev \
|
libprotobuf-dev \
|
||||||
libqt5multimedia5-plugins \
|
libqt5multimedia5-plugins \
|
||||||
libqt5svg5-dev \
|
|
||||||
libqt5sql5-mysql \
|
libqt5sql5-mysql \
|
||||||
|
libqt5svg5-dev \
|
||||||
libqt5websockets5-dev \
|
libqt5websockets5-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
qt5-default \
|
qt5-default \
|
||||||
|
qtmultimedia5-dev \
|
||||||
qttools5-dev \
|
qttools5-dev \
|
||||||
qttools5-dev-tools \
|
qttools5-dev-tools \
|
||||||
qtmultimedia5-dev \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|||||||
25
.ci/UbuntuFocal/Dockerfile
Normal file
25
.ci/UbuntuFocal/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM ubuntu:focal
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
ccache \
|
||||||
|
clang-format \
|
||||||
|
cmake \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt5multimedia5-plugins \
|
||||||
|
libqt5sql5-mysql \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5websockets5-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt5-default \
|
||||||
|
qtmultimedia5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
26
.ci/UbuntuJammy/Dockerfile
Normal file
26
.ci/UbuntuJammy/Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
FROM ubuntu:jammy
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
ccache \
|
||||||
|
clang-format \
|
||||||
|
cmake \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
libgl-dev \
|
||||||
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt6multimedia6 \
|
||||||
|
libqt6sql6-mysql \
|
||||||
|
libqt6svg6-dev \
|
||||||
|
libqt6websockets6-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt6-l10n-tools \
|
||||||
|
qt6-multimedia-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
26
.ci/UbuntuKinetic/Dockerfile
Normal file
26
.ci/UbuntuKinetic/Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
FROM ubuntu:kinetic
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
ccache \
|
||||||
|
clang-format \
|
||||||
|
cmake \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
libgl-dev \
|
||||||
|
liblzma-dev \
|
||||||
|
libmariadb-dev-compat \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt6multimedia6 \
|
||||||
|
libqt6sql6-mysql \
|
||||||
|
libqt6svg6-dev \
|
||||||
|
libqt6websockets6-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt6-l10n-tools \
|
||||||
|
qt6-multimedia-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
195
.ci/compile.sh
Executable file
195
.ci/compile.sh
Executable file
@@ -0,0 +1,195 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
||||||
|
|
||||||
|
# Compiles cockatrice inside of a ci environment
|
||||||
|
# --install runs make install
|
||||||
|
# --package [<package type>] runs make package, optionally force the type
|
||||||
|
# --suffix <suffix> renames package with this suffix, requires arg
|
||||||
|
# --server compiles servatrice
|
||||||
|
# --test runs tests
|
||||||
|
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||||
|
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||||
|
# --dir <dir> sets the name of the build dir, default is "build"
|
||||||
|
# --parallel <core count> sets how many cores cmake should build with in parallel
|
||||||
|
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR PARALLEL_COUNT
|
||||||
|
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir> --parallel <core_count>)
|
||||||
|
# exitcode: 1 for failure, 3 for invalid arguments
|
||||||
|
|
||||||
|
# Read arguments
|
||||||
|
while [[ $# != 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
'--')
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--install')
|
||||||
|
MAKE_INSTALL=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--package')
|
||||||
|
MAKE_PACKAGE=1
|
||||||
|
shift
|
||||||
|
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||||
|
PACKAGE_TYPE="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'--suffix')
|
||||||
|
shift
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
echo "::error file=$0::--suffix expects an argument"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
PACKAGE_SUFFIX="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--server')
|
||||||
|
MAKE_SERVER=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--test')
|
||||||
|
MAKE_TEST=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--debug')
|
||||||
|
BUILDTYPE="Debug"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--release')
|
||||||
|
BUILDTYPE="Release"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--ccache')
|
||||||
|
USE_CCACHE=1
|
||||||
|
shift
|
||||||
|
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||||
|
CCACHE_SIZE="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'--dir')
|
||||||
|
shift
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
echo "::error file=$0::--dir expects an argument"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
BUILD_DIR="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--parallel')
|
||||||
|
shift
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
echo "::error file=$0::--parallel expects an argument"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
PARALLEL_COUNT="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "::error file=$0::unrecognized option: $1"
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
./servatrice/check_schema_version.sh
|
||||||
|
if [[ ! $BUILDTYPE ]]; then
|
||||||
|
BUILDTYPE=Release
|
||||||
|
fi
|
||||||
|
if [[ ! $BUILD_DIR ]]; then
|
||||||
|
BUILD_DIR="build"
|
||||||
|
fi
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
|
# Add cmake flags
|
||||||
|
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||||
|
if [[ $MAKE_SERVER ]]; then
|
||||||
|
flags+=("-DWITH_SERVER=1")
|
||||||
|
fi
|
||||||
|
if [[ $MAKE_TEST ]]; then
|
||||||
|
flags+=("-DTEST=1")
|
||||||
|
fi
|
||||||
|
if [[ $USE_CCACHE ]]; then
|
||||||
|
flags+=("-DUSE_CCACHE=1")
|
||||||
|
if [[ $CCACHE_SIZE ]]; then
|
||||||
|
# note, this setting persists after running the script
|
||||||
|
ccache --max-size "$CCACHE_SIZE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $PACKAGE_TYPE ]]; then
|
||||||
|
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add cmake --build flags
|
||||||
|
buildflags=(--config "$BUILDTYPE")
|
||||||
|
if [[ $PARALLEL_COUNT ]]; then
|
||||||
|
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
|
||||||
|
# workaround for bionic having an old cmake
|
||||||
|
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
||||||
|
buildflags+=(-- -j "$PARALLEL_COUNT")
|
||||||
|
# note, no normal build flags should be added after this
|
||||||
|
else
|
||||||
|
buildflags+=(--parallel "$PARALLEL_COUNT")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
function ccachestatsverbose() {
|
||||||
|
# note, verbose only works on newer ccache, discard the error
|
||||||
|
local got
|
||||||
|
if got="$(ccache --show-stats --verbose 2>/dev/null)"; then
|
||||||
|
echo "$got"
|
||||||
|
else
|
||||||
|
ccache --show-stats
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compile
|
||||||
|
if [[ $USE_CCACHE ]]; then
|
||||||
|
echo "::group::Show ccache stats"
|
||||||
|
ccachestatsverbose
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "::group::Configure cmake"
|
||||||
|
cmake --version
|
||||||
|
cmake .. "${flags[@]}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
echo "::group::Build project"
|
||||||
|
cmake --build . "${buildflags[@]}"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ $USE_CCACHE ]]; then
|
||||||
|
echo "::group::Show ccache stats again"
|
||||||
|
ccachestatsverbose
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAKE_TEST ]]; then
|
||||||
|
echo "::group::Run tests"
|
||||||
|
ctest -C "$BUILDTYPE" --output-on-failure
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAKE_INSTALL ]]; then
|
||||||
|
echo "::group::Install"
|
||||||
|
cmake --build . --target install --config "$BUILDTYPE"
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAKE_PACKAGE ]]; then
|
||||||
|
echo "::group::Create package"
|
||||||
|
cmake --build . --target package --config "$BUILDTYPE"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
if [[ $PACKAGE_SUFFIX ]]; then
|
||||||
|
echo "::group::Update package name"
|
||||||
|
cd ..
|
||||||
|
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
165
.ci/docker.sh
Normal file
165
.ci/docker.sh
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
||||||
|
|
||||||
|
# Creates or loads docker images to use in compilation, creates RUN function to start compilation on the docker image.
|
||||||
|
# <arg> sets the name of the docker image, these correspond to directories in .ci
|
||||||
|
# --get loads the image from a previously saved image cache, will build if no image is found
|
||||||
|
# --build builds the image from the Dockerfile in .ci/$NAME
|
||||||
|
# --save stores the image, if an image was loaded it will not be stored
|
||||||
|
# --interactive immediately starts the image interactively for debugging
|
||||||
|
# --set-cache <location> sets the location to cache the image or for ccache
|
||||||
|
# requires: docker
|
||||||
|
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE
|
||||||
|
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||||
|
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
||||||
|
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||||
|
export BUILD_SCRIPT=".ci/compile.sh"
|
||||||
|
|
||||||
|
project_name="cockatrice"
|
||||||
|
save_extension=".tar.gz"
|
||||||
|
image_cache="image"
|
||||||
|
ccache_cache=".ccache"
|
||||||
|
|
||||||
|
# Read arguments
|
||||||
|
while [[ $# != 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
'--build')
|
||||||
|
BUILD=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--get')
|
||||||
|
GET=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--interactive')
|
||||||
|
INTERACTIVE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--save')
|
||||||
|
SAVE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--set-cache')
|
||||||
|
CACHE=$2
|
||||||
|
if ! [[ -d $CACHE ]]; then
|
||||||
|
echo "could not find cache path: $CACHE" >&2
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ ${1:0:1} == - ]]; then
|
||||||
|
echo "unrecognized option: $1"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
NAME="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
if ! [[ $NAME ]]; then
|
||||||
|
echo "no build name given" >&2
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
export IMAGE_NAME="${project_name,,}_${NAME,,}" # lower case
|
||||||
|
|
||||||
|
docker_dir=".ci/$NAME"
|
||||||
|
if ! [[ -r $docker_dir/Dockerfile ]]; then
|
||||||
|
echo "could not find Dockerfile in $docker_dir" >&2
|
||||||
|
return 2 # even if the image is cached, we do not want to run if there is no way to build this image
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ $CACHE ]]; then
|
||||||
|
echo "cache dir is not set!" >&2
|
||||||
|
CACHE="$(mktemp -d)"
|
||||||
|
echo "set cache dir to $CACHE" >&2
|
||||||
|
fi
|
||||||
|
if ! [[ -d $CACHE ]]; then
|
||||||
|
echo "could not find cache dir: $CACHE" >&2
|
||||||
|
mkdir -p "$CACHE"
|
||||||
|
unset GET # the dir is empty
|
||||||
|
fi
|
||||||
|
if [[ $GET || $SAVE ]]; then
|
||||||
|
img_dir="$CACHE/$image_cache"
|
||||||
|
img_save="$img_dir/$IMAGE_NAME$save_extension"
|
||||||
|
if ! [[ -d $img_dir ]]; then
|
||||||
|
echo "could not find image dir: $img_dir" >&2
|
||||||
|
mkdir -p "$img_dir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
export CCACHE_DIR="$CACHE/$ccache_cache"
|
||||||
|
if ! [[ -d $CCACHE_DIR ]]; then
|
||||||
|
echo "could not find ccache dir: $CCACHE_DIR" >&2
|
||||||
|
mkdir -p "$CCACHE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the docker image from previously stored save
|
||||||
|
if [[ $GET ]]; then
|
||||||
|
if [[ $img_save ]] && docker load --input "$img_save"; then
|
||||||
|
echo "loaded image"
|
||||||
|
docker images
|
||||||
|
unset BUILD # do not overwrite the loaded image with build
|
||||||
|
unset SAVE # do not overwrite the stored image with the same image
|
||||||
|
if [[ $(find "$CCACHE_DIR" -type f -print -quit) ]]; then # check contents of ccache
|
||||||
|
echo "setting ccache to readonly"
|
||||||
|
export RUN_ARGS="$RUN_ARGS -e CCACHE_READONLY=1 -e CCACHE_NOSTATS=1" # do not overwrite ccache
|
||||||
|
else
|
||||||
|
echo "ccache is empty: $(find "$CCACHE_DIR")" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "could not load cached image, building instead" >&2
|
||||||
|
BUILD=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the docker image from dockerfile
|
||||||
|
if [[ $BUILD ]]; then
|
||||||
|
if docker build --tag "$IMAGE_NAME" "$docker_dir"; then
|
||||||
|
echo "built image"
|
||||||
|
docker images
|
||||||
|
else
|
||||||
|
echo "could not build image $IMAGE_NAME" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Save docker image to cache (compressed)
|
||||||
|
if [[ $SAVE ]]; then
|
||||||
|
if [[ $img_save ]] && docker save --output "$img_save" "$IMAGE_NAME"; then
|
||||||
|
echo "saved image to: $img_save"
|
||||||
|
else
|
||||||
|
echo "could not save image $IMAGE_NAME" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set compile function, runs the compile script on the image, passes arguments to the script
|
||||||
|
function RUN ()
|
||||||
|
{
|
||||||
|
echo "running image:"
|
||||||
|
if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
|
||||||
|
local args=(--mount "type=bind,source=$PWD,target=/src")
|
||||||
|
args+=(--workdir "/src")
|
||||||
|
args+=(--user "$(id -u):$(id -g)")
|
||||||
|
if [[ $CCACHE_DIR ]]; then
|
||||||
|
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
|
||||||
|
args+=(--env "CCACHE_DIR=/.ccache")
|
||||||
|
fi
|
||||||
|
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
|
||||||
|
return $?
|
||||||
|
else
|
||||||
|
echo "could not find docker image: $IMAGE_NAME" >&2
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# for debugging, start the docker image interactively instead of building
|
||||||
|
# starts immediately, does not require sourcing or RUN
|
||||||
|
if [[ $INTERACTIVE ]]; then
|
||||||
|
export BUILD_SCRIPT="-i"
|
||||||
|
export RUN_ARGS="$RUN_ARGS -it"
|
||||||
|
RUN
|
||||||
|
fi
|
||||||
69
.ci/lint_cpp.sh
Executable file
69
.ci/lint_cpp.sh
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# fetch master branch
|
||||||
|
git fetch origin master
|
||||||
|
|
||||||
|
# unshallow if needed
|
||||||
|
echo "Finding merge base"
|
||||||
|
if ! git merge-base origin/master HEAD; then
|
||||||
|
echo "Could not find merge base, unshallowing repo"
|
||||||
|
git fetch --unshallow
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check formatting using format.sh
|
||||||
|
echo "Checking your code using clang-format/cmake-format..."
|
||||||
|
|
||||||
|
diff="$(./format.sh --diff --cmake --cf-version --branch origin/master)"
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
case $err in
|
||||||
|
1)
|
||||||
|
cat <<EOM
|
||||||
|
|
||||||
|
***********************************************************
|
||||||
|
*** ***
|
||||||
|
*** Your code does not comply with our style guide. ***
|
||||||
|
*** ***
|
||||||
|
*** Please correct it or run the "format.sh" script. ***
|
||||||
|
*** Then commit and push those changes to this branch. ***
|
||||||
|
*** Check our CONTRIBUTING.md file for more details. ***
|
||||||
|
*** ***
|
||||||
|
*** Thank you ❤️ ***
|
||||||
|
*** ***
|
||||||
|
***********************************************************
|
||||||
|
|
||||||
|
Used version:
|
||||||
|
${diff%%
|
||||||
|
----------
|
||||||
|
*}
|
||||||
|
|
||||||
|
The following changes should be made:
|
||||||
|
${diff#*
|
||||||
|
----------
|
||||||
|
}
|
||||||
|
|
||||||
|
Exiting...
|
||||||
|
EOM
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
|
||||||
|
0)
|
||||||
|
cat <<EOM
|
||||||
|
|
||||||
|
***********************************************************
|
||||||
|
*** ***
|
||||||
|
*** Your code complies with our style guide! ***
|
||||||
|
*** ***
|
||||||
|
*** Awesome 👍 ***
|
||||||
|
*** ***
|
||||||
|
***********************************************************
|
||||||
|
|
||||||
|
Exiting...
|
||||||
|
EOM
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Something went wrong in our formatting checks: format.sh returned $err" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
55
.ci/name_build.sh
Executable file
55
.ci/name_build.sh
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# used by the ci to rename build artifacts
|
||||||
|
# renames the file to [original name][SUFFIX].[original extension]
|
||||||
|
# where SUFFIX is either available in the environment or as the first arg
|
||||||
|
# if MAKE_ZIP is set instead a zip is made
|
||||||
|
# expected to be run in the build directory unless BUILD_DIR is set
|
||||||
|
# adds output to GITHUB_OUTPUT
|
||||||
|
builddir="${BUILD_DIR:=.}"
|
||||||
|
findrx="Cockatrice-*.*"
|
||||||
|
|
||||||
|
if [[ $1 ]]; then
|
||||||
|
SUFFIX="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check env
|
||||||
|
if [[ ! $SUFFIX ]]; then
|
||||||
|
echo "::error file=$0::SUFFIX is missing"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# find file
|
||||||
|
found="$(find "$builddir" -maxdepth 1 -type f -name "$findrx" -print -quit)"
|
||||||
|
path="${found%/*}" # remove all after last /
|
||||||
|
file="${found##*/}" # remove all before last /
|
||||||
|
if [[ ! $file ]]; then
|
||||||
|
echo "::error file=$0::could not find package"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
oldpwd="$PWD"
|
||||||
|
if ! cd "$path"; then
|
||||||
|
echo "::error file=$0::could not get file path"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set filename
|
||||||
|
name="${file%.*}" # remove all after last .
|
||||||
|
new_name="$name$SUFFIX."
|
||||||
|
if [[ $MAKE_ZIP ]]; then
|
||||||
|
filename="${new_name}zip"
|
||||||
|
echo "creating zip '$filename' from '$file'"
|
||||||
|
zip "$filename" "$file"
|
||||||
|
else
|
||||||
|
extension="${file##*.}" # remove all before last .
|
||||||
|
filename="$new_name$extension"
|
||||||
|
echo "renaming '$file' to '$filename'"
|
||||||
|
mv "$file" "$filename"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$oldpwd"
|
||||||
|
relative_path="$path/$filename"
|
||||||
|
ls -l "$relative_path"
|
||||||
|
echo "path=$relative_path" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "name=$filename" >>"$GITHUB_OUTPUT"
|
||||||
113
.ci/prep_release.sh
Executable file
113
.ci/prep_release.sh
Executable file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# sets the properties of ci releases
|
||||||
|
# this doesn't have to be 100% foolproof
|
||||||
|
# the releases are first made as drafts and will be vetted by a human
|
||||||
|
# it just has to provide a template
|
||||||
|
# this requires the repo to be unshallowed
|
||||||
|
# adds output to GITHUB_OUTPUT
|
||||||
|
template_path=".ci/release_template.md"
|
||||||
|
body_path="/tmp/release.md"
|
||||||
|
beta_regex='beta'
|
||||||
|
name_regex='set\(GIT_TAG_RELEASENAME "([[:print:]]+)")'
|
||||||
|
whitespace='^\s*$'
|
||||||
|
|
||||||
|
if [[ $1 ]]; then
|
||||||
|
TAG="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check env
|
||||||
|
if [[ ! $TAG ]]; then
|
||||||
|
echo "::error file=$0::TAG is missing"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create title
|
||||||
|
if [[ $TAG =~ $beta_regex ]]; then
|
||||||
|
echo "is_beta=yes" >>"$GITHUB_OUTPUT"
|
||||||
|
title="$TAG"
|
||||||
|
echo "creating beta release '$title'"
|
||||||
|
elif [[ ! $(cat CMakeLists.txt) =~ $name_regex ]]; then
|
||||||
|
echo "::error file=$0::could not find releasename in CMakeLists.txt"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "is_beta=no" >>"$GITHUB_OUTPUT"
|
||||||
|
name="${BASH_REMATCH[1]}"
|
||||||
|
version="${TAG##*-}"
|
||||||
|
title="Cockatrice $version: $name"
|
||||||
|
no_beta=1
|
||||||
|
echo "friendly_name=$name" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "creating full release '$title'"
|
||||||
|
fi
|
||||||
|
echo "title=$title" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# add release notes template
|
||||||
|
if [[ $no_beta ]]; then
|
||||||
|
body="$(cat "$template_path")"
|
||||||
|
if [[ ! $body ]]; then
|
||||||
|
echo "::warning file=$0::could not find release template"
|
||||||
|
fi
|
||||||
|
body="${body//--REPLACE-WITH-RELEASE-TITLE--/$title}"
|
||||||
|
else
|
||||||
|
body="--REPLACE-WITH-COMMIT-COUNT-- commits have been included over the previous --REPLACE-WITH-PREVIOUS-RELEASE-TYPE--
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>show changes</b></summary>
|
||||||
|
|
||||||
|
--REPLACE-WITH-GENERATED-LIST--
|
||||||
|
</details>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# add git log to release notes
|
||||||
|
all_tags="
|
||||||
|
$(git tag)" # tags are ordered alphabetically
|
||||||
|
before="${all_tags%%
|
||||||
|
"$TAG"*}" # strip line with current tag an all lines after it
|
||||||
|
# note the extra newlines are needed to always have a last line
|
||||||
|
if [[ $all_tags == "$before" ]]; then
|
||||||
|
echo "::warning file=$0::could not find current tag"
|
||||||
|
else
|
||||||
|
while
|
||||||
|
previous="${before##*
|
||||||
|
}" # get the last line
|
||||||
|
# skip this tag if this is a full release and it's a beta or if empty
|
||||||
|
[[ $no_beta && $previous =~ $beta_regex || ! $previous ]]
|
||||||
|
do
|
||||||
|
beta_list+=" $previous" # add to list of skipped betas
|
||||||
|
next_before="${before%
|
||||||
|
*}" # strip the last line
|
||||||
|
if [[ $next_before == "$before" ]]; then
|
||||||
|
unset previous
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
before="$next_before"
|
||||||
|
done
|
||||||
|
if [[ $previous ]]; then
|
||||||
|
if generated_list="$(git log "$previous..$TAG" --pretty="- %s")"; then
|
||||||
|
count="$(git rev-list --count "$previous..$TAG")"
|
||||||
|
[[ $previous =~ $beta_regex ]] && previousreleasetype="beta release" || previousreleasetype="full release"
|
||||||
|
echo "adding list of commits to release notes:"
|
||||||
|
echo "'$previous' to '$TAG' ($count commits)"
|
||||||
|
# --> is the markdown comment escape sequence, emojis are way better
|
||||||
|
generated_list="${generated_list//-->/→}"
|
||||||
|
body="${body//--REPLACE-WITH-GENERATED-LIST--/$generated_list}"
|
||||||
|
body="${body//--REPLACE-WITH-COMMIT-COUNT--/$count}"
|
||||||
|
body="${body//--REPLACE-WITH-PREVIOUS-RELEASE-TAG--/$previous}"
|
||||||
|
body="${body//--REPLACE-WITH-PREVIOUS-RELEASE-TYPE--/$previousreleasetype}"
|
||||||
|
if [[ $beta_list =~ $whitespace ]]; then
|
||||||
|
beta_list="-n there are no betas to delete!"
|
||||||
|
else
|
||||||
|
echo "the following betas should be deleted after publishing:"
|
||||||
|
echo "$beta_list"
|
||||||
|
fi
|
||||||
|
body="${body//--REPLACE-WITH-BETA-LIST--/$beta_list}"
|
||||||
|
else
|
||||||
|
echo "::warning file=$0::failed to produce git log"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "::warning file=$0::could not find previous tag"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# write to file
|
||||||
|
echo "body_path=$body_path" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "$body" >"$body_path"
|
||||||
94
.ci/release_template.md
Normal file
94
.ci/release_template.md
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<!-- this template comes from .ci/release_template.md -->
|
||||||
|
|
||||||
|
<!-- Don't forget to delete the previous betas after publishing this!
|
||||||
|
git push -d origin --REPLACE-WITH-BETA-LIST--
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- This list of binaries should be updated every time the ci is changed to
|
||||||
|
include different targets -->
|
||||||
|
<pre>
|
||||||
|
<b>Pre-compiled binaries we serve:</b>
|
||||||
|
- <kbd>Windows 7+ (32-bit)</kbd>
|
||||||
|
- <kbd>Windows 7+</kbd>
|
||||||
|
- <kbd>Windows 10+</kbd>
|
||||||
|
- <kbd>macOS 10.15+</kbd> ("Catalina")
|
||||||
|
- <kbd>macOS 11+</kbd> ("Big Sur")
|
||||||
|
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")
|
||||||
|
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")
|
||||||
|
- <kbd>Ubuntu 22.04</kbd> ("Jammy Jellyfish")
|
||||||
|
- <kbd>Ubuntu 22.10</kbd> ("Kinetic Kudu")
|
||||||
|
- <kbd>Debian 10</kbd> ("Buster")
|
||||||
|
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||||
|
- <kbd>Fedora 36</kbd>
|
||||||
|
- <kbd>Fedora 37</kbd>
|
||||||
|
<kbd>We are also packaged in Arch Linux's official community repository, courtesy of @FFY00</kbd></i>
|
||||||
|
<kbd>General linux support is available via a flatpak package (Flathub)</kbd></i>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
## General Notes
|
||||||
|
|
||||||
|
We're pleased to announce the newest official release: <kbd>--REPLACE-WITH-RELEASE-TITLE--</kbd>
|
||||||
|
|
||||||
|
We hope you enjoy the changes made and we have listed all changes, with their corresponding tickets, since the last version of Cockatrice was released for your convenience.
|
||||||
|
|
||||||
|
If you ever encounter a bug, have a suggestion or idea, or feel a need for a developer to look into something, please feel free to [open a ticket](https://github.com/Cockatrice/Cockatrice/issues). ([How to create a GitHub Ticket for Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))
|
||||||
|
|
||||||
|
For any information relating to Cockatrice, please take a look at our official site: **https://cockatrice.github.io**
|
||||||
|
|
||||||
|
If you'd like to help contribute to Cockatrice in any way, check out our [README](https://github.com/Cockatrice/Cockatrice#get-involved-). We're always available to answer questions you may have on how the program works and how you can provide a meaningful contribution.
|
||||||
|
|
||||||
|
|
||||||
|
## Upgrading Cockatrice
|
||||||
|
<!-- this optional section puts a warning banner for problems with updating
|
||||||
|
> ⚠️ **With this release, we no longer provide a ready-to-install binary for:**
|
||||||
|
> --DEPRECATED-OS-HERE--
|
||||||
|
-->
|
||||||
|
|
||||||
|
- Run the internal software updater: <kbd>Help → Check for Client Updates</kbd>
|
||||||
|
|
||||||
|
Don't forget to update your card database right after! (<kbd>Help → Check for Card Updates...</kbd>)
|
||||||
|
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
<!--
|
||||||
|
This list is generated and should be moved to their respective header and
|
||||||
|
possibly edited a little.
|
||||||
|
Append PR numbers of fixups to their main PR to keep the list coherent.
|
||||||
|
Put the quantity of remaining PR's below the highlights section.
|
||||||
|
Remove empty headers when done.
|
||||||
|
|
||||||
|
--REPLACE-WITH-GENERATED-LIST--
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Highlights of the release -->
|
||||||
|
### ⚠️ Important:
|
||||||
|
### ✨ New Features:
|
||||||
|
### 🐛 Fixed Bugs / Resolved issues:
|
||||||
|
|
||||||
|
<!-- Complete list of changes (foldable) -->
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
📘 <b>Show all changes</b> (--REPLACE-WITH-COMMIT-COUNT-- commits)
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
### User Interface
|
||||||
|
### Under the Hood
|
||||||
|
### Oracle
|
||||||
|
### Servatrice
|
||||||
|
### Webatrice
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
## Translations
|
||||||
|
- **Thanks for over 300 people contributing to 20+ different languages up to now!**
|
||||||
|
- Without the help of the community we couldn't offer that great language support... keep up the good work!
|
||||||
|
- It's actually very easy to join and help for yourself - find out more here:
|
||||||
|
- [Help us Translate Cockatrice into your native language!](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ)
|
||||||
|
|
||||||
|
|
||||||
|
## Special Thanks
|
||||||
|
<!-- Personalise this a bit! -->
|
||||||
|
We continue to find it amazing that so many people contribute their time, knowledge, code, testing and more to the project. We'd like to thank the entire Cockatrice community for their efforts.
|
||||||
|
<!-- We'd like to especially recognize @ZeldaZach, --ADD-CONTRIBUTORS-HERE-- for their help in preparing so many amazing new features for the user base. -->
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This script is to be used in .travis.yaml from the project root directory, do not use it from somewhere else.
|
|
||||||
|
|
||||||
# Read arguments
|
|
||||||
while [[ "$@" ]]; do
|
|
||||||
case "$1" in
|
|
||||||
'--format')
|
|
||||||
CHECK_FORMAT=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--install')
|
|
||||||
MAKE_INSTALL=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--package')
|
|
||||||
MAKE_PACKAGE=1
|
|
||||||
shift
|
|
||||||
if [[ $# != 0 && $1 != -* ]]; then
|
|
||||||
PACKAGE_NAME="$1"
|
|
||||||
shift
|
|
||||||
if [[ $# != 0 && $1 != -* ]]; then
|
|
||||||
PACKAGE_TYPE="$1"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
'--server')
|
|
||||||
MAKE_SERVER=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--test')
|
|
||||||
MAKE_TEST=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--debug')
|
|
||||||
BUILDTYPE="Debug"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--release')
|
|
||||||
BUILDTYPE="Release"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [[ $1 == -* ]]; then
|
|
||||||
echo "unrecognized option: $1"
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
BUILDTYPE="$1"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Check formatting using clang-format
|
|
||||||
if [[ $CHECK_FORMAT ]]; then
|
|
||||||
echo "Checking your code using clang-format..."
|
|
||||||
diff="$(./clangify.sh --diff --cf-version)"
|
|
||||||
err=$?
|
|
||||||
case $err in
|
|
||||||
1)
|
|
||||||
cat <<EOM
|
|
||||||
***********************************************************
|
|
||||||
*** ***
|
|
||||||
*** Your code does not comply with our styleguide. ***
|
|
||||||
*** ***
|
|
||||||
*** Please correct it or run the "clangify.sh" script. ***
|
|
||||||
*** Then commit and push those changes to this branch. ***
|
|
||||||
*** Check our CONTRIBUTING.md file for more details. ***
|
|
||||||
*** ***
|
|
||||||
*** Thank you ♥ ***
|
|
||||||
*** ***
|
|
||||||
***********************************************************
|
|
||||||
|
|
||||||
Used clang-format version:
|
|
||||||
${diff%%
|
|
||||||
*}
|
|
||||||
|
|
||||||
The following changes should be made:
|
|
||||||
${diff#*
|
|
||||||
}
|
|
||||||
|
|
||||||
Exiting...
|
|
||||||
EOM
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
0)
|
|
||||||
echo "Thank you for complying with our code standards."
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Setup
|
|
||||||
./servatrice/check_schema_version.sh
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
|
|
||||||
# Add cmake flags
|
|
||||||
if [[ $MAKE_SERVER ]]; then
|
|
||||||
flags+=" -DWITH_SERVER=1"
|
|
||||||
fi
|
|
||||||
if [[ $MAKE_TEST ]]; then
|
|
||||||
flags+=" -DTEST=1"
|
|
||||||
BUILDTYPE="Debug" # test requires buildtype Debug
|
|
||||||
fi
|
|
||||||
if [[ $BUILDTYPE ]]; then
|
|
||||||
flags+=" -DCMAKE_BUILD_TYPE=$BUILDTYPE"
|
|
||||||
fi
|
|
||||||
if [[ $PACKAGE_TYPE ]]; then
|
|
||||||
flags+=" -DCPACK_GENERATOR=$PACKAGE_TYPE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add qt install location when using brew
|
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
|
||||||
PATH="/usr/local/opt/ccache/bin:$PATH"
|
|
||||||
flags+=" -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Compile
|
|
||||||
cmake --version
|
|
||||||
cmake .. $flags
|
|
||||||
make -j2
|
|
||||||
|
|
||||||
if [[ $MAKE_TEST ]]; then
|
|
||||||
make test
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $MAKE_INSTALL ]]; then
|
|
||||||
make install
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $MAKE_PACKAGE ]]; then
|
|
||||||
make package
|
|
||||||
if [[ $PACKAGE_NAME ]]; then
|
|
||||||
found=$(find . -maxdepth 1 -type f -name "Cockatrice-*.*" -print -quit)
|
|
||||||
path=${found%/*}
|
|
||||||
file=${found##*/}
|
|
||||||
if [[ ! $file ]]; then
|
|
||||||
echo "could not find package" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
mv "$path/$file" "$path/${file%.*}-$PACKAGE_NAME.${file##*.}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
@@ -23,3 +23,9 @@ BinPackParameters: false
|
|||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
|
SortIncludes: true
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
---
|
||||||
|
Language: Proto
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
|||||||
109
.cmake-format.json
Normal file
109
.cmake-format.json
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
{
|
||||||
|
"format": {
|
||||||
|
"_help_line_width": [
|
||||||
|
"How wide to allow formatted cmake files"
|
||||||
|
],
|
||||||
|
"line_width": 120,
|
||||||
|
"_help_tab_size": [
|
||||||
|
"How many spaces to tab for indent"
|
||||||
|
],
|
||||||
|
"tab_size": 2,
|
||||||
|
"_help_max_subgroups_hwrap": [
|
||||||
|
"If an argument group contains more than this many sub-groups",
|
||||||
|
"(parg or kwarg groups) then force it to a vertical layout."
|
||||||
|
],
|
||||||
|
"max_subgroups_hwrap": 2,
|
||||||
|
"_help_max_pargs_hwrap": [
|
||||||
|
"If a positional argument group contains more than this many",
|
||||||
|
"arguments, then force it to a vertical layout."
|
||||||
|
],
|
||||||
|
"max_pargs_hwrap": 6,
|
||||||
|
"_help_max_rows_cmdline": [
|
||||||
|
"If a cmdline positional group consumes more than this many",
|
||||||
|
"lines without nesting, then invalidate the layout (and nest)"
|
||||||
|
],
|
||||||
|
"max_rows_cmdline": 5,
|
||||||
|
"_help_separate_ctrl_name_with_space": [
|
||||||
|
"If true, separate flow control names from their parentheses",
|
||||||
|
"with a space"
|
||||||
|
],
|
||||||
|
"separate_ctrl_name_with_space": false,
|
||||||
|
"_help_separate_fn_name_with_space": [
|
||||||
|
"If true, separate function names from parentheses with a",
|
||||||
|
"space"
|
||||||
|
],
|
||||||
|
"separate_fn_name_with_space": false,
|
||||||
|
"_help_dangle_parens": [
|
||||||
|
"If a statement is wrapped to more than one line, than dangle",
|
||||||
|
"the closing parenthesis on its own line."
|
||||||
|
],
|
||||||
|
"dangle_parens": true,
|
||||||
|
"_help_dangle_align": [
|
||||||
|
"If the trailing parenthesis must be 'dangled' on its on",
|
||||||
|
"line, then align it to this reference: `prefix`: the start",
|
||||||
|
"of the statement, `prefix-indent`: the start of the",
|
||||||
|
"statement, plus one indentation level, `child`: align to",
|
||||||
|
"the column of the arguments"
|
||||||
|
],
|
||||||
|
"dangle_align": "prefix",
|
||||||
|
"_help_min_prefix_chars": [
|
||||||
|
"If the statement spelling length (including space and",
|
||||||
|
"parenthesis) is smaller than this amount, then force reject",
|
||||||
|
"nested layouts."
|
||||||
|
],
|
||||||
|
"min_prefix_chars": 4,
|
||||||
|
"_help_max_prefix_chars": [
|
||||||
|
"If the statement spelling length (including space and",
|
||||||
|
"parenthesis) is larger than the tab width by more than this",
|
||||||
|
"amount, then force reject un-nested layouts."
|
||||||
|
],
|
||||||
|
"max_prefix_chars": 10,
|
||||||
|
"_help_max_lines_hwrap": [
|
||||||
|
"If a candidate layout is wrapped horizontally but it exceeds",
|
||||||
|
"this many lines, then reject the layout."
|
||||||
|
],
|
||||||
|
"max_lines_hwrap": 2,
|
||||||
|
"_help_line_ending": [
|
||||||
|
"What style line endings to use in the output."
|
||||||
|
],
|
||||||
|
"line_ending": "auto",
|
||||||
|
"_help_command_case": [
|
||||||
|
"Format command names consistently as 'lower' or 'upper' case"
|
||||||
|
],
|
||||||
|
"command_case": "lower",
|
||||||
|
"_help_keyword_case": [
|
||||||
|
"Format keywords consistently as 'lower' or 'upper' case"
|
||||||
|
],
|
||||||
|
"keyword_case": "upper",
|
||||||
|
"_help_always_wrap": [
|
||||||
|
"A list of command names which should always be wrapped"
|
||||||
|
],
|
||||||
|
"always_wrap": [],
|
||||||
|
"_help_enable_sort": [
|
||||||
|
"If true, the argument lists which are known to be sortable",
|
||||||
|
"will be sorted lexicographically"
|
||||||
|
],
|
||||||
|
"enable_sort": true,
|
||||||
|
"_help_autosort": [
|
||||||
|
"If true, the parsers may infer whether or not an argument",
|
||||||
|
"list is sortable (without annotation)."
|
||||||
|
],
|
||||||
|
"autosort": true,
|
||||||
|
"_help_require_valid_layout": [
|
||||||
|
"By default, if cmake-format cannot successfully fit",
|
||||||
|
"everything into the desired line-width it will apply the",
|
||||||
|
"last, most aggressive attempt that it made. If this flag is",
|
||||||
|
"True, however, cmake-format will print error, exit with non-",
|
||||||
|
"zero status code, and write-out nothing"
|
||||||
|
],
|
||||||
|
"require_valid_layout": false,
|
||||||
|
"_help_layout_passes": [
|
||||||
|
"A dictionary mapping layout nodes to a list of wrap",
|
||||||
|
"decisions. See the documentation for more information."
|
||||||
|
],
|
||||||
|
"layout_passes": {}
|
||||||
|
},
|
||||||
|
"markup": {
|
||||||
|
"enable_markup": false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
.git/
|
.git/
|
||||||
build/
|
build/
|
||||||
.github/
|
.github/
|
||||||
.travis/
|
|
||||||
.tx/
|
.tx/
|
||||||
cockatrice/
|
cockatrice/
|
||||||
doc/
|
doc/
|
||||||
|
|||||||
285
.github/CONTRIBUTING.md
vendored
285
.github/CONTRIBUTING.md
vendored
@@ -1,4 +1,6 @@
|
|||||||
[Introduction](#contributing-to-cockatrice) | [Code Style Guide](#code-style-guide) | [Translations](#translations) | [Release Management](#release-management)
|
[Introduction](#contributing-to-cockatrice) | [Code Style Guide](
|
||||||
|
#code-style-guide) | [Translations](#translations) | [Release Management](
|
||||||
|
#release-management)
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -7,50 +9,89 @@
|
|||||||
# Contributing to Cockatrice #
|
# Contributing to Cockatrice #
|
||||||
First off, thanks for taking the time to contribute to our project! 🎉 ❤ ️✨
|
First off, thanks for taking the time to contribute to our project! 🎉 ❤ ️✨
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to Cockatrice. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
The following is a set of guidelines for contributing to Cockatrice. These are
|
||||||
|
mostly guidelines, not rules. Use your best judgment, and feel free to propose
|
||||||
|
changes to this document in a pull request.
|
||||||
|
|
||||||
|
|
||||||
# Recommended Setups #
|
# Recommended Setups #
|
||||||
|
|
||||||
For those developers who like the Linux or MacOS environment, many of our developers like working with a nifty program called [CLion](https://www.jetbrains.com/clion/). The program's a great asset and one of the best tools you'll find on these systems, but you're welcomed to use any IDE you most enjoy.
|
For those developers who like the Linux or MacOS environment, many of our
|
||||||
|
developers like working with a nifty program called [CLion](
|
||||||
|
https://www.jetbrains.com/clion/). The program's a great asset and one of the
|
||||||
|
best tools you'll find on these systems, but you're welcomed to use any IDE
|
||||||
|
you most enjoy.
|
||||||
|
|
||||||
Developers who like Windows development tend to find [Visual Studio](https://www.visualstudio.com/) the best tool for the job.
|
Developers who like Windows development tend to find [Visual Studio](
|
||||||
|
https://www.visualstudio.com/) the best tool for the job.
|
||||||
|
|
||||||
If you have any questions on IDEs, feel free to chat with us on [Gitter](https://gitter.im/Cockatrice/Cockatrice) and we would love to help answer your questions!
|
[](https://discord.gg/ZASRzKu)
|
||||||
|
[](https://gitter.im/Cockatrice/Cockatrice)
|
||||||
|
|
||||||
|
If you'd like to ask questions, get advice, or just want to say hi,
|
||||||
|
the Cockatrice Development Team uses [Discord](https://discord.gg/ZASRzKu)
|
||||||
|
for communications in the #dev channel. If you're not into Discord, we also
|
||||||
|
have a [Gitter](https://gitter.im/Cockatrice/Cockatrice) channel available,
|
||||||
|
albeit slightly less active.
|
||||||
|
|
||||||
|
|
||||||
# Code Style Guide #
|
# Code Style Guide #
|
||||||
|
|
||||||
### Formatting and continuous integration (ci) ###
|
### Formatting and continuous integration (CI) ###
|
||||||
|
|
||||||
We currently use Travis CI to check your code for formatting issues, if your pull request was rejected because of this it would show a message in the logs. Click on "Details" next to the failed Travis CI build and then click on the failed build (most likely the fastest one) to see the log.
|
We use a separate job on the CI to check your code for formatting issues. If
|
||||||
|
your pull request failed the test, you can check the output on the checks tab.
|
||||||
|
It's the first job called "linter", you can click the "Check code formatting"
|
||||||
|
step to see the output of the test.
|
||||||
|
|
||||||
The message will look somewhat similar to this:
|
The message will look like this:
|
||||||
```
|
```
|
||||||
************************************************************
|
***********************************************************
|
||||||
*** Your code does not meet our formatting guidelines. ***
|
*** ***
|
||||||
*** Please correct it then commit and push your changes. ***
|
*** Your code does not comply with our style guide. ***
|
||||||
*** See our CONTRIBUTING.md file for more information. ***
|
*** ***
|
||||||
************************************************************
|
*** Please correct it or run the "format.sh" script. ***
|
||||||
|
*** Then commit and push those changes to this branch. ***
|
||||||
|
*** Check our CONTRIBUTING.md file for more details. ***
|
||||||
|
*** ***
|
||||||
|
*** Thank you ❤️ ***
|
||||||
|
*** ***
|
||||||
|
***********************************************************
|
||||||
```
|
```
|
||||||
The CONTRIBUTING.md file mentioned is this file. Please read [this section](#Formatting) for full information on our formatting guidelines.
|
The CONTRIBUTING.md file mentioned in that message is the file you are
|
||||||
|
currently reading. Please see [this section](#formatting) below for full
|
||||||
|
information on our formatting guidelines.
|
||||||
|
|
||||||
### Compatibility ###
|
### Compatibility ###
|
||||||
|
|
||||||
Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>. You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free to help convert it over!
|
Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>.
|
||||||
|
You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free
|
||||||
|
to help convert it over!
|
||||||
|
|
||||||
For consistency, we use Qt data structures where possible. For example, `QString` over
|
For consistency, we use Qt data structures where possible. For example,
|
||||||
`std::string` and `QList` over `std::vector`.
|
`QString` over `std::string` and `QList` over `std::vector`.
|
||||||
|
|
||||||
|
Do not use old C style casts in new code, instead use a [`static_cast<>`](
|
||||||
|
https://en.cppreference.com/w/cpp/language/static_cast)
|
||||||
|
or other appropriate conversion.
|
||||||
|
|
||||||
### Formatting ###
|
### Formatting ###
|
||||||
|
|
||||||
The handy tool `clang-format` can format your code for you, it is available for almost any environment. A special `.clang-format` configuration file is included in the project and is used to format your code.
|
The handy tool `clang-format` can format your code for you, it is available for
|
||||||
|
almost any environment. A special `.clang-format` configuration file is
|
||||||
|
included in the project and is used to format your code.
|
||||||
|
|
||||||
We've also included a bash script, `clangify.sh`, that will use clang-format to format all files in one go. Use `./clangify.sh --help` to show a full help page.
|
We've also included a bash script, `format.sh`, that will use clang-format to
|
||||||
|
format all files in your pr in one go. Use `./format.sh --help` to show a full
|
||||||
|
help page.
|
||||||
|
|
||||||
To run clang-format on a single source file simply use the command `clang-format -i <filename>` to format it in place. (some systems install clang-format with a specific version number appended, `find /usr/bin -name clang-format*` should find it for you)
|
To run clang-format on a single source file simply use the command
|
||||||
|
`clang-format -i <filename>` to format it in place. (Some systems install
|
||||||
|
clang-format with a specific version number appended,
|
||||||
|
`find /usr/bin -name clang-format*` should find it for you)
|
||||||
|
|
||||||
See [the clang-format documentation](https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool.
|
See [the clang-format documentation](
|
||||||
|
https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool.
|
||||||
|
|
||||||
#### Header files ####
|
#### Header files ####
|
||||||
|
|
||||||
@@ -62,7 +103,8 @@ Use header guards in the form of `FILE_NAME_H`.
|
|||||||
Simple functions, such as getters, may be written inline in the header file,
|
Simple functions, such as getters, may be written inline in the header file,
|
||||||
but other functions should be written in the source file.
|
but other functions should be written in the source file.
|
||||||
|
|
||||||
Group library includes after project includes, and in alphabetic order. Like this:
|
Group project includes first, followed by library includes. All in alphabetic order.
|
||||||
|
Like this:
|
||||||
```c++
|
```c++
|
||||||
// Good
|
// Good
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
@@ -88,9 +130,15 @@ Group library includes after project includes, and in alphabetic order. Like thi
|
|||||||
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
|
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
|
||||||
function and variable names.
|
function and variable names.
|
||||||
|
|
||||||
Member variables aren't decorated in any way. Don't prefix or suffix with
|
Don't use [Hungarian Notation](
|
||||||
|
https://en.wikipedia.org/wiki/Hungarian_notation).
|
||||||
|
|
||||||
|
Member variables aren't decorated in any way. Don't prefix or suffix them with
|
||||||
underscores, etc.
|
underscores, etc.
|
||||||
|
|
||||||
|
Use a separate line for each declaration, don't use a single line like this
|
||||||
|
`int one = 1, two = 2` and instead split them into two lines.
|
||||||
|
|
||||||
For arguments to constructors which have the same names as member variables,
|
For arguments to constructors which have the same names as member variables,
|
||||||
prefix those arguments with underscores:
|
prefix those arguments with underscores:
|
||||||
```c++
|
```c++
|
||||||
@@ -115,7 +163,8 @@ If you find any usage of the old keywords, we encourage you to fix it.
|
|||||||
|
|
||||||
#### Braces ####
|
#### Braces ####
|
||||||
|
|
||||||
Braces should go on their own line except for control statements, the use of braces around single line statements is preferred.
|
Braces should go on their own line except for control statements, the use of
|
||||||
|
braces around single line statements is preferred.
|
||||||
See the following example:
|
See the following example:
|
||||||
```c++
|
```c++
|
||||||
int main()
|
int main()
|
||||||
@@ -136,17 +185,25 @@ int main()
|
|||||||
|
|
||||||
#### Indentation and Spacing ####
|
#### Indentation and Spacing ####
|
||||||
|
|
||||||
Always indent using 4 spaces, do not use tabs. Opening and closing braces should be on the same indentation layer, member access specifiers in classes or structs should not be indented.
|
Always indent using 4 spaces, do not use tabs. Opening and closing braces
|
||||||
|
should be on the same indentation layer, member access specifiers in classes or
|
||||||
|
structs should not be indented.
|
||||||
|
|
||||||
All operators and braces should be separated by spaces, do not add a space next to the inside of a brace.
|
All operators and braces should be separated by spaces, do not add a space next
|
||||||
|
to the inside of a brace.
|
||||||
|
|
||||||
If multiple lines of code that follow eachother have single line comments behind them, place all of them on the same indentation level. This indentation level should be equal to the longest line of code for each of these comments, without added spacing.
|
If multiple lines of code that follow eachother have single line comments
|
||||||
|
behind them, place all of them on the same indentation level. This indentation
|
||||||
|
level should be equal to the longest line of code for each of these comments,
|
||||||
|
without added spacing.
|
||||||
|
|
||||||
#### Lines ####
|
#### Lines ####
|
||||||
|
|
||||||
Do not have trailing whitespace in your lines. Most IDEs check for this nowadays and clean it up for you.
|
Do not leave trailing whitespace on any line. Most IDEs check for this
|
||||||
|
nowadays and clean it up for you.
|
||||||
|
|
||||||
Lines should be 120 characters or less. Please break up lines that are too long into smaller parts, for example at spaces or after opening a brace.
|
Lines should be 120 characters or less. Please break up lines that are too long
|
||||||
|
into smaller parts, for example at spaces or after opening a brace.
|
||||||
|
|
||||||
### Memory Management ###
|
### Memory Management ###
|
||||||
|
|
||||||
@@ -182,44 +239,93 @@ as `QScopedPointer`, or, less preferably, `QSharedPointer`.
|
|||||||
The servatrice database's schema can be found at `servatrice/servatrice.sql`.
|
The servatrice database's schema can be found at `servatrice/servatrice.sql`.
|
||||||
Everytime the schema gets modified, some other steps are due:
|
Everytime the schema gets modified, some other steps are due:
|
||||||
1. Increment the value of `cockatrice_schema_version` in `servatrice.sql`;
|
1. Increment the value of `cockatrice_schema_version` in `servatrice.sql`;
|
||||||
2. Increment the value of `DATABASE_SCHEMA_VERSION` in `servatrice_database_interface.h` accordingly;
|
2. Increment the value of `DATABASE_SCHEMA_VERSION` in
|
||||||
3. Create a new migration file inside the `servatrice/migrations` directory named after the new schema version.
|
`servatrice_database_interface.h` accordingly;
|
||||||
4. Run the `servatrice/check_schema_version.sh` script to ensure everything is fine.
|
3. Create a new migration file inside the `servatrice/migrations` directory
|
||||||
|
named after the new schema version.
|
||||||
|
4. Run the `servatrice/check_schema_version.sh` script to ensure everything is
|
||||||
|
fine.
|
||||||
|
|
||||||
The migration file should include the sql statements needed to migrate the database schema and data from the previous to the new version, and an additional statement that updates `cockatrice_schema_version` to the correct value.
|
The migration file should include the sql statements needed to migrate the
|
||||||
|
database schema and data from the previous to the new version, and an
|
||||||
|
additional statement that updates `cockatrice_schema_version` to the correct
|
||||||
|
value.
|
||||||
|
|
||||||
Ensure that the migration produces the expected effects; e.g. if you add a new column, make sure the migration places it in the same order as servatrice.sql.
|
Ensure that the migration produces the expected effects; e.g. if you add a
|
||||||
|
new column, make sure the migration places it in the same order as
|
||||||
|
servatrice.sql.
|
||||||
|
|
||||||
### Protocol buffer ###
|
### Protocol buffer ###
|
||||||
|
|
||||||
Cockatrice and Servatrice exchange data using binary messages. The syntax of these messages is defined in the `proto` files in the `common/pb` folder. These files defines the way data contained in each message is serialized using Google's [protocol buffer](https://developers.google.com/protocol-buffers/).
|
Cockatrice and Servatrice exchange data using binary messages. The syntax of
|
||||||
Any change to the `proto` file should be taken with caution and tested intensively before being merged, becaus a change to the protocol could make new clients incompatible to the old server and vice versa.
|
these messages is defined in the `proto` files in the `common/pb` folder. These
|
||||||
|
files define the way data contained in each message is serialized using
|
||||||
|
Google's [protocol buffers](https://developers.google.com/protocol-buffers/).
|
||||||
|
Any change to the `proto` files should be taken with caution and tested
|
||||||
|
intensively before being merged, because a change to the protocol could make
|
||||||
|
new clients incompatible to the old server and vice versa.
|
||||||
|
|
||||||
You can find more information on how we use Protobuf on [our wiki!](https://github.com/Cockatrice/Cockatrice/wiki/Client-server-protocol)
|
You can find more information on how we use Protobuf on [our wiki!](
|
||||||
|
https://github.com/Cockatrice/Cockatrice/wiki/Client-server-protocol)
|
||||||
|
|
||||||
|
# Reviewing Pull Requests #
|
||||||
|
|
||||||
|
After you have finished your changes to the project you should put them on a
|
||||||
|
separate branch of your fork on GitHub and open a [pull request](
|
||||||
|
https://docs.github.com/en/free-pro-team@latest/desktop/contributing-and-collaborating-using-github-desktop/creating-an-issue-or-pull-request
|
||||||
|
).
|
||||||
|
Your code will then be automatically compiled by GitHub actions for Linux and
|
||||||
|
macOS, and by Appveyor for Windows. Additionally GitHub will perform a [Linting
|
||||||
|
check](#formatting-and-continuous-integration-ci). If any issues come up you
|
||||||
|
can check their status at the bottom of the pull request page, click on details
|
||||||
|
to go to the CI website and see the different build logs.
|
||||||
|
|
||||||
|
If your pull request passes our tests and has no merge conflicts, it will be
|
||||||
|
reviewed by our team members. You can then address any requested changes. When
|
||||||
|
all changes have been approved your pull request will be squashed into a single
|
||||||
|
commit and merged into the master branch by a team member. Your change will then
|
||||||
|
be included in the next release 👍
|
||||||
|
|
||||||
# Translations #
|
# Translations #
|
||||||
|
|
||||||
Basic workflow for translations:
|
Basic workflow for translations:
|
||||||
1. Developer adds a `tr("foo")` string in the code;
|
1. Developer adds a `tr("foo")` string in the code;
|
||||||
2. Every few days, a maintainer updates the `*_en.ts files` with the new strings;
|
2. Every few days, a maintainer updates the `*_en@source.ts files` with the new strings;
|
||||||
3. Transifex picks up the new files from github every 24 hours;
|
3. Transifex picks up the new files from GitHub every 24 hours;
|
||||||
4. Translators translate the new untranslated strings on Transifex;
|
4. Translators translate the new untranslated strings on Transifex;
|
||||||
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
||||||
|
|
||||||
### Using Translations (for developers) ###
|
### Using Translations (for developers) ###
|
||||||
|
|
||||||
All the user-interface strings inside Cockatrice's source code must be written in english.
|
All the user-interface strings inside Cockatrice's source code must be written
|
||||||
Translations to other languages are managed using [Transifex](https://www.transifex.com/projects/p/cockatrice/).
|
in English(US).
|
||||||
|
Translations to other languages are managed using [Transifex](
|
||||||
|
https://www.transifex.com/projects/p/cockatrice/).
|
||||||
|
|
||||||
Adding a new string to translate is as easy as adding the string in the 'tr("")' function, the string will be picked up as translatable automatically and translated as needed.
|
Adding a new string to translate is as easy as adding the string in the
|
||||||
For example setting the text of this label in a way that the string "My name is:" can be translated:
|
'tr("")' function, the string will be picked up as translatable automatically
|
||||||
|
and translated as needed.
|
||||||
|
For example, setting the text of a label in the way that the string
|
||||||
|
`"My name is:"` can be translated:
|
||||||
```c++
|
```c++
|
||||||
nameLabel.setText(tr("My name is:"));
|
nameLabel.setText(tr("My name is:"));
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're about to propose a change that adds or modifies any translatable string in the code, you don't need to take care of adding the new strings to the translation files.
|
To translate a string that would have plural forms you can add the amount to
|
||||||
Every few days, or when a lot of new strings have been added, someone from the development team will take care of extracting all the new strings and adding them to the english translation files and making them available to translators on Transifex.
|
the tr call, also you can add an extra string as a hint for translators:
|
||||||
|
```c++
|
||||||
|
QString message = tr("Everyone draws %n cards", "pop up message", amount);
|
||||||
|
```
|
||||||
|
See [QT's wiki on translations](
|
||||||
|
https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals)
|
||||||
|
|
||||||
|
If you're about to propose a change that adds or modifies any translatable
|
||||||
|
string in the code, you don't need to take care of adding the new strings to
|
||||||
|
the translation files.
|
||||||
|
Every few days, or when a lot of new strings have been added, someone from the
|
||||||
|
development team will take care of extracting all the new strings and adding
|
||||||
|
them to the english translation files and making them available to translators
|
||||||
|
on Transifex.
|
||||||
|
|
||||||
### Maintaining Translations (for maintainers) ###
|
### Maintaining Translations (for maintainers) ###
|
||||||
|
|
||||||
@@ -238,14 +344,14 @@ make
|
|||||||
If the parameter has been enabled correctly, when running "make" you should see
|
If the parameter has been enabled correctly, when running "make" you should see
|
||||||
a line similar to this one (the numbers may vary):
|
a line similar to this one (the numbers may vary):
|
||||||
```sh
|
```sh
|
||||||
[ 76%] Generating ../../cockatrice/translations/cockatrice_en.ts
|
[ 76%] Generating ../../cockatrice/translations/cockatrice_en@source.ts
|
||||||
Updating '../../cockatrice/translations/cockatrice_en.ts'...
|
Updating '../../cockatrice/translations/cockatrice_en@source.ts'...
|
||||||
Found 857 source text(s) (8 new and 849 already existing)
|
Found 857 source text(s) (8 new and 849 already existing)
|
||||||
```
|
```
|
||||||
You should then notice that the following files have uncommitted changes:
|
You should then notice that the following files have uncommitted changes:
|
||||||
|
|
||||||
cockatrice/translations/cockatrice_en.ts
|
cockatrice/translations/cockatrice_en@source.ts
|
||||||
oracle/translations/oracle_en.ts
|
oracle/translations/oracle_en@source.ts
|
||||||
|
|
||||||
It is recommended to disable the parameter afterwards using:
|
It is recommended to disable the parameter afterwards using:
|
||||||
```sh
|
```sh
|
||||||
@@ -253,8 +359,9 @@ cmake .. -DUPDATE_TRANSLATIONS=OFF
|
|||||||
```
|
```
|
||||||
Now you are ready to propose your change.
|
Now you are ready to propose your change.
|
||||||
|
|
||||||
Once your change gets merged, Transifex will pick up the modified files automatically (checked every 24 hours)
|
Once your change gets merged, Transifex will pick up the modified files
|
||||||
and update the interface where translators will be able to translate the new strings.
|
automatically (checked every 24 hours) and update the interface where
|
||||||
|
translators will be able to translate the new strings.
|
||||||
|
|
||||||
### Releasing Translations (for maintainers) ###
|
### Releasing Translations (for maintainers) ###
|
||||||
|
|
||||||
@@ -272,51 +379,85 @@ from Transifex to the source code and vice versa.
|
|||||||
|
|
||||||
### Adding Translations (for translators) ###
|
### Adding Translations (for translators) ###
|
||||||
|
|
||||||
As a translator you can help translate the new strings on [Transifex](https://www.transifex.com/projects/p/cockatrice/).
|
As a translator you can help translate the new strings on [Transifex](
|
||||||
Please have a look at the specific [FAQ for translators](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
https://www.transifex.com/projects/p/cockatrice/).
|
||||||
|
Please have a look at the specific [FAQ for translators](
|
||||||
|
https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
||||||
|
|
||||||
|
|
||||||
# Release Management #
|
# Release Management #
|
||||||
|
|
||||||
### Publishing A New Beta Release ###
|
### Publishing A New Release ###
|
||||||
|
|
||||||
Travis and AppVeyor have been configured to upload files to GitHub Releases whenever a <kbd>tag</kbd> is pushed.<br>
|
We use [GitHub Releases](https://github.com/Cockatrice/Cockatrice/releases) to
|
||||||
Usually, tags are created through publishing a (pre-)release, but there's a way around that.
|
publish new stable versions and betas.
|
||||||
|
Whenever a git tag is pushed to the repository github will create a draft
|
||||||
|
release and upload binaries automatically.
|
||||||
|
|
||||||
To trigger Travis and AppVeyor, simply do the following:
|
To create a tag, simply do the following:
|
||||||
```bash
|
```bash
|
||||||
cd $COCKATRICE_REPO
|
|
||||||
git checkout master
|
git checkout master
|
||||||
git remote update -p
|
git remote update -p
|
||||||
git pull
|
git pull
|
||||||
git tag $TAG_NAME
|
git tag $TAG_NAME
|
||||||
git push upstream $TAG_NAME
|
git push $UPSTREAM $TAG_NAME
|
||||||
```
|
```
|
||||||
|
|
||||||
You should define the variables as such:
|
You should define the variables as such:
|
||||||
```
|
```
|
||||||
upstream - git@github.com:Cockatrice/Cockatrice.git
|
`$UPSTREAM` - the remote for git@github.com:Cockatrice/Cockatrice.git
|
||||||
$COCKATRICE_REPO - /Location/of/repository/cockatrice.git
|
`$TAG_NAME` should be formatted as:
|
||||||
`$TAG_NAME` should be:
|
|
||||||
- `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases**
|
- `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases**
|
||||||
- `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br>
|
- `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br>
|
||||||
With *MAJ.MIN.PATCH* being the NEXT release version!
|
With *MAJ.MIN.PATCH* being the NEXT release version!
|
||||||
```
|
```
|
||||||
|
|
||||||
This will cause a tagged release to be established on the GitHub repository, which will then lead to the upload of binaries. If you use this method, the tags (releases) that you create will be marked as a "Pre-release". The `/latest` URL will not be impacted (for stable release downloads) so that's good.
|
This will cause a tagged release to be established on the GitHub repository,
|
||||||
|
with the binaries being added to the release whenever they are ready.
|
||||||
|
The release is initially a draft, where the path notes can be edited and after
|
||||||
|
all is good and ready it can be published on GitHub.
|
||||||
|
If you use a SemVer tag including "beta", the release that will be created at
|
||||||
|
GitHub will be marked as a "Pre-release" automatically.
|
||||||
|
The target of the `.../latest` URL will not be changed in that case, it always
|
||||||
|
points to the latest stable release and not pre-releases/betas.
|
||||||
|
|
||||||
If you accidentally push a tag incorrectly (the tag is outdated, you didn't pull in the latest branch accidentally, you named the tag wrong, etc.) you can revoke the tag by doing the following:
|
If you accidentally push a tag incorrectly (the tag is outdated, you didn't
|
||||||
|
pull in the latest branch accidentally, you named the tag wrong, etc.) you can
|
||||||
|
revoke the tag by doing the following:
|
||||||
```bash
|
```bash
|
||||||
git push --delete upstream $TAG_NAME
|
git push --delete upstream $TAG_NAME
|
||||||
git tag -d $TAG_NAME
|
git tag -d $TAG_NAME
|
||||||
```
|
```
|
||||||
|
You can also do this on GitHub, you'll also want to delete the new release.
|
||||||
|
|
||||||
**NOTE:** Unfortunately, due to the method of how Travis and AppVeyor work, to publish a stable release you will need to make a copy of the release notes locally and then paste them into the GitHub GUI once the binaries have been uploaded by them. These CI services will automatically overwrite the name of the release (to "Cockatrice $TAG_NAME"), the status of the release (to "Pre-release"), and the release body (to "Beta build of Cockatrice").
|
In the first lines of [CMakeLists.txt](
|
||||||
|
https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt)
|
||||||
**NOTE 2:** In the first lines of https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt there's an hardcoded version number used when compiling custom (not tagged) versions. While on tagged versions these numbers are overridden by the version numbers coming from the tag title, it's good practice to keep them aligned with the real ones.
|
there's an hardcoded version number and pretty name used when compiling from
|
||||||
|
master or custom (not tagged) versions.
|
||||||
|
While on tagged versions these numbers are overridden by the version numbers
|
||||||
|
coming from the tag title, it's good practice to increment the ones at CMake
|
||||||
|
after every full release to stress that master is ahead of the last stable
|
||||||
|
release.
|
||||||
The preferred flow of operation is:
|
The preferred flow of operation is:
|
||||||
* just before a release, update the version number in CMakeLists.txt to "next release version";
|
* Just before a release, make sure the version number in CMakeLists.txt is set
|
||||||
* tag the release following the previously described syntax in order to get it built by CI;
|
to the same release version you are about to tag.
|
||||||
* wait for CI to upload the binaries, double check if everything is in order
|
* This is also the time to change the pretty name in CMakeLists.txt called
|
||||||
* after the release is complete, update the version number again to "next targeted beta version", typically increasing `PROJECT_VERSION_PATCH` by one.
|
GIT_TAG_RELEASENAME and commit and push these changes.
|
||||||
|
* Tag the release following the previously described syntax in order to get it
|
||||||
|
correctly built and deployed by CI.
|
||||||
|
* Wait for the configure step to create the release and update the patch
|
||||||
|
notes.
|
||||||
|
* Check on the github actions page for build progress which should be the top
|
||||||
|
listed [here](
|
||||||
|
https://github.com/Cockatrice/Cockatrice/actions?query=event%3Apush+-branch%3Amaster
|
||||||
|
).
|
||||||
|
* When the build has been completed you can verify all uploaded files on the
|
||||||
|
release are in order and hit the publish button.
|
||||||
|
* After the release is complete, update the CMake version number again to the
|
||||||
|
next targeted beta version, typically increasing `PROJECT_VERSION_PATCH` by
|
||||||
|
one.
|
||||||
|
|
||||||
**NOTE 3:** When releasing a new stable version, all the previous beta versions should be deleted. This is needed for Cockatrice to update users of the "beta" release channel to the latest version like other users.
|
When releasing a new stable version, all previous beta releases (and tags)
|
||||||
|
should be deleted. This is needed for Cockatrice to update users of the "Beta"
|
||||||
|
release channel correctly to the latest stable version as well.
|
||||||
|
This can be done the same way as revoking tags, mentioned above.
|
||||||
|
|||||||
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [ZeldaZach]
|
||||||
|
patreon: mtgjson
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: ["paypal.me/zachhalpern"]
|
||||||
14
.github/ISSUE_TEMPLATE.md
vendored
14
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,14 +0,0 @@
|
|||||||
<b>System Information:</b>
|
|
||||||
<!-- Go to "Help → View Debug Log" and copy all lines above the separation here! -->
|
|
||||||
|
|
||||||
<!-- If you can't install Cockatrice to access that information, make
|
|
||||||
sure to include your OS and the app version from the setup file here -->
|
|
||||||
__________________________________________________________________________________________
|
|
||||||
|
|
||||||
<!-- Explain your issue/request/suggestion in detail here! -->
|
|
||||||
|
|
||||||
<!-- This repository is ONLY about development of the Cockatrice app.
|
|
||||||
If you have any problems with a server (e.g. registering, connecting, ban...)
|
|
||||||
you have to contact that server's owner/admin.
|
|
||||||
Check this list of public servers with webpage links and contact details:
|
|
||||||
https://github.com/Cockatrice/Cockatrice/wiki/Public-Servers -->
|
|
||||||
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
name: "🐛 Bug Report"
|
||||||
|
about: Report an issue encountered while using Cockatrice
|
||||||
|
title: ''
|
||||||
|
labels: 'Bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- READ THIS BEFORE POSTING
|
||||||
|
Go to "Help → View Debug Log" in Cockatrice and copy all information at the
|
||||||
|
top (above the separation line) below "System Information" in this ticket!
|
||||||
|
If you can't start Cockatrice to access these details, make
|
||||||
|
sure to post your OS and the file name of the setup binary instead. -->
|
||||||
|
|
||||||
|
**System Information:**
|
||||||
|
|
||||||
|
|
||||||
|
_______________________________________________________________________________________
|
||||||
|
|
||||||
|
<!-- Explain your issue in detail here! Please attach screenshots if possible. -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_______________________________________________________________________________________
|
||||||
|
|
||||||
|
<!-- Describe the sequence of actions needed to experience the bug -->
|
||||||
|
|
||||||
|
**Steps to reproduce:**
|
||||||
|
- Do A
|
||||||
|
- Do B
|
||||||
|
- Do C ...
|
||||||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: 💬 Discord Community (Get help with server issues, e.g. Login)
|
||||||
|
url: https://discord.gg/3Z9yzmA
|
||||||
|
about: Need help with using the client? Want to find some games? Try the Discord server!
|
||||||
|
- name: 🌐 Translations (Help improve the localization of the app)
|
||||||
|
url: https://www.transifex.com/cockatrice/cockatrice/
|
||||||
|
# it is not possible to add a link to the wiki to this description
|
||||||
|
about: For more information and guidance check our Translation FAQ on our wiki!
|
||||||
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: "💡 Feature Request"
|
||||||
|
about: Request a new feature
|
||||||
|
title: ''
|
||||||
|
labels: 'Feature Request'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please search the issue tracker for similar issues before posting!
|
||||||
|
If your request is related to another request (but not the same!) list it here
|
||||||
|
-->
|
||||||
|
**Similar Requests**
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Describe your feature idea here in detail -->
|
||||||
|
**Description of New Feature**
|
||||||
|
|
||||||
|
|
||||||
|
<!-- If your feature requires some context, provide it here -->
|
||||||
|
**Additional Context**
|
||||||
|
|
||||||
389
.github/workflows/desktop-build.yml
vendored
Normal file
389
.github/workflows/desktop-build.yml
vendored
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
name: Build Desktop
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
configure:
|
||||||
|
name: Configure
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
tag: ${{steps.configure.outputs.tag}}
|
||||||
|
sha: ${{steps.configure.outputs.sha}}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Cancel previous runs
|
||||||
|
uses: styfle/cancel-workflow-action@0.11.0
|
||||||
|
with:
|
||||||
|
access_token: ${{github.token}} # needs other token https://github.com/styfle/cancel-workflow-action/issues/7
|
||||||
|
|
||||||
|
- name: Configure
|
||||||
|
id: configure
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
tag_regex='^refs/tags/'
|
||||||
|
if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request
|
||||||
|
sha="${{github.event.pull_request.head.sha}}"
|
||||||
|
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
|
||||||
|
sha="$GITHUB_SHA"
|
||||||
|
tag="${GITHUB_REF/refs\/tags\//}"
|
||||||
|
echo "tag=$tag" >>"$GITHUB_OUTPUT"
|
||||||
|
else # push to branch
|
||||||
|
sha="$GITHUB_SHA"
|
||||||
|
fi
|
||||||
|
echo "sha=$sha" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
if: steps.configure.outputs.tag != null
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Prepare release parameters
|
||||||
|
id: prepare
|
||||||
|
if: steps.configure.outputs.tag != null
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
TAG: ${{steps.configure.outputs.tag}}
|
||||||
|
run: .ci/prep_release.sh
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
if: steps.configure.outputs.tag != null
|
||||||
|
id: create_release
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{github.token}}
|
||||||
|
tag_name: ${{steps.configure.outputs.tag}}
|
||||||
|
target: ${{steps.configure.outputs.sha}}
|
||||||
|
release_name: ${{steps.prepare.outputs.title}}
|
||||||
|
body_path: ${{steps.prepare.outputs.body_path}}
|
||||||
|
prerelease: ${{steps.prepare.outputs.is_beta}}
|
||||||
|
run: |
|
||||||
|
if [[ $prerelease == yes ]]; then
|
||||||
|
args="--prerelease"
|
||||||
|
fi
|
||||||
|
gh release create "$tag_name" --draft --verify-tag $args \
|
||||||
|
--target "$target" --title "$release_name" \
|
||||||
|
--notes-file "$body_path"
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# these names correspond to the files in .ci/$distro
|
||||||
|
include:
|
||||||
|
- distro: ArchLinux
|
||||||
|
package: skip # we are packaged in arch already
|
||||||
|
allow-failure: yes
|
||||||
|
|
||||||
|
- distro: Debian10
|
||||||
|
package: DEB
|
||||||
|
test: skip # running tests on all distros is superfluous
|
||||||
|
|
||||||
|
- distro: Debian11
|
||||||
|
package: DEB
|
||||||
|
|
||||||
|
- distro: Fedora36
|
||||||
|
package: RPM
|
||||||
|
test: skip
|
||||||
|
|
||||||
|
- distro: Fedora37
|
||||||
|
package: RPM
|
||||||
|
|
||||||
|
- distro: UbuntuBionic
|
||||||
|
package: DEB
|
||||||
|
|
||||||
|
- distro: UbuntuFocal
|
||||||
|
package: DEB
|
||||||
|
test: skip # UbuntuFocal has a broken qt for debug builds
|
||||||
|
|
||||||
|
- distro: UbuntuJammy
|
||||||
|
package: DEB
|
||||||
|
test: skip # running tests on all distros is superfluous
|
||||||
|
|
||||||
|
- distro: UbuntuKinetic
|
||||||
|
package: DEB
|
||||||
|
|
||||||
|
name: ${{matrix.distro}}
|
||||||
|
needs: configure
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
|
env:
|
||||||
|
NAME: ${{matrix.distro}}
|
||||||
|
CACHE: /tmp/${{matrix.distro}}-cache # ${{runner.temp}} does not work?
|
||||||
|
# cache size over the entire repo is 10Gi link:
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||||
|
CCACHE_SIZE: 200M
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get cache timestamp
|
||||||
|
id: cache_timestamp
|
||||||
|
shell: bash
|
||||||
|
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Restore cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
env:
|
||||||
|
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
||||||
|
with:
|
||||||
|
path: ${{env.CACHE}}
|
||||||
|
key: docker-${{matrix.distro}}-cache-${{env.timestamp}}
|
||||||
|
restore-keys: |
|
||||||
|
docker-${{matrix.distro}}-cache-
|
||||||
|
|
||||||
|
- name: Build ${{matrix.distro}} Docker image
|
||||||
|
shell: bash
|
||||||
|
run: source .ci/docker.sh --build
|
||||||
|
|
||||||
|
- name: Build debug and test
|
||||||
|
if: matrix.test != 'skip'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
distro: '${{matrix.distro}}'
|
||||||
|
run: |
|
||||||
|
source .ci/docker.sh
|
||||||
|
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 2
|
||||||
|
|
||||||
|
- name: Build release package
|
||||||
|
id: build
|
||||||
|
if: matrix.package != 'skip'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
BUILD_DIR: build
|
||||||
|
SUFFIX: '-${{matrix.distro}}'
|
||||||
|
distro: '${{matrix.distro}}'
|
||||||
|
type: '${{matrix.package}}'
|
||||||
|
run: |
|
||||||
|
source .ci/docker.sh
|
||||||
|
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
|
||||||
|
--ccache "$CCACHE_SIZE" --parallel 2
|
||||||
|
.ci/name_build.sh
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: matrix.package != 'skip'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{matrix.distro}}-package
|
||||||
|
path: ${{steps.build.outputs.path}}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload to release
|
||||||
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{github.token}}
|
||||||
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
|
|
||||||
|
build-macos:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: Debug # tests only
|
||||||
|
os: macos-latest
|
||||||
|
xcode: 14.2
|
||||||
|
qt_version: 6.*
|
||||||
|
qt_modules: "qtmultimedia qtwebsockets"
|
||||||
|
type: Debug
|
||||||
|
do_tests: 1
|
||||||
|
|
||||||
|
- target: 10.15_Catalina
|
||||||
|
os: macos-11
|
||||||
|
xcode: 11.7 # allows using macOS 10.15 SDK
|
||||||
|
qt_version: 6.2.* # LTS (is compatible with 10.14 and 10.15)
|
||||||
|
qt_modules: "qtmultimedia qtwebsockets"
|
||||||
|
type: Release
|
||||||
|
do_tests: 1
|
||||||
|
make_package: 1
|
||||||
|
|
||||||
|
- target: 11_Big_Sur
|
||||||
|
os: macos-11
|
||||||
|
xcode: 12.5.1
|
||||||
|
qt_version: homebrew
|
||||||
|
type: Release
|
||||||
|
do_tests: 1
|
||||||
|
make_package: 1
|
||||||
|
|
||||||
|
# - target: 12_Monterey
|
||||||
|
# os: macos-12
|
||||||
|
# xcode: 13.3
|
||||||
|
# qt_version: homebrew
|
||||||
|
# type: Release
|
||||||
|
# do_tests: 1
|
||||||
|
# make_package: 1
|
||||||
|
|
||||||
|
name: macOS ${{matrix.target}}
|
||||||
|
needs: configure
|
||||||
|
runs-on: ${{matrix.os}}
|
||||||
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
|
env:
|
||||||
|
DEVELOPER_DIR:
|
||||||
|
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install dependencies using homebrew
|
||||||
|
shell: bash
|
||||||
|
# cmake cannot find the mysql connector
|
||||||
|
# neither of these works: mariadb-connector-c mysql-connector-c++
|
||||||
|
env:
|
||||||
|
install_qt: ${{matrix.qt_version}}
|
||||||
|
run: |
|
||||||
|
brew update
|
||||||
|
brew install protobuf
|
||||||
|
if [[ $install_qt == homebrew ]]; then
|
||||||
|
brew install qt --force-bottle
|
||||||
|
else # for some reason the tests fail with the action installed qt?
|
||||||
|
brew install googletest
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install Qt ${{matrix.qt_version}} for ${{matrix.target}}
|
||||||
|
if: matrix.qt_version != 'homebrew'
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
setup-python: false
|
||||||
|
version: ${{matrix.qt_version}}
|
||||||
|
modules: ${{matrix.qt_modules}}
|
||||||
|
|
||||||
|
- name: Build on Xcode ${{matrix.xcode}}
|
||||||
|
shell: bash
|
||||||
|
id: build
|
||||||
|
env:
|
||||||
|
BUILDTYPE: '${{matrix.type}}'
|
||||||
|
MAKE_TEST: '${{matrix.do_tests}}'
|
||||||
|
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||||
|
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
|
||||||
|
# Mac machines actually have 3 cores
|
||||||
|
run: .ci/compile.sh --server --parallel 3
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: matrix.make_package
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: macOS-${{matrix.target}}-dmg
|
||||||
|
path: ${{steps.build.outputs.path}}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload to release
|
||||||
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{github.token}}
|
||||||
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- target: Win-32bit
|
||||||
|
bit: 32
|
||||||
|
arch: x86
|
||||||
|
cmake_generator_platform: Win32
|
||||||
|
qt_version: 5.15.*
|
||||||
|
qt_arch: msvc2019
|
||||||
|
qt_tools: "tools_openssl_x86"
|
||||||
|
|
||||||
|
- target: Win7+-64bit
|
||||||
|
bit: 64
|
||||||
|
arch: x64
|
||||||
|
cmake_generator_platform: x64
|
||||||
|
qt_version: 5.15.*
|
||||||
|
qt_arch: msvc2019_64
|
||||||
|
qt_tools: "tools_openssl_x64"
|
||||||
|
|
||||||
|
- target: Win10+-64bit
|
||||||
|
bit: 64
|
||||||
|
arch: x64
|
||||||
|
cmake_generator_platform: x64
|
||||||
|
qt_version: 6.3.*
|
||||||
|
qt_arch: msvc2019_64
|
||||||
|
qt_tools: "tools_openssl_x64"
|
||||||
|
qt_modules: "qtmultimedia qtwebsockets"
|
||||||
|
|
||||||
|
name: ${{matrix.target}}
|
||||||
|
needs: configure
|
||||||
|
runs-on: windows-2019
|
||||||
|
env:
|
||||||
|
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
id: add-msbuild
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Qt ${{matrix.qt_version}} for ${{matrix.target}}
|
||||||
|
uses: jurplel/install-qt-action@v3
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
setup-python: false
|
||||||
|
version: ${{matrix.qt_version}}
|
||||||
|
arch: win${{matrix.bit}}_${{matrix.qt_arch}}
|
||||||
|
tools: ${{matrix.qt_tools}}
|
||||||
|
modules: ${{matrix.qt_modules}}
|
||||||
|
|
||||||
|
- name: Run vcpkg
|
||||||
|
uses: lukka/run-vcpkg@v10.6
|
||||||
|
with:
|
||||||
|
runVcpkgInstall: true
|
||||||
|
appendedCacheKey: ${{matrix.bit}}-bit
|
||||||
|
env:
|
||||||
|
VCPKG_DEFAULT_TRIPLET: '${{matrix.arch}}-windows'
|
||||||
|
VCPKG_DISABLE_METRICS: 1
|
||||||
|
|
||||||
|
- name: Build Cockatrice
|
||||||
|
id: build
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
PACKAGE_SUFFIX: '-${{matrix.target}}'
|
||||||
|
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||||
|
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake_generator_platform}}'
|
||||||
|
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win${{matrix.bit}}_${{matrix.qt_arch}}'
|
||||||
|
run: .ci/compile.sh --server --release --test --package --parallel 2
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{matrix.target}}-installer
|
||||||
|
path: ${{steps.build.outputs.path}}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload to release
|
||||||
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{github.token}}
|
||||||
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
28
.github/workflows/desktop-lint.yml
vendored
Normal file
28
.github/workflows/desktop-lint.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: Code Style (C++)
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 20 # should be enough to find merge base
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --no-install-recommends clang-format cmake-format
|
||||||
|
|
||||||
|
- name: Check code formatting
|
||||||
|
shell: bash
|
||||||
|
run: ./.ci/lint_cpp.sh
|
||||||
66
.github/workflows/translations.yml
vendored
Normal file
66
.github/workflows/translations.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Update translation source
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
# runs once per month
|
||||||
|
- cron: '0 0 1 * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
translations:
|
||||||
|
# Do not run the scheduled workflow on forks
|
||||||
|
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install lupdate
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --no-install-recommends qttools5-dev-tools
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Update cockatrice translations
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
shopt -s globstar # globstar is needed for recursive **
|
||||||
|
lupdate -version
|
||||||
|
echo "reading the following source files:"
|
||||||
|
# note: there are three strings to translate in common right now
|
||||||
|
echo {cockatrice,common}/**/*.{cpp,h}
|
||||||
|
echo "$(echo {cockatrice,common}/**/*.{cpp,h} | wc -w) files total"
|
||||||
|
lupdate {cockatrice,common}/**/*.{cpp,h} -ts cockatrice/translations/cockatrice_en@source.ts
|
||||||
|
|
||||||
|
- name: Update oracle translations
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
shopt -s globstar # globstar is needed for recursive **
|
||||||
|
lupdate -version
|
||||||
|
echo "reading the following source files:"
|
||||||
|
echo oracle/**/*.{cpp,h}
|
||||||
|
echo "$(echo oracle/**/*.{cpp,h} | wc -w) files total"
|
||||||
|
lupdate oracle/**/*.{cpp,h} -ts oracle/translations/oracle_en@source.ts
|
||||||
|
|
||||||
|
- name: Check for updates
|
||||||
|
id: check
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set +e # do not fail, just save the exit state
|
||||||
|
git diff --exit-code
|
||||||
|
echo "deploy=$?" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
if: steps.check.outputs.deploy == '1'
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{env.OUTPUT_PATH}}
|
||||||
|
run: |
|
||||||
|
git config user.name github-actions
|
||||||
|
git config user.email github-actions@github.com
|
||||||
|
git add cockatrice/translations/cockatrice_en@source.ts oracle/translations/oracle_en@source.ts
|
||||||
|
git commit -m "Automated translation update ( $GITHUB_SHA )"
|
||||||
|
git push
|
||||||
|
deploy_commit=$(git rev-parse HEAD)
|
||||||
|
echo "Created commit: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$deploy_commit"
|
||||||
53
.github/workflows/web-build.yml
vendored
Normal file
53
.github/workflows/web-build.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: Build Web
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '!**.md'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '!**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-web:
|
||||||
|
name: React (Node ${{matrix.node_version}})
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: webclient
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node_version:
|
||||||
|
- 16
|
||||||
|
- lts/*
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{matrix.node_version}}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: 'webclient/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm clean-install
|
||||||
|
|
||||||
|
- name: Build app
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Test app
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
32
.github/workflows/web-lint.yml
vendored
Normal file
32
.github/workflows/web-lint.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: Code Style (TypeScript)
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '!**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ESLint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: webclient
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: 'webclient/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install ESLint
|
||||||
|
run: npm clean-install --ignore-scripts
|
||||||
|
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run lint
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -6,5 +6,8 @@ mysql.cnf
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea/
|
.idea/
|
||||||
*.aps
|
*.aps
|
||||||
cmake-build-debug/
|
cmake-build-debug*
|
||||||
preferences
|
preferences
|
||||||
|
compile_commands.json
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
|||||||
139
.gitlab-ci.yml
139
.gitlab-ci.yml
@@ -1,139 +0,0 @@
|
|||||||
---
|
|
||||||
stages:
|
|
||||||
- build
|
|
||||||
|
|
||||||
.artifacts: &artifacts
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- build/
|
|
||||||
|
|
||||||
.cache: &cache
|
|
||||||
cache:
|
|
||||||
key: "$CI_BUILD_NAME"
|
|
||||||
paths:
|
|
||||||
- cache/
|
|
||||||
|
|
||||||
.branches: &branches
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
.tags: &tags
|
|
||||||
tags:
|
|
||||||
- linux
|
|
||||||
- docker
|
|
||||||
|
|
||||||
|
|
||||||
#================================ DEBIAN-BASED ================================
|
|
||||||
|
|
||||||
.build_rc_package_deb: &build_rc_package_deb
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- mkdir -p build
|
|
||||||
- cd build
|
|
||||||
- cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=Release -DCPACK_GENERATOR=DEB
|
|
||||||
- make package -j2
|
|
||||||
|
|
||||||
.build_debug_package_deb: &build_debug_package_deb
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- mkdir -p build
|
|
||||||
- cd build
|
|
||||||
- cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=Debug -DCPACK_GENERATOR=DEB
|
|
||||||
- make package -j2
|
|
||||||
|
|
||||||
.deb-artifacts: &artifacts_deb
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- build/*.deb
|
|
||||||
- build/CMakeFiles/*.log
|
|
||||||
when: always
|
|
||||||
|
|
||||||
#----------------------------------- UBUNTU -----------------------------------
|
|
||||||
|
|
||||||
.requirements_16xx: &install_requirements_16xx
|
|
||||||
before_script:
|
|
||||||
- apt-get -o dir::cache::archives="cache" update -qq
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y build-essential g++ cmake git
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libprotobuf-dev protobuf-compiler
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qt5-default qttools5-dev qttools5-dev-tools
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qtmultimedia5-dev libqt5multimedia5-plugins
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libqt5svg5-dev libqt5sql5-mysql
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libqt5websockets5-dev
|
|
||||||
|
|
||||||
.requirements_17xx: &install_requirements_17xx
|
|
||||||
before_script:
|
|
||||||
- apt-get -o dir::cache::archives="cache" update -qq
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y build-essential g++ cmake git
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libprotobuf-dev protobuf-compiler
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qt5-default qttools5-dev qttools5-dev-tools
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qtmultimedia5-dev libqt5multimedia5-plugins
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libqt5svg5-dev libqt5sql5-mysql
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libqt5websockets5-dev
|
|
||||||
|
|
||||||
.build_1604: &1604
|
|
||||||
image: ubuntu:16.04
|
|
||||||
<<: *tags
|
|
||||||
<<: *branches
|
|
||||||
<<: *install_requirements_16xx
|
|
||||||
<<: *artifacts_deb
|
|
||||||
<<: *cache
|
|
||||||
|
|
||||||
.build_1710: &1710
|
|
||||||
image: ubuntu:17.10
|
|
||||||
<<: *tags
|
|
||||||
<<: *branches
|
|
||||||
<<: *install_requirements_17xx
|
|
||||||
<<: *artifacts_deb
|
|
||||||
<<: *cache
|
|
||||||
|
|
||||||
build_rc_1604:
|
|
||||||
<<: *1604
|
|
||||||
<<: *build_rc_package_deb
|
|
||||||
when: always
|
|
||||||
|
|
||||||
build_debug_1604:
|
|
||||||
<<: *1604
|
|
||||||
<<: *build_debug_package_deb
|
|
||||||
when: always
|
|
||||||
|
|
||||||
build_rc_1710:
|
|
||||||
<<: *1710
|
|
||||||
<<: *build_rc_package_deb
|
|
||||||
when: always
|
|
||||||
|
|
||||||
build_debug_1710:
|
|
||||||
<<: *1710
|
|
||||||
<<: *build_debug_package_deb
|
|
||||||
when: always
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
#----------------------------------- DEBIAN -----------------------------------
|
|
||||||
|
|
||||||
.requirements_stretch: &install_requirements_stretch
|
|
||||||
before_script:
|
|
||||||
- apt-get -o dir::cache::archives="cache" update -qq
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y build-essential g++ cmake git
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qt5-default qtbase5-dev-tools
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y qttools5-dev-tools qtmultimedia5-dev
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libqt5svg5-dev libqt5websockets5-dev
|
|
||||||
- apt-get -o dir::cache::archives="cache" install -y libprotobuf-dev protobuf-compiler
|
|
||||||
|
|
||||||
.build_stretch: &stretch
|
|
||||||
image: debian:stretch
|
|
||||||
<<: *tags
|
|
||||||
<<: *branches
|
|
||||||
<<: *install_requirements_stretch
|
|
||||||
<<: *artifacts_deb
|
|
||||||
<<: *cache
|
|
||||||
|
|
||||||
build_rc_stretch:
|
|
||||||
<<: *stretch
|
|
||||||
<<: *build_rc_package_deb
|
|
||||||
when: always
|
|
||||||
|
|
||||||
build_debug_stretch:
|
|
||||||
<<: *stretch
|
|
||||||
<<: *build_debug_package_deb
|
|
||||||
when: always
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "vcpkg"]
|
||||||
|
path = vcpkg
|
||||||
|
url = https://github.com/microsoft/vcpkg.git
|
||||||
7
.husky/pre-commit
Executable file
7
.husky/pre-commit
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
cd webclient
|
||||||
|
npm run translate
|
||||||
|
|
||||||
|
git add src/i18n-default.json
|
||||||
166
.travis.yml
166
.travis.yml
@@ -1,166 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
compiler: gcc
|
|
||||||
|
|
||||||
git:
|
|
||||||
depth: 15
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
#Ubuntu Xenial (Debug only)
|
|
||||||
- name: Ubuntu Xenial (Debug)
|
|
||||||
if: tag IS NOT present
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
group: stable
|
|
||||||
cache: ccache
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libprotobuf-dev
|
|
||||||
- protobuf-compiler
|
|
||||||
- liblzma-dev
|
|
||||||
- qt5-default
|
|
||||||
- qttools5-dev
|
|
||||||
- qttools5-dev-tools
|
|
||||||
- qtmultimedia5-dev
|
|
||||||
- libqt5multimedia5-plugins
|
|
||||||
- libqt5svg5-dev
|
|
||||||
- libqt5sql5-mysql
|
|
||||||
- libqt5websockets5-dev
|
|
||||||
script: bash ./.ci/travis-compile.sh --format --server --test --debug
|
|
||||||
|
|
||||||
#Ubuntu Bionic (on docker)
|
|
||||||
- name: Ubuntu Bionic (Debug)
|
|
||||||
if: tag IS NOT present
|
|
||||||
services: docker
|
|
||||||
env: NAME=UbuntuBionic
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/$NAME/
|
|
||||||
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
|
||||||
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
|
||||||
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
|
||||||
"cockatrice_${NAME,,}"
|
|
||||||
bash .ci/travis-compile.sh --server --debug
|
|
||||||
|
|
||||||
- name: Ubuntu Bionic (Release)
|
|
||||||
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
|
||||||
services: docker
|
|
||||||
env: NAME=UbuntuBionic
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/$NAME/
|
|
||||||
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
|
||||||
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
|
||||||
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
|
||||||
"cockatrice_${NAME,,}"
|
|
||||||
bash .ci/travis-compile.sh --server --package "$NAME" --release
|
|
||||||
|
|
||||||
#Fedora 29 (on docker)
|
|
||||||
- name: Fedora 29 (Debug)
|
|
||||||
if: tag IS NOT present
|
|
||||||
services: docker
|
|
||||||
env: NAME=Fedora29
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/$NAME/
|
|
||||||
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
|
||||||
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
|
||||||
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
|
||||||
"cockatrice_${NAME,,}"
|
|
||||||
bash .ci/travis-compile.sh --server --debug
|
|
||||||
|
|
||||||
- name: Fedora 29 (Release)
|
|
||||||
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
|
||||||
services: docker
|
|
||||||
env: NAME=Fedora29
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/$NAME/
|
|
||||||
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
|
||||||
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
|
||||||
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
|
||||||
"cockatrice_${NAME,,}"
|
|
||||||
bash .ci/travis-compile.sh --server --package "$NAME" "RPM" --release
|
|
||||||
|
|
||||||
#macOS
|
|
||||||
- name: macOS (Debug)
|
|
||||||
if: tag IS NOT present
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode10.1
|
|
||||||
cache: ccache
|
|
||||||
addons:
|
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
- ccache
|
|
||||||
- protobuf
|
|
||||||
- qt
|
|
||||||
- xz
|
|
||||||
script: bash ./.ci/travis-compile.sh --server --install --debug
|
|
||||||
|
|
||||||
- name: macOS (Release)
|
|
||||||
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode9.2
|
|
||||||
cache: ccache
|
|
||||||
addons:
|
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
- ccache
|
|
||||||
- protobuf
|
|
||||||
- qt
|
|
||||||
- xz
|
|
||||||
update: true
|
|
||||||
script: bash ./.ci/travis-compile.sh --server --package "$TRAVIS_OS_NAME" --release
|
|
||||||
|
|
||||||
# Builds for pull requests skip the deployment step altogether
|
|
||||||
deploy:
|
|
||||||
# Deploy configuration for "beta" releases
|
|
||||||
- provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: mLMF41q7xgOR1sjczsilEy7HQis2PkZCzhfOGbn/8FoOQnmmPOZjrsdhn06ZSl3SFsbfCLuClDYXAbFscQmdgjcGN5AmHV+JYfW650QEuQa/f4/lQFsVRtEqUA1O3FQ0OuRxdpCfJubZBdFVH8SbZ93GLC5zXJbkWQNq+xCX1fU=
|
|
||||||
skip_cleanup: true
|
|
||||||
name: "Cockatrice $TRAVIS_TAG"
|
|
||||||
body: "Beta release of Cockatrice"
|
|
||||||
file_glob: true
|
|
||||||
file: "build/Cockatrice-*"
|
|
||||||
overwrite: true
|
|
||||||
draft: false
|
|
||||||
prerelease: true
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
repo: Cockatrice/Cockatrice
|
|
||||||
condition: $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}-beta(\.([2-9]|[1-9][0-9]))?$ # regex to match semver naming convention for beta pre-releases
|
|
||||||
|
|
||||||
# Deploy configuration for "stable" releases
|
|
||||||
- provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: mLMF41q7xgOR1sjczsilEy7HQis2PkZCzhfOGbn/8FoOQnmmPOZjrsdhn06ZSl3SFsbfCLuClDYXAbFscQmdgjcGN5AmHV+JYfW650QEuQa/f4/lQFsVRtEqUA1O3FQ0OuRxdpCfJubZBdFVH8SbZ93GLC5zXJbkWQNq+xCX1fU=
|
|
||||||
skip_cleanup: true
|
|
||||||
file_glob: true
|
|
||||||
file: "build/Cockatrice-*"
|
|
||||||
overwrite: true
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
repo: Cockatrice/Cockatrice
|
|
||||||
condition: $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}$ # regex to match semver naming convention for stable full releases
|
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
webhooks:
|
|
||||||
urls:
|
|
||||||
- https://webhooks.gitter.im/e/d94969c3b01b22cbdcb7
|
|
||||||
on_success: change
|
|
||||||
on_failure: change
|
|
||||||
on_start: never
|
|
||||||
on_cancel: change
|
|
||||||
on_error: change
|
|
||||||
|
|
||||||
|
|
||||||
# Announcements of build image updates: https://docs.travis-ci.com/user/build-environment-updates/
|
|
||||||
# For precise versions of preinstalled tools on the VM, check “Build system information” in the build log!
|
|
||||||
# Official validator for ".travis.yml" config file: https://yaml.travis-ci.org
|
|
||||||
# Travis CI config documentation: https://docs.travis-ci.com/user/customizing-the-build
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
[main]
|
[main]
|
||||||
host = https://www.transifex.com
|
host = https://www.transifex.com
|
||||||
|
|
||||||
[cockatrice.cockatrice]
|
[cockatrice.cockatrice-translations-cockatrice-en-source-ts--master]
|
||||||
file_filter = cockatrice/translations/cockatrice_<lang>.ts
|
file_filter = cockatrice/translations/cockatrice_<lang>.ts
|
||||||
source_file = cockatrice/translations/cockatrice_en.ts
|
source_file = cockatrice/translations/cockatrice_en@source.ts
|
||||||
source_lang = en
|
source_lang = en
|
||||||
|
|
||||||
[cockatrice.oracle]
|
[cockatrice.oracle-translations-oracle-en-source-ts--master]
|
||||||
file_filter = oracle/translations/oracle_<lang>.ts
|
file_filter = oracle/translations/oracle_<lang>.ts
|
||||||
source_file = oracle/translations/oracle_en.ts
|
source_file = oracle/translations/oracle_en@source.ts
|
||||||
source_lang = en
|
source_lang = en
|
||||||
|
|
||||||
|
|||||||
424
CMakeLists.txt
424
CMakeLists.txt
@@ -5,48 +5,96 @@
|
|||||||
# This file sets all the variables shared between the projects
|
# This file sets all the variables shared between the projects
|
||||||
# like the installation path, compilation flags etc..
|
# like the installation path, compilation flags etc..
|
||||||
|
|
||||||
# Cmake 3.1 is required to enable C++11 support correctly
|
# cmake 3.16 is required if using qt6
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
if(POLICY CMP0064)
|
# Early detect ccache
|
||||||
cmake_policy(SET CMP0064 NEW)
|
option(USE_CCACHE "Cache the build results with ccache" ON)
|
||||||
endif()
|
# Treat warnings as errors (Debug builds only)
|
||||||
|
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||||
if(POLICY CMP0071)
|
# Check for translation updates
|
||||||
cmake_policy(SET CMP0071 NEW)
|
option(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
||||||
endif()
|
# Compile servatrice
|
||||||
|
option(WITH_SERVER "build servatrice" OFF)
|
||||||
|
# Compile cockatrice
|
||||||
|
option(WITH_CLIENT "build cockatrice" ON)
|
||||||
|
# Compile oracle
|
||||||
|
option(WITH_ORACLE "build oracle" ON)
|
||||||
|
# Compile dbconverter
|
||||||
|
option(WITH_DBCONVERTER "build dbconverter" ON)
|
||||||
|
# Compile tests
|
||||||
|
option(TEST "build tests" OFF)
|
||||||
|
|
||||||
# Default to "Release" build type
|
# Default to "Release" build type
|
||||||
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
||||||
IF(DEFINED CMAKE_BUILD_TYPE)
|
if(DEFINED CMAKE_BUILD_TYPE)
|
||||||
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
|
set(CMAKE_BUILD_TYPE
|
||||||
ELSE()
|
${CMAKE_BUILD_TYPE}
|
||||||
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
|
CACHE STRING "Type of build"
|
||||||
ENDIF()
|
)
|
||||||
|
else()
|
||||||
|
set(CMAKE_BUILD_TYPE
|
||||||
|
Release
|
||||||
|
CACHE STRING "Type of build"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Early detect ccache
|
if(USE_CCACHE)
|
||||||
find_program(CCACHE_PROGRAM ccache)
|
find_program(CCACHE_PROGRAM ccache)
|
||||||
if(CCACHE_PROGRAM)
|
if(CCACHE_PROGRAM)
|
||||||
# Support Unix Makefiles and Ninja
|
# Support Unix Makefiles and Ninja
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||||
MESSAGE(STATUS "Found CCache ${CCACHE_PROGRAM}")
|
message(STATUS "Found CCache ${CCACHE_PROGRAM}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# Use vcpkg toolchain on Windows
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||||
|
CACHE STRING "Vcpkg toolchain file"
|
||||||
|
)
|
||||||
|
# Qt path set by user or env var
|
||||||
|
if(QTDIR
|
||||||
|
OR DEFINED ENV{QTDIR}
|
||||||
|
OR DEFINED ENV{QTDIR32}
|
||||||
|
OR DEFINED ENV{QTDIR64}
|
||||||
|
)
|
||||||
|
|
||||||
|
else()
|
||||||
|
set(QTDIR
|
||||||
|
""
|
||||||
|
CACHE PATH "Path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
|
||||||
|
)
|
||||||
|
message(
|
||||||
|
WARNING "QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# A project name is needed for CPack
|
# A project name is needed for CPack
|
||||||
# Version can be overriden by git tags, see cmake/getversion.cmake
|
# Version can be overriden by git tags, see cmake/getversion.cmake
|
||||||
PROJECT("Cockatrice" VERSION 2.7.0)
|
project("Cockatrice" VERSION 2.8.1)
|
||||||
|
|
||||||
# Use c++11 for all targets
|
# Set release name if not provided via env/cmake var
|
||||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||||
|
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Use c++17 for all targets
|
||||||
|
set(CMAKE_CXX_STANDARD
|
||||||
|
17
|
||||||
|
CACHE STRING "C++ ISO Standard"
|
||||||
|
)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
# Set conventional loops
|
# Set conventional loops
|
||||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
||||||
|
|
||||||
# Search path for cmake modules
|
# Search path for cmake modules
|
||||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}")
|
||||||
|
|
||||||
# Retrieve git version hash
|
|
||||||
include(getversion)
|
include(getversion)
|
||||||
|
|
||||||
# Create a header and a cpp file containing the version hash
|
# Create a header and a cpp file containing the version hash
|
||||||
@@ -54,126 +102,140 @@ include(createversionfile)
|
|||||||
|
|
||||||
# Define a proper install path
|
# Define a proper install path
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# macOS
|
# macOS
|
||||||
# Due to the special bundle structure ignore
|
# Due to the special bundle structure ignore
|
||||||
# the prefix eventually set by the user.
|
# the prefix eventually set by the user.
|
||||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
|
|
||||||
|
|
||||||
# Force ccache usage if available
|
|
||||||
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
|
|
||||||
if(RULE_LAUNCH_COMPILE)
|
|
||||||
MESSAGE(STATUS "Force enabling CCache usage under macOS")
|
|
||||||
# Set up wrapper scripts
|
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-c.in launch-c)
|
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-cxx.in launch-cxx)
|
|
||||||
execute_process(COMMAND chmod a+rx
|
|
||||||
"${CMAKE_BINARY_DIR}/launch-c"
|
|
||||||
"${CMAKE_BINARY_DIR}/launch-cxx")
|
|
||||||
|
|
||||||
# Set Xcode project attributes to route compilation through our scripts
|
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
|
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
|
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
|
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
# Linux / BSD
|
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
|
||||||
#fix package build
|
|
||||||
if(PREFIX)
|
|
||||||
set(CMAKE_INSTALL_PREFIX ${PREFIX})
|
|
||||||
else()
|
|
||||||
set(CMAKE_INSTALL_PREFIX /usr/local)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
elseif(WIN32)
|
|
||||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
|
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
|
||||||
|
|
||||||
|
# Force ccache usage if available
|
||||||
|
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
|
||||||
|
if(RULE_LAUNCH_COMPILE)
|
||||||
|
message(STATUS "Force enabling CCache usage under macOS")
|
||||||
|
# Set up wrapper scripts
|
||||||
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
||||||
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
|
||||||
|
execute_process(COMMAND chmod a+rx "${CMAKE_BINARY_DIR}/launch-c" "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
|
|
||||||
|
# Set Xcode project attributes to route compilation through our scripts
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# Linux / BSD
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
#fix package build
|
||||||
|
if(PREFIX)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${PREFIX})
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_PREFIX /usr/local)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Treat warnings as errors (Debug builds only)
|
|
||||||
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
|
||||||
|
|
||||||
# Define proper compilation flags
|
# Define proper compilation flags
|
||||||
IF(MSVC)
|
if(MSVC)
|
||||||
# Visual Studio:
|
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
|
||||||
# Maximum optimization
|
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive-")
|
||||||
# Disable warning C4251
|
# Generate complete debugging information
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251")
|
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||||
# Generate complete debugging information
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
# linux/gcc, bsd/gcc, windows/mingw
|
||||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
include(CheckCXXCompilerFlag)
|
||||||
# linux/gcc, bsd/gcc, windows/mingw
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
||||||
if(WARNING_AS_ERROR)
|
if(WARNING_AS_ERROR)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ADDITIONAL_DEBUG_FLAGS
|
||||||
|
-Wcast-align
|
||||||
|
-Wmissing-declarations
|
||||||
|
-Wno-long-long
|
||||||
|
-Wno-error=extra
|
||||||
|
-Wno-error=delete-non-virtual-dtor
|
||||||
|
-Wno-error=sign-compare
|
||||||
|
-Wno-error=missing-declarations
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
||||||
|
check_cxx_compiler_flag("${FLAG}" CXX_HAS_WARNING_${FLAG})
|
||||||
|
if(CXX_HAS_WARNING_${FLAG})
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
|
||||||
endif()
|
endif()
|
||||||
|
endforeach()
|
||||||
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Wno-long-long -Wno-error=extra -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=missing-declarations)
|
else()
|
||||||
|
# other: osx/llvm, bsd/llvm
|
||||||
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
||||||
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
|
if(WARNING_AS_ERROR)
|
||||||
IF(CXX_HAS_WARNING_${FLAG})
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror")
|
||||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
|
else()
|
||||||
ENDIF()
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
|
||||||
ENDFOREACH()
|
endif()
|
||||||
ELSE()
|
endif()
|
||||||
# other: osx/llvm, bsd/llvm
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
|
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
|
||||||
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
ADD_DEFINITIONS("-DSFMT_MEXP=19937")
|
add_definitions("-DSFMT_MEXP=19937")
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
# Find Qt5
|
find_package(Threads REQUIRED)
|
||||||
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
|
||||||
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
|
|
||||||
|
|
||||||
FIND_PACKAGE(Qt5Core 5.5.0 REQUIRED)
|
# Determine 32 or 64 bit build
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(_lib_suffix 64)
|
||||||
|
else()
|
||||||
|
set(_lib_suffix 32)
|
||||||
|
endif()
|
||||||
|
|
||||||
IF(Qt5Core_FOUND)
|
if(DEFINED QTDIR${_lib_suffix})
|
||||||
MESSAGE(STATUS "Found Qt ${Qt5Core_VERSION_STRING}")
|
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
|
||||||
|
elseif(DEFINED QTDIR)
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
|
||||||
|
elseif(DEFINED ENV{QTDIR${_lib_suffix}})
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
|
||||||
|
elseif(DEFINED ENV{QTDIR})
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# FIX: Qt was built with -reduce-relocations
|
message(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
||||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# guess plugins and libraries directory
|
include(FindQtRuntime)
|
||||||
set(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins")
|
|
||||||
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
|
|
||||||
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
|
|
||||||
|
|
||||||
ELSE()
|
|
||||||
MESSAGE(FATAL_ERROR "No Qt5 found!")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC TRUE)
|
set(CMAKE_AUTOMOC TRUE)
|
||||||
|
|
||||||
# Find other needed libraries
|
# Find other needed libraries
|
||||||
FIND_PACKAGE(Protobuf REQUIRED)
|
find_package(Protobuf REQUIRED)
|
||||||
|
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||||
|
message(FATAL_ERROR "No protoc command found!")
|
||||||
|
else()
|
||||||
|
message(STATUS "Found Protobuf ${Protobuf_VERSION} at: ${Protobuf_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
#Find OpenSSL
|
#Find OpenSSL
|
||||||
IF(WIN32)
|
if(WIN32)
|
||||||
FIND_PACKAGE(Win32SslRuntime)
|
find_package(Win32SslRuntime)
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
#Find VCredist
|
#Find VCredist
|
||||||
IF(MSVC)
|
if(MSVC)
|
||||||
FIND_PACKAGE(VCredistRuntime)
|
find_package(VCredistRuntime)
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
# Package builder
|
# Package builder
|
||||||
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zahalpern+github@gmail.com>")
|
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
|
||||||
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||||
@@ -183,75 +245,93 @@ set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
|||||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}")
|
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}")
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
|
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
|
||||||
set(CPACK_GENERATOR "DragNDrop")
|
set(CPACK_GENERATOR "DragNDrop")
|
||||||
set(CPACK_DMG_FORMAT "UDBZ")
|
set(CPACK_DMG_FORMAT "UDBZ")
|
||||||
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
||||||
set(CPACK_SYSTEM_NAME "OSX")
|
set(CPACK_SYSTEM_NAME "OSX")
|
||||||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
|
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
|
||||||
|
else()
|
||||||
|
# linux
|
||||||
|
if(CPACK_GENERATOR STREQUAL "RPM")
|
||||||
|
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
||||||
|
set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia")
|
||||||
|
elseif(Qt5_FOUND)
|
||||||
|
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
||||||
|
endif()
|
||||||
|
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
|
||||||
|
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
|
||||||
|
# stop directories from making package conflicts
|
||||||
|
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||||
|
/usr/share/applications
|
||||||
|
/usr/share/icons
|
||||||
|
/usr/share/icons/hicolor
|
||||||
|
/usr/share/icons/hicolor/48x48
|
||||||
|
/usr/share/icons/hicolor/48x48/apps
|
||||||
|
/usr/share/icons/hicolor/scalable
|
||||||
|
/usr/share/icons/hicolor/scalable/apps
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
# linux
|
set(CPACK_GENERATOR DEB)
|
||||||
IF(CPACK_GENERATOR STREQUAL "RPM")
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||||
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
|
if(Qt6_FOUND)
|
||||||
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins")
|
||||||
ELSE()
|
elseif(Qt5_FOUND)
|
||||||
set(CPACK_GENERATOR DEB)
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
endif()
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
|
||||||
ENDIF()
|
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
|
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
|
||||||
if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
|
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "(x64)")
|
||||||
set(TRICE_IS_64_BIT 1)
|
set(TRICE_IS_64_BIT 1)
|
||||||
else()
|
else()
|
||||||
set(TRICE_IS_64_BIT 0)
|
set(TRICE_IS_64_BIT 0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configure file with custom definitions for NSIS.
|
# Configure file with custom definitions for NSIS.
|
||||||
configure_file(
|
configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh")
|
||||||
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
|
|
||||||
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
|
|
||||||
)
|
|
||||||
|
|
||||||
# include vcredist into the package; NSIS will take care of running it
|
# include vcredist into the package; NSIS will take care of running it
|
||||||
if(VCREDISTRUNTIME_FOUND)
|
if(VCREDISTRUNTIME_FOUND)
|
||||||
INSTALL(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
|
install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
# Compile servatrice (default off)
|
|
||||||
option(WITH_SERVER "build servatrice" OFF)
|
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
if(WITH_SERVER)
|
if(WITH_SERVER)
|
||||||
add_subdirectory(servatrice)
|
add_subdirectory(servatrice)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile cockatrice (default on)
|
|
||||||
option(WITH_CLIENT "build cockatrice" ON)
|
|
||||||
if(WITH_CLIENT)
|
if(WITH_CLIENT)
|
||||||
add_subdirectory(cockatrice)
|
add_subdirectory(cockatrice)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
set(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile oracle (default on)
|
|
||||||
option(WITH_ORACLE "build oracle" ON)
|
|
||||||
if(WITH_ORACLE)
|
if(WITH_ORACLE)
|
||||||
add_subdirectory(oracle)
|
add_subdirectory(oracle)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
set(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile tests (default off)
|
if(WITH_DBCONVERTER)
|
||||||
option(TEST "build tests" OFF)
|
add_subdirectory(dbconverter)
|
||||||
if(TEST)
|
set(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
include(CTest)
|
endif()
|
||||||
add_subdirectory(tests)
|
|
||||||
|
if(TEST)
|
||||||
|
include(CTest)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt6_FOUND AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
|
||||||
|
# Qt6.3+ requires project finalization to support translations
|
||||||
|
qt6_finalize_project()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y\
|
|||||||
git\
|
git\
|
||||||
libprotobuf-dev\
|
libprotobuf-dev\
|
||||||
libqt5sql5-mysql\
|
libqt5sql5-mysql\
|
||||||
|
libmysqlclient-dev\
|
||||||
libqt5websockets5-dev\
|
libqt5websockets5-dev\
|
||||||
protobuf-compiler\
|
protobuf-compiler\
|
||||||
qt5-default\
|
qt5-default\
|
||||||
@@ -18,7 +19,7 @@ COPY . /home/servatrice/code/
|
|||||||
WORKDIR /home/servatrice/code
|
WORKDIR /home/servatrice/code
|
||||||
|
|
||||||
WORKDIR build
|
WORKDIR build
|
||||||
RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 &&\
|
RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 &&\
|
||||||
make &&\
|
make &&\
|
||||||
make install
|
make install
|
||||||
|
|
||||||
@@ -26,4 +27,5 @@ WORKDIR /home/servatrice
|
|||||||
|
|
||||||
EXPOSE 4747
|
EXPOSE 4747
|
||||||
|
|
||||||
CMD [ "servatrice", "--log-to-console" ]
|
ENTRYPOINT [ "servatrice", "--log-to-console" ]
|
||||||
|
|
||||||
|
|||||||
57
README.md
57
README.md
@@ -5,7 +5,7 @@
|
|||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
|
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
|
||||||
<a href="#download-">Download</a> <b>|</b>
|
<a href="#download-">Download</a> <b>|</b>
|
||||||
<a href="#get-involved-">Get Involved</a> <b>|</b>
|
<a href="#get-involved--">Get Involved</a> <b>|</b>
|
||||||
<a href="#community-resources">Community</a> <b>|</b>
|
<a href="#community-resources">Community</a> <b>|</b>
|
||||||
<a href="#translations-">Translations</a> <b>|</b>
|
<a href="#translations-">Translations</a> <b>|</b>
|
||||||
<a href="#build--">Build</a> <b>|</b>
|
<a href="#build--">Build</a> <b>|</b>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<br><pre>
|
<br><pre>
|
||||||
<b>To get started, ⇢ [view our webpage](https://cockatrice.github.io/)</b><br>
|
<b>To get started, ⇢ [view our webpage](https://cockatrice.github.io/)</b><br>
|
||||||
<b>To get support or suggest changes ⇢ [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
|
<b>To get support or suggest changes ⇢ [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
|
||||||
<b>To help with development, see how to [get involved](#get-involved-)</b>
|
<b>To help with development, see how to [get involved](#get-involved--)</b>
|
||||||
</pre><br>
|
</pre><br>
|
||||||
|
|
||||||
|
|
||||||
@@ -29,21 +29,21 @@ Cockatrice is an open-source, multiplatform program for playing tabletop card ga
|
|||||||
|
|
||||||
# Download [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
# Download [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
||||||
|
|
||||||
Downloads are available for full releases and the current beta version in development.<br>
|
Downloads are available for full releases and the current beta version in development. There is no strict release schedule for either of them.
|
||||||
Full releases are checkpoints featuring major feature or UI enhancements - we recommend to use those. There is no strict schedule for new full releases.
|
|
||||||
|
|
||||||
The beta release contains the most recently added features and bugfixes, but can be unstable. They are released as we feel need.
|
- Latest `stable` release: [](https://github.com/cockatrice/cockatrice/releases/latest) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)<br>
|
||||||
|
- Stable versions are checkpoints featuring major feature and UI enhancements.
|
||||||
|
- **Recommended for most users!**
|
||||||
|
|
||||||
- Latest `stable` release (**recommended**): [](https://github.com/cockatrice/cockatrice/releases/latest) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)<br>
|
- Latest `beta` release: [](https://github.com/cockatrice/cockatrice/releases) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
||||||
|
- Beta versions include the most recently added features and bugfixes, but can be unstable.
|
||||||
- Latest `beta` release: [](https://github.com/cockatrice/cockatrice/releases) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
|
||||||
- Beta versions may be unstable and contain bugs.
|
|
||||||
- To be a Cockatrice Beta Tester, use this version. Find more information [here](https://github.com/Cockatrice/Cockatrice/wiki/Release-Channels)!
|
- To be a Cockatrice Beta Tester, use this version. Find more information [here](https://github.com/Cockatrice/Cockatrice/wiki/Release-Channels)!
|
||||||
|
|
||||||
|
|
||||||
# Get Involved [](https://gitter.im/Cockatrice/Cockatrice)
|
# Get Involved [](https://discord.gg/3Z9yzmA) [](https://gitter.im/Cockatrice/Cockatrice)
|
||||||
|
|
||||||
[Chat](https://gitter.im/Cockatrice/Cockatrice) with the Cockatrice developers on Gitter. Come here to talk about the application, features, or just to hang out. For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
|
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project or fellow users of the app. The Cockatrice developers are also available on [Gitter](https://gitter.im/Cockatrice/Cockatrice). Come here to talk about the application, features, or just to hang out.<br>
|
||||||
|
For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
|
||||||
|
|
||||||
To contribute code to the project, please review [the guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md).
|
To contribute code to the project, please review [the guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md).
|
||||||
We maintain two tags for contributors to find issues to work on:
|
We maintain two tags for contributors to find issues to work on:
|
||||||
@@ -52,8 +52,6 @@ We maintain two tags for contributors to find issues to work on:
|
|||||||
|
|
||||||
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code review for changes they submit.
|
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code review for changes they submit.
|
||||||
|
|
||||||
Read the long-term project **roadmap** to see planned edits and milestones [here](https://docs.google.com/document/d/1Ewe5uSaRE2nR2pNPMaGmP6gVZdqgFbBgwSscGqIr4W0/edit).
|
|
||||||
|
|
||||||
We try to be responsive to new issues. We'll provide advice on how best to implement a feature; alternately, we can show you where the codebase is doing something similar before you get too far along.
|
We try to be responsive to new issues. We'll provide advice on how best to implement a feature; alternately, we can show you where the codebase is doing something similar before you get too far along.
|
||||||
|
|
||||||
Cockatrice uses the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
Cockatrice uses the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
||||||
@@ -67,7 +65,7 @@ Cockatrice uses the [Google Developer Documentation Style Guide](https://develop
|
|||||||
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
|
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
|
||||||
|
|
||||||
|
|
||||||
# Translations [](https://www.transifex.com/projects/p/cockatrice/)
|
# Translations [](https://www.transifex.com/projects/p/cockatrice/)
|
||||||
|
|
||||||
Cockatrice uses Transifex for translations. You can help us bring Cockatrice and Oracle to your language or just edit single wordings right from within your browser by visiting our [Transifex project page](https://www.transifex.com/projects/p/cockatrice/).<br>
|
Cockatrice uses Transifex for translations. You can help us bring Cockatrice and Oracle to your language or just edit single wordings right from within your browser by visiting our [Transifex project page](https://www.transifex.com/projects/p/cockatrice/).<br>
|
||||||
|
|
||||||
@@ -78,18 +76,18 @@ Cockatrice uses Transifex for translations. You can help us bring Cockatrice and
|
|||||||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
|
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
|
||||||
|
|
||||||
|
|
||||||
# Build [](https://travis-ci.org/Cockatrice/Cockatrice) [](https://ci.appveyor.com/project/ZeldaZach/cockatrice/branch/master) <!-- link to zachs appveyor not correct yet -->
|
# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
|
||||||
|
|
||||||
**Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
|
**Detailed compiling instructions can be found on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
|
||||||
|
|
||||||
Dependencies: *(for minimum requirements search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
Dependencies: *(for minimum requirements search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
||||||
- [Qt](https://www.qt.io/developers/)
|
- [Qt](https://www.qt.io/developers/)
|
||||||
- [protobuf](https://github.com/google/protobuf)
|
- [protobuf](https://github.com/protocolbuffers/protobuf)
|
||||||
- [CMake](https://www.cmake.org/)
|
- [CMake](https://www.cmake.org/)
|
||||||
|
|
||||||
Oracle can optionally use zlib and xz to load compressed files:
|
Oracle can optionally use zlib and xz to load compressed files:
|
||||||
- [zlib](https://www.zlib.net/)
|
|
||||||
- [xz](https://tukaani.org/xz/)
|
- [xz](https://tukaani.org/xz/)
|
||||||
|
- [zlib](https://www.zlib.net/)
|
||||||
|
|
||||||
To compile:
|
To compile:
|
||||||
|
|
||||||
@@ -117,6 +115,8 @@ The following flags can be passed to `cmake`:
|
|||||||
- `-DWARNING_AS_ERROR=0` Whether to treat compilation warnings as errors in debug mode (default 1 = yes).
|
- `-DWARNING_AS_ERROR=0` Whether to treat compilation warnings as errors in debug mode (default 1 = yes).
|
||||||
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
|
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
|
||||||
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
|
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
|
||||||
|
- `-DFORCE_USE_QT5=1` Skip looking for Qt6 before trying to find Qt5
|
||||||
|
- `-DOPEN_SSL_PATH=C:/Path/To/Tools/OpenSSL/Win_x64/bin"` Designate the OpenSSL Path if you're using non-standard directives
|
||||||
|
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
@@ -125,7 +125,6 @@ The following flags can be passed to `cmake`:
|
|||||||
`Oracle` fetches card data<br>
|
`Oracle` fetches card data<br>
|
||||||
`Servatrice` is the server<br>
|
`Servatrice` is the server<br>
|
||||||
|
|
||||||
|
|
||||||
**Servatrice Docker container**
|
**Servatrice Docker container**
|
||||||
|
|
||||||
You can run an instance of Servatrice (the Cockatrice server) using [Docker](https://www.docker.com/what-docker) and the Cockatrice Dockerfile.<br>
|
You can run an instance of Servatrice (the Cockatrice server) using [Docker](https://www.docker.com/what-docker) and the Cockatrice Dockerfile.<br>
|
||||||
@@ -141,6 +140,26 @@ to permit connections to the server.
|
|||||||
|
|
||||||
Find more information on how to use Servatrice with Docker in our [wiki](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).
|
Find more information on how to use Servatrice with Docker in our [wiki](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).
|
||||||
|
|
||||||
|
**Docker compose**
|
||||||
|
|
||||||
|
There is also a docker-compose file available which will configure and run both a MySQL server and Servatrice. The docker-compose setup scripts can be found in the `servatrice/docker` folder and vary only slightly from the default sql and server .ini files. The setup scripts can either be modified in place, or docker-compose can mount alternative files into the images, as you prefer.
|
||||||
|
|
||||||
|
To run Servatrice via docker-compose, first install docker-compose following the [install instructions](https://docs.docker.com/compose/install/). Once installed, run the following from the root of the repository:
|
||||||
|
```bash
|
||||||
|
docker-compose build # Build the Servatrice image using the same Dockerfile as above.
|
||||||
|
docker-compose up # Setup and run both the MySQL server and Servatrice.
|
||||||
|
```
|
||||||
|
|
||||||
|
>Note: Similar to the above Docker setup, this will expose TCP ports 4747 and 4748.
|
||||||
|
|
||||||
|
>Note: The first time running the docker-compose setup, the MySQL server will take a little time to run the initial setup scripts. Due to this, the Servatrice instance may fail the first few attempts to connect to the database. Servatrice is set to `restart: always` in the docker-compose.yml, which will allow it to continue attempting to start up. Once the MySQL scripts have completed, Servatrice should then connect automatically on the next attempt.
|
||||||
|
|
||||||
|
**Docker compose in Windows**
|
||||||
|
A out of box working docker-compose file has been added to help setup in Windows.
|
||||||
|
|
||||||
|
Docker in Windows requires additional steps in form of using Docker Desktop to allow resource sharing from the drive the volumes are mapped from, as well as potential workarounds needed to get file sharing working in Windows. This [StackOverflow discussion sheds some light on it](https://stackoverflow.com/questions/42203488/settings-to-windows-firewall-to-allow-docker-for-windows-to-share-drive)
|
||||||
|
|
||||||
|
|
||||||
# License [](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE)
|
# License [](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE)
|
||||||
|
|
||||||
Cockatrice is free software, licensed under the [GPLv2](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE).
|
Cockatrice is free software, licensed under the [GPLv2](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE).
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
# Find the LibExecinfo library - FreeBSD only
|
# Find the LibExecinfo library - FreeBSD only
|
||||||
|
|
||||||
FIND_PATH(LIBEXECINFO_INCLUDE_DIR execinfo.h)
|
find_path(LIBEXECINFO_INCLUDE_DIR execinfo.h)
|
||||||
FIND_LIBRARY(LIBEXECINFO_LIBRARY NAMES execinfo)
|
find_library(LIBEXECINFO_LIBRARY NAMES execinfo)
|
||||||
|
|
||||||
IF(LIBEXECINFO_INCLUDE_DIR AND LIBEXECINFO_LIBRARY)
|
if(LIBEXECINFO_INCLUDE_DIR AND LIBEXECINFO_LIBRARY)
|
||||||
SET(LIBEXECINFO_FOUND TRUE)
|
set(LIBEXECINFO_FOUND TRUE)
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
IF(LIBEXECINFO_FOUND)
|
if(LIBEXECINFO_FOUND)
|
||||||
IF(NOT LIBEXECINFO_FIND_QUIETLY)
|
if(NOT LIBEXECINFO_FIND_QUIETLY)
|
||||||
MESSAGE(STATUS "Found LibExecinfo: ${EXECINFO_LIBRARY}")
|
message(STATUS "Found LibExecinfo: ${EXECINFO_LIBRARY}")
|
||||||
ENDIF()
|
endif()
|
||||||
ELSE()
|
else()
|
||||||
IF(LIBEXECINFO_FIND_REQUIRED)
|
if(LIBEXECINFO_FIND_REQUIRED)
|
||||||
MESSAGE(FATAL_ERROR "Could not find LibExecinfo")
|
message(FATAL_ERROR "Could not find LibExecinfo")
|
||||||
ENDIF()
|
endif()
|
||||||
ENDIF()
|
endif()
|
||||||
|
|||||||
117
cmake/FindQtRuntime.cmake
Normal file
117
cmake/FindQtRuntime.cmake
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Find a compatible Qt version
|
||||||
|
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, WITH_DBCONVERTER, FORCE_USE_QT5
|
||||||
|
# Optional Input: QT6_DIR -- Hint as to where Qt6 lives on the system
|
||||||
|
# Optional Input: QT5_DIR -- Hint as to where Qt5 lives on the system
|
||||||
|
# Output: COCKATRICE_QT_VERSION_NAME -- Example values: Qt5, Qt6
|
||||||
|
# Output: SERVATRICE_QT_MODULES
|
||||||
|
# Output: COCKATRICE_QT_MODULES
|
||||||
|
# Output: ORACLE_QT_MODULES
|
||||||
|
# Output: DBCONVERTER_QT_MODULES
|
||||||
|
# Output: TEST_QT_MODULES
|
||||||
|
|
||||||
|
set(REQUIRED_QT_COMPONENTS Core)
|
||||||
|
if(WITH_SERVER)
|
||||||
|
set(_SERVATRICE_NEEDED Network Sql WebSockets)
|
||||||
|
endif()
|
||||||
|
if(WITH_CLIENT)
|
||||||
|
set(_COCKATRICE_NEEDED
|
||||||
|
Concurrent
|
||||||
|
Gui
|
||||||
|
Multimedia
|
||||||
|
Network
|
||||||
|
PrintSupport
|
||||||
|
Svg
|
||||||
|
WebSockets
|
||||||
|
Widgets
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(WITH_ORACLE)
|
||||||
|
set(_ORACLE_NEEDED Concurrent Network Svg Widgets)
|
||||||
|
endif()
|
||||||
|
if(WITH_DBCONVERTER)
|
||||||
|
set(_DBCONVERTER_NEEDED Network Widgets)
|
||||||
|
endif()
|
||||||
|
if(TEST)
|
||||||
|
set(_TEST_NEEDED Widgets)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED}
|
||||||
|
${_DBCONVERTER_NEEDED} ${_TEST_NEEDED}
|
||||||
|
)
|
||||||
|
list(REMOVE_DUPLICATES REQUIRED_QT_COMPONENTS)
|
||||||
|
|
||||||
|
if(NOT FORCE_USE_QT5)
|
||||||
|
# Linguist is now a component in Qt6 instead of an external package
|
||||||
|
find_package(
|
||||||
|
Qt6 6.2.3
|
||||||
|
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
|
||||||
|
QUIET HINTS ${Qt6_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
||||||
|
|
||||||
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
||||||
|
if(QT6_LRELEASE_INDEX EQUAL -1)
|
||||||
|
message(WARNING "Qt6 lrelease not found.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
||||||
|
if(QT6_LUPDATE_INDEX EQUAL -1)
|
||||||
|
message(WARNING "Qt6 lupdate not found.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
find_package(
|
||||||
|
Qt5 5.8.0
|
||||||
|
COMPONENTS ${REQUIRED_QT_COMPONENTS}
|
||||||
|
QUIET HINTS ${Qt5_DIR}
|
||||||
|
)
|
||||||
|
if(Qt5_FOUND)
|
||||||
|
set(COCKATRICE_QT_VERSION_NAME Qt5)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No suitable version of Qt was found")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Qt5 Linguist is in a separate package
|
||||||
|
find_package(Qt5LinguistTools QUIET)
|
||||||
|
if(Qt5LinguistTools_FOUND)
|
||||||
|
if(NOT Qt5_LRELEASE_EXECUTABLE)
|
||||||
|
message(WARNING "Qt5 lrelease not found.")
|
||||||
|
endif()
|
||||||
|
if(NOT Qt5_LUPDATE_EXECUTABLE)
|
||||||
|
message(WARNING "Qt5 lupdate not found.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "Linguist Tools not found, cannot handle translations")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt5_POSITION_INDEPENDENT_CODE OR Qt6_FOUND)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Establish Qt Plugins directory & Library directories
|
||||||
|
get_target_property(QT_LIBRARY_DIR ${COCKATRICE_QT_VERSION_NAME}::Core LOCATION)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} DIRECTORY)
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
get_filename_component(QT_PLUGINS_DIR "${Qt6Core_DIR}/../../../${QT6_INSTALL_PLUGINS}" ABSOLUTE)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/../../.." ABSOLUTE)
|
||||||
|
if(UNIX AND APPLE)
|
||||||
|
# Mac needs a bit more help finding all necessary components
|
||||||
|
list(APPEND QT_LIBRARY_DIR "/usr/local/lib")
|
||||||
|
endif()
|
||||||
|
elseif(Qt5_FOUND)
|
||||||
|
get_filename_component(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins" ABSOLUTE)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
message(DEBUG "QT_PLUGINS_DIR = ${QT_PLUGINS_DIR}")
|
||||||
|
message(DEBUG "QT_LIBRARY_DIR = ${QT_LIBRARY_DIR}")
|
||||||
|
|
||||||
|
# Establish exports
|
||||||
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" SERVATRICE_QT_MODULES "${_SERVATRICE_NEEDED}")
|
||||||
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" COCKATRICE_QT_MODULES "${_COCKATRICE_NEEDED}")
|
||||||
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" ORACLE_QT_MODULES "${_ORACLE_NEEDED}")
|
||||||
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" DB_CONVERTER_QT_MODULES "${_DBCONVERTER_NEEDED}")
|
||||||
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}")
|
||||||
|
|
||||||
|
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")
|
||||||
@@ -1,36 +1,42 @@
|
|||||||
# Find the MS Visual Studio VC redistributable package
|
# Find the MS Visual Studio VC redistributable package
|
||||||
|
|
||||||
if (WIN32)
|
if(WIN32)
|
||||||
set(VCREDISTRUNTIME_FOUND "NO")
|
set(VCREDISTRUNTIME_FOUND "NO")
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
|
||||||
set(REDIST_ARCH x64)
|
set(REDIST_ARCH x64)
|
||||||
else()
|
else()
|
||||||
set(REDIST_ARCH x86)
|
set(REDIST_ARCH x86)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(REDIST_FILE vcredist_${REDIST_ARCH}.exe)
|
# VS 2017 uses vcredist_ARCH.exe, VS 2022 uses vc_redist.ARCH.exe
|
||||||
|
set(REDIST_FILE_NAMES vcredist_${REDIST_ARCH}.exe vc_redist.${REDIST_ARCH}.exe)
|
||||||
|
|
||||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||||
include(InstallRequiredSystemLibraries)
|
include(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
# Check if the list contains minimum one element, to get the path from
|
# Check if the list contains minimum one element, to get the path from
|
||||||
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
|
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
|
||||||
if (libsCount GREATER 0)
|
if(libsCount GREATER 0)
|
||||||
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
|
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
|
||||||
|
|
||||||
get_filename_component(_path ${_path} DIRECTORY)
|
get_filename_component(_path ${_path} DIRECTORY)
|
||||||
get_filename_component(_path ${_path}/../../ ABSOLUTE)
|
get_filename_component(_path ${_path}/../../ ABSOLUTE)
|
||||||
|
|
||||||
if (EXISTS "${_path}/${REDIST_FILE}") # VS 2017
|
foreach(redist_file ${REDIST_FILE_NAMES})
|
||||||
set(VCREDISTRUNTIME_FOUND "YES")
|
if(EXISTS "${_path}/${REDIST_FILE}")
|
||||||
set(VCREDISTRUNTIME_FILE ${_path}/${REDIST_FILE})
|
set(VCREDISTRUNTIME_FOUND "YES")
|
||||||
endif()
|
set(VCREDISTRUNTIME_FILE ${_path}/${redist_file})
|
||||||
endif()
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(VCREDISTRUNTIME_FOUND)
|
if(VCREDISTRUNTIME_FOUND)
|
||||||
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
|
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
|
||||||
else()
|
else()
|
||||||
message(WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime.")
|
message(
|
||||||
endif()
|
WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,71 +1,79 @@
|
|||||||
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
||||||
# will be needed by Qt in order to access https urls.
|
# will be needed by Qt in order to access https urls.
|
||||||
|
if(NOT DEFINED WIN32 OR NOT ${WIN32})
|
||||||
|
message(STATUS "Non-Windows device trying to execute FindWin32SslRuntime, skipping")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||||
# Get standard installation paths for OpenSSL under Windows
|
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||||
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
set(_OPENSSL_ROOT_PATHS
|
||||||
|
${OPEN_SSL_PATH}
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
"$ENV{VCPKG_PACKAGES_DIR}/x64-windows/bin"
|
||||||
# target win64
|
"C:/OpenSSL-Win64/bin"
|
||||||
set(_OPENSSL_ROOT_HINTS
|
"C:/OpenSSL-Win64"
|
||||||
${OPENSSL_ROOT_DIR}
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
|
||||||
ENV OPENSSL_ROOT_DIR
|
|
||||||
)
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
|
||||||
set(_OPENSSL_ROOT_PATHS
|
|
||||||
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
||||||
"${_programfiles}/OpenSSL-Win64"
|
"${_programfiles}/OpenSSL-Win64"
|
||||||
"C:/OpenSSL-Win64/"
|
"D:/a/Cockatrice/Qt/Tools/OpenSSL/Win_x64/bin"
|
||||||
)
|
)
|
||||||
unset(_programfiles)
|
unset(_programfiles)
|
||||||
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||||
# target win32
|
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||||
set(_OPENSSL_ROOT_HINTS
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
${OPENSSL_ROOT_DIR}
|
set(_OPENSSL_ROOT_PATHS
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
${OPEN_SSL_PATH}
|
||||||
ENV OPENSSL_ROOT_DIR
|
"$ENV{VCPKG_PACKAGES_DIR}/x86-windows/bin"
|
||||||
)
|
"C:/OpenSSL-Win32/bin"
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
"C:/OpenSSL-Win32"
|
||||||
set(_OPENSSL_ROOT_PATHS
|
"C:/OpenSSL"
|
||||||
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
||||||
"${_programfiles}/OpenSSL"
|
"${_programfiles}/OpenSSL"
|
||||||
"${_programfiles}/OpenSSL-Win32"
|
"${_programfiles}/OpenSSL-Win32"
|
||||||
"C:/OpenSSL/"
|
"D:/a/Cockatrice/Qt/Tools/OpenSSL/Win_x86/bin"
|
||||||
"C:/OpenSSL-Win32/"
|
|
||||||
)
|
|
||||||
unset(_programfiles)
|
|
||||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
|
|
||||||
else ()
|
|
||||||
set(_OPENSSL_ROOT_HINTS
|
|
||||||
${OPENSSL_ROOT_DIR}
|
|
||||||
ENV OPENSSL_ROOT_DIR
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS
|
|
||||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# For OpenSSL < 1.1, they are named libeay32 and ssleay32 and even if the dll is 64bit, it's still suffixed as *32.dll
|
|
||||||
# For OpenSSL >= 1.1, they are named libcrypto and libssl with no suffix
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libeay32.dll libcrypto.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES ssleay32.dll libssl.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
|
|
||||||
|
|
||||||
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
|
||||||
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
|
||||||
SET(WIN32SSLRUNTIME_FOUND "YES")
|
|
||||||
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
|
||||||
ELSE()
|
|
||||||
SET(WIN32SSLRUNTIME_FOUND "NO")
|
|
||||||
message(WARNING "Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime.")
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
MARK_AS_ADVANCED(
|
|
||||||
WIN32SSLRUNTIME_LIBEAY
|
|
||||||
WIN32SSLRUNTIME_SSLEAY
|
|
||||||
)
|
)
|
||||||
|
unset(_programfiles)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Looking for OpenSSL @ ${CMAKE_GENERATOR_PLATFORM} in ${_OPENSSL_ROOT_PATHS}")
|
||||||
|
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||||
|
find_file(
|
||||||
|
WIN32SSLRUNTIME_LIBEAY
|
||||||
|
NAMES libcrypto-1_1-x64.dll libcrypto.dll
|
||||||
|
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
find_file(
|
||||||
|
WIN32SSLRUNTIME_SSLEAY
|
||||||
|
NAMES libssl-1_1-x64.dll libssl.dll
|
||||||
|
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||||
|
find_file(
|
||||||
|
WIN32SSLRUNTIME_LIBEAY
|
||||||
|
NAMES libcrypto-1_1.dll libcrypto.dll
|
||||||
|
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
find_file(
|
||||||
|
WIN32SSLRUNTIME_SSLEAY
|
||||||
|
NAMES libssl-1_1.dll libssl.dll
|
||||||
|
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
||||||
|
set(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
||||||
|
set(WIN32SSLRUNTIME_FOUND "YES")
|
||||||
|
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
set(WIN32SSLRUNTIME_FOUND "NO")
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(WIN32SSLRUNTIME_LIBEAY WIN32SSLRUNTIME_SSLEAY)
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ ${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
|||||||
Delete "$INSTDIR\uninstall.exe"
|
Delete "$INSTDIR\uninstall.exe"
|
||||||
Delete "$INSTDIR\cockatrice.exe"
|
Delete "$INSTDIR\cockatrice.exe"
|
||||||
Delete "$INSTDIR\oracle.exe"
|
Delete "$INSTDIR\oracle.exe"
|
||||||
|
Delete "$INSTDIR\dbconverter.exe"
|
||||||
Delete "$INSTDIR\servatrice.exe"
|
Delete "$INSTDIR\servatrice.exe"
|
||||||
Delete "$INSTDIR\Qt*.dll"
|
Delete "$INSTDIR\Qt*.dll"
|
||||||
Delete "$INSTDIR\libmysql.dll"
|
Delete "$INSTDIR\libmysql.dll"
|
||||||
@@ -250,7 +251,7 @@ ${If} $PortableMode = 0
|
|||||||
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
|
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
|
||||||
VcRedist86Exists:
|
VcRedist86Exists:
|
||||||
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
|
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
|
||||||
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
DetailPrint "Wait to ensure unlock of vc_redist file after installation..."
|
||||||
Sleep 3000
|
Sleep 3000
|
||||||
Delete "$INSTDIR\vcredist_x86.exe"
|
Delete "$INSTDIR\vcredist_x86.exe"
|
||||||
PastVcRedist86Check:
|
PastVcRedist86Check:
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
|
set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
|
||||||
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
|
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
|
||||||
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
include_directories(${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
set( hstring "extern const char *VERSION_STRING\;
|
set(hstring
|
||||||
|
"extern const char *VERSION_STRING\;
|
||||||
extern const char *VERSION_COMMIT\;
|
extern const char *VERSION_COMMIT\;
|
||||||
extern const char *VERSION_DATE\;\n" )
|
extern const char *VERSION_DATE\;\n"
|
||||||
set( cppstring "const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
|
)
|
||||||
|
set(cppstring
|
||||||
|
"const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
|
||||||
const char *VERSION_COMMIT = \"${GIT_COMMIT_ID}\"\;
|
const char *VERSION_COMMIT = \"${GIT_COMMIT_ID}\"\;
|
||||||
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n")
|
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n"
|
||||||
|
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
|
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
|
|
||||||
)
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring})
|
||||||
|
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring})
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,188 +1,187 @@
|
|||||||
# HELPER FUNCTIONS
|
# HELPER FUNCTIONS
|
||||||
|
|
||||||
function(get_commit_id)
|
function(get_commit_id)
|
||||||
# get last commit hash
|
# get last commit hash
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT_EXECUTABLE} log -1 --abbrev=7 --date=short "--pretty=%h"
|
COMMAND ${GIT_EXECUTABLE} log -1 --abbrev=7 --date=short "--pretty=%h"
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
RESULT_VARIABLE res_var
|
RESULT_VARIABLE res_var
|
||||||
OUTPUT_VARIABLE GIT_COM_ID
|
OUTPUT_VARIABLE GIT_COM_ID
|
||||||
)
|
)
|
||||||
if(NOT ${res_var} EQUAL 0)
|
if(NOT ${res_var} EQUAL 0)
|
||||||
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
|
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
string(REPLACE "\n" "" GIT_COM_ID "${GIT_COM_ID}")
|
string(REPLACE "\n" "" GIT_COM_ID "${GIT_COM_ID}")
|
||||||
set(GIT_COMMIT_ID "${GIT_COM_ID}" PARENT_SCOPE)
|
set(GIT_COMMIT_ID
|
||||||
set(PROJECT_VERSION_LABEL "custom(${GIT_COM_ID})" PARENT_SCOPE)
|
"${GIT_COM_ID}"
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
set(PROJECT_VERSION_LABEL
|
||||||
|
"custom(${GIT_COM_ID})"
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(get_commit_date)
|
function(get_commit_date)
|
||||||
# get last commit date
|
# get last commit date
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%cd"
|
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%cd"
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
RESULT_VARIABLE res_var
|
RESULT_VARIABLE res_var
|
||||||
OUTPUT_VARIABLE GIT_COM_DATE
|
OUTPUT_VARIABLE GIT_COM_DATE
|
||||||
)
|
)
|
||||||
if(NOT ${res_var} EQUAL 0)
|
if(NOT ${res_var} EQUAL 0)
|
||||||
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
|
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
string(REPLACE "\n" "" GIT_COM_DATE "${GIT_COM_DATE}")
|
string(REPLACE "\n" "" GIT_COM_DATE "${GIT_COM_DATE}")
|
||||||
set(GIT_COMMIT_DATE_FRIENDLY "${GIT_COM_DATE}" PARENT_SCOPE)
|
set(GIT_COMMIT_DATE_FRIENDLY
|
||||||
|
"${GIT_COM_DATE}"
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
|
||||||
string(REPLACE "-" "" GIT_COM_DATE "${GIT_COM_DATE}")
|
string(REPLACE "-" "" GIT_COM_DATE "${GIT_COM_DATE}")
|
||||||
set(GIT_COMMIT_DATE "${GIT_COM_DATE}" PARENT_SCOPE)
|
set(GIT_COMMIT_DATE
|
||||||
endfunction()
|
"${GIT_COM_DATE}"
|
||||||
|
PARENT_SCOPE
|
||||||
function(clean_release_name name)
|
)
|
||||||
# "name": "Cockatrice: Thopter Pie Network, Revision 2"
|
|
||||||
|
|
||||||
# Remove all double quotes
|
|
||||||
STRING(REPLACE "\"" "" name "${name}")
|
|
||||||
# Remove json prefix "name: "
|
|
||||||
STRING(REPLACE " name: " "" name "${name}")
|
|
||||||
# Remove "cockatrice" name
|
|
||||||
STRING(REPLACE "Cockatrice" "" name "${name}")
|
|
||||||
# Remove all unwanted chars
|
|
||||||
STRING(REGEX REPLACE "[^A-Za-z0-9_ ]" "" name "${name}")
|
|
||||||
# Strip (trim) whitespaces
|
|
||||||
STRING(STRIP "${name}" name)
|
|
||||||
# Replace all spaces with underscores
|
|
||||||
STRING(REPLACE " " "_" name "${name}")
|
|
||||||
|
|
||||||
set(GIT_TAG_RELEASENAME "${name}" PARENT_SCOPE)
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(get_tag_name commit)
|
function(get_tag_name commit)
|
||||||
if(${commit} STREQUAL "unknown")
|
if(${commit} STREQUAL "unknown")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT_EXECUTABLE} describe --exact-match --tags ${commit}
|
COMMAND ${GIT_EXECUTABLE} describe --exact-match --tags ${commit}
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
RESULT_VARIABLE res_var
|
RESULT_VARIABLE res_var
|
||||||
OUTPUT_VARIABLE GIT_TAG
|
OUTPUT_VARIABLE GIT_TAG
|
||||||
ERROR_VARIABLE GIT_TAG_ERR
|
ERROR_VARIABLE GIT_TAG_ERR
|
||||||
)
|
)
|
||||||
|
|
||||||
if((NOT ${res_var} EQUAL 0) OR (${GIT_TAG_ERR} MATCHES "fatal: no tag exactly matches.*"))
|
if((NOT ${res_var} EQUAL 0) OR (${GIT_TAG_ERR} MATCHES "fatal: no tag exactly matches.*"))
|
||||||
message(STATUS "Commit is not a release or prerelease (no git tag found)")
|
message(STATUS "Commit is not a release or prerelease (no git tag found)")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
string(REPLACE "\n" "" GIT_TAG "${GIT_TAG}")
|
string(REPLACE "\n" "" GIT_TAG "${GIT_TAG}")
|
||||||
message(STATUS "Commit is a release or prerelease, git tag: ${GIT_TAG}")
|
message(STATUS "Commit is a release or prerelease, git tag: ${GIT_TAG}")
|
||||||
|
|
||||||
# Extract information from tag:
|
# Extract information from tag:
|
||||||
# YYYY-MM-DD-Release-MAJ.MIN.PATCH
|
# YYYY-MM-DD-Release-MAJ.MIN.PATCH
|
||||||
# YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X
|
# YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X
|
||||||
string(REPLACE "-" ";" GIT_TAG_EXPLODED "${GIT_TAG}")
|
string(REPLACE "-" ";" GIT_TAG_EXPLODED "${GIT_TAG}")
|
||||||
string(REPLACE "." ";" GIT_TAG_EXPLODED "${GIT_TAG_EXPLODED}")
|
string(REPLACE "." ";" GIT_TAG_EXPLODED "${GIT_TAG_EXPLODED}")
|
||||||
|
|
||||||
# Sanity checks: length
|
# Sanity checks: length
|
||||||
list(LENGTH GIT_TAG_EXPLODED GIT_TAG_LISTCOUNT)
|
list(LENGTH GIT_TAG_EXPLODED GIT_TAG_LISTCOUNT)
|
||||||
if(${GIT_TAG_LISTCOUNT} LESS 7 OR ${GIT_TAG_LISTCOUNT} GREATER 9)
|
if(${GIT_TAG_LISTCOUNT} LESS 7 OR ${GIT_TAG_LISTCOUNT} GREATER 9)
|
||||||
message(WARNING "Invalid tag format, got ${GIT_TAG_LISTCOUNT} tokens")
|
message(WARNING "Invalid tag format, got ${GIT_TAG_LISTCOUNT} tokens")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Year
|
# Year
|
||||||
list(GET GIT_TAG_EXPLODED 0 GIT_TAG_YEAR)
|
list(GET GIT_TAG_EXPLODED 0 GIT_TAG_YEAR)
|
||||||
if(${GIT_TAG_YEAR} LESS 2017 OR ${GIT_TAG_LISTCOUNT} GREATER 2100)
|
if(${GIT_TAG_YEAR} LESS 2017 OR ${GIT_TAG_LISTCOUNT} GREATER 2100)
|
||||||
message(WARNING "Invalid tag year ${GIT_TAG_YEAR}")
|
message(WARNING "Invalid tag year ${GIT_TAG_YEAR}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Month
|
# Month
|
||||||
list(GET GIT_TAG_EXPLODED 1 GIT_TAG_MONTH)
|
list(GET GIT_TAG_EXPLODED 1 GIT_TAG_MONTH)
|
||||||
if(${GIT_TAG_MONTH} LESS 1 OR ${GIT_TAG_MONTH} GREATER 12)
|
if(${GIT_TAG_MONTH} LESS 1 OR ${GIT_TAG_MONTH} GREATER 12)
|
||||||
message(WARNING "Invalid tag month ${GIT_TAG_MONTH}")
|
message(WARNING "Invalid tag month ${GIT_TAG_MONTH}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Day
|
# Day
|
||||||
list(GET GIT_TAG_EXPLODED 2 GIT_TAG_DAY)
|
list(GET GIT_TAG_EXPLODED 2 GIT_TAG_DAY)
|
||||||
if(${GIT_TAG_DAY} LESS 1 OR ${GIT_TAG_DAY} GREATER 31)
|
if(${GIT_TAG_DAY} LESS 1 OR ${GIT_TAG_DAY} GREATER 31)
|
||||||
message(WARNING "Invalid tag day ${GIT_TAG_DAY}")
|
message(WARNING "Invalid tag day ${GIT_TAG_DAY}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Type
|
# Type
|
||||||
list(GET GIT_TAG_EXPLODED 3 GIT_TAG_TYPE)
|
list(GET GIT_TAG_EXPLODED 3 GIT_TAG_TYPE)
|
||||||
if(NOT(${GIT_TAG_TYPE} STREQUAL "Release" OR ${GIT_TAG_TYPE} STREQUAL "Development"))
|
if(NOT (${GIT_TAG_TYPE} STREQUAL "Release" OR ${GIT_TAG_TYPE} STREQUAL "Development"))
|
||||||
message(WARNING "Invalid tag type ${GIT_TAG_TYPE}")
|
message(WARNING "Invalid tag type ${GIT_TAG_TYPE}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Major
|
# Major
|
||||||
list(GET GIT_TAG_EXPLODED 4 GIT_TAG_MAJOR)
|
list(GET GIT_TAG_EXPLODED 4 GIT_TAG_MAJOR)
|
||||||
if(${GIT_TAG_MAJOR} LESS 0 OR ${GIT_TAG_MAJOR} GREATER 99)
|
if(${GIT_TAG_MAJOR} LESS 0 OR ${GIT_TAG_MAJOR} GREATER 99)
|
||||||
message(WARNING "Invalid tag major version ${GIT_TAG_MAJOR}")
|
message(WARNING "Invalid tag major version ${GIT_TAG_MAJOR}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Minor
|
# Minor
|
||||||
list(GET GIT_TAG_EXPLODED 5 GIT_TAG_MINOR)
|
list(GET GIT_TAG_EXPLODED 5 GIT_TAG_MINOR)
|
||||||
if(${GIT_TAG_MINOR} LESS 0 OR ${GIT_TAG_MINOR} GREATER 99)
|
if(${GIT_TAG_MINOR} LESS 0 OR ${GIT_TAG_MINOR} GREATER 99)
|
||||||
message(WARNING "Invalid tag minor version ${GIT_TAG_MINOR}")
|
message(WARNING "Invalid tag minor version ${GIT_TAG_MINOR}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Patch
|
# Patch
|
||||||
list(GET GIT_TAG_EXPLODED 6 GIT_TAG_PATCH)
|
list(GET GIT_TAG_EXPLODED 6 GIT_TAG_PATCH)
|
||||||
if(${GIT_TAG_PATCH} LESS 0 OR ${GIT_TAG_PATCH} GREATER 99)
|
if(${GIT_TAG_PATCH} LESS 0 OR ${GIT_TAG_PATCH} GREATER 99)
|
||||||
message(WARNING "Invalid tag patch version ${GIT_TAG_PATCH}")
|
message(WARNING "Invalid tag patch version ${GIT_TAG_PATCH}")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Label
|
# Label
|
||||||
# 7 = Stable release
|
# 7 = Stable release
|
||||||
# 8 = Dev release, first beta so only "beta" attached
|
# 8 = Dev release, first beta so only "beta" attached
|
||||||
# 9 = Dev release, subsequent beta so "beta.N" attached (N>=2)
|
# 9 = Dev release, subsequent beta so "beta.N" attached (N>=2)
|
||||||
if(${GIT_TAG_LISTCOUNT} EQUAL 8)
|
if(${GIT_TAG_LISTCOUNT} EQUAL 8)
|
||||||
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
|
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
|
||||||
elseif(${GIT_TAG_LISTCOUNT} EQUAL 9)
|
elseif(${GIT_TAG_LISTCOUNT} EQUAL 9)
|
||||||
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
|
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
|
||||||
list(GET GIT_TAG_EXPLODED 8 GIT_TAG_LABEL_NUM)
|
list(GET GIT_TAG_EXPLODED 8 GIT_TAG_LABEL_NUM)
|
||||||
set(GIT_TAG_LABEL ${GIT_TAG_LABEL} ${GIT_TAG_LABEL_NUM})
|
set(GIT_TAG_LABEL ${GIT_TAG_LABEL} ${GIT_TAG_LABEL_NUM})
|
||||||
string(REPLACE ";" "." GIT_TAG_LABEL "${GIT_TAG_LABEL}")
|
string(REPLACE ";" "." GIT_TAG_LABEL "${GIT_TAG_LABEL}")
|
||||||
else()
|
else()
|
||||||
SET(GIT_TAG_LABEL "")
|
set(GIT_TAG_LABEL "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Override hardcoded version with the informations from the tag
|
# Override hardcoded version with the informations from the tag
|
||||||
set(PROJECT_VERSION_MAJOR ${GIT_TAG_MAJOR} PARENT_SCOPE)
|
set(PROJECT_VERSION_MAJOR
|
||||||
set(PROJECT_VERSION_MINOR ${GIT_TAG_MINOR} PARENT_SCOPE)
|
${GIT_TAG_MAJOR}
|
||||||
set(PROJECT_VERSION_PATCH ${GIT_TAG_PATCH} PARENT_SCOPE)
|
PARENT_SCOPE
|
||||||
set(PROJECT_VERSION_LABEL ${GIT_TAG_LABEL} PARENT_SCOPE)
|
)
|
||||||
|
set(PROJECT_VERSION_MINOR
|
||||||
|
${GIT_TAG_MINOR}
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
set(PROJECT_VERSION_PATCH
|
||||||
|
${GIT_TAG_PATCH}
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
set(PROJECT_VERSION_LABEL
|
||||||
|
${GIT_TAG_LABEL}
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
|
||||||
if(${GIT_TAG_TYPE} STREQUAL "Development")
|
if(${GIT_TAG_TYPE} STREQUAL "Development")
|
||||||
set(PROJECT_VERSION_LABEL ${GIT_TAG_LABEL} PARENT_SCOPE)
|
set(PROJECT_VERSION_LABEL
|
||||||
elseif(${GIT_TAG_TYPE} STREQUAL "Release")
|
${GIT_TAG_LABEL}
|
||||||
set(PROJECT_VERSION_LABEL "" PARENT_SCOPE)
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
# get version name from github
|
elseif(${GIT_TAG_TYPE} STREQUAL "Release")
|
||||||
set(GIT_TAG_TEMP_FILE "${PROJECT_BINARY_DIR}/tag_informations.txt")
|
set(PROJECT_VERSION_LABEL
|
||||||
set(GIT_TAG_TEMP_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/tags/${GIT_TAG}")
|
""
|
||||||
message(STATUS "Fetching tag informations from ${GIT_TAG_TEMP_URL}")
|
PARENT_SCOPE
|
||||||
file(REMOVE "${GIT_TAG_TEMP_FILE}")
|
)
|
||||||
file(DOWNLOAD "${GIT_TAG_TEMP_URL}" "${GIT_TAG_TEMP_FILE}" STATUS status LOG log INACTIVITY_TIMEOUT 30 TIMEOUT 300 SHOW_PROGRESS)
|
# set release name from env var
|
||||||
list(GET status 0 err)
|
set(PROJECT_VERSION_RELEASENAME
|
||||||
list(GET status 1 msg)
|
"${GIT_TAG_RELEASENAME}"
|
||||||
if(err)
|
PARENT_SCOPE
|
||||||
message(WARNING "Download failed with error ${msg}: ${log}")
|
)
|
||||||
return()
|
endif()
|
||||||
endif()
|
|
||||||
file(STRINGS "${GIT_TAG_TEMP_FILE}" GIT_TAG_RAW_RELEASENAME REGEX "\"name\": \"" LIMIT_COUNT 1)
|
|
||||||
|
|
||||||
clean_release_name("${GIT_TAG_RAW_RELEASENAME}")
|
|
||||||
set(PROJECT_VERSION_RELEASENAME "${GIT_TAG_RELEASENAME}" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@@ -190,23 +189,23 @@ endfunction()
|
|||||||
|
|
||||||
# fallback defaults
|
# fallback defaults
|
||||||
set(GIT_COMMIT_ID "unknown")
|
set(GIT_COMMIT_ID "unknown")
|
||||||
set(GIT_COMMIT_DATE "unknown")
|
set(GIT_COMMIT_DATE "")
|
||||||
set(GIT_COMMIT_DATE_FRIENDLY "unknown")
|
set(GIT_COMMIT_DATE_FRIENDLY "")
|
||||||
set(PROJECT_VERSION_LABEL "custom(unknown)")
|
set(PROJECT_VERSION_LABEL "")
|
||||||
set(PROJECT_VERSION_RELEASENAME "")
|
set(PROJECT_VERSION_RELEASENAME "")
|
||||||
|
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
if(GIT_FOUND)
|
if(GIT_FOUND)
|
||||||
get_commit_id()
|
get_commit_id()
|
||||||
get_commit_date()
|
get_commit_date()
|
||||||
get_tag_name(${GIT_COMMIT_ID})
|
get_tag_name(${GIT_COMMIT_ID})
|
||||||
else()
|
else()
|
||||||
message( WARNING "Git not found. Build will not contain git revision info." )
|
message(WARNING "Git not found. Build will not contain git revision info.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
if(PROJECT_VERSION_LABEL)
|
if(PROJECT_VERSION_LABEL)
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_LABEL}")
|
set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_LABEL}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
|
set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
|
||||||
@@ -214,7 +213,7 @@ set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
|
|||||||
# Format: <program name>[-ReleaseName]-MAJ.MIN.PATCH[-prerelease_label]
|
# Format: <program name>[-ReleaseName]-MAJ.MIN.PATCH[-prerelease_label]
|
||||||
set(PROJECT_VERSION_FILENAME "${PROJECT_NAME}")
|
set(PROJECT_VERSION_FILENAME "${PROJECT_NAME}")
|
||||||
if(PROJECT_VERSION_RELEASENAME)
|
if(PROJECT_VERSION_RELEASENAME)
|
||||||
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME}")
|
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME}")
|
||||||
endif()
|
endif()
|
||||||
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION}")
|
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION}")
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ project(gtest-download LANGUAGES NONE)
|
|||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(googletest
|
ExternalProject_Add(googletest
|
||||||
URL https://github.com/google/googletest/archive/release-1.7.0.zip
|
URL https://github.com/google/googletest/archive/release-1.11.0.zip
|
||||||
URL_HASH SHA1=f89bc9f55477df2fde082481e2d709bfafdb057b
|
URL_HASH SHA1=9ffb7b5923f4a8fcdabf2f42c6540cce299f44c0
|
||||||
SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest-src"
|
SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest-src"
|
||||||
BINARY_DIR "${CMAKE_BINARY_DIR}/gtest-build"
|
BINARY_DIR "${CMAKE_BINARY_DIR}/gtest-build"
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
|
|||||||
@@ -2,283 +2,393 @@
|
|||||||
#
|
#
|
||||||
# provides the cockatrice binary
|
# provides the cockatrice binary
|
||||||
|
|
||||||
PROJECT(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
|
|
||||||
SET(cockatrice_SOURCES
|
set(cockatrice_SOURCES
|
||||||
|
src/abstractcarddragitem.cpp
|
||||||
|
src/abstractcarditem.cpp
|
||||||
|
src/abstractclient.cpp
|
||||||
src/abstractcounter.cpp
|
src/abstractcounter.cpp
|
||||||
|
src/abstractgraphicsitem.cpp
|
||||||
|
src/arrowitem.cpp
|
||||||
|
src/arrowtarget.cpp
|
||||||
|
src/carddatabase.cpp
|
||||||
|
src/carddatabasemodel.cpp
|
||||||
|
src/carddbparser/carddatabaseparser.cpp
|
||||||
|
src/carddbparser/cockatricexml3.cpp
|
||||||
|
src/carddbparser/cockatricexml4.cpp
|
||||||
|
src/carddragitem.cpp
|
||||||
|
src/cardfilter.cpp
|
||||||
|
src/cardframe.cpp
|
||||||
|
src/cardinfopicture.cpp
|
||||||
|
src/cardinfotext.cpp
|
||||||
|
src/cardinfowidget.cpp
|
||||||
|
src/carditem.cpp
|
||||||
|
src/cardlist.cpp
|
||||||
|
src/cardzone.cpp
|
||||||
|
src/chatview/chatview.cpp
|
||||||
src/counter_general.cpp
|
src/counter_general.cpp
|
||||||
src/dlg_creategame.cpp
|
src/customlineedit.cpp
|
||||||
src/dlg_filter_games.cpp
|
src/deck_loader.cpp
|
||||||
|
src/decklistmodel.cpp
|
||||||
|
src/deckstats_interface.cpp
|
||||||
|
src/deckview.cpp
|
||||||
src/dlg_connect.cpp
|
src/dlg_connect.cpp
|
||||||
src/dlg_create_token.cpp
|
src/dlg_create_token.cpp
|
||||||
|
src/dlg_creategame.cpp
|
||||||
src/dlg_edit_avatar.cpp
|
src/dlg_edit_avatar.cpp
|
||||||
src/dlg_edit_password.cpp
|
src/dlg_edit_password.cpp
|
||||||
src/dlg_edit_tokens.cpp
|
src/dlg_edit_tokens.cpp
|
||||||
src/dlg_edit_user.cpp
|
src/dlg_edit_user.cpp
|
||||||
|
src/dlg_filter_games.cpp
|
||||||
|
src/dlg_forgotpasswordchallenge.cpp
|
||||||
src/dlg_forgotpasswordrequest.cpp
|
src/dlg_forgotpasswordrequest.cpp
|
||||||
src/dlg_forgotpasswordreset.cpp
|
src/dlg_forgotpasswordreset.cpp
|
||||||
src/dlg_forgotpasswordchallenge.cpp
|
|
||||||
src/dlg_register.cpp
|
|
||||||
src/dlg_tip_of_the_day.cpp
|
|
||||||
src/tip_of_the_day.cpp
|
|
||||||
src/dlg_update.cpp
|
|
||||||
src/dlg_viewlog.cpp
|
|
||||||
src/abstractclient.cpp
|
|
||||||
src/remoteclient.cpp
|
|
||||||
src/main.cpp
|
|
||||||
src/window_main.cpp
|
|
||||||
src/gamesmodel.cpp
|
|
||||||
src/player.cpp
|
|
||||||
src/playertarget.cpp
|
|
||||||
src/cardzone.cpp
|
|
||||||
src/selectzone.cpp
|
|
||||||
src/cardlist.cpp
|
|
||||||
src/abstractcarditem.cpp
|
|
||||||
src/carditem.cpp
|
|
||||||
src/tablezone.cpp
|
|
||||||
src/handzone.cpp
|
|
||||||
src/handcounter.cpp
|
|
||||||
src/carddatabase.cpp
|
|
||||||
src/keysignals.cpp
|
|
||||||
src/gameview.cpp
|
|
||||||
src/gameselector.cpp
|
|
||||||
src/decklistmodel.cpp
|
|
||||||
src/deck_loader.cpp
|
|
||||||
src/dlg_load_deck_from_clipboard.cpp
|
src/dlg_load_deck_from_clipboard.cpp
|
||||||
src/dlg_load_remote_deck.cpp
|
src/dlg_load_remote_deck.cpp
|
||||||
src/cardinfowidget.cpp
|
src/dlg_manage_sets.cpp
|
||||||
src/cardframe.cpp
|
src/dlg_register.cpp
|
||||||
src/cardinfopicture.cpp
|
|
||||||
src/cardinfotext.cpp
|
|
||||||
src/filterbuilder.cpp
|
|
||||||
src/cardfilter.cpp
|
|
||||||
src/filtertreemodel.cpp
|
|
||||||
src/filtertree.cpp
|
|
||||||
src/messagelogwidget.cpp
|
|
||||||
src/zoneviewzone.cpp
|
|
||||||
src/zoneviewwidget.cpp
|
|
||||||
src/pilezone.cpp
|
|
||||||
src/stackzone.cpp
|
|
||||||
src/carddragitem.cpp
|
|
||||||
src/carddatabasemodel.cpp
|
|
||||||
src/setsmodel.cpp
|
|
||||||
src/window_sets.cpp
|
|
||||||
src/abstractgraphicsitem.cpp
|
|
||||||
src/abstractcarddragitem.cpp
|
|
||||||
src/dlg_settings.cpp
|
src/dlg_settings.cpp
|
||||||
src/phasestoolbar.cpp
|
src/dlg_tip_of_the_day.cpp
|
||||||
|
src/dlg_update.cpp
|
||||||
|
src/dlg_viewlog.cpp
|
||||||
|
src/filter_string.cpp
|
||||||
|
src/filterbuilder.cpp
|
||||||
|
src/filtertree.cpp
|
||||||
|
src/filtertreemodel.cpp
|
||||||
src/gamescene.cpp
|
src/gamescene.cpp
|
||||||
src/arrowitem.cpp
|
src/gameselector.cpp
|
||||||
src/arrowtarget.cpp
|
src/gamesmodel.cpp
|
||||||
src/tab.cpp
|
src/gameview.cpp
|
||||||
src/tab_server.cpp
|
src/gettextwithmax.cpp
|
||||||
src/tab_room.cpp
|
src/handcounter.cpp
|
||||||
src/tab_message.cpp
|
src/handle_public_servers.cpp
|
||||||
src/tab_game.cpp
|
src/handzone.cpp
|
||||||
src/tab_deck_storage.cpp
|
src/keysignals.cpp
|
||||||
src/tab_replays.cpp
|
src/lineeditcompleter.cpp
|
||||||
src/tab_supervisor.cpp
|
src/localclient.cpp
|
||||||
src/tab_admin.cpp
|
|
||||||
src/tab_userlists.cpp
|
|
||||||
src/tab_deck_editor.cpp
|
|
||||||
src/tab_logs.cpp
|
|
||||||
src/replay_timeline_widget.cpp
|
|
||||||
src/deckstats_interface.cpp
|
|
||||||
src/tappedout_interface.cpp
|
|
||||||
src/chatview/chatview.cpp
|
|
||||||
src/chatview/userlistProxy.h
|
|
||||||
src/userlist.cpp
|
|
||||||
src/userinfobox.cpp
|
|
||||||
src/user_context_menu.cpp
|
|
||||||
src/remotedecklist_treewidget.cpp
|
|
||||||
src/remotereplaylist_treewidget.cpp
|
|
||||||
src/deckview.cpp
|
|
||||||
src/playerlistwidget.cpp
|
|
||||||
src/pixmapgenerator.cpp
|
|
||||||
src/settingscache.cpp
|
|
||||||
src/thememanager.cpp
|
|
||||||
src/localserver.cpp
|
src/localserver.cpp
|
||||||
src/localserverinterface.cpp
|
src/localserverinterface.cpp
|
||||||
src/localclient.cpp
|
src/logger.cpp
|
||||||
src/soundengine.cpp
|
src/main.cpp
|
||||||
|
src/messagelogwidget.cpp
|
||||||
src/pending_command.cpp
|
src/pending_command.cpp
|
||||||
|
src/phase.cpp
|
||||||
|
src/phasestoolbar.cpp
|
||||||
src/pictureloader.cpp
|
src/pictureloader.cpp
|
||||||
src/shortcutssettings.cpp
|
src/pilezone.cpp
|
||||||
|
src/pixmapgenerator.cpp
|
||||||
|
src/player.cpp
|
||||||
|
src/playerlistwidget.cpp
|
||||||
|
src/playertarget.cpp
|
||||||
|
src/releasechannel.cpp
|
||||||
|
src/remoteclient.cpp
|
||||||
|
src/remotedecklist_treewidget.cpp
|
||||||
|
src/remotereplaylist_treewidget.cpp
|
||||||
|
src/replay_timeline_widget.cpp
|
||||||
|
src/selectzone.cpp
|
||||||
src/sequenceEdit/sequenceedit.cpp
|
src/sequenceEdit/sequenceedit.cpp
|
||||||
src/sequenceEdit/shortcutstab.cpp
|
src/setsmodel.cpp
|
||||||
src/lineeditcompleter.cpp
|
|
||||||
src/settings/settingsmanager.cpp
|
|
||||||
src/settings/carddatabasesettings.cpp
|
src/settings/carddatabasesettings.cpp
|
||||||
src/settings/serverssettings.cpp
|
src/settings/downloadsettings.cpp
|
||||||
src/settings/messagesettings.cpp
|
|
||||||
src/settings/gamefilterssettings.cpp
|
src/settings/gamefilterssettings.cpp
|
||||||
src/settings/layoutssettings.cpp
|
src/settings/layoutssettings.cpp
|
||||||
src/settings/downloadsettings.cpp
|
src/settings/messagesettings.cpp
|
||||||
src/update_downloader.cpp
|
src/settings/serverssettings.cpp
|
||||||
src/logger.cpp
|
src/settings/settingsmanager.cpp
|
||||||
src/releasechannel.cpp
|
src/settingscache.cpp
|
||||||
src/userconnection_information.cpp
|
src/shortcutssettings.cpp
|
||||||
|
src/soundengine.cpp
|
||||||
src/spoilerbackgroundupdater.cpp
|
src/spoilerbackgroundupdater.cpp
|
||||||
src/handle_public_servers.cpp
|
src/stackzone.cpp
|
||||||
src/carddbparser/carddatabaseparser.cpp
|
src/tab.cpp
|
||||||
src/carddbparser/cockatricexml3.cpp
|
src/tab_account.cpp
|
||||||
src/carddbparser/cockatricexml4.cpp
|
src/tab_admin.cpp
|
||||||
src/filter_string.cpp
|
src/tab_deck_editor.cpp
|
||||||
|
src/tab_deck_storage.cpp
|
||||||
|
src/tab_game.cpp
|
||||||
|
src/tab_logs.cpp
|
||||||
|
src/tab_message.cpp
|
||||||
|
src/tab_replays.cpp
|
||||||
|
src/tab_room.cpp
|
||||||
|
src/tab_server.cpp
|
||||||
|
src/tab_supervisor.cpp
|
||||||
|
src/tablezone.cpp
|
||||||
|
src/tappedout_interface.cpp
|
||||||
|
src/thememanager.cpp
|
||||||
|
src/tip_of_the_day.cpp
|
||||||
|
src/translatecountername.cpp
|
||||||
|
src/update_downloader.cpp
|
||||||
|
src/user_context_menu.cpp
|
||||||
|
src/userconnection_information.cpp
|
||||||
|
src/userinfobox.cpp
|
||||||
|
src/userlist.cpp
|
||||||
|
src/window_main.cpp
|
||||||
|
src/zoneviewwidget.cpp
|
||||||
|
src/zoneviewzone.cpp
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(sounds)
|
add_subdirectory(sounds)
|
||||||
add_subdirectory(themes)
|
add_subdirectory(themes)
|
||||||
|
|
||||||
set(cockatrice_RESOURCES cockatrice.qrc)
|
set(cockatrice_RESOURCES cockatrice.qrc)
|
||||||
|
|
||||||
IF(UPDATE_TRANSLATIONS)
|
if(UPDATE_TRANSLATIONS)
|
||||||
FILE(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/*.h)
|
file(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp
|
||||||
FILE(GLOB_RECURSE translate_common_SRCS ${CMAKE_SOURCE_DIR}/common/*.cpp ${CMAKE_SOURCE_DIR}/common/*.h)
|
${CMAKE_SOURCE_DIR}/cockatrice/src/*.h
|
||||||
SET(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
|
)
|
||||||
SET(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/cockatrice_en.ts")
|
file(GLOB_RECURSE translate_common_SRCS ${CMAKE_SOURCE_DIR}/common/*.cpp ${CMAKE_SOURCE_DIR}/common/*.h)
|
||||||
ELSE()
|
set(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
|
||||||
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
set(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts")
|
||||||
ENDIF(UPDATE_TRANSLATIONS)
|
else()
|
||||||
|
file(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||||
|
endif(UPDATE_TRANSLATIONS)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
|
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
||||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
set_source_files_properties(
|
||||||
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources
|
||||||
ENDIF(APPLE)
|
)
|
||||||
|
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||||
|
endif(APPLE)
|
||||||
|
|
||||||
# Qt5
|
if(Qt6_FOUND)
|
||||||
find_package(Qt5 COMPONENTS Concurrent Multimedia Network PrintSupport Svg WebSockets Widgets REQUIRED)
|
qt6_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||||
set(COCKATRICE_QT_MODULES Qt5::Concurrent Qt5::Multimedia Qt5::Network Qt5::PrintSupport Qt5::Svg Qt5::Widgets Qt5::WebSockets)
|
elseif(Qt5_FOUND)
|
||||||
|
qt5_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||||
# Qt5LinguistTools
|
|
||||||
find_package(Qt5LinguistTools)
|
|
||||||
if(Qt5LinguistTools_FOUND)
|
|
||||||
list(APPEND COCKATRICE_LIBS Qt5::LinguistTools)
|
|
||||||
|
|
||||||
if(NOT Qt5_LRELEASE_EXECUTABLE)
|
|
||||||
MESSAGE(WARNING "Qt's lrelease not found.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UPDATE_TRANSLATIONS)
|
|
||||||
if(NOT Qt5_LUPDATE_EXECUTABLE)
|
|
||||||
MESSAGE(WARNING "Qt's lupdate not found.")
|
|
||||||
endif()
|
|
||||||
QT5_CREATE_TRANSLATION(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
|
|
||||||
else()
|
|
||||||
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
QT5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
|
||||||
|
|
||||||
# Declare path variables
|
# Declare path variables
|
||||||
set(ICONDIR share/icons CACHE STRING "icon dir")
|
set(ICONDIR
|
||||||
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination")
|
share/icons
|
||||||
|
CACHE STRING "icon dir"
|
||||||
|
)
|
||||||
|
set(DESKTOPDIR
|
||||||
|
share/applications
|
||||||
|
CACHE STRING "desktop file destination"
|
||||||
|
)
|
||||||
|
|
||||||
# Include directories
|
# Include directories
|
||||||
INCLUDE_DIRECTORIES(../common)
|
include_directories(../common)
|
||||||
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
|
include_directories(${PROTOBUF_INCLUDE_DIR})
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
|
include_directories(${CMAKE_BINARY_DIR}/common)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# Build cockatrice binary and link it
|
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||||
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
|
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||||
|
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
|
if(Qt6_FOUND)
|
||||||
|
qt6_add_executable(
|
||||||
|
cockatrice
|
||||||
|
WIN32
|
||||||
|
MACOSX_BUNDLE
|
||||||
|
${cockatrice_SOURCES}
|
||||||
|
${cockatrice_RESOURCES_RCC}
|
||||||
|
${cockatrice_MOC_SRCS}
|
||||||
|
MANUAL_FINALIZATION
|
||||||
|
)
|
||||||
|
elseif(Qt5_FOUND)
|
||||||
|
# Qt5 Translations need to be linked at executable creation time
|
||||||
|
if(Qt5LinguistTools_FOUND)
|
||||||
|
if(UPDATE_TRANSLATIONS)
|
||||||
|
qt5_create_translation(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
|
||||||
|
else()
|
||||||
|
qt5_add_translation(cockatrice_QM ${cockatrice_TS})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
add_executable(
|
||||||
|
cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_MOC_SRCS} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC}
|
||||||
|
${cockatrice_SOURCES}
|
||||||
|
)
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_MAC_QM_INSTALL_DIR})
|
||||||
|
else()
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_UNIX_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt5_FOUND)
|
||||||
|
target_link_libraries(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
|
||||||
|
else()
|
||||||
|
target_link_libraries(cockatrice PUBLIC cockatrice_common ${COCKATRICE_QT_MODULES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}")
|
set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}")
|
||||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.cockatrice.${PROJECT_NAME}")
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.cockatrice.${PROJECT_NAME}")
|
||||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
|
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}")
|
set(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}")
|
||||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
|
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
|
||||||
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
|
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
|
||||||
|
|
||||||
set_target_properties(cockatrice PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
set_target_properties(cockatrice PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
||||||
|
|
||||||
INSTALL(TARGETS cockatrice BUNDLE DESTINATION ./)
|
install(TARGETS cockatrice BUNDLE DESTINATION ./)
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./cockatrice.app/Contents/Resources/translations)
|
else()
|
||||||
else()
|
# Assume linux
|
||||||
# Assume linux
|
install(TARGETS cockatrice RUNTIME DESTINATION bin/)
|
||||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION bin/)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
endif()
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION share/cockatrice/translations)
|
|
||||||
endif()
|
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
|
install(TARGETS cockatrice RUNTIME DESTINATION ./)
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
||||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
|
||||||
|
|
||||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(
|
||||||
FILES_MATCHING
|
DIRECTORY "${QT_PLUGINS_DIR}/"
|
||||||
PATTERN "*.dSYM" EXCLUDE
|
DESTINATION ${plugin_dest_dir}
|
||||||
PATTERN "*_debug.dylib" EXCLUDE
|
COMPONENT Runtime
|
||||||
PATTERN "audio/*.dylib"
|
FILES_MATCHING
|
||||||
PATTERN "iconengines/*.dylib"
|
PATTERN "*.dSYM" EXCLUDE
|
||||||
PATTERN "imageformats/*.dylib"
|
PATTERN "*_debug.dylib" EXCLUDE
|
||||||
PATTERN "platforms/*.dylib"
|
PATTERN "audio/*.dylib"
|
||||||
PATTERN "printsupport/*.dylib"
|
PATTERN "iconengines/*.dylib"
|
||||||
PATTERN "styles/*.dylib"
|
PATTERN "imageformats/*.dylib"
|
||||||
)
|
PATTERN "platforms/*.dylib"
|
||||||
|
PATTERN "printsupport/*.dylib"
|
||||||
|
PATTERN "styles/*.dylib"
|
||||||
|
PATTERN "tls/*.dylib"
|
||||||
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(
|
||||||
|
CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
Plugins = Plugins
|
Plugins = Plugins
|
||||||
Translations = Resources/translations
|
Translations = Resources/translations
|
||||||
Data = Resources\")
|
Data = Resources\")
|
||||||
" COMPONENT Runtime)
|
"
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(
|
||||||
|
CODE "
|
||||||
file(GLOB_RECURSE QTPLUGINS
|
file(GLOB_RECURSE QTPLUGINS
|
||||||
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dylib\")
|
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dylib\")
|
||||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||||
include(BundleUtilities)
|
include(BundleUtilities)
|
||||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
||||||
" COMPONENT Runtime)
|
"
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir Plugins)
|
set(plugin_dest_dir Plugins)
|
||||||
set(qtconf_dest_dir .)
|
set(qtconf_dest_dir .)
|
||||||
|
|
||||||
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
|
install(
|
||||||
|
DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/"
|
||||||
|
DESTINATION ./
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.dll"
|
||||||
|
)
|
||||||
|
|
||||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(
|
||||||
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport)/.*[^d]\\.dll")
|
DIRECTORY "${QT_PLUGINS_DIR}/"
|
||||||
|
DESTINATION ${plugin_dest_dir}
|
||||||
|
COMPONENT Runtime
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "audio/qtaudio_wasapi.dll"
|
||||||
|
PATTERN "audio/qtaudio_windows.dll"
|
||||||
|
PATTERN "iconengines/qsvgicon.dll"
|
||||||
|
PATTERN "imageformats/qgif.dll"
|
||||||
|
PATTERN "imageformats/qicns.dll"
|
||||||
|
PATTERN "imageformats/qico.dll"
|
||||||
|
PATTERN "imageformats/qjpeg.dll"
|
||||||
|
PATTERN "imageformats/qsvg.dll"
|
||||||
|
PATTERN "imageformats/qtga.dll"
|
||||||
|
PATTERN "imageformats/qtiff.dll"
|
||||||
|
PATTERN "imageformats/qwbmp.dll"
|
||||||
|
PATTERN "imageformats/qwebp.dll"
|
||||||
|
PATTERN "mediaservice/dsengine.dll"
|
||||||
|
PATTERN "mediaservice/wmfengine.dll"
|
||||||
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
|
PATTERN "platforms/qminimal.dll"
|
||||||
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
|
PATTERN "platforms/qwindows.dll"
|
||||||
|
PATTERN "printsupport/windowsprintersupport.dll"
|
||||||
|
PATTERN "styles/qcertonlybackend.dll"
|
||||||
|
PATTERN "styles/qopensslbackend.dll"
|
||||||
|
PATTERN "styles/qschannelbackend.dll"
|
||||||
|
PATTERN "styles/qwindowsvistastyle.dll"
|
||||||
|
PATTERN "tls/qcertonlybackend.dll"
|
||||||
|
PATTERN "tls/qopensslbackend.dll"
|
||||||
|
PATTERN "tls/qschannelbackend.dll"
|
||||||
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(
|
||||||
|
CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
Plugins = Plugins
|
Plugins = Plugins
|
||||||
Translations = Resources/translations
|
Translations = Resources/translations
|
||||||
Data = Resources\")
|
Data = Resources\")
|
||||||
" COMPONENT Runtime)
|
"
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(
|
||||||
|
CODE "
|
||||||
file(GLOB_RECURSE QTPLUGINS
|
file(GLOB_RECURSE QTPLUGINS
|
||||||
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
|
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
|
||||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||||
include(BundleUtilities)
|
include(BundleUtilities)
|
||||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/Cockatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/Cockatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
||||||
" COMPONENT Runtime)
|
"
|
||||||
|
COMPONENT Runtime
|
||||||
|
)
|
||||||
|
|
||||||
if(WIN32SSLRUNTIME_FOUND)
|
if(WIN32SSLRUNTIME_FOUND)
|
||||||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt6_FOUND AND Qt6LinguistTools_FOUND)
|
||||||
|
#Qt6 Translations happen after the executable is built up
|
||||||
|
if(UPDATE_TRANSLATIONS)
|
||||||
|
qt6_add_translations(
|
||||||
|
cockatrice
|
||||||
|
TS_FILES
|
||||||
|
${cockatrice_TS}
|
||||||
|
SOURCES
|
||||||
|
${translate_SRCS}
|
||||||
|
QM_FILES_OUTPUT_VARIABLE
|
||||||
|
cockatrice_QM
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
qt6_add_translations(cockatrice TS_FILES ${cockatrice_TS} QM_FILES_OUTPUT_VARIABLE cockatrice_QM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_MAC_QM_INSTALL_DIR})
|
||||||
|
else()
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_UNIX_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
qt6_finalize_target(cockatrice)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -126,6 +126,7 @@
|
|||||||
<file>resources/countries/er.svg</file>
|
<file>resources/countries/er.svg</file>
|
||||||
<file>resources/countries/es.svg</file>
|
<file>resources/countries/es.svg</file>
|
||||||
<file>resources/countries/et.svg</file>
|
<file>resources/countries/et.svg</file>
|
||||||
|
<file>resources/countries/eu.svg</file>
|
||||||
<file>resources/countries/fi.svg</file>
|
<file>resources/countries/fi.svg</file>
|
||||||
<file>resources/countries/fj.svg</file>
|
<file>resources/countries/fj.svg</file>
|
||||||
<file>resources/countries/fk.svg</file>
|
<file>resources/countries/fk.svg</file>
|
||||||
@@ -301,16 +302,13 @@
|
|||||||
<file>resources/countries/vu.svg</file>
|
<file>resources/countries/vu.svg</file>
|
||||||
<file>resources/countries/wf.svg</file>
|
<file>resources/countries/wf.svg</file>
|
||||||
<file>resources/countries/ws.svg</file>
|
<file>resources/countries/ws.svg</file>
|
||||||
|
<file>resources/countries/xk.svg</file>
|
||||||
<file>resources/countries/ye.svg</file>
|
<file>resources/countries/ye.svg</file>
|
||||||
<file>resources/countries/yt.svg</file>
|
<file>resources/countries/yt.svg</file>
|
||||||
<file>resources/countries/za.svg</file>
|
<file>resources/countries/za.svg</file>
|
||||||
<file>resources/countries/zm.svg</file>
|
<file>resources/countries/zm.svg</file>
|
||||||
<file>resources/countries/zw.svg</file>
|
<file>resources/countries/zw.svg</file>
|
||||||
|
|
||||||
<file>resources/genders/male.svg</file>
|
|
||||||
<file>resources/genders/female.svg</file>
|
|
||||||
<file>resources/genders/unknown.svg</file>
|
|
||||||
|
|
||||||
<file>resources/phases/untap.svg</file>
|
<file>resources/phases/untap.svg</file>
|
||||||
<file>resources/phases/upkeep.svg</file>
|
<file>resources/phases/upkeep.svg</file>
|
||||||
<file>resources/phases/draw.svg</file>
|
<file>resources/phases/draw.svg</file>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
92
cockatrice/resources/countries/xk.svg
Normal file
92
cockatrice/resources/countries/xk.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.3 KiB |
@@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<svg
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.0"
|
|
||||||
width="75"
|
|
||||||
height="75"
|
|
||||||
id="svg34864">
|
|
||||||
<defs
|
|
||||||
id="defs34866" />
|
|
||||||
<g
|
|
||||||
transform="translate(-348.7552,-478.0905)"
|
|
||||||
id="layer1">
|
|
||||||
<g
|
|
||||||
transform="matrix(1.071197,0,0,1.075147,-13.30677,-36.99488)"
|
|
||||||
id="g3773">
|
|
||||||
<path
|
|
||||||
d="M 176 33 A 11 11 0 1 1 154,33 A 11 11 0 1 1 176 33 z"
|
|
||||||
transform="matrix(1.540096,0,0,1.5384,118.8893,454.0543)"
|
|
||||||
style="color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
|
||||||
id="path3939" />
|
|
||||||
<path
|
|
||||||
d="M 373.00525,521.74399 L 373.00525,543.28159"
|
|
||||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4.61774349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path3941" />
|
|
||||||
<path
|
|
||||||
d="M 363.76467,534.05119 L 382.24582,534.05119"
|
|
||||||
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4.61774349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
id="path4816" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="75" height="75" id="svg34864">
|
|
||||||
<defs id="defs34866"/>
|
|
||||||
<g transform="translate(-348.755, -478.091)" id="layer1">
|
|
||||||
<g transform="matrix(1.94812, 0, 0, 1.93731, -342.43, -460.01)" id="g1872">
|
|
||||||
<path d="M 387.95009,489.60348 L 378.66214,498.89143" style="opacity: 1; color: black; fill: none; fill-opacity: 0.75; fill-rule: evenodd; stroke: black; stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; marker: none; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline; overflow: visible;" id="path26867"/>
|
|
||||||
<path d="M 49.396475 36.70454 A 15.623922 16.319134 0 1 1 18.14863,36.70454 A 15.623922 16.319134 0 1 1 49.396475 36.70454 z" transform="matrix(0.48802, 0.48802, -0.467594, 0.467594, 371.609, 473.136)" style="opacity: 1; color: black; fill: none; fill-opacity: 1; fill-rule: evenodd; stroke: black; stroke-width: 4.44072; stroke-linecap: butt; stroke-linejoin: miter; marker: none; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline; overflow: visible;" id="path26871"/>
|
|
||||||
<path d="M 379.92823,489.70212 C 387.842,489.70212 387.842,489.70212 387.842,489.70212 L 387.842,497.61589" style="fill: none; fill-rule: evenodd; stroke: black; stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-opacity: 1;" id="path27759"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Intersexual/Transgendered symbol by Gregory Maxwell. Copyright 2005. GFDL-1.2 only -->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
|
||||||
width="210"
|
|
||||||
height="280">
|
|
||||||
<path d="M 188,38 v 20 l 14,-8 v -42 h -42 l -8,14 h 20 l -37,37 a 79,79 0 1,0 -59,141 v 22 h -27 v 23 h 27 v 27 h 23 v -27 h 27 v -23 h -27 v -22 a 79,79 0 0,0 52,-125 zm -100,27 a 57,57 0 1,1 0,114 a 57,57 0 1,1 0,-114 z"/>
|
|
||||||
<!-- 88,65 // -63,-10 -->
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 500 B |
@@ -28,11 +28,12 @@ The search bar recognizes a set of special commands similar to some other card d
|
|||||||
<dd>[c=wubrg](#c%3Dwubrg) <small>(Cards that are all five colors)</small></dd>
|
<dd>[c=wubrg](#c%3Dwubrg) <small>(Cards that are all five colors)</small></dd>
|
||||||
-->
|
-->
|
||||||
<dd>[c:c](#c:c) <small>(Any colorless card)</small></dd>
|
<dd>[c:c](#c:c) <small>(Any colorless card)</small></dd>
|
||||||
|
<dd>[ci:w](#ci:w) <small>(Any card that has white in it's color identity)</small></dd>
|
||||||
|
|
||||||
<dt><u>Pow</u>er, <u>Tou</u>ghness, <u>C</u>onverted <u>M</u>ana <u>C</u>ost:</dt>
|
<dt><u>Pow</u>er, <u>Tou</u>ghness, <u>M</u>ana <u>V</u>alue:</dt>
|
||||||
<dd>[tou:1](#tou:1) <small>(Any card with a toughness of 1)</small></dd>
|
<dd>[tou:1](#tou:1) <small>(Any card with a toughness of 1)</small></dd>
|
||||||
<dd>[pow>=8](#pow>=8) <small>(Any card with a power greater than or equal to 8)</small></dd>
|
<dd>[pow>=8](#pow>=8) <small>(Any card with a power greater than or equal to 8)</small></dd>
|
||||||
<dd>[cmc=7](#cmc=7) <small>(Any card with a converted mana cost equal to 7)</small></dd>
|
<dd>[mv=7](#mv=7) <small>(Any card with a mana value equal to 7)</small></dd>
|
||||||
|
|
||||||
<dt><u>R</u>arity:</dt>
|
<dt><u>R</u>arity:</dt>
|
||||||
<dd>[r:mythic](#r:mythic) <small>(Any card that has the mythic-rare rarity)</small></dd>
|
<dd>[r:mythic](#r:mythic) <small>(Any card that has the mythic-rare rarity)</small></dd>
|
||||||
@@ -45,10 +46,9 @@ The search bar recognizes a set of special commands similar to some other card d
|
|||||||
|
|
||||||
<dt><u>E</u>dition:</dt>
|
<dt><u>E</u>dition:</dt>
|
||||||
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
||||||
<dd>[e:lea,leb](#e:lea,leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
<dd>[e:lea or e:leb](#e:lea or e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||||
<dd><a href="#e:lea,leb -(e:lea e:leb)">e:lea,leb -(e:lea e:leb)</a> <small>(Cards that appear in Alpha or Beta but not in both editions)</small></dd>
|
|
||||||
|
|
||||||
<dt>Inverse:</dt>
|
<dt>Negate:</dt>
|
||||||
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
||||||
|
|
||||||
<dt>Branching:</dt>
|
<dt>Branching:</dt>
|
||||||
|
|||||||
@@ -2,18 +2,15 @@
|
|||||||
#
|
#
|
||||||
# add sounds subfolders
|
# add sounds subfolders
|
||||||
|
|
||||||
SET(defsounds
|
set(defsounds Default Legacy)
|
||||||
Default
|
|
||||||
Legacy
|
|
||||||
)
|
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
INSTALL(DIRECTORY ${defsounds} DESTINATION Cockatrice.app/Contents/Resources/sounds/)
|
install(DIRECTORY ${defsounds} DESTINATION Cockatrice.app/Contents/Resources/sounds/)
|
||||||
else()
|
else()
|
||||||
# Assume linux
|
# Assume linux
|
||||||
INSTALL(DIRECTORY ${defsounds} DESTINATION share/cockatrice/sounds/)
|
install(DIRECTORY ${defsounds} DESTINATION share/cockatrice/sounds/)
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
INSTALL(DIRECTORY ${defsounds} DESTINATION sounds/)
|
install(DIRECTORY ${defsounds} DESTINATION sounds/)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "abstractcarddragitem.h"
|
#include "abstractcarddragitem.h"
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
@@ -39,7 +41,6 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||||||
|
|
||||||
AbstractCardDragItem::~AbstractCardDragItem()
|
AbstractCardDragItem::~AbstractCardDragItem()
|
||||||
{
|
{
|
||||||
qDebug("CardDragItem destructor");
|
|
||||||
for (int i = 0; i < childDrags.size(); i++)
|
for (int i = 0; i < childDrags.size(); i++)
|
||||||
delete childDrags[i];
|
delete childDrags[i];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
#include <QCursor>
|
|
||||||
#include <QGraphicsScene>
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cmath>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "round.h"
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
#include "abstractcarditem.h"
|
#include "abstractcarditem.h"
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "gamescene.h"
|
#include "gamescene.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "pictureloader.h"
|
#include "pictureloader.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
|
||||||
|
#include <QCursor>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, int _id, QGraphicsItem *parent)
|
AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, int _id, QGraphicsItem *parent)
|
||||||
: ArrowTarget(_owner, parent), id(_id), name(_name), tapped(false), facedown(false), tapAngle(0),
|
: ArrowTarget(_owner, parent), id(_id), name(_name), tapped(false), facedown(false), tapAngle(0),
|
||||||
bgColor(Qt::transparent), isHovered(false), realZValue(0)
|
bgColor(Qt::transparent), isHovered(false), realZValue(0)
|
||||||
@@ -22,7 +20,7 @@ AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, int _id
|
|||||||
setFlag(ItemIsSelectable);
|
setFlag(ItemIsSelectable);
|
||||||
setCacheMode(DeviceCoordinateCache);
|
setCacheMode(DeviceCoordinateCache);
|
||||||
|
|
||||||
connect(settingsCache, SIGNAL(displayCardNamesChanged()), this, SLOT(callUpdate()));
|
connect(&SettingsCache::instance(), SIGNAL(displayCardNamesChanged()), this, SLOT(callUpdate()));
|
||||||
cardInfoUpdated();
|
cardInfoUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,13 +44,15 @@ void AbstractCardItem::cardInfoUpdated()
|
|||||||
{
|
{
|
||||||
info = db->getCard(name);
|
info = db->getCard(name);
|
||||||
|
|
||||||
if (!info) {
|
if (!info && !name.isEmpty()) {
|
||||||
QVariantHash properties = QVariantHash();
|
QVariantHash properties = QVariantHash();
|
||||||
|
|
||||||
info = CardInfo::newInstance(name, "", true, QVariantHash(), QList<CardRelation *>(), QList<CardRelation *>(),
|
info = CardInfo::newInstance(name, "", true, QVariantHash(), QList<CardRelation *>(), QList<CardRelation *>(),
|
||||||
CardInfoPerSetMap(), false, -1, false);
|
CardInfoPerSetMap(), false, -1, false);
|
||||||
}
|
}
|
||||||
connect(info.data(), SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
|
if (info.data()) {
|
||||||
|
connect(info.data(), SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
|
||||||
|
}
|
||||||
|
|
||||||
cacheBgColor();
|
cacheBgColor();
|
||||||
update();
|
update();
|
||||||
@@ -72,7 +72,7 @@ QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const
|
|||||||
|
|
||||||
void AbstractCardItem::transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle)
|
void AbstractCardItem::transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle)
|
||||||
{
|
{
|
||||||
const int MAX_FONT_SIZE = settingsCache->getMaxFontSize();
|
const int MAX_FONT_SIZE = SettingsCache::instance().getMaxFontSize();
|
||||||
const int fontSize = std::max(9, MAX_FONT_SIZE);
|
const int fontSize = std::max(9, MAX_FONT_SIZE);
|
||||||
|
|
||||||
QRectF totalBoundingRect = painter->combinedTransform().mapRect(boundingRect());
|
QRectF totalBoundingRect = painter->combinedTransform().mapRect(boundingRect());
|
||||||
@@ -131,7 +131,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
|
|||||||
else
|
else
|
||||||
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 1.5));
|
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 1.5));
|
||||||
|
|
||||||
if (translatedPixmap.isNull() || settingsCache->getDisplayCardNames() || facedown) {
|
if (translatedPixmap.isNull() || SettingsCache::instance().getDisplayCardNames() || facedown) {
|
||||||
painter->save();
|
painter->save();
|
||||||
transformPainter(painter, translatedSize, angle);
|
transformPainter(painter, translatedSize, angle);
|
||||||
painter->setPen(Qt::white);
|
painter->setPen(Qt::white);
|
||||||
@@ -201,7 +201,7 @@ void AbstractCardItem::setHovered(bool _hovered)
|
|||||||
processHoverEvent();
|
processHoverEvent();
|
||||||
isHovered = _hovered;
|
isHovered = _hovered;
|
||||||
setZValue(_hovered ? 2000000004 : realZValue);
|
setZValue(_hovered ? 2000000004 : realZValue);
|
||||||
setScale(_hovered && settingsCache->getScaleCards() ? 1.1 : 1);
|
setScale(_hovered && SettingsCache::instance().getScaleCards() ? 1.1 : 1);
|
||||||
setTransformOriginPoint(_hovered ? CARD_WIDTH / 2 : 0, _hovered ? CARD_HEIGHT / 2 : 0);
|
setTransformOriginPoint(_hovered ? CARD_WIDTH / 2 : 0, _hovered ? CARD_HEIGHT / 2 : 0);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
tapped = _tapped;
|
tapped = _tapped;
|
||||||
if (settingsCache->getTapAnimation() && canAnimate)
|
if (SettingsCache::instance().getTapAnimation() && canAnimate)
|
||||||
static_cast<GameScene *>(scene())->registerAnimationItem(this);
|
static_cast<GameScene *>(scene())->registerAnimationItem(this);
|
||||||
else {
|
else {
|
||||||
tapAngle = tapped ? 90 : 0;
|
tapAngle = tapped ? 90 : 0;
|
||||||
@@ -270,7 +270,6 @@ void AbstractCardItem::setFaceDown(bool _facedown)
|
|||||||
{
|
{
|
||||||
facedown = _facedown;
|
facedown = _facedown;
|
||||||
update();
|
update();
|
||||||
emit updateCardMenu(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
@@ -285,14 +284,14 @@ void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
if (event->button() == Qt::LeftButton)
|
if (event->button() == Qt::LeftButton)
|
||||||
setCursor(Qt::ClosedHandCursor);
|
setCursor(Qt::ClosedHandCursor);
|
||||||
else if (event->button() == Qt::MidButton)
|
else if (event->button() == Qt::MiddleButton)
|
||||||
emit showCardInfoPopup(event->screenPos(), name);
|
emit showCardInfoPopup(event->screenPos(), name);
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::MidButton)
|
if (event->button() == Qt::MiddleButton)
|
||||||
emit deleteCardInfoPopup(name);
|
emit deleteCardInfoPopup(name);
|
||||||
|
|
||||||
// This function ensures the parent function doesn't mess around with our selection.
|
// This function ensures the parent function doesn't mess around with our selection.
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ signals:
|
|||||||
void hovered(AbstractCardItem *card);
|
void hovered(AbstractCardItem *card);
|
||||||
void showCardInfoPopup(QPoint pos, QString cardName);
|
void showCardInfoPopup(QPoint pos, QString cardName);
|
||||||
void deleteCardInfoPopup(QString cardName);
|
void deleteCardInfoPopup(QString cardName);
|
||||||
void updateCardMenu(AbstractCardItem *card);
|
|
||||||
void sigPixmapUpdated();
|
void sigPixmapUpdated();
|
||||||
void cardShiftClicked(QString cardName);
|
void cardShiftClicked(QString cardName);
|
||||||
|
|
||||||
@@ -49,7 +48,10 @@ public:
|
|||||||
{
|
{
|
||||||
return Type;
|
return Type;
|
||||||
}
|
}
|
||||||
AbstractCardItem(const QString &_name = QString(), Player *_owner = 0, int _id = -1, QGraphicsItem *parent = 0);
|
AbstractCardItem(const QString &_name = QString(),
|
||||||
|
Player *_owner = nullptr,
|
||||||
|
int _id = -1,
|
||||||
|
QGraphicsItem *parent = nullptr);
|
||||||
~AbstractCardItem();
|
~AbstractCardItem();
|
||||||
QRectF boundingRect() const;
|
QRectF boundingRect() const;
|
||||||
QSizeF getTranslatedSize(QPainter *painter) const;
|
QSizeF getTranslatedSize(QPainter *painter) const;
|
||||||
|
|||||||
@@ -19,9 +19,11 @@
|
|||||||
#include "pb/event_user_message.pb.h"
|
#include "pb/event_user_message.pb.h"
|
||||||
#include "pb/server_message.pb.h"
|
#include "pb/server_message.pb.h"
|
||||||
#include "pending_command.h"
|
#include "pending_command.h"
|
||||||
|
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
|
|
||||||
AbstractClient::AbstractClient(QObject *parent) : QObject(parent), nextCmdId(0), status(StatusDisconnected)
|
AbstractClient::AbstractClient(QObject *parent)
|
||||||
|
: QObject(parent), nextCmdId(0), status(StatusDisconnected), serverSupportsPasswordHash(false)
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QVariant>("QVariant");
|
qRegisterMetaType<QVariant>("QVariant");
|
||||||
qRegisterMetaType<CommandContainer>("CommandContainer");
|
qRegisterMetaType<CommandContainer>("CommandContainer");
|
||||||
@@ -46,6 +48,7 @@ AbstractClient::AbstractClient(QObject *parent) : QObject(parent), nextCmdId(0),
|
|||||||
qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
|
qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
|
||||||
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
||||||
qRegisterMetaType<QList<QString>>("missingFeatures");
|
qRegisterMetaType<QList<QString>>("missingFeatures");
|
||||||
|
qRegisterMetaType<PendingCommand *>("pendingCommand");
|
||||||
|
|
||||||
FeatureSet features;
|
FeatureSet features;
|
||||||
features.initalizeFeatureList(clientFeatures);
|
features.initalizeFeatureList(clientFeatures);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pb/serverinfo_user.pb.h"
|
#include "pb/serverinfo_user.pb.h"
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
@@ -39,6 +40,7 @@ enum ClientStatus
|
|||||||
StatusRequestingForgotPassword,
|
StatusRequestingForgotPassword,
|
||||||
StatusSubmitForgotPasswordReset,
|
StatusSubmitForgotPasswordReset,
|
||||||
StatusSubmitForgotPasswordChallenge,
|
StatusSubmitForgotPasswordChallenge,
|
||||||
|
StatusGettingPasswordSalt,
|
||||||
};
|
};
|
||||||
|
|
||||||
class AbstractClient : public QObject
|
class AbstractClient : public QObject
|
||||||
@@ -86,7 +88,7 @@ protected slots:
|
|||||||
protected:
|
protected:
|
||||||
QMap<int, PendingCommand *> pendingCommands;
|
QMap<int, PendingCommand *> pendingCommands;
|
||||||
QString userName, password, email, country, realName, token;
|
QString userName, password, email, country, realName, token;
|
||||||
int gender;
|
bool serverSupportsPasswordHash;
|
||||||
void setStatus(ClientStatus _status);
|
void setStatus(ClientStatus _status);
|
||||||
int getNewCmdId()
|
int getNewCmdId()
|
||||||
{
|
{
|
||||||
@@ -95,7 +97,7 @@ protected:
|
|||||||
virtual void sendCommandContainer(const CommandContainer &cont) = 0;
|
virtual void sendCommandContainer(const CommandContainer &cont) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractClient(QObject *parent = 0);
|
AbstractClient(QObject *parent = nullptr);
|
||||||
~AbstractClient();
|
~AbstractClient();
|
||||||
|
|
||||||
ClientStatus getStatus() const
|
ClientStatus getStatus() const
|
||||||
@@ -106,7 +108,11 @@ public:
|
|||||||
void sendCommand(const CommandContainer &cont);
|
void sendCommand(const CommandContainer &cont);
|
||||||
void sendCommand(PendingCommand *pend);
|
void sendCommand(PendingCommand *pend);
|
||||||
|
|
||||||
const QString getUserName()
|
bool getServerSupportsPasswordHash() const
|
||||||
|
{
|
||||||
|
return serverSupportsPasswordHash;
|
||||||
|
}
|
||||||
|
const QString &getUserName() const
|
||||||
{
|
{
|
||||||
return userName;
|
return userName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
#include "abstractcounter.h"
|
#include "abstractcounter.h"
|
||||||
|
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "pb/command_inc_counter.pb.h"
|
#include "pb/command_inc_counter.pb.h"
|
||||||
#include "pb/command_set_counter.pb.h"
|
#include "pb/command_set_counter.pb.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
#include "translatecountername.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGraphicsSceneHoverEvent>
|
#include <QGraphicsSceneHoverEvent>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QKeyEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
AbstractCounter::AbstractCounter(Player *_player,
|
AbstractCounter::AbstractCounter(Player *_player,
|
||||||
int _id,
|
int _id,
|
||||||
@@ -17,22 +22,24 @@ AbstractCounter::AbstractCounter(Player *_player,
|
|||||||
bool _shownInCounterArea,
|
bool _shownInCounterArea,
|
||||||
int _value,
|
int _value,
|
||||||
bool _useNameForShortcut,
|
bool _useNameForShortcut,
|
||||||
QGraphicsItem *parent)
|
QGraphicsItem *parent,
|
||||||
|
QWidget *_game)
|
||||||
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value),
|
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value),
|
||||||
useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false),
|
useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false),
|
||||||
deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
|
deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea), game(_game)
|
||||||
{
|
{
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
|
|
||||||
shortcutActive = false;
|
shortcutActive = false;
|
||||||
|
|
||||||
if (player->getLocalOrJudge()) {
|
if (player->getLocalOrJudge()) {
|
||||||
menu = new QMenu(name);
|
QString displayName = TranslateCounterName::getDisplayName(_name);
|
||||||
|
menu = new TearOffMenu(displayName);
|
||||||
aSet = new QAction(this);
|
aSet = new QAction(this);
|
||||||
connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
|
connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
|
||||||
menu->addAction(aSet);
|
menu->addAction(aSet);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
for (int i = 10; i >= -10; --i)
|
for (int i = 10; i >= -10; --i) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
} else {
|
} else {
|
||||||
@@ -45,10 +52,12 @@ AbstractCounter::AbstractCounter(Player *_player,
|
|||||||
connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter()));
|
connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter()));
|
||||||
menu->addAction(aIncrement);
|
menu->addAction(aIncrement);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
menu = nullptr;
|
menu = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
}
|
}
|
||||||
@@ -78,16 +87,17 @@ void AbstractCounter::setShortcutsActive()
|
|||||||
if (!player->getLocal()) {
|
if (!player->getLocal()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
|
||||||
if (name == "life") {
|
if (name == "life") {
|
||||||
shortcutActive = true;
|
shortcutActive = true;
|
||||||
aSet->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aSet"));
|
aSet->setShortcuts(shortcuts.getShortcut("Player/aSet"));
|
||||||
aDec->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aDec"));
|
aDec->setShortcuts(shortcuts.getShortcut("Player/aDec"));
|
||||||
aInc->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aInc"));
|
aInc->setShortcuts(shortcuts.getShortcut("Player/aInc"));
|
||||||
} else if (useNameForShortcut) {
|
} else if (useNameForShortcut) {
|
||||||
shortcutActive = true;
|
shortcutActive = true;
|
||||||
aSet->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aSetCounter_" + name));
|
aSet->setShortcuts(shortcuts.getShortcut("Player/aSetCounter_" + name));
|
||||||
aDec->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aDecCounter_" + name));
|
aDec->setShortcuts(shortcuts.getShortcut("Player/aDecCounter_" + name));
|
||||||
aInc->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aIncCounter_" + name));
|
aInc->setShortcuts(shortcuts.getShortcut("Player/aIncCounter_" + name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +113,9 @@ void AbstractCounter::setShortcutsInactive()
|
|||||||
|
|
||||||
void AbstractCounter::refreshShortcuts()
|
void AbstractCounter::refreshShortcuts()
|
||||||
{
|
{
|
||||||
if (shortcutActive)
|
if (shortcutActive) {
|
||||||
setShortcutsActive();
|
setShortcutsActive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCounter::setValue(int _value)
|
void AbstractCounter::setValue(int _value)
|
||||||
@@ -116,7 +127,7 @@ void AbstractCounter::setValue(int _value)
|
|||||||
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (isUnderMouse() && player->getLocalOrJudge()) {
|
if (isUnderMouse() && player->getLocalOrJudge()) {
|
||||||
if (event->button() == Qt::MidButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
|
if (event->button() == Qt::MiddleButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
|
||||||
if (menu)
|
if (menu)
|
||||||
menu->exec(event->screenPos());
|
menu->exec(event->screenPos());
|
||||||
event->accept();
|
event->accept();
|
||||||
@@ -160,24 +171,60 @@ void AbstractCounter::incrementCounter()
|
|||||||
|
|
||||||
void AbstractCounter::setCounter()
|
void AbstractCounter::setCounter()
|
||||||
{
|
{
|
||||||
bool ok;
|
|
||||||
dialogSemaphore = true;
|
dialogSemaphore = true;
|
||||||
QString expression = QInputDialog::getText(nullptr, tr("Set counter"), tr("New value for counter '%1':").arg(name),
|
AbstractCounterDialog dialog(name, QString::number(value), game);
|
||||||
QLineEdit::Normal, QString::number(value), &ok);
|
const int ok = dialog.exec();
|
||||||
|
|
||||||
Expression exp(value);
|
|
||||||
int newValue = static_cast<int>(exp.parse(expression));
|
|
||||||
|
|
||||||
if (deleteAfterDialog) {
|
if (deleteAfterDialog) {
|
||||||
deleteLater();
|
deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dialogSemaphore = false;
|
dialogSemaphore = false;
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Expression exp(value);
|
||||||
|
int newValue = static_cast<int>(exp.parse(dialog.textValue()));
|
||||||
|
|
||||||
Command_SetCounter cmd;
|
Command_SetCounter cmd;
|
||||||
cmd.set_counter_id(id);
|
cmd.set_counter_id(id);
|
||||||
cmd.set_value(newValue);
|
cmd.set_value(newValue);
|
||||||
player->sendGameCommand(cmd);
|
player->sendGameCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractCounterDialog::AbstractCounterDialog(const QString &name, const QString &value, QWidget *parent)
|
||||||
|
: QInputDialog(parent)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Set counter"));
|
||||||
|
setLabelText(tr("New value for counter '%1':").arg(name));
|
||||||
|
setTextValue(value);
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractCounterDialog::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(obj);
|
||||||
|
if (event->type() == QEvent::KeyPress) {
|
||||||
|
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||||
|
switch (keyEvent->key()) {
|
||||||
|
case Qt::Key_Up:
|
||||||
|
changeValue(+1);
|
||||||
|
return true;
|
||||||
|
case Qt::Key_Down:
|
||||||
|
changeValue(-1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractCounterDialog::changeValue(int diff)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int curValue = textValue().toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
curValue += diff;
|
||||||
|
setTextValue(QString::number(curValue));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
#ifndef COUNTER_H
|
#ifndef COUNTER_H
|
||||||
#define COUNTER_H
|
#define COUNTER_H
|
||||||
|
|
||||||
|
#include "tearoffmenu.h"
|
||||||
|
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
class QMenu;
|
|
||||||
class QAction;
|
class QAction;
|
||||||
|
class QKeyEvent;
|
||||||
|
class QMenu;
|
||||||
|
class QString;
|
||||||
|
|
||||||
class AbstractCounter : public QObject, public QGraphicsItem
|
class AbstractCounter : public QObject, public QGraphicsItem
|
||||||
{
|
{
|
||||||
@@ -25,10 +30,11 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QAction *aSet, *aDec, *aInc;
|
QAction *aSet, *aDec, *aInc;
|
||||||
QMenu *menu;
|
TearOffMenu *menu;
|
||||||
bool dialogSemaphore, deleteAfterDialog;
|
bool dialogSemaphore, deleteAfterDialog;
|
||||||
bool shownInCounterArea;
|
bool shownInCounterArea;
|
||||||
bool shortcutActive;
|
bool shortcutActive;
|
||||||
|
QWidget *game;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void refreshShortcuts();
|
void refreshShortcuts();
|
||||||
@@ -42,7 +48,8 @@ public:
|
|||||||
bool _shownInCounterArea,
|
bool _shownInCounterArea,
|
||||||
int _value,
|
int _value,
|
||||||
bool _useNameForShortcut = false,
|
bool _useNameForShortcut = false,
|
||||||
QGraphicsItem *parent = nullptr);
|
QGraphicsItem *parent = nullptr,
|
||||||
|
QWidget *game = nullptr);
|
||||||
~AbstractCounter() override;
|
~AbstractCounter() override;
|
||||||
|
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
@@ -74,4 +81,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AbstractCounterDialog : public QInputDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
AbstractCounterDialog(const QString &name, const QString &value, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
void changeValue(int diff);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "abstractgraphicsitem.h"
|
#include "abstractgraphicsitem.h"
|
||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
void AbstractGraphicsItem::paintNumberEllipse(int number,
|
void AbstractGraphicsItem::paintNumberEllipse(int number,
|
||||||
@@ -16,7 +17,12 @@ void AbstractGraphicsItem::paintNumberEllipse(int number,
|
|||||||
font.setWeight(QFont::Bold);
|
font.setWeight(QFont::Bold);
|
||||||
|
|
||||||
QFontMetrics fm(font);
|
QFontMetrics fm(font);
|
||||||
double w = fm.width(numStr) * 1.3;
|
double w = 1.3 *
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||||
|
fm.horizontalAdvance(numStr);
|
||||||
|
#else
|
||||||
|
fm.width(numStr);
|
||||||
|
#endif
|
||||||
double h = fm.height() * 1.3;
|
double h = fm.height() * 1.3;
|
||||||
if (w < h)
|
if (w < h)
|
||||||
w = h;
|
w = h;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ protected:
|
|||||||
void paintNumberEllipse(int number, int radius, const QColor &color, int position, int count, QPainter *painter);
|
void paintNumberEllipse(int number, int radius, const QColor &color, int position, int count, QPainter *painter);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractGraphicsItem(QGraphicsItem *parent = 0) : QObject(), QGraphicsItem(parent)
|
AbstractGraphicsItem(QGraphicsItem *parent = nullptr) : QObject(), QGraphicsItem(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "arrowitem.h"
|
#include "arrowitem.h"
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "cardzone.h"
|
#include "cardzone.h"
|
||||||
#include "player.h"
|
|
||||||
#include "playertarget.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QGraphicsScene>
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "pb/command_attach_card.pb.h"
|
#include "pb/command_attach_card.pb.h"
|
||||||
#include "pb/command_create_arrow.pb.h"
|
#include "pb/command_create_arrow.pb.h"
|
||||||
#include "pb/command_delete_arrow.pb.h"
|
#include "pb/command_delete_arrow.pb.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "playertarget.h"
|
||||||
|
#include "settingscache.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QtMath>
|
||||||
|
|
||||||
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
||||||
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color),
|
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color),
|
||||||
@@ -71,7 +71,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||||||
const double arrowWidth = 15.0;
|
const double arrowWidth = 15.0;
|
||||||
const double headWidth = 40.0;
|
const double headWidth = 40.0;
|
||||||
const double headLength =
|
const double headLength =
|
||||||
headWidth / pow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
|
headWidth / qPow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
|
||||||
const double phi = 15;
|
const double phi = 15;
|
||||||
|
|
||||||
if (!startItem)
|
if (!startItem)
|
||||||
@@ -86,7 +86,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||||||
if (lineLength < 30)
|
if (lineLength < 30)
|
||||||
path = QPainterPath();
|
path = QPainterPath();
|
||||||
else {
|
else {
|
||||||
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
|
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
|
||||||
|
|
||||||
QPainterPath centerLine;
|
QPainterPath centerLine;
|
||||||
centerLine.moveTo(0, 0);
|
centerLine.moveTo(0, 0);
|
||||||
@@ -97,22 +97,22 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||||||
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
|
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
|
||||||
qreal alpha = testLine.angle() - 90;
|
qreal alpha = testLine.angle() - 90;
|
||||||
QPointF endPoint1 =
|
QPointF endPoint1 =
|
||||||
arrowBodyEndPoint + arrowWidth / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
|
arrowBodyEndPoint + arrowWidth / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
|
||||||
QPointF endPoint2 =
|
QPointF endPoint2 =
|
||||||
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
|
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
|
||||||
QPointF point1 =
|
QPointF point1 =
|
||||||
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
|
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
|
||||||
QPointF point2 =
|
QPointF point2 =
|
||||||
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
|
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
|
||||||
|
|
||||||
path = QPainterPath(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path = QPainterPath(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
path.quadTo(c, endPoint1);
|
path.quadTo(c, endPoint1);
|
||||||
path.lineTo(point1);
|
path.lineTo(point1);
|
||||||
path.lineTo(QPointF(lineLength, 0));
|
path.lineTo(QPointF(lineLength, 0));
|
||||||
path.lineTo(point2);
|
path.lineTo(point2);
|
||||||
path.lineTo(endPoint2);
|
path.lineTo(endPoint2);
|
||||||
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path.quadTo(c, arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path.lineTo(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
}
|
}
|
||||||
|
|
||||||
setPos(startPoint);
|
setPos(startPoint);
|
||||||
@@ -138,8 +138,8 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<QGraphicsItem *> colliding = scene()->items(event->scenePos());
|
QList<QGraphicsItem *> colliding = scene()->items(event->scenePos());
|
||||||
for (int i = 0; i < colliding.size(); ++i) {
|
for (QGraphicsItem *item : colliding) {
|
||||||
if (qgraphicsitem_cast<CardItem *>(colliding[i])) {
|
if (qgraphicsitem_cast<CardItem *>(item)) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -205,8 +205,8 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
||||||
for (int i = 0; i < childArrows.size(); ++i) {
|
for (ArrowDragItem *child : childArrows) {
|
||||||
childArrows[i]->mouseMoveEvent(event);
|
child->mouseMoveEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,19 +240,20 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
if (startZone->getName().compare("hand") == 0) {
|
if (startZone->getName().compare("hand") == 0) {
|
||||||
startCard->playCard(false);
|
startCard->playCard(false);
|
||||||
CardInfoPtr ci = startCard->getInfo();
|
CardInfoPtr ci = startCard->getInfo();
|
||||||
if (ci && (((!settingsCache->getPlayToStack() && ci->getTableRow() == 3) ||
|
if (ci && (((!SettingsCache::instance().getPlayToStack() && ci->getTableRow() == 3) ||
|
||||||
((settingsCache->getPlayToStack() && ci->getTableRow() != 0) &&
|
((SettingsCache::instance().getPlayToStack() && ci->getTableRow() != 0) &&
|
||||||
startCard->getZone()->getName().toStdString() != "stack"))))
|
startCard->getZone()->getName().toStdString() != "stack"))))
|
||||||
cmd.set_start_zone("stack");
|
cmd.set_start_zone("stack");
|
||||||
else
|
else
|
||||||
cmd.set_start_zone(settingsCache->getPlayToStack() ? "stack" : "table");
|
cmd.set_start_zone(SettingsCache::instance().getPlayToStack() ? "stack" : "table");
|
||||||
}
|
}
|
||||||
player->sendGameCommand(cmd);
|
player->sendGameCommand(cmd);
|
||||||
}
|
}
|
||||||
delArrow();
|
delArrow();
|
||||||
|
|
||||||
for (int i = 0; i < childArrows.size(); ++i)
|
for (ArrowDragItem *child : childArrows) {
|
||||||
childArrows[i]->mouseReleaseEvent(event);
|
child->mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
|
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
|
||||||
@@ -260,6 +261,11 @@ ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArrowAttachItem::addChildArrow(ArrowAttachItem *childArrow)
|
||||||
|
{
|
||||||
|
childArrows.append(childArrow);
|
||||||
|
}
|
||||||
|
|
||||||
void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (!startItem)
|
if (!startItem)
|
||||||
@@ -295,9 +301,13 @@ void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
updatePath();
|
updatePath();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
for (ArrowAttachItem *child : childArrows) {
|
||||||
|
child->mouseMoveEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/)
|
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (!startItem)
|
if (!startItem)
|
||||||
return;
|
return;
|
||||||
@@ -319,4 +329,8 @@ void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
delArrow();
|
delArrow();
|
||||||
|
|
||||||
|
for (ArrowAttachItem *child : childArrows) {
|
||||||
|
child->mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,8 +85,12 @@ protected:
|
|||||||
class ArrowAttachItem : public ArrowItem
|
class ArrowAttachItem : public ArrowItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QList<ArrowAttachItem *> childArrows;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArrowAttachItem(ArrowTarget *_startItem);
|
ArrowAttachItem(ArrowTarget *_startItem);
|
||||||
|
void addChildArrow(ArrowAttachItem *childArrow);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "arrowtarget.h"
|
#include "arrowtarget.h"
|
||||||
|
|
||||||
#include "arrowitem.h"
|
#include "arrowitem.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define ARROWTARGET_H
|
#define ARROWTARGET_H
|
||||||
|
|
||||||
#include "abstractgraphicsitem.h"
|
#include "abstractgraphicsitem.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
@@ -18,7 +19,7 @@ private:
|
|||||||
QList<ArrowItem *> arrowsFrom, arrowsTo;
|
QList<ArrowItem *> arrowsFrom, arrowsTo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArrowTarget(Player *_owner, QGraphicsItem *parent = 0);
|
ArrowTarget(Player *_owner, QGraphicsItem *parent = nullptr);
|
||||||
~ArrowTarget();
|
~ArrowTarget();
|
||||||
|
|
||||||
Player *getOwner() const
|
Player *getOwner() const
|
||||||
@@ -42,9 +43,8 @@ public:
|
|||||||
}
|
}
|
||||||
void removeArrowFrom(ArrowItem *arrow)
|
void removeArrowFrom(ArrowItem *arrow)
|
||||||
{
|
{
|
||||||
arrowsFrom.removeAt(arrowsFrom.indexOf(arrow));
|
arrowsFrom.removeOne(arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<ArrowItem *> &getArrowsTo() const
|
const QList<ArrowItem *> &getArrowsTo() const
|
||||||
{
|
{
|
||||||
return arrowsTo;
|
return arrowsTo;
|
||||||
@@ -55,8 +55,7 @@ public:
|
|||||||
}
|
}
|
||||||
void removeArrowTo(ArrowItem *arrow)
|
void removeArrowTo(ArrowItem *arrow)
|
||||||
{
|
{
|
||||||
arrowsTo.removeAt(arrowsTo.indexOf(arrow));
|
arrowsTo.removeOne(arrow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
#include "carddbparser/cockatricexml3.h"
|
#include "carddbparser/cockatricexml3.h"
|
||||||
#include "carddbparser/cockatricexml4.h"
|
#include "carddbparser/cockatricexml4.h"
|
||||||
#include "game_specific_terms.h"
|
#include "game_specific_terms.h"
|
||||||
@@ -9,8 +10,11 @@
|
|||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
const char *CardDatabase::TOKENS_SETNAME = "TK";
|
const char *CardDatabase::TOKENS_SETNAME = "TK";
|
||||||
@@ -66,27 +70,27 @@ QString CardSet::getCorrectedShortName() const
|
|||||||
|
|
||||||
void CardSet::loadSetOptions()
|
void CardSet::loadSetOptions()
|
||||||
{
|
{
|
||||||
sortKey = settingsCache->cardDatabase().getSortKey(shortName);
|
sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName);
|
||||||
enabled = settingsCache->cardDatabase().isEnabled(shortName);
|
enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName);
|
||||||
isknown = settingsCache->cardDatabase().isKnown(shortName);
|
isknown = SettingsCache::instance().cardDatabase().isKnown(shortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardSet::setSortKey(unsigned int _sortKey)
|
void CardSet::setSortKey(unsigned int _sortKey)
|
||||||
{
|
{
|
||||||
sortKey = _sortKey;
|
sortKey = _sortKey;
|
||||||
settingsCache->cardDatabase().setSortKey(shortName, _sortKey);
|
SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardSet::setEnabled(bool _enabled)
|
void CardSet::setEnabled(bool _enabled)
|
||||||
{
|
{
|
||||||
enabled = _enabled;
|
enabled = _enabled;
|
||||||
settingsCache->cardDatabase().setEnabled(shortName, _enabled);
|
SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardSet::setIsKnown(bool _isknown)
|
void CardSet::setIsKnown(bool _isknown)
|
||||||
{
|
{
|
||||||
isknown = _isknown;
|
isknown = _isknown;
|
||||||
settingsCache->cardDatabase().setIsKnown(shortName, _isknown);
|
SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetList::KeyCompareFunctor
|
class SetList::KeyCompareFunctor
|
||||||
@@ -105,7 +109,7 @@ public:
|
|||||||
|
|
||||||
void SetList::sortByKey()
|
void SetList::sortByKey()
|
||||||
{
|
{
|
||||||
qSort(begin(), end(), KeyCompareFunctor());
|
std::sort(begin(), end(), KeyCompareFunctor());
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetList::getEnabledSetsNum()
|
int SetList::getEnabledSetsNum()
|
||||||
@@ -289,22 +293,23 @@ void CardInfo::refreshCachedSetNames()
|
|||||||
|
|
||||||
QString CardInfo::simplifyName(const QString &name)
|
QString CardInfo::simplifyName(const QString &name)
|
||||||
{
|
{
|
||||||
QString simpleName(name);
|
static const QRegularExpression spaceOrSplit("(\\s+|\\/\\/.*)");
|
||||||
|
static const QRegularExpression nonAlnum("[^a-z0-9]");
|
||||||
|
|
||||||
|
QString simpleName = name.toLower();
|
||||||
|
|
||||||
|
// remove spaces and right halves of split cards
|
||||||
|
simpleName.remove(spaceOrSplit);
|
||||||
|
|
||||||
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
|
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
|
||||||
// with nothing.
|
// with nothing.
|
||||||
simpleName.replace("æ", "ae");
|
simpleName.replace("æ", "ae");
|
||||||
simpleName.replace("Æ", "AE");
|
|
||||||
|
|
||||||
// Replace Jötun Grunt with Jotun Grunt.
|
// Replace Jötun Grunt with Jotun Grunt.
|
||||||
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
|
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
|
||||||
|
|
||||||
// Replace dashes with spaces so that we can say "garruk the veil cursed"
|
// remove all non alphanumeric characters from the name
|
||||||
// instead of the unintuitive "garruk the veilcursed".
|
simpleName.remove(nonAlnum);
|
||||||
simpleName = simpleName.replace("-", " ");
|
|
||||||
|
|
||||||
simpleName.remove(QRegExp("[^a-zA-Z0-9 ]"));
|
|
||||||
simpleName = simpleName.toLower();
|
|
||||||
return simpleName;
|
return simpleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,15 +332,15 @@ CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoa
|
|||||||
qRegisterMetaType<CardInfoPtr>("CardSetPtr");
|
qRegisterMetaType<CardInfoPtr>("CardSetPtr");
|
||||||
|
|
||||||
// add new parsers here
|
// add new parsers here
|
||||||
availableParsers << new CockatriceXml3Parser;
|
|
||||||
availableParsers << new CockatriceXml4Parser;
|
availableParsers << new CockatriceXml4Parser;
|
||||||
|
availableParsers << new CockatriceXml3Parser;
|
||||||
|
|
||||||
for (auto &parser : availableParsers) {
|
for (auto &parser : availableParsers) {
|
||||||
connect(parser, SIGNAL(addCard(CardInfoPtr)), this, SLOT(addCard(CardInfoPtr)), Qt::DirectConnection);
|
connect(parser, SIGNAL(addCard(CardInfoPtr)), this, SLOT(addCard(CardInfoPtr)), Qt::DirectConnection);
|
||||||
connect(parser, SIGNAL(addSet(CardSetPtr)), this, SLOT(addSet(CardSetPtr)), Qt::DirectConnection);
|
connect(parser, SIGNAL(addSet(CardSetPtr)), this, SLOT(addSet(CardSetPtr)), Qt::DirectConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabases()));
|
connect(&SettingsCache::instance(), SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabases()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CardDatabase::~CardDatabase()
|
CardDatabase::~CardDatabase()
|
||||||
@@ -435,6 +440,19 @@ CardInfoPtr CardDatabase::getCardBySimpleName(const QString &cardName) const
|
|||||||
return getCardFromMap(simpleNameCards, CardInfo::simplifyName(cardName));
|
return getCardFromMap(simpleNameCards, CardInfo::simplifyName(cardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CardInfoPtr CardDatabase::guessCard(const QString &cardName) const
|
||||||
|
{
|
||||||
|
CardInfoPtr temp = getCard(cardName);
|
||||||
|
if (temp == nullptr) { // get card by simple name instead
|
||||||
|
temp = getCardBySimpleName(cardName);
|
||||||
|
if (temp == nullptr) { // still could not find the card, so simplify the cardName too
|
||||||
|
QString simpleCardName = CardInfo::simplifyName(cardName);
|
||||||
|
temp = getCardBySimpleName(simpleCardName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temp; // returns nullptr if not found
|
||||||
|
}
|
||||||
|
|
||||||
CardSetPtr CardDatabase::getSet(const QString &setName)
|
CardSetPtr CardDatabase::getSet(const QString &setName)
|
||||||
{
|
{
|
||||||
if (sets.contains(setName)) {
|
if (sets.contains(setName)) {
|
||||||
@@ -492,6 +510,7 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName)
|
|||||||
|
|
||||||
LoadStatus CardDatabase::loadCardDatabase(const QString &path)
|
LoadStatus CardDatabase::loadCardDatabase(const QString &path)
|
||||||
{
|
{
|
||||||
|
auto startTime = QTime::currentTime();
|
||||||
LoadStatus tempLoadStatus = NotLoaded;
|
LoadStatus tempLoadStatus = NotLoaded;
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
loadFromFileMutex->lock();
|
loadFromFileMutex->lock();
|
||||||
@@ -499,8 +518,9 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path)
|
|||||||
loadFromFileMutex->unlock();
|
loadFromFileMutex->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msecs = startTime.msecsTo(QTime::currentTime());
|
||||||
qDebug() << "[CardDatabase] loadCardDatabase(): Path =" << path << "Status =" << tempLoadStatus
|
qDebug() << "[CardDatabase] loadCardDatabase(): Path =" << path << "Status =" << tempLoadStatus
|
||||||
<< "Cards =" << cards.size() << "Sets=" << sets.size();
|
<< "Cards =" << cards.size() << "Sets =" << sets.size() << QString("%1ms").arg(msecs);
|
||||||
|
|
||||||
return tempLoadStatus;
|
return tempLoadStatus;
|
||||||
}
|
}
|
||||||
@@ -513,15 +533,25 @@ LoadStatus CardDatabase::loadCardDatabases()
|
|||||||
|
|
||||||
clear(); // remove old db
|
clear(); // remove old db
|
||||||
|
|
||||||
loadStatus = loadCardDatabase(settingsCache->getCardDatabasePath()); // load main card database
|
loadStatus = loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database
|
||||||
loadCardDatabase(settingsCache->getTokenDatabasePath()); // load tokens database
|
loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database
|
||||||
loadCardDatabase(settingsCache->getSpoilerCardDatabasePath()); // load spoilers database
|
loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database
|
||||||
|
|
||||||
// load custom card databases
|
// find all custom card databases, recursively & following symlinks
|
||||||
QDir dir(settingsCache->getCustomCardDatabasePath());
|
// then load them alphabetically
|
||||||
for (const QString &fileName :
|
QDirIterator customDatabaseIterator(SettingsCache::instance().getCustomCardDatabasePath(), QStringList() << "*.xml",
|
||||||
dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase)) {
|
QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||||
loadCardDatabase(dir.absoluteFilePath(fileName));
|
QStringList databasePaths;
|
||||||
|
while (customDatabaseIterator.hasNext()) {
|
||||||
|
customDatabaseIterator.next();
|
||||||
|
databasePaths.push_back(customDatabaseIterator.filePath());
|
||||||
|
}
|
||||||
|
databasePaths.sort();
|
||||||
|
|
||||||
|
for (auto i = 0; i < databasePaths.size(); ++i) {
|
||||||
|
const auto &databasePath = databasePaths.at(i);
|
||||||
|
qDebug() << "Loading Custom Set" << i << "(" << databasePath << ")";
|
||||||
|
loadCardDatabase(databasePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AFTER all the cards have been loaded
|
// AFTER all the cards have been loaded
|
||||||
@@ -557,9 +587,9 @@ void CardDatabase::refreshCachedReverseRelatedCards()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *newCardRelation = new CardRelation(card->getName(), cardRelation->getDoesAttach(),
|
auto *newCardRelation = new CardRelation(
|
||||||
cardRelation->getIsCreateAllExclusion(),
|
card->getName(), cardRelation->getAttachType(), cardRelation->getIsCreateAllExclusion(),
|
||||||
cardRelation->getIsVariable(), cardRelation->getDefaultCount());
|
cardRelation->getIsVariable(), cardRelation->getDefaultCount(), cardRelation->getIsPersistent());
|
||||||
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
|
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -572,7 +602,7 @@ QStringList CardDatabase::getAllMainCardTypes() const
|
|||||||
while (cardIterator.hasNext()) {
|
while (cardIterator.hasNext()) {
|
||||||
types.insert(cardIterator.next().value()->getMainCardType());
|
types.insert(cardIterator.next().value()->getMainCardType());
|
||||||
}
|
}
|
||||||
return types.toList();
|
return types.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::checkUnknownSets()
|
void CardDatabase::checkUnknownSets()
|
||||||
@@ -623,7 +653,8 @@ void CardDatabase::notifyEnabledSetsChanged()
|
|||||||
|
|
||||||
bool CardDatabase::saveCustomTokensToFile()
|
bool CardDatabase::saveCustomTokensToFile()
|
||||||
{
|
{
|
||||||
QString fileName = settingsCache->getCustomCardDatabasePath() + "/" + CardDatabase::TOKENS_SETNAME + ".xml";
|
QString fileName =
|
||||||
|
SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardDatabase::TOKENS_SETNAME + ".xml";
|
||||||
|
|
||||||
SetNameMap tmpSets;
|
SetNameMap tmpSets;
|
||||||
CardSetPtr customTokensSet = getSet(CardDatabase::TOKENS_SETNAME);
|
CardSetPtr customTokensSet = getSet(CardDatabase::TOKENS_SETNAME);
|
||||||
@@ -641,12 +672,13 @@ bool CardDatabase::saveCustomTokensToFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardRelation::CardRelation(const QString &_name,
|
CardRelation::CardRelation(const QString &_name,
|
||||||
bool _doesAttach,
|
AttachType _attachType,
|
||||||
bool _isCreateAllExclusion,
|
bool _isCreateAllExclusion,
|
||||||
bool _isVariableCount,
|
bool _isVariableCount,
|
||||||
int _defaultCount)
|
int _defaultCount,
|
||||||
: name(_name), doesAttach(_doesAttach), isCreateAllExclusion(_isCreateAllExclusion),
|
bool _isPersistent)
|
||||||
isVariableCount(_isVariableCount), defaultCount(_defaultCount)
|
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
|
||||||
|
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ public:
|
|||||||
void removeCard(CardInfoPtr card);
|
void removeCard(CardInfoPtr card);
|
||||||
CardInfoPtr getCard(const QString &cardName) const;
|
CardInfoPtr getCard(const QString &cardName) const;
|
||||||
QList<CardInfoPtr> getCards(const QStringList &cardNames) const;
|
QList<CardInfoPtr> getCards(const QStringList &cardNames) const;
|
||||||
|
CardInfoPtr guessCard(const QString &cardName) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a card by its simple name. The name will be simplified in this
|
* Get a card by its simple name. The name will be simplified in this
|
||||||
@@ -437,7 +438,7 @@ public slots:
|
|||||||
LoadStatus loadCardDatabases();
|
LoadStatus loadCardDatabases();
|
||||||
void addCard(CardInfoPtr card);
|
void addCard(CardInfoPtr card);
|
||||||
void addSet(CardSetPtr set);
|
void addSet(CardSetPtr set);
|
||||||
private slots:
|
protected slots:
|
||||||
LoadStatus loadCardDatabase(const QString &path);
|
LoadStatus loadCardDatabase(const QString &path);
|
||||||
signals:
|
signals:
|
||||||
void cardDatabaseLoadingFailed();
|
void cardDatabaseLoadingFailed();
|
||||||
@@ -451,31 +452,60 @@ signals:
|
|||||||
class CardRelation : public QObject
|
class CardRelation : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum AttachType
|
||||||
|
{
|
||||||
|
DoesNotAttach = 0,
|
||||||
|
AttachTo = 1,
|
||||||
|
TransformInto = 2,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString name;
|
QString name;
|
||||||
bool doesAttach;
|
AttachType attachType;
|
||||||
bool isCreateAllExclusion;
|
bool isCreateAllExclusion;
|
||||||
bool isVariableCount;
|
bool isVariableCount;
|
||||||
int defaultCount;
|
int defaultCount;
|
||||||
|
bool isPersistent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CardRelation(const QString &_name = QString(),
|
explicit CardRelation(const QString &_name = QString(),
|
||||||
bool _doesAttach = false,
|
AttachType _attachType = DoesNotAttach,
|
||||||
bool _isCreateAllExclusion = false,
|
bool _isCreateAllExclusion = false,
|
||||||
bool _isVariableCount = false,
|
bool _isVariableCount = false,
|
||||||
int _defaultCount = 1);
|
int _defaultCount = 1,
|
||||||
|
bool _isPersistent = false);
|
||||||
|
|
||||||
inline const QString &getName() const
|
inline const QString &getName() const
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
AttachType getAttachType() const
|
||||||
|
{
|
||||||
|
return attachType;
|
||||||
|
}
|
||||||
bool getDoesAttach() const
|
bool getDoesAttach() const
|
||||||
{
|
{
|
||||||
return doesAttach;
|
return attachType != DoesNotAttach;
|
||||||
|
}
|
||||||
|
bool getDoesTransform() const
|
||||||
|
{
|
||||||
|
return attachType == TransformInto;
|
||||||
|
}
|
||||||
|
QString getAttachTypeAsString() const
|
||||||
|
{
|
||||||
|
switch (attachType) {
|
||||||
|
case AttachTo:
|
||||||
|
return "attach";
|
||||||
|
case TransformInto:
|
||||||
|
return "transform";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool getCanCreateAnother() const
|
bool getCanCreateAnother() const
|
||||||
{
|
{
|
||||||
return !doesAttach;
|
return !getDoesAttach();
|
||||||
}
|
}
|
||||||
bool getIsCreateAllExclusion() const
|
bool getIsCreateAllExclusion() const
|
||||||
{
|
{
|
||||||
@@ -489,5 +519,9 @@ public:
|
|||||||
{
|
{
|
||||||
return defaultCount;
|
return defaultCount;
|
||||||
}
|
}
|
||||||
|
bool getIsPersistent() const
|
||||||
|
{
|
||||||
|
return isPersistent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "carddatabasemodel.h"
|
#include "carddatabasemodel.h"
|
||||||
|
|
||||||
#include "filtertree.h"
|
#include "filtertree.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
#define CARDDBMODEL_COLUMNS 6
|
#define CARDDBMODEL_COLUMNS 6
|
||||||
@@ -349,6 +351,7 @@ const QString CardDatabaseDisplayModel::sanitizeCardName(const QString &dirtyNam
|
|||||||
}
|
}
|
||||||
return QString::fromStdWString(toReturn);
|
return QString::fromStdWString(toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenDisplayModel::TokenDisplayModel(QObject *parent) : CardDatabaseDisplayModel(parent)
|
TokenDisplayModel::TokenDisplayModel(QObject *parent) : CardDatabaseDisplayModel(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -364,3 +367,19 @@ int TokenDisplayModel::rowCount(const QModelIndex &parent) const
|
|||||||
// always load all tokens at start
|
// always load all tokens at start
|
||||||
return QSortFilterProxyModel::rowCount(parent);
|
return QSortFilterProxyModel::rowCount(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TokenEditModel::TokenEditModel(QObject *parent) : CardDatabaseDisplayModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TokenEditModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
|
||||||
|
{
|
||||||
|
CardInfoPtr info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
|
||||||
|
return info->getIsToken() && info->getSets().contains(CardDatabase::TOKENS_SETNAME) && rowMatchesCardName(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int TokenEditModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
// always load all tokens at start
|
||||||
|
return QSortFilterProxyModel::rowCount(parent);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "filter_string.h"
|
#include "filter_string.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
@@ -140,4 +141,15 @@ protected:
|
|||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TokenEditModel : public CardDatabaseDisplayModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TokenEditModel(QObject *parent = nullptr);
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#ifndef CARDDATABASE_PARSER_H
|
#ifndef CARDDATABASE_PARSER_H
|
||||||
#define CARDDATABASE_PARSER_H
|
#define CARDDATABASE_PARSER_H
|
||||||
|
|
||||||
|
#include "../carddatabase.h"
|
||||||
|
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "../carddatabase.h"
|
#define COCKATRICE_XML_XSI_NAMESPACE "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
|
||||||
class ICardDatabaseParser : public QObject
|
class ICardDatabaseParser : public QObject
|
||||||
{
|
{
|
||||||
@@ -13,7 +15,11 @@ public:
|
|||||||
|
|
||||||
virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0;
|
virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0;
|
||||||
virtual void parseFile(QIODevice &device) = 0;
|
virtual void parseFile(QIODevice &device) = 0;
|
||||||
virtual bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) = 0;
|
virtual bool saveToFile(SetNameMap sets,
|
||||||
|
CardNameMap cards,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &sourceUrl = "unknown",
|
||||||
|
const QString &sourceVersion = "unknown") = 0;
|
||||||
static void clearSetlist();
|
static void clearSetlist();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include "cockatricexml3.h"
|
#include "cockatricexml3.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
#include <version_string.h>
|
||||||
|
|
||||||
#define COCKATRICE_XML3_TAGNAME "cockatrice_carddatabase"
|
#define COCKATRICE_XML3_TAGNAME "cockatrice_carddatabase"
|
||||||
#define COCKATRICE_XML3_TAGVER 3
|
#define COCKATRICE_XML3_TAGVER 3
|
||||||
|
#define COCKATRICE_XML3_SCHEMALOCATION \
|
||||||
|
"https://raw.githubusercontent.com/Cockatrice/Cockatrice/master/doc/carddatabase_v3/cards.xsd"
|
||||||
|
|
||||||
bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &device)
|
bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &device)
|
||||||
{
|
{
|
||||||
@@ -19,7 +23,7 @@ bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
|||||||
QXmlStreamReader xml(&device);
|
QXmlStreamReader xml(&device);
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
if (xml.name() == COCKATRICE_XML3_TAGNAME) {
|
if (xml.name().toString() == COCKATRICE_XML3_TAGNAME) {
|
||||||
int version = xml.attributes().value("version").toString().toInt();
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
if (version == COCKATRICE_XML3_TAGVER) {
|
if (version == COCKATRICE_XML3_TAGVER) {
|
||||||
return true;
|
return true;
|
||||||
@@ -48,12 +52,13 @@ void CockatriceXml3Parser::parseFile(QIODevice &device)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "sets") {
|
auto name = xml.name().toString();
|
||||||
|
if (name == "sets") {
|
||||||
loadSetsFromXml(xml);
|
loadSetsFromXml(xml);
|
||||||
} else if (xml.name() == "cards") {
|
} else if (name == "cards") {
|
||||||
loadCardsFromXml(xml);
|
loadCardsFromXml(xml);
|
||||||
} else if (xml.name() != "") {
|
} else if (!name.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
qDebug() << "[CockatriceXml3Parser] Unknown item" << name << ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,26 +73,27 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "set") {
|
auto name = xml.name().toString();
|
||||||
|
if (name == "set") {
|
||||||
QString shortName, longName, setType;
|
QString shortName, longName, setType;
|
||||||
QDate releaseDate;
|
QDate releaseDate;
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
name = xml.name().toString();
|
||||||
|
|
||||||
if (xml.name() == "name") {
|
if (name == "name") {
|
||||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "longname") {
|
} else if (name == "longname") {
|
||||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "settype") {
|
} else if (name == "settype") {
|
||||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "releasedate") {
|
} else if (name == "releasedate") {
|
||||||
releaseDate =
|
releaseDate =
|
||||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||||
} else if (xml.name() != "") {
|
} else if (!name.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown set property" << xml.name()
|
qDebug() << "[CockatriceXml3Parser] Unknown set property" << name << ", trying to continue anyway";
|
||||||
<< ", trying to continue anyway";
|
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,7 +148,8 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "card") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "card") {
|
||||||
QString name = QString("");
|
QString name = QString("");
|
||||||
QString text = QString("");
|
QString text = QString("");
|
||||||
QVariantHash properties = QVariantHash();
|
QVariantHash properties = QVariantHash();
|
||||||
@@ -158,37 +165,39 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
// variable - assigned properties
|
// variable - assigned properties
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "text") {
|
} else if (xmlName == "text") {
|
||||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "color") {
|
} else if (xmlName == "color") {
|
||||||
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "token") {
|
} else if (xmlName == "token") {
|
||||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||||
// generic properties
|
// generic properties
|
||||||
} else if (xml.name() == "manacost") {
|
} else if (xmlName == "manacost") {
|
||||||
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "cmc") {
|
} else if (xmlName == "cmc") {
|
||||||
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "type") {
|
} else if (xmlName == "type") {
|
||||||
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
properties.insert("type", type);
|
properties.insert("type", type);
|
||||||
properties.insert("maintype", getMainCardType(type));
|
properties.insert("maintype", getMainCardType(type));
|
||||||
} else if (xml.name() == "pt") {
|
} else if (xmlName == "pt") {
|
||||||
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "loyalty") {
|
} else if (xmlName == "loyalty") {
|
||||||
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
// positioning info
|
// positioning info
|
||||||
} else if (xml.name() == "tablerow") {
|
} else if (xmlName == "tablerow") {
|
||||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||||
} else if (xml.name() == "cipt") {
|
} else if (xmlName == "cipt") {
|
||||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
} else if (xml.name() == "upsidedown") {
|
} else if (xmlName == "upsidedown") {
|
||||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
// sets
|
// sets
|
||||||
} else if (xml.name() == "set") {
|
} else if (xmlName == "set") {
|
||||||
// NOTE: attributes must be read before readElementText()
|
// NOTE: attributes must be read before readElementText()
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
@@ -213,9 +222,9 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
||||||
}
|
}
|
||||||
sets.insert(setName, setInfo);
|
sets.insert(setName, setInfo);
|
||||||
// relatd cards
|
// related cards
|
||||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||||
bool attach = false;
|
CardRelation::AttachType attach = CardRelation::DoesNotAttach;
|
||||||
bool exclude = false;
|
bool exclude = false;
|
||||||
bool variable = false;
|
bool variable = false;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
@@ -237,7 +246,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("attach")) {
|
if (attrs.hasAttribute("attach")) {
|
||||||
attach = true;
|
attach = CardRelation::AttachTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("exclude")) {
|
if (attrs.hasAttribute("exclude")) {
|
||||||
@@ -245,13 +254,13 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||||
if (xml.name() == "reverse-related") {
|
if (xmlName == "reverse-related") {
|
||||||
reverseRelatedCards << relation;
|
reverseRelatedCards << relation;
|
||||||
} else {
|
} else {
|
||||||
relatedCards << relation;
|
relatedCards << relation;
|
||||||
}
|
}
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
|
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@@ -403,7 +412,11 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
|||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CockatriceXml3Parser::saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName)
|
bool CockatriceXml3Parser::saveToFile(SetNameMap sets,
|
||||||
|
CardNameMap cards,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &sourceUrl,
|
||||||
|
const QString &sourceVersion)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (!file.open(QIODevice::WriteOnly)) {
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
@@ -416,6 +429,15 @@ bool CockatriceXml3Parser::saveToFile(SetNameMap sets, CardNameMap cards, const
|
|||||||
xml.writeStartDocument();
|
xml.writeStartDocument();
|
||||||
xml.writeStartElement(COCKATRICE_XML3_TAGNAME);
|
xml.writeStartElement(COCKATRICE_XML3_TAGNAME);
|
||||||
xml.writeAttribute("version", QString::number(COCKATRICE_XML3_TAGVER));
|
xml.writeAttribute("version", QString::number(COCKATRICE_XML3_TAGVER));
|
||||||
|
xml.writeAttribute("xmlns:xsi", COCKATRICE_XML_XSI_NAMESPACE);
|
||||||
|
xml.writeAttribute("xsi:schemaLocation", COCKATRICE_XML3_SCHEMALOCATION);
|
||||||
|
|
||||||
|
xml.writeStartElement("info");
|
||||||
|
xml.writeTextElement("author", QCoreApplication::applicationName() + QString(" %1").arg(VERSION_STRING));
|
||||||
|
xml.writeTextElement("createdAt", QDateTime::currentDateTimeUtc().toString(Qt::ISODate));
|
||||||
|
xml.writeTextElement("sourceUrl", sourceUrl);
|
||||||
|
xml.writeTextElement("sourceVersion", sourceVersion);
|
||||||
|
xml.writeEndElement();
|
||||||
|
|
||||||
if (sets.count() > 0) {
|
if (sets.count() > 0) {
|
||||||
xml.writeStartElement("sets");
|
xml.writeStartElement("sets");
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef COCKATRICE_XML3_H
|
#ifndef COCKATRICE_XML3_H
|
||||||
#define COCKATRICE_XML3_H
|
#define COCKATRICE_XML3_H
|
||||||
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
|
|
||||||
#include "carddatabaseparser.h"
|
#include "carddatabaseparser.h"
|
||||||
|
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
class CockatriceXml3Parser : public ICardDatabaseParser
|
class CockatriceXml3Parser : public ICardDatabaseParser
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -14,7 +14,11 @@ public:
|
|||||||
~CockatriceXml3Parser() override = default;
|
~CockatriceXml3Parser() override = default;
|
||||||
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||||
void parseFile(QIODevice &device) override;
|
void parseFile(QIODevice &device) override;
|
||||||
bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override;
|
bool saveToFile(SetNameMap sets,
|
||||||
|
CardNameMap cards,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &sourceUrl = "unknown",
|
||||||
|
const QString &sourceVersion = "unknown") override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include "cockatricexml4.h"
|
#include "cockatricexml4.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
#include <version_string.h>
|
||||||
|
|
||||||
#define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase"
|
#define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase"
|
||||||
#define COCKATRICE_XML4_TAGVER 4
|
#define COCKATRICE_XML4_TAGVER 4
|
||||||
|
#define COCKATRICE_XML4_SCHEMALOCATION \
|
||||||
|
"https://raw.githubusercontent.com/Cockatrice/Cockatrice/master/doc/carddatabase_v4/cards.xsd"
|
||||||
|
|
||||||
bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device)
|
bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device)
|
||||||
{
|
{
|
||||||
@@ -19,7 +23,7 @@ bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
|||||||
QXmlStreamReader xml(&device);
|
QXmlStreamReader xml(&device);
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
if (xml.name() == COCKATRICE_XML4_TAGNAME) {
|
if (xml.name().toString() == COCKATRICE_XML4_TAGNAME) {
|
||||||
int version = xml.attributes().value("version").toString().toInt();
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
if (version == COCKATRICE_XML4_TAGVER) {
|
if (version == COCKATRICE_XML4_TAGVER) {
|
||||||
return true;
|
return true;
|
||||||
@@ -48,12 +52,13 @@ void CockatriceXml4Parser::parseFile(QIODevice &device)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "sets") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "sets") {
|
||||||
loadSetsFromXml(xml);
|
loadSetsFromXml(xml);
|
||||||
} else if (xml.name() == "cards") {
|
} else if (xmlName == "cards") {
|
||||||
loadCardsFromXml(xml);
|
loadCardsFromXml(xml);
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
qDebug() << "[CockatriceXml4Parser] Unknown item" << xmlName << ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,25 +73,27 @@ void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "set") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "set") {
|
||||||
QString shortName, longName, setType;
|
QString shortName, longName, setType;
|
||||||
QDate releaseDate;
|
QDate releaseDate;
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "longname") {
|
} else if (xmlName == "longname") {
|
||||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "settype") {
|
} else if (xmlName == "settype") {
|
||||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "releasedate") {
|
} else if (xmlName == "releasedate") {
|
||||||
releaseDate =
|
releaseDate =
|
||||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name()
|
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@@ -105,8 +112,9 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() != "") {
|
auto xmlName = xml.name().toString();
|
||||||
properties.insert(xml.name().toString(), xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
if (!xmlName.isEmpty()) {
|
||||||
|
properties.insert(xmlName, xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
@@ -119,7 +127,9 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "card") {
|
auto xmlName = xml.name().toString();
|
||||||
|
|
||||||
|
if (xmlName == "card") {
|
||||||
QString name = QString("");
|
QString name = QString("");
|
||||||
QString text = QString("");
|
QString text = QString("");
|
||||||
QVariantHash properties = QVariantHash();
|
QVariantHash properties = QVariantHash();
|
||||||
@@ -134,41 +144,48 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
// variable - assigned properties
|
// variable - assigned properties
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "text") {
|
} else if (xmlName == "text") {
|
||||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "token") {
|
} else if (xmlName == "token") {
|
||||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||||
// generic properties
|
// generic properties
|
||||||
} else if (xml.name() == "prop") {
|
} else if (xmlName == "prop") {
|
||||||
properties = loadCardPropertiesFromXml(xml);
|
properties = loadCardPropertiesFromXml(xml);
|
||||||
// positioning info
|
// positioning info
|
||||||
} else if (xml.name() == "tablerow") {
|
} else if (xmlName == "tablerow") {
|
||||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||||
} else if (xml.name() == "cipt") {
|
} else if (xmlName == "cipt") {
|
||||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
} else if (xml.name() == "upsidedown") {
|
} else if (xmlName == "upsidedown") {
|
||||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
// sets
|
// sets
|
||||||
} else if (xml.name() == "set") {
|
} else if (xmlName == "set") {
|
||||||
// NOTE: attributes but be read before readElementText()
|
// NOTE: attributes but be read before readElementText()
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
CardInfoPerSet setInfo(internalAddSet(setName));
|
auto set = internalAddSet(setName);
|
||||||
for (QXmlStreamAttribute attr : attrs) {
|
if (set->getEnabled()) {
|
||||||
QString attrName = attr.name().toString();
|
CardInfoPerSet setInfo(set);
|
||||||
if (attrName == "picURL")
|
for (QXmlStreamAttribute attr : attrs) {
|
||||||
attrName = "picurl";
|
QString attrName = attr.name().toString();
|
||||||
setInfo.setProperty(attrName, attr.value().toString());
|
if (attrName == "picURL")
|
||||||
|
attrName = "picurl";
|
||||||
|
setInfo.setProperty(attrName, attr.value().toString());
|
||||||
|
}
|
||||||
|
sets.insert(setName, setInfo);
|
||||||
}
|
}
|
||||||
sets.insert(setName, setInfo);
|
// related cards
|
||||||
// relatd cards
|
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
CardRelation::AttachType attachType = CardRelation::DoesNotAttach;
|
||||||
bool attach = false;
|
|
||||||
bool exclude = false;
|
bool exclude = false;
|
||||||
bool variable = false;
|
bool variable = false;
|
||||||
|
bool persistent = false;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString cardName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString cardName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
@@ -188,21 +205,26 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("attach")) {
|
if (attrs.hasAttribute("attach")) {
|
||||||
attach = true;
|
attachType = attrs.value("attach").toString() == "transform" ? CardRelation::TransformInto
|
||||||
|
: CardRelation::AttachTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("exclude")) {
|
if (attrs.hasAttribute("exclude")) {
|
||||||
exclude = true;
|
exclude = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
if (attrs.hasAttribute("persistent")) {
|
||||||
if (xml.name() == "reverse-related") {
|
persistent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *relation = new CardRelation(cardName, attachType, exclude, variable, count, persistent);
|
||||||
|
if (xmlName == "reverse-related") {
|
||||||
reverseRelatedCards << relation;
|
reverseRelatedCards << relation;
|
||||||
} else {
|
} else {
|
||||||
relatedCards << relation;
|
relatedCards << relation;
|
||||||
}
|
}
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name()
|
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@@ -273,12 +295,14 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
|||||||
for (auto i : related) {
|
for (auto i : related) {
|
||||||
xml.writeStartElement("related");
|
xml.writeStartElement("related");
|
||||||
if (i->getDoesAttach()) {
|
if (i->getDoesAttach()) {
|
||||||
xml.writeAttribute("attach", "attach");
|
xml.writeAttribute("attach", i->getAttachTypeAsString());
|
||||||
}
|
}
|
||||||
if (i->getIsCreateAllExclusion()) {
|
if (i->getIsCreateAllExclusion()) {
|
||||||
xml.writeAttribute("exclude", "exclude");
|
xml.writeAttribute("exclude", "exclude");
|
||||||
}
|
}
|
||||||
|
if (i->getIsPersistent()) {
|
||||||
|
xml.writeAttribute("persistent", "persistent");
|
||||||
|
}
|
||||||
if (i->getIsVariable()) {
|
if (i->getIsVariable()) {
|
||||||
if (1 == i->getDefaultCount()) {
|
if (1 == i->getDefaultCount()) {
|
||||||
xml.writeAttribute("count", "x");
|
xml.writeAttribute("count", "x");
|
||||||
@@ -295,13 +319,16 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
|||||||
for (auto i : reverseRelated) {
|
for (auto i : reverseRelated) {
|
||||||
xml.writeStartElement("reverse-related");
|
xml.writeStartElement("reverse-related");
|
||||||
if (i->getDoesAttach()) {
|
if (i->getDoesAttach()) {
|
||||||
xml.writeAttribute("attach", "attach");
|
xml.writeAttribute("attach", i->getAttachTypeAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->getIsCreateAllExclusion()) {
|
if (i->getIsCreateAllExclusion()) {
|
||||||
xml.writeAttribute("exclude", "exclude");
|
xml.writeAttribute("exclude", "exclude");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i->getIsPersistent()) {
|
||||||
|
xml.writeAttribute("persistent", "persistent");
|
||||||
|
}
|
||||||
if (i->getIsVariable()) {
|
if (i->getIsVariable()) {
|
||||||
if (1 == i->getDefaultCount()) {
|
if (1 == i->getDefaultCount()) {
|
||||||
xml.writeAttribute("count", "x");
|
xml.writeAttribute("count", "x");
|
||||||
@@ -329,7 +356,11 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
|||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CockatriceXml4Parser::saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName)
|
bool CockatriceXml4Parser::saveToFile(SetNameMap sets,
|
||||||
|
CardNameMap cards,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &sourceUrl,
|
||||||
|
const QString &sourceVersion)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
if (!file.open(QIODevice::WriteOnly)) {
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
@@ -342,6 +373,15 @@ bool CockatriceXml4Parser::saveToFile(SetNameMap sets, CardNameMap cards, const
|
|||||||
xml.writeStartDocument();
|
xml.writeStartDocument();
|
||||||
xml.writeStartElement(COCKATRICE_XML4_TAGNAME);
|
xml.writeStartElement(COCKATRICE_XML4_TAGNAME);
|
||||||
xml.writeAttribute("version", QString::number(COCKATRICE_XML4_TAGVER));
|
xml.writeAttribute("version", QString::number(COCKATRICE_XML4_TAGVER));
|
||||||
|
xml.writeAttribute("xmlns:xsi", COCKATRICE_XML_XSI_NAMESPACE);
|
||||||
|
xml.writeAttribute("xsi:schemaLocation", COCKATRICE_XML4_SCHEMALOCATION);
|
||||||
|
|
||||||
|
xml.writeStartElement("info");
|
||||||
|
xml.writeTextElement("author", QCoreApplication::applicationName() + QString(" %1").arg(VERSION_STRING));
|
||||||
|
xml.writeTextElement("createdAt", QDateTime::currentDateTimeUtc().toString(Qt::ISODate));
|
||||||
|
xml.writeTextElement("sourceUrl", sourceUrl);
|
||||||
|
xml.writeTextElement("sourceVersion", sourceVersion);
|
||||||
|
xml.writeEndElement();
|
||||||
|
|
||||||
if (sets.count() > 0) {
|
if (sets.count() > 0) {
|
||||||
xml.writeStartElement("sets");
|
xml.writeStartElement("sets");
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef COCKATRICE_XML4_H
|
#ifndef COCKATRICE_XML4_H
|
||||||
#define COCKATRICE_XML4_H
|
#define COCKATRICE_XML4_H
|
||||||
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
|
|
||||||
#include "carddatabaseparser.h"
|
#include "carddatabaseparser.h"
|
||||||
|
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
class CockatriceXml4Parser : public ICardDatabaseParser
|
class CockatriceXml4Parser : public ICardDatabaseParser
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -14,7 +14,11 @@ public:
|
|||||||
~CockatriceXml4Parser() override = default;
|
~CockatriceXml4Parser() override = default;
|
||||||
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||||
void parseFile(QIODevice &device) override;
|
void parseFile(QIODevice &device) override;
|
||||||
bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override;
|
bool saveToFile(SetNameMap sets,
|
||||||
|
CardNameMap cards,
|
||||||
|
const QString &fileName,
|
||||||
|
const QString &sourceUrl = "unknown",
|
||||||
|
const QString &sourceVersion = "unknown") override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml);
|
QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml);
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "carddragitem.h"
|
#include "carddragitem.h"
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "cardzone.h"
|
#include "cardzone.h"
|
||||||
#include "gamescene.h"
|
#include "gamescene.h"
|
||||||
#include "tablezone.h"
|
#include "tablezone.h"
|
||||||
#include "zoneviewzone.h"
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const QString CardFilter::attrName(Attr a)
|
|||||||
case AttrManaCost:
|
case AttrManaCost:
|
||||||
return tr("Mana Cost");
|
return tr("Mana Cost");
|
||||||
case AttrCmc:
|
case AttrCmc:
|
||||||
return tr("CMC");
|
return tr("Mana Value");
|
||||||
case AttrRarity:
|
case AttrRarity:
|
||||||
return tr("Rarity");
|
return tr("Rarity");
|
||||||
case AttrPow:
|
case AttrPow:
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "cardframe.h"
|
#include "cardframe.h"
|
||||||
|
|
||||||
#include "cardinfopicture.h"
|
#include "cardinfopicture.h"
|
||||||
@@ -10,6 +8,7 @@
|
|||||||
|
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
CardFrame::CardFrame(const QString &cardName, QWidget *parent) : QTabWidget(parent), info(nullptr), cardTextOnly(false)
|
CardFrame::CardFrame(const QString &cardName, QWidget *parent) : QTabWidget(parent), info(nullptr), cardTextOnly(false)
|
||||||
{
|
{
|
||||||
@@ -56,7 +55,7 @@ CardFrame::CardFrame(const QString &cardName, QWidget *parent) : QTabWidget(pare
|
|||||||
tab3Layout->addWidget(splitter);
|
tab3Layout->addWidget(splitter);
|
||||||
tab3->setLayout(tab3Layout);
|
tab3->setLayout(tab3Layout);
|
||||||
|
|
||||||
setViewMode(settingsCache->getCardInfoViewMode());
|
setViewMode(SettingsCache::instance().getCardInfoViewMode());
|
||||||
|
|
||||||
setCard(db->getCard(cardName));
|
setCard(db->getCard(cardName));
|
||||||
}
|
}
|
||||||
@@ -87,7 +86,7 @@ void CardFrame::setViewMode(int mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsCache->setCardInfoViewMode(mode);
|
SettingsCache::instance().setCardInfoViewMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardFrame::setCard(CardInfoPtr card)
|
void CardFrame::setCard(CardInfoPtr card)
|
||||||
@@ -108,7 +107,7 @@ void CardFrame::setCard(CardInfoPtr card)
|
|||||||
|
|
||||||
void CardFrame::setCard(const QString &cardName)
|
void CardFrame::setCard(const QString &cardName)
|
||||||
{
|
{
|
||||||
setCard(db->getCardBySimpleName(cardName));
|
setCard(db->guessCard(cardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardFrame::setCard(AbstractCardItem *card)
|
void CardFrame::setCard(AbstractCardItem *card)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef CARDFRAME_H
|
#ifndef CARDFRAME_H
|
||||||
#define CARDFRAME_H
|
#define CARDFRAME_H
|
||||||
|
|
||||||
#include <QTabWidget>
|
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
#include <QTabWidget>
|
||||||
|
|
||||||
class AbstractCardItem;
|
class AbstractCardItem;
|
||||||
class CardInfoPicture;
|
class CardInfoPicture;
|
||||||
class CardInfoText;
|
class CardInfoText;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#include "cardinfopicture.h"
|
#include "cardinfopicture.h"
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "pictureloader.h"
|
#include "pictureloader.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true)
|
CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true)
|
||||||
{
|
{
|
||||||
setMinimumHeight(100);
|
setMinimumHeight(100);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef CARDINFOPICTURE_H
|
#ifndef CARDINFOPICTURE_H
|
||||||
#define CARDINFOPICTURE_H
|
#define CARDINFOPICTURE_H
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
class AbstractCardItem;
|
class AbstractCardItem;
|
||||||
|
|
||||||
class CardInfoPicture : public QWidget
|
class CardInfoPicture : public QWidget
|
||||||
@@ -17,7 +17,7 @@ private:
|
|||||||
bool pixmapDirty;
|
bool pixmapDirty;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardInfoPicture(QWidget *parent = 0);
|
CardInfoPicture(QWidget *parent = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "cardinfotext.h"
|
#include "cardinfotext.h"
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "game_specific_terms.h"
|
#include "game_specific_terms.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@@ -47,9 +48,8 @@ void CardInfoText::setCard(CardInfoPtr card)
|
|||||||
QString("<tr><td>%1</td><td></td><td>%2</td></tr>").arg(keyText, card->getProperty(key).toHtmlEscaped());
|
QString("<tr><td>%1</td><td></td><td>%2</td></tr>").arg(keyText, card->getProperty(key).toHtmlEscaped());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto relatedCards = card->getRelatedCards();
|
auto relatedCards = card->getAllRelatedCards();
|
||||||
auto reverserelatedCards2Me = card->getReverseRelatedCards2Me();
|
if (!relatedCards.empty()) {
|
||||||
if (!relatedCards.empty() || !reverserelatedCards2Me.empty()) {
|
|
||||||
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>").arg(tr("Related cards:"));
|
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>").arg(tr("Related cards:"));
|
||||||
|
|
||||||
for (auto *relatedCard : relatedCards) {
|
for (auto *relatedCard : relatedCards) {
|
||||||
@@ -57,11 +57,6 @@ void CardInfoText::setCard(CardInfoPtr card)
|
|||||||
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
|
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto *i : reverserelatedCards2Me) {
|
|
||||||
QString tmp = i->getName().toHtmlEscaped();
|
|
||||||
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
|
|
||||||
}
|
|
||||||
|
|
||||||
text += "</td></tr>";
|
text += "</td></tr>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#ifndef CARDINFOTEXT_H
|
#ifndef CARDINFOTEXT_H
|
||||||
#define CARDINFOTEXT_H
|
#define CARDINFOTEXT_H
|
||||||
|
|
||||||
#include <QFrame>
|
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QTextEdit;
|
class QTextEdit;
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#include <utility>
|
#include "cardinfowidget.h"
|
||||||
|
|
||||||
#include "cardinfopicture.h"
|
#include "cardinfopicture.h"
|
||||||
#include "cardinfotext.h"
|
#include "cardinfotext.h"
|
||||||
#include "cardinfowidget.h"
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <QDesktopWidget>
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScreen>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
|
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
|
||||||
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr)
|
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr)
|
||||||
@@ -27,8 +29,8 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win
|
|||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
QDesktopWidget desktopWidget;
|
|
||||||
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
|
int pixmapHeight = QGuiApplication::primaryScreen()->geometry().height() / 3;
|
||||||
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
||||||
pic->setFixedWidth(pixmapWidth);
|
pic->setFixedWidth(pixmapWidth);
|
||||||
pic->setFixedHeight(pixmapHeight);
|
pic->setFixedHeight(pixmapHeight);
|
||||||
@@ -54,9 +56,10 @@ void CardInfoWidget::setCard(CardInfoPtr card)
|
|||||||
|
|
||||||
void CardInfoWidget::setCard(const QString &cardName)
|
void CardInfoWidget::setCard(const QString &cardName)
|
||||||
{
|
{
|
||||||
setCard(db->getCardBySimpleName(cardName));
|
setCard(db->guessCard(cardName));
|
||||||
if (!info)
|
if (info == nullptr) {
|
||||||
text->setInvalidCardName(cardName);
|
text->setInvalidCardName(cardName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoWidget::setCard(AbstractCardItem *card)
|
void CardInfoWidget::setCard(AbstractCardItem *card)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#ifndef CARDINFOWIDGET_H
|
#ifndef CARDINFOWIDGET_H
|
||||||
#define CARDINFOWIDGET_H
|
#define CARDINFOWIDGET_H
|
||||||
|
|
||||||
|
#include "carddatabase.h"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include "carddatabase.h"
|
|
||||||
|
|
||||||
class CardInfoPicture;
|
class CardInfoPicture;
|
||||||
class CardInfoText;
|
class CardInfoText;
|
||||||
class AbstractCardItem;
|
class AbstractCardItem;
|
||||||
@@ -22,7 +22,7 @@ private:
|
|||||||
CardInfoText *text;
|
CardInfoText *text;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CardInfoWidget(const QString &cardName, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
|
explicit CardInfoWidget(const QString &cardName, QWidget *parent = nullptr, Qt::WindowFlags f = {});
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setCard(CardInfoPtr card);
|
void setCard(CardInfoPtr card);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
|
|
||||||
#include "arrowitem.h"
|
#include "arrowitem.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "carddragitem.h"
|
#include "carddragitem.h"
|
||||||
@@ -11,14 +12,20 @@
|
|||||||
#include "tab_game.h"
|
#include "tab_game.h"
|
||||||
#include "tablezone.h"
|
#include "tablezone.h"
|
||||||
#include "zoneviewzone.h"
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _revealedCard, QGraphicsItem *parent)
|
CardItem::CardItem(Player *_owner,
|
||||||
: AbstractCardItem(_name, _owner, _cardid, parent), zone(0), revealedCard(_revealedCard), attacking(false),
|
const QString &_name,
|
||||||
destroyOnZoneChange(false), doesntUntap(false), dragItem(0), attachedTo(0)
|
int _cardid,
|
||||||
|
bool _revealedCard,
|
||||||
|
QGraphicsItem *parent,
|
||||||
|
CardZone *_zone)
|
||||||
|
: AbstractCardItem(_name, _owner, _cardid, parent), zone(_zone), revealedCard(_revealedCard), attacking(false),
|
||||||
|
destroyOnZoneChange(false), doesntUntap(false), dragItem(nullptr), attachedTo(nullptr)
|
||||||
{
|
{
|
||||||
owner->addCard(this);
|
owner->addCard(this);
|
||||||
|
|
||||||
@@ -27,7 +34,6 @@ CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _reve
|
|||||||
moveMenu = new QMenu;
|
moveMenu = new QMenu;
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
emit updateCardMenu(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CardItem::~CardItem()
|
CardItem::~CardItem()
|
||||||
@@ -46,22 +52,22 @@ CardItem::~CardItem()
|
|||||||
|
|
||||||
void CardItem::prepareDelete()
|
void CardItem::prepareDelete()
|
||||||
{
|
{
|
||||||
if (owner) {
|
if (owner != nullptr) {
|
||||||
if (owner->getCardMenu() == cardMenu) {
|
if (owner->getCardMenu() == cardMenu) {
|
||||||
owner->setCardMenu(0);
|
owner->setCardMenu(nullptr);
|
||||||
owner->getGame()->setActiveCard(0);
|
owner->getGame()->setActiveCard(nullptr);
|
||||||
}
|
}
|
||||||
owner = 0;
|
owner = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!attachedCards.isEmpty()) {
|
while (!attachedCards.isEmpty()) {
|
||||||
attachedCards.first()->setZone(0); // so that it won't try to call reorganizeCards()
|
attachedCards.first()->setZone(nullptr); // so that it won't try to call reorganizeCards()
|
||||||
attachedCards.first()->setAttachedTo(0);
|
attachedCards.first()->setAttachedTo(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attachedTo) {
|
if (attachedTo != nullptr) {
|
||||||
attachedTo->removeAttachedCard(this);
|
attachedTo->removeAttachedCard(this);
|
||||||
attachedTo = 0;
|
attachedTo = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +80,6 @@ void CardItem::deleteLater()
|
|||||||
void CardItem::setZone(CardZone *_zone)
|
void CardItem::setZone(CardZone *_zone)
|
||||||
{
|
{
|
||||||
zone = _zone;
|
zone = _zone;
|
||||||
emit updateCardMenu(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardItem::retranslateUi()
|
void CardItem::retranslateUi()
|
||||||
@@ -193,23 +198,25 @@ void CardItem::setPT(const QString &_pt)
|
|||||||
|
|
||||||
void CardItem::setAttachedTo(CardItem *_attachedTo)
|
void CardItem::setAttachedTo(CardItem *_attachedTo)
|
||||||
{
|
{
|
||||||
if (attachedTo)
|
if (attachedTo != nullptr) {
|
||||||
attachedTo->removeAttachedCard(this);
|
attachedTo->removeAttachedCard(this);
|
||||||
|
}
|
||||||
|
|
||||||
gridPoint.setX(-1);
|
gridPoint.setX(-1);
|
||||||
attachedTo = _attachedTo;
|
attachedTo = _attachedTo;
|
||||||
if (attachedTo) {
|
if (attachedTo != nullptr) {
|
||||||
setParentItem(attachedTo->getZone());
|
setParentItem(attachedTo->getZone());
|
||||||
attachedTo->addAttachedCard(this);
|
attachedTo->addAttachedCard(this);
|
||||||
if (zone != attachedTo->getZone())
|
if (zone != attachedTo->getZone()) {
|
||||||
attachedTo->getZone()->reorganizeCards();
|
attachedTo->getZone()->reorganizeCards();
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
setParentItem(zone);
|
setParentItem(zone);
|
||||||
|
}
|
||||||
|
|
||||||
if (zone)
|
if (zone != nullptr) {
|
||||||
zone->reorganizeCards();
|
zone->reorganizeCards();
|
||||||
|
}
|
||||||
emit updateCardMenu(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardItem::resetState()
|
void CardItem::resetState()
|
||||||
@@ -263,9 +270,10 @@ CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPoin
|
|||||||
|
|
||||||
void CardItem::deleteDragItem()
|
void CardItem::deleteDragItem()
|
||||||
{
|
{
|
||||||
if (dragItem)
|
if (dragItem) {
|
||||||
dragItem->deleteLater();
|
dragItem->deleteLater();
|
||||||
dragItem = NULL;
|
}
|
||||||
|
dragItem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardItem::drawArrow(const QColor &arrowColor)
|
void CardItem::drawArrow(const QColor &arrowColor)
|
||||||
@@ -278,15 +286,36 @@ void CardItem::drawArrow(const QColor &arrowColor)
|
|||||||
scene()->addItem(arrow);
|
scene()->addItem(arrow);
|
||||||
arrow->grabMouse();
|
arrow->grabMouse();
|
||||||
|
|
||||||
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
|
for (const auto &item : scene()->selectedItems()) {
|
||||||
while (itemIterator.hasNext()) {
|
CardItem *card = qgraphicsitem_cast<CardItem *>(item);
|
||||||
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
|
if (card == nullptr || card == this)
|
||||||
if (!c || (c == this))
|
|
||||||
continue;
|
continue;
|
||||||
if (c->getZone() != zone)
|
if (card->getZone() != zone)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
|
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor);
|
||||||
|
scene()->addItem(childArrow);
|
||||||
|
arrow->addChildArrow(childArrow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardItem::drawAttachArrow()
|
||||||
|
{
|
||||||
|
if (static_cast<TabGame *>(owner->parent())->getSpectator())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *arrow = new ArrowAttachItem(this);
|
||||||
|
scene()->addItem(arrow);
|
||||||
|
arrow->grabMouse();
|
||||||
|
|
||||||
|
for (const auto &item : scene()->selectedItems()) {
|
||||||
|
CardItem *card = qgraphicsitem_cast<CardItem *>(item);
|
||||||
|
if (card == nullptr)
|
||||||
|
continue;
|
||||||
|
if (card->getZone() != zone)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ArrowAttachItem *childArrow = new ArrowAttachItem(card);
|
||||||
scene()->addItem(childArrow);
|
scene()->addItem(childArrow);
|
||||||
arrow->addChildArrow(childArrow);
|
arrow->addChildArrow(childArrow);
|
||||||
}
|
}
|
||||||
@@ -324,19 +353,19 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
|
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
|
||||||
dragItem->grabMouse();
|
dragItem->grabMouse();
|
||||||
|
|
||||||
QList<QGraphicsItem *> sel = scene()->selectedItems();
|
int childIndex = 0;
|
||||||
int j = 0;
|
for (const auto &item : scene()->selectedItems()) {
|
||||||
for (int i = 0; i < sel.size(); i++) {
|
CardItem *card = static_cast<CardItem *>(item);
|
||||||
CardItem *c = static_cast<CardItem *>(sel.at(i));
|
if ((card == this) || (card->getZone() != zone))
|
||||||
if ((c == this) || (c->getZone() != zone))
|
|
||||||
continue;
|
continue;
|
||||||
++j;
|
++childIndex;
|
||||||
QPointF childPos;
|
QPointF childPos;
|
||||||
if (zone->getHasCardAttr())
|
if (zone->getHasCardAttr())
|
||||||
childPos = c->pos() - pos();
|
childPos = card->pos() - pos();
|
||||||
else
|
else
|
||||||
childPos = QPointF(j * CARD_WIDTH / 2, 0);
|
childPos = QPointF(childIndex * CARD_WIDTH / 2, 0);
|
||||||
CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem);
|
CardDragItem *drag =
|
||||||
|
new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem);
|
||||||
drag->setPos(dragItem->pos() + childPos);
|
drag->setPos(dragItem->pos() + childPos);
|
||||||
scene()->addItem(drag);
|
scene()->addItem(drag);
|
||||||
}
|
}
|
||||||
@@ -360,15 +389,15 @@ void CardItem::playCard(bool faceDown)
|
|||||||
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::RightButton) {
|
if (event->button() == Qt::RightButton) {
|
||||||
if (cardMenu && !cardMenu->isEmpty() && owner) {
|
if (cardMenu != nullptr && !cardMenu->isEmpty() && owner != nullptr) {
|
||||||
owner->updateCardMenu(this);
|
cardMenu->popup(event->screenPos());
|
||||||
cardMenu->exec(event->screenPos());
|
return;
|
||||||
}
|
}
|
||||||
} else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
|
} else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
|
||||||
(!settingsCache->getDoubleClickToPlay())) {
|
(!SettingsCache::instance().getDoubleClickToPlay())) {
|
||||||
bool hideCard = false;
|
bool hideCard = false;
|
||||||
if (zone && zone->getIsView()) {
|
if (zone && zone->getIsView()) {
|
||||||
ZoneViewZone *view = static_cast<ZoneViewZone *>(zone);
|
auto *view = static_cast<ZoneViewZone *>(zone);
|
||||||
if (view->getRevealZone() && !view->getWriteableRevealZone())
|
if (view->getRevealZone() && !view->getWriteableRevealZone())
|
||||||
hideCard = true;
|
hideCard = true;
|
||||||
}
|
}
|
||||||
@@ -379,13 +408,15 @@ void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCursor(Qt::OpenHandCursor);
|
if (owner != nullptr) { // cards without owner will be deleted
|
||||||
|
setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
AbstractCardItem::mouseReleaseEvent(event);
|
AbstractCardItem::mouseReleaseEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if ((event->modifiers() != Qt::AltModifier) && (settingsCache->getDoubleClickToPlay()) &&
|
if ((event->modifiers() != Qt::AltModifier) && (SettingsCache::instance().getDoubleClickToPlay()) &&
|
||||||
(event->buttons() == Qt::LeftButton)) {
|
(event->buttons() == Qt::LeftButton)) {
|
||||||
if (revealedCard)
|
if (revealedCard)
|
||||||
zone->removeCard(this);
|
zone->removeCard(this);
|
||||||
@@ -424,13 +455,13 @@ bool CardItem::animationEvent()
|
|||||||
|
|
||||||
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||||
{
|
{
|
||||||
if ((change == ItemSelectedHasChanged) && owner) {
|
if ((change == ItemSelectedHasChanged) && owner != nullptr) {
|
||||||
if (value == true) {
|
if (value == true) {
|
||||||
owner->setCardMenu(cardMenu);
|
owner->setCardMenu(cardMenu);
|
||||||
owner->getGame()->setActiveCard(this);
|
owner->getGame()->setActiveCard(this);
|
||||||
} else if (owner->getCardMenu() == cardMenu) {
|
} else if (owner->getCardMenu() == cardMenu) {
|
||||||
owner->setCardMenu(0);
|
owner->setCardMenu(nullptr);
|
||||||
owner->getGame()->setActiveCard(0);
|
owner->getGame()->setActiveCard(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QGraphicsItem::itemChange(change, value);
|
return QGraphicsItem::itemChange(change, value);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define CARDITEM_H
|
#define CARDITEM_H
|
||||||
|
|
||||||
#include "abstractcarditem.h"
|
#include "abstractcarditem.h"
|
||||||
|
#include "server_card.h"
|
||||||
|
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class CardDragItem;
|
class CardDragItem;
|
||||||
@@ -52,7 +53,8 @@ public:
|
|||||||
const QString &_name = QString(),
|
const QString &_name = QString(),
|
||||||
int _cardid = -1,
|
int _cardid = -1,
|
||||||
bool revealedCard = false,
|
bool revealedCard = false,
|
||||||
QGraphicsItem *parent = 0);
|
QGraphicsItem *parent = nullptr,
|
||||||
|
CardZone *_zone = nullptr);
|
||||||
~CardItem();
|
~CardItem();
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
CardZone *getZone() const
|
CardZone *getZone() const
|
||||||
@@ -129,7 +131,7 @@ public:
|
|||||||
}
|
}
|
||||||
void removeAttachedCard(CardItem *card)
|
void removeAttachedCard(CardItem *card)
|
||||||
{
|
{
|
||||||
attachedCards.removeAt(attachedCards.indexOf(card));
|
attachedCards.removeOne(card);
|
||||||
}
|
}
|
||||||
const QList<CardItem *> &getAttachedCards() const
|
const QList<CardItem *> &getAttachedCards() const
|
||||||
{
|
{
|
||||||
@@ -155,6 +157,7 @@ public:
|
|||||||
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
|
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
|
||||||
void deleteDragItem();
|
void deleteDragItem();
|
||||||
void drawArrow(const QColor &arrowColor);
|
void drawArrow(const QColor &arrowColor);
|
||||||
|
void drawAttachArrow();
|
||||||
void playCard(bool faceDown);
|
void playCard(bool faceDown);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "cardlist.h"
|
#include "cardlist.h"
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
CardList::CardList(bool _contentsKnown) : QList<CardItem *>(), contentsKnown(_contentsKnown)
|
CardList::CardList(bool _contentsKnown) : QList<CardItem *>(), contentsKnown(_contentsKnown)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -56,5 +59,5 @@ public:
|
|||||||
void CardList::sort(int flags)
|
void CardList::sort(int flags)
|
||||||
{
|
{
|
||||||
compareFunctor cf(flags);
|
compareFunctor cf(flags);
|
||||||
qSort(begin(), end(), cf);
|
std::sort(begin(), end(), cf);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "cardzone.h"
|
#include "cardzone.h"
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "pb/command_move_card.pb.h"
|
#include "pb/command_move_card.pb.h"
|
||||||
#include "pb/serverinfo_user.pb.h"
|
#include "pb/serverinfo_user.pb.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "zoneviewzone.h"
|
#include "zoneviewzone.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
@@ -16,7 +18,7 @@ CardZone::CardZone(Player *_p,
|
|||||||
bool _contentsKnown,
|
bool _contentsKnown,
|
||||||
QGraphicsItem *parent,
|
QGraphicsItem *parent,
|
||||||
bool _isView)
|
bool _isView)
|
||||||
: AbstractGraphicsItem(parent), player(_p), name(_name), cards(_contentsKnown), view(NULL), menu(NULL),
|
: AbstractGraphicsItem(parent), player(_p), name(_name), cards(_contentsKnown), views{}, menu(nullptr),
|
||||||
doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable), isView(_isView)
|
doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable), isView(_isView)
|
||||||
{
|
{
|
||||||
if (!isView)
|
if (!isView)
|
||||||
@@ -26,7 +28,11 @@ CardZone::CardZone(Player *_p,
|
|||||||
CardZone::~CardZone()
|
CardZone::~CardZone()
|
||||||
{
|
{
|
||||||
qDebug() << "CardZone destructor: " << name;
|
qDebug() << "CardZone destructor: " << name;
|
||||||
delete view;
|
for (auto *view : views) {
|
||||||
|
if (view != nullptr) {
|
||||||
|
view->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
clearContents();
|
clearContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +124,11 @@ void CardZone::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
void CardZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
void CardZone::addCard(CardItem *card, bool reorganize, int x, int y)
|
||||||
{
|
{
|
||||||
if (view)
|
for (auto *view : views) {
|
||||||
if ((x <= view->getCards().size()) || (view->getNumberCards() == -1))
|
if ((x <= view->getCards().size()) || (view->getNumberCards() == -1)) {
|
||||||
view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y);
|
view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
card->setZone(this);
|
card->setZone(this);
|
||||||
addCardImpl(card, x, y);
|
addCardImpl(card, x, y);
|
||||||
@@ -166,8 +174,9 @@ CardItem *CardZone::takeCard(int position, int cardId, bool /*canResize*/)
|
|||||||
|
|
||||||
CardItem *c = cards.takeAt(position);
|
CardItem *c = cards.takeAt(position);
|
||||||
|
|
||||||
if (view)
|
for (auto *view : views) {
|
||||||
view->removeCard(position);
|
view->removeCard(position);
|
||||||
|
}
|
||||||
|
|
||||||
c->setId(cardId);
|
c->setId(cardId);
|
||||||
|
|
||||||
@@ -178,7 +187,7 @@ CardItem *CardZone::takeCard(int position, int cardId, bool /*canResize*/)
|
|||||||
|
|
||||||
void CardZone::removeCard(CardItem *card)
|
void CardZone::removeCard(CardItem *card)
|
||||||
{
|
{
|
||||||
cards.removeAt(cards.indexOf(card));
|
cards.removeOne(card);
|
||||||
reorganizeCards();
|
reorganizeCards();
|
||||||
emit cardCountChanged();
|
emit cardCountChanged();
|
||||||
player->deleteCard(card);
|
player->deleteCard(card);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "abstractgraphicsitem.h"
|
#include "abstractgraphicsitem.h"
|
||||||
#include "cardlist.h"
|
#include "cardlist.h"
|
||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
@@ -20,7 +21,7 @@ protected:
|
|||||||
Player *player;
|
Player *player;
|
||||||
QString name;
|
QString name;
|
||||||
CardList cards;
|
CardList cards;
|
||||||
ZoneViewZone *view;
|
QList<ZoneViewZone *> views;
|
||||||
QMenu *menu;
|
QMenu *menu;
|
||||||
QAction *doubleClickAction;
|
QAction *doubleClickAction;
|
||||||
bool hasCardAttr;
|
bool hasCardAttr;
|
||||||
@@ -52,7 +53,7 @@ public:
|
|||||||
bool _hasCardAttr,
|
bool _hasCardAttr,
|
||||||
bool _isShufflable,
|
bool _isShufflable,
|
||||||
bool _contentsKnown,
|
bool _contentsKnown,
|
||||||
QGraphicsItem *parent = 0,
|
QGraphicsItem *parent = nullptr,
|
||||||
bool _isView = false);
|
bool _isView = false);
|
||||||
~CardZone();
|
~CardZone();
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
@@ -97,13 +98,9 @@ public:
|
|||||||
// takeCard() finds a card by position and removes it from the zone and from all of its views.
|
// takeCard() finds a card by position and removes it from the zone and from all of its views.
|
||||||
virtual CardItem *takeCard(int position, int cardId, bool canResize = true);
|
virtual CardItem *takeCard(int position, int cardId, bool canResize = true);
|
||||||
void removeCard(CardItem *card);
|
void removeCard(CardItem *card);
|
||||||
ZoneViewZone *getView() const
|
QList<ZoneViewZone *> &getViews()
|
||||||
{
|
{
|
||||||
return view;
|
return views;
|
||||||
}
|
|
||||||
void setView(ZoneViewZone *_view)
|
|
||||||
{
|
|
||||||
view = _view;
|
|
||||||
}
|
}
|
||||||
virtual void reorganizeCards() = 0;
|
virtual void reorganizeCards() = 0;
|
||||||
virtual QPointF closestGridPoint(const QPointF &point);
|
virtual QPointF closestGridPoint(const QPointF &point);
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
#include "chatview.h"
|
#include "chatview.h"
|
||||||
|
|
||||||
#include "../pixmapgenerator.h"
|
#include "../pixmapgenerator.h"
|
||||||
#include "../settingscache.h"
|
#include "../settingscache.h"
|
||||||
#include "../soundengine.h"
|
#include "../soundengine.h"
|
||||||
#include "../tab_userlists.h"
|
#include "../tab_account.h"
|
||||||
#include "../user_context_menu.h"
|
#include "../user_context_menu.h"
|
||||||
#include "user_level.h"
|
#include "user_level.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QTextEdit>
|
|
||||||
|
|
||||||
const QColor DEFAULT_MENTION_COLOR = QColor(194, 31, 47);
|
const QColor DEFAULT_MENTION_COLOR = QColor(194, 31, 47);
|
||||||
|
|
||||||
ChatView::ChatView(const TabSupervisor *_tabSupervisor,
|
UserMessagePosition::UserMessagePosition(QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
block = cursor.block();
|
||||||
|
relativePosition = cursor.position() - block.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatView::ChatView(TabSupervisor *_tabSupervisor,
|
||||||
const UserlistProxy *_userlistProxy,
|
const UserlistProxy *_userlistProxy,
|
||||||
TabGame *_game,
|
TabGame *_game,
|
||||||
bool _showTimestamps,
|
bool _showTimestamps,
|
||||||
@@ -29,23 +36,25 @@ ChatView::ChatView(const TabSupervisor *_tabSupervisor,
|
|||||||
)");
|
)");
|
||||||
serverMessageColor = QColor(0xFF, 0x73, 0x83);
|
serverMessageColor = QColor(0xFF, 0x73, 0x83);
|
||||||
otherUserColor = otherUserColor.lighter(150);
|
otherUserColor = otherUserColor.lighter(150);
|
||||||
|
linkColor = QColor(71, 158, 252);
|
||||||
} else {
|
} else {
|
||||||
document()->setDefaultStyleSheet(R"(
|
document()->setDefaultStyleSheet(R"(
|
||||||
a { text-decoration: none; color: blue; }
|
a { text-decoration: none; color: blue; }
|
||||||
.blue { color: blue }
|
.blue { color: blue }
|
||||||
)");
|
)");
|
||||||
|
linkColor = palette().link().color();
|
||||||
}
|
}
|
||||||
|
|
||||||
userContextMenu = new UserContextMenu(tabSupervisor, this, game);
|
userContextMenu = new UserContextMenu(tabSupervisor, this, game);
|
||||||
connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
||||||
|
|
||||||
userName = userlistProxy->getOwnUsername();
|
ownUserName = userlistProxy->getOwnUsername();
|
||||||
mention = "@" + userName;
|
mention = "@" + ownUserName;
|
||||||
|
|
||||||
mentionFormat.setFontWeight(QFont::Bold);
|
mentionFormat.setFontWeight(QFont::Bold);
|
||||||
|
|
||||||
mentionFormatOtherUser.setFontWeight(QFont::Bold);
|
mentionFormatOtherUser.setFontWeight(QFont::Bold);
|
||||||
mentionFormatOtherUser.setForeground(palette().link());
|
mentionFormatOtherUser.setForeground(linkColor);
|
||||||
mentionFormatOtherUser.setAnchor(true);
|
mentionFormatOtherUser.setAnchor(true);
|
||||||
|
|
||||||
viewport()->setCursor(Qt::IBeamCursor);
|
viewport()->setCursor(Qt::IBeamCursor);
|
||||||
@@ -64,7 +73,7 @@ QTextCursor ChatView::prepareBlock(bool same)
|
|||||||
{
|
{
|
||||||
lastSender.clear();
|
lastSender.clear();
|
||||||
|
|
||||||
QTextCursor cursor(document()->lastBlock());
|
QTextCursor cursor(document());
|
||||||
cursor.movePosition(QTextCursor::End);
|
cursor.movePosition(QTextCursor::End);
|
||||||
if (same) {
|
if (same) {
|
||||||
cursor.insertHtml("<br>");
|
cursor.insertHtml("<br>");
|
||||||
@@ -111,7 +120,7 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName)
|
|||||||
{
|
{
|
||||||
QTextCharFormat oldFormat = cursor.charFormat();
|
QTextCharFormat oldFormat = cursor.charFormat();
|
||||||
QTextCharFormat anchorFormat = oldFormat;
|
QTextCharFormat anchorFormat = oldFormat;
|
||||||
anchorFormat.setForeground(palette().link());
|
anchorFormat.setForeground(linkColor);
|
||||||
anchorFormat.setAnchor(true);
|
anchorFormat.setAnchor(true);
|
||||||
anchorFormat.setAnchorHref("card://" + cardName);
|
anchorFormat.setAnchorHref("card://" + cardName);
|
||||||
anchorFormat.setFontItalic(true);
|
anchorFormat.setFontItalic(true);
|
||||||
@@ -124,14 +133,14 @@ void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName)
|
|||||||
void ChatView::appendUrlTag(QTextCursor &cursor, QString url)
|
void ChatView::appendUrlTag(QTextCursor &cursor, QString url)
|
||||||
{
|
{
|
||||||
if (!url.contains("://"))
|
if (!url.contains("://"))
|
||||||
url.prepend("http://");
|
url.prepend("https://");
|
||||||
|
|
||||||
QTextCharFormat oldFormat = cursor.charFormat();
|
QTextCharFormat oldFormat = cursor.charFormat();
|
||||||
QTextCharFormat anchorFormat = oldFormat;
|
QTextCharFormat anchorFormat = oldFormat;
|
||||||
anchorFormat.setForeground(palette().link());
|
anchorFormat.setForeground(linkColor);
|
||||||
anchorFormat.setAnchor(true);
|
anchorFormat.setAnchor(true);
|
||||||
anchorFormat.setAnchorHref(url);
|
anchorFormat.setAnchorHref(url);
|
||||||
anchorFormat.setUnderlineColor(palette().link().color());
|
anchorFormat.setUnderlineColor(linkColor);
|
||||||
anchorFormat.setFontUnderline(true);
|
anchorFormat.setFontUnderline(true);
|
||||||
|
|
||||||
cursor.setCharFormat(anchorFormat);
|
cursor.setCharFormat(anchorFormat);
|
||||||
@@ -141,81 +150,95 @@ void ChatView::appendUrlTag(QTextCursor &cursor, QString url)
|
|||||||
|
|
||||||
void ChatView::appendMessage(QString message,
|
void ChatView::appendMessage(QString message,
|
||||||
RoomMessageTypeFlags messageType,
|
RoomMessageTypeFlags messageType,
|
||||||
QString sender,
|
const QString &userName,
|
||||||
UserLevelFlags userLevel,
|
UserLevelFlags userLevel,
|
||||||
QString UserPrivLevel,
|
QString UserPrivLevel,
|
||||||
bool playerBold)
|
bool playerBold)
|
||||||
{
|
{
|
||||||
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
|
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
|
||||||
bool sameSender = (sender == lastSender) && !lastSender.isEmpty();
|
// messageType should be Event_RoomSay::UserMessage though we don't actually check
|
||||||
|
bool isUserMessage = !(userName.toLower() == "servatrice" || userName.isEmpty());
|
||||||
|
bool sameSender = isUserMessage && userName == lastSender;
|
||||||
QTextCursor cursor = prepareBlock(sameSender);
|
QTextCursor cursor = prepareBlock(sameSender);
|
||||||
lastSender = sender;
|
lastSender = userName;
|
||||||
|
|
||||||
// timestamp
|
// timestamp
|
||||||
if (showTimestamps && (!sameSender || sender.toLower() == "servatrice") && !sender.isEmpty()) {
|
if (showTimestamps && ((!sameSender && isUserMessage) || userName.toLower() == "servatrice")) {
|
||||||
QTextCharFormat timeFormat;
|
QTextCharFormat timeFormat;
|
||||||
timeFormat.setForeground(serverMessageColor);
|
timeFormat.setForeground(serverMessageColor);
|
||||||
if (sender.isEmpty())
|
timeFormat.setFontWeight(QFont::Bold);
|
||||||
timeFormat.setFontWeight(QFont::Bold);
|
|
||||||
cursor.setCharFormat(timeFormat);
|
cursor.setCharFormat(timeFormat);
|
||||||
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm:ss] "));
|
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm:ss] "));
|
||||||
}
|
}
|
||||||
|
|
||||||
// nickname
|
// nickname
|
||||||
if (sender.toLower() != "servatrice") {
|
if (isUserMessage) {
|
||||||
QTextCharFormat senderFormat;
|
QTextCharFormat senderFormat;
|
||||||
if (sender == userName) {
|
if (userName == ownUserName) {
|
||||||
senderFormat.setForeground(QBrush(getCustomMentionColor()));
|
senderFormat.setForeground(QBrush(getCustomMentionColor()));
|
||||||
senderFormat.setFontWeight(QFont::Bold);
|
senderFormat.setFontWeight(QFont::Bold);
|
||||||
} else {
|
} else {
|
||||||
senderFormat.setForeground(QBrush(otherUserColor));
|
senderFormat.setForeground(QBrush(otherUserColor));
|
||||||
if (playerBold)
|
if (playerBold) {
|
||||||
senderFormat.setFontWeight(QFont::Bold);
|
senderFormat.setFontWeight(QFont::Bold);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
senderFormat.setAnchor(true);
|
senderFormat.setAnchor(true);
|
||||||
senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + sender);
|
senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + userName);
|
||||||
if (sameSender) {
|
if (sameSender) {
|
||||||
cursor.insertText(" ");
|
cursor.insertText(" ");
|
||||||
} else {
|
} else {
|
||||||
if (!sender.isEmpty()) {
|
const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize();
|
||||||
const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize();
|
bool isBuddy = userlistProxy->isUserBuddy(userName);
|
||||||
bool isBuddy = userlistProxy->isUserBuddy(sender);
|
cursor.insertImage(
|
||||||
cursor.insertImage(
|
UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel, isBuddy, UserPrivLevel).toImage());
|
||||||
UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel, isBuddy, UserPrivLevel).toImage());
|
cursor.insertText(" ");
|
||||||
cursor.insertText(" ");
|
|
||||||
}
|
|
||||||
cursor.setCharFormat(senderFormat);
|
cursor.setCharFormat(senderFormat);
|
||||||
if (!sender.isEmpty())
|
cursor.insertText(userName);
|
||||||
sender.append(": ");
|
cursor.insertText(": ");
|
||||||
cursor.insertText(sender);
|
userMessagePositions[userName].append(cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use different color for server messages
|
// use different color for server messages
|
||||||
defaultFormat = QTextCharFormat();
|
defaultFormat = QTextCharFormat();
|
||||||
if (sender.isEmpty()) {
|
if (!isUserMessage) {
|
||||||
switch (messageType) {
|
if (messageType == Event_RoomSay::ChatHistory) {
|
||||||
case Event_RoomSay::Welcome:
|
defaultFormat.setForeground(Qt::gray); // FIXME : hardcoded color
|
||||||
defaultFormat.setForeground(Qt::darkGreen);
|
defaultFormat.setFontWeight(QFont::Light);
|
||||||
defaultFormat.setFontWeight(QFont::Bold);
|
defaultFormat.setFontItalic(true);
|
||||||
break;
|
static const QRegularExpression userNameRegex("^(\\[[^\\]]*\\]\\s)(\\S+):\\s");
|
||||||
case Event_RoomSay::ChatHistory:
|
auto match = userNameRegex.match(message);
|
||||||
defaultFormat.setForeground(Qt::gray);
|
if (match.hasMatch()) {
|
||||||
defaultFormat.setFontWeight(QFont::Light);
|
cursor.setCharFormat(defaultFormat);
|
||||||
defaultFormat.setFontItalic(true);
|
UserMessagePosition pos(cursor);
|
||||||
break;
|
pos.relativePosition = match.captured(0).length(); // set message start
|
||||||
default:
|
auto before = match.captured(1);
|
||||||
defaultFormat.setForeground(Qt::darkGreen);
|
auto sentBy = match.captured(2);
|
||||||
defaultFormat.setFontWeight(QFont::Bold);
|
cursor.insertText(before); // add message timestamp
|
||||||
|
QTextCharFormat senderFormat(defaultFormat);
|
||||||
|
senderFormat.setAnchor(true);
|
||||||
|
// this underscore is important, it is used to add the user level, but in this case the level is
|
||||||
|
// unknown, if the name contains an underscore it would split up the name
|
||||||
|
senderFormat.setAnchorHref("user://_" + sentBy);
|
||||||
|
cursor.setCharFormat(senderFormat);
|
||||||
|
cursor.insertText(sentBy); // add username with href so it shows the menu
|
||||||
|
userMessagePositions[sentBy].append(pos); // save message position
|
||||||
|
message.remove(0, pos.relativePosition - 2); // do not remove semicolon
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
defaultFormat.setForeground(Qt::darkGreen); // FIXME : hardcoded color
|
||||||
|
defaultFormat.setFontWeight(QFont::Bold);
|
||||||
}
|
}
|
||||||
} else if (sender.toLower() == "servatrice") {
|
|
||||||
defaultFormat.setForeground(Qt::darkGreen);
|
|
||||||
defaultFormat.setFontWeight(QFont::Bold);
|
|
||||||
}
|
}
|
||||||
cursor.setCharFormat(defaultFormat);
|
cursor.setCharFormat(defaultFormat);
|
||||||
|
|
||||||
bool mentionEnabled = settingsCache->getChatMention();
|
bool mentionEnabled = SettingsCache::instance().getChatMention();
|
||||||
highlightedWords = settingsCache->getHighlightWords().split(' ', QString::SkipEmptyParts);
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
|
highlightedWords = SettingsCache::instance().getHighlightWords().split(' ', Qt::SkipEmptyParts);
|
||||||
|
#else
|
||||||
|
highlightedWords = SettingsCache::instance().getHighlightWords().split(' ', QString::SkipEmptyParts);
|
||||||
|
#endif
|
||||||
|
|
||||||
// parse the message
|
// parse the message
|
||||||
while (message.size()) {
|
while (message.size()) {
|
||||||
@@ -226,7 +249,7 @@ void ChatView::appendMessage(QString message,
|
|||||||
break;
|
break;
|
||||||
case '@':
|
case '@':
|
||||||
if (mentionEnabled) {
|
if (mentionEnabled) {
|
||||||
checkMention(cursor, message, sender, userLevel);
|
checkMention(cursor, message, userName, userLevel);
|
||||||
} else {
|
} else {
|
||||||
cursor.insertText(c, defaultFormat);
|
cursor.insertText(c, defaultFormat);
|
||||||
message = message.mid(1);
|
message = message.mid(1);
|
||||||
@@ -296,9 +319,9 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message)
|
|||||||
checkWord(cursor, message);
|
checkWord(cursor, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatView::checkMention(QTextCursor &cursor, QString &message, QString &sender, UserLevelFlags userLevel)
|
void ChatView::checkMention(QTextCursor &cursor, QString &message, const QString &userName, UserLevelFlags userLevel)
|
||||||
{
|
{
|
||||||
const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]");
|
const static auto notALetterOrNumber = QRegularExpression("[^a-zA-Z0-9]");
|
||||||
|
|
||||||
int firstSpace = message.indexOf(' ');
|
int firstSpace = message.indexOf(' ');
|
||||||
QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1);
|
QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1);
|
||||||
@@ -308,16 +331,16 @@ void ChatView::checkMention(QTextCursor &cursor, QString &message, QString &send
|
|||||||
const ServerInfo_User *onlineUser = userlistProxy->getOnlineUser(fullMentionUpToSpaceOrEnd);
|
const ServerInfo_User *onlineUser = userlistProxy->getOnlineUser(fullMentionUpToSpaceOrEnd);
|
||||||
if (onlineUser) // Is there a user online named this?
|
if (onlineUser) // Is there a user online named this?
|
||||||
{
|
{
|
||||||
if (userName.toLower() == fullMentionUpToSpaceOrEnd.toLower()) // Is this user you?
|
if (ownUserName.toLower() == fullMentionUpToSpaceOrEnd.toLower()) // Is this user you?
|
||||||
{
|
{
|
||||||
// You have received a valid mention!!
|
// You have received a valid mention!!
|
||||||
soundEngine->playSound("chat_mention");
|
soundEngine->playSound("chat_mention");
|
||||||
mentionFormat.setBackground(QBrush(getCustomMentionColor()));
|
mentionFormat.setBackground(QBrush(getCustomMentionColor()));
|
||||||
mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white)
|
mentionFormat.setForeground(SettingsCache::instance().getChatMentionForeground() ? QBrush(Qt::white)
|
||||||
: QBrush(Qt::black));
|
: QBrush(Qt::black));
|
||||||
cursor.insertText(mention, mentionFormat);
|
cursor.insertText(mention, mentionFormat);
|
||||||
message = message.mid(mention.size());
|
message = message.mid(mention.size());
|
||||||
showSystemPopup(sender);
|
showSystemPopup(userName);
|
||||||
} else {
|
} else {
|
||||||
QString correctUserName = QString::fromStdString(onlineUser->name());
|
QString correctUserName = QString::fromStdString(onlineUser->name());
|
||||||
mentionFormatOtherUser.setAnchorHref("user://" + QString::number(onlineUser->user_level()) + "_" +
|
mentionFormatOtherUser.setAnchorHref("user://" + QString::number(onlineUser->user_level()) + "_" +
|
||||||
@@ -335,11 +358,11 @@ void ChatView::checkMention(QTextCursor &cursor, QString &message, QString &send
|
|||||||
// Moderator Sending Global Message
|
// Moderator Sending Global Message
|
||||||
soundEngine->playSound("all_mention");
|
soundEngine->playSound("all_mention");
|
||||||
mentionFormat.setBackground(QBrush(getCustomMentionColor()));
|
mentionFormat.setBackground(QBrush(getCustomMentionColor()));
|
||||||
mentionFormat.setForeground(settingsCache->getChatMentionForeground() ? QBrush(Qt::white)
|
mentionFormat.setForeground(SettingsCache::instance().getChatMentionForeground() ? QBrush(Qt::white)
|
||||||
: QBrush(Qt::black));
|
: QBrush(Qt::black));
|
||||||
cursor.insertText("@" + fullMentionUpToSpaceOrEnd, mentionFormat);
|
cursor.insertText("@" + fullMentionUpToSpaceOrEnd, mentionFormat);
|
||||||
message = message.mid(fullMentionUpToSpaceOrEnd.size() + 1);
|
message = message.mid(fullMentionUpToSpaceOrEnd.size() + 1);
|
||||||
showSystemPopup(sender);
|
showSystemPopup(userName);
|
||||||
|
|
||||||
cursor.setCharFormat(defaultFormat);
|
cursor.setCharFormat(defaultFormat);
|
||||||
return;
|
return;
|
||||||
@@ -383,8 +406,8 @@ void ChatView::checkWord(QTextCursor &cursor, QString &message)
|
|||||||
if (fullWordUpToSpaceOrEnd.compare(word, Qt::CaseInsensitive) == 0) {
|
if (fullWordUpToSpaceOrEnd.compare(word, Qt::CaseInsensitive) == 0) {
|
||||||
// You have received a valid mention of custom word!!
|
// You have received a valid mention of custom word!!
|
||||||
highlightFormat.setBackground(QBrush(getCustomHighlightColor()));
|
highlightFormat.setBackground(QBrush(getCustomHighlightColor()));
|
||||||
highlightFormat.setForeground(settingsCache->getChatHighlightForeground() ? QBrush(Qt::white)
|
highlightFormat.setForeground(SettingsCache::instance().getChatHighlightForeground() ? QBrush(Qt::white)
|
||||||
: QBrush(Qt::black));
|
: QBrush(Qt::black));
|
||||||
cursor.insertText(fullWordUpToSpaceOrEnd, highlightFormat);
|
cursor.insertText(fullWordUpToSpaceOrEnd, highlightFormat);
|
||||||
cursor.insertText(rest, defaultFormat);
|
cursor.insertText(rest, defaultFormat);
|
||||||
QApplication::alert(this);
|
QApplication::alert(this);
|
||||||
@@ -437,26 +460,25 @@ void ChatView::actMessageClicked()
|
|||||||
emit messageClickedSignal();
|
emit messageClickedSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatView::showSystemPopup(QString &sender)
|
void ChatView::showSystemPopup(const QString &userName)
|
||||||
{
|
{
|
||||||
QApplication::alert(this);
|
QApplication::alert(this);
|
||||||
if (settingsCache->getShowMentionPopup()) {
|
if (SettingsCache::instance().getShowMentionPopup()) {
|
||||||
QString ref = sender.left(sender.length() - 2);
|
emit showMentionPopup(userName);
|
||||||
emit showMentionPopup(ref);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor ChatView::getCustomMentionColor()
|
QColor ChatView::getCustomMentionColor()
|
||||||
{
|
{
|
||||||
QColor customColor;
|
QColor customColor;
|
||||||
customColor.setNamedColor("#" + settingsCache->getChatMentionColor());
|
customColor.setNamedColor("#" + SettingsCache::instance().getChatMentionColor());
|
||||||
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor ChatView::getCustomHighlightColor()
|
QColor ChatView::getCustomHighlightColor()
|
||||||
{
|
{
|
||||||
QColor customColor;
|
QColor customColor;
|
||||||
customColor.setNamedColor("#" + settingsCache->getChatHighlightColor());
|
customColor.setNamedColor("#" + SettingsCache::instance().getChatHighlightColor());
|
||||||
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +488,33 @@ void ChatView::clearChat()
|
|||||||
lastSender = "";
|
lastSender = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatView::redactMessages(const QString &userName, int amount)
|
||||||
|
{
|
||||||
|
auto &messagePositions = userMessagePositions[userName];
|
||||||
|
bool removedLastMessage = false;
|
||||||
|
QTextCursor cursor(document());
|
||||||
|
for (; !messagePositions.isEmpty() && amount != 0; --amount) {
|
||||||
|
auto position = messagePositions.takeLast(); // go backwards from last message
|
||||||
|
cursor.setPosition(position.block.position()); // move to start of block, then continue to start of message
|
||||||
|
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, position.relativePosition);
|
||||||
|
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); // select until end of block
|
||||||
|
cursor.removeSelectedText();
|
||||||
|
// if the cursor is at the end of the text it is possible to add text to this block still
|
||||||
|
removedLastMessage |= cursor.atEnd();
|
||||||
|
// we will readd this position later
|
||||||
|
}
|
||||||
|
if (removedLastMessage) {
|
||||||
|
cursor.movePosition(QTextCursor::End);
|
||||||
|
messagePositions.append(cursor);
|
||||||
|
// note that this message might stay empty, this is not harmful as it will simply remove nothing the next time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void ChatView::enterEvent(QEnterEvent * /*event*/)
|
||||||
|
#else
|
||||||
void ChatView::enterEvent(QEvent * /*event*/)
|
void ChatView::enterEvent(QEvent * /*event*/)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
@@ -521,18 +569,26 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
switch (hoveredItemType) {
|
switch (hoveredItemType) {
|
||||||
case HoveredCard: {
|
case HoveredCard: {
|
||||||
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
|
if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton))
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
emit showCardInfoPopup(event->globalPosition().toPoint(), hoveredContent);
|
||||||
|
#else
|
||||||
emit showCardInfoPopup(event->globalPos(), hoveredContent);
|
emit showCardInfoPopup(event->globalPos(), hoveredContent);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HoveredUser: {
|
case HoveredUser: {
|
||||||
if (event->button() != Qt::MidButton) {
|
if (event->button() != Qt::MiddleButton) {
|
||||||
const int delimiterIndex = hoveredContent.indexOf("_");
|
const int delimiterIndex = hoveredContent.indexOf("_");
|
||||||
const QString userName = hoveredContent.mid(delimiterIndex + 1);
|
const QString userName = hoveredContent.mid(delimiterIndex + 1);
|
||||||
switch (event->button()) {
|
switch (event->button()) {
|
||||||
case Qt::RightButton: {
|
case Qt::RightButton: {
|
||||||
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
|
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
|
||||||
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel);
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
userContextMenu->showContextMenu(event->globalPosition().toPoint(), userName, userLevel, this);
|
||||||
|
#else
|
||||||
|
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel, this);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::LeftButton: {
|
case Qt::LeftButton: {
|
||||||
@@ -556,7 +612,7 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void ChatView::mouseReleaseEvent(QMouseEvent *event)
|
void ChatView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
|
if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton))
|
||||||
emit deleteCardInfoPopup(QString("_"));
|
emit deleteCardInfoPopup(QString("_"));
|
||||||
|
|
||||||
QTextBrowser::mouseReleaseEvent(event);
|
QTextBrowser::mouseReleaseEvent(event);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "room_message_type.h"
|
#include "room_message_type.h"
|
||||||
#include "user_level.h"
|
#include "user_level.h"
|
||||||
#include "userlistProxy.h"
|
#include "userlistProxy.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
@@ -17,11 +18,22 @@ class QMouseEvent;
|
|||||||
class UserContextMenu;
|
class UserContextMenu;
|
||||||
class TabGame;
|
class TabGame;
|
||||||
|
|
||||||
|
class UserMessagePosition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
|
||||||
|
UserMessagePosition() = default; // older qt versions require a default constructor to use in containers
|
||||||
|
#endif
|
||||||
|
UserMessagePosition(QTextCursor &cursor);
|
||||||
|
int relativePosition;
|
||||||
|
QTextBlock block;
|
||||||
|
};
|
||||||
|
|
||||||
class ChatView : public QTextBrowser
|
class ChatView : public QTextBrowser
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
const TabSupervisor *const tabSupervisor;
|
TabSupervisor *const tabSupervisor;
|
||||||
TabGame *const game;
|
TabGame *const game;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -35,7 +47,7 @@ private:
|
|||||||
const UserlistProxy *const userlistProxy;
|
const UserlistProxy *const userlistProxy;
|
||||||
UserContextMenu *userContextMenu;
|
UserContextMenu *userContextMenu;
|
||||||
QString lastSender;
|
QString lastSender;
|
||||||
QString userName;
|
QString ownUserName;
|
||||||
QString mention;
|
QString mention;
|
||||||
QTextCharFormat mentionFormat;
|
QTextCharFormat mentionFormat;
|
||||||
QTextCharFormat highlightFormat;
|
QTextCharFormat highlightFormat;
|
||||||
@@ -47,47 +59,55 @@ private:
|
|||||||
HoveredItemType hoveredItemType;
|
HoveredItemType hoveredItemType;
|
||||||
QString hoveredContent;
|
QString hoveredContent;
|
||||||
QAction *messageClicked;
|
QAction *messageClicked;
|
||||||
|
QMap<QString, QVector<UserMessagePosition>> userMessagePositions;
|
||||||
|
|
||||||
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
|
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
|
||||||
QTextCursor prepareBlock(bool same = false);
|
QTextCursor prepareBlock(bool same = false);
|
||||||
void appendCardTag(QTextCursor &cursor, const QString &cardName);
|
void appendCardTag(QTextCursor &cursor, const QString &cardName);
|
||||||
void appendUrlTag(QTextCursor &cursor, QString url);
|
void appendUrlTag(QTextCursor &cursor, QString url);
|
||||||
QColor getCustomMentionColor();
|
QColor getCustomMentionColor();
|
||||||
QColor getCustomHighlightColor();
|
QColor getCustomHighlightColor();
|
||||||
void showSystemPopup(QString &sender);
|
void showSystemPopup(const QString &userName);
|
||||||
bool isModeratorSendingGlobal(QFlags<ServerInfo_User::UserLevelFlag> userLevelFlag, QString message);
|
bool isModeratorSendingGlobal(QFlags<ServerInfo_User::UserLevelFlag> userLevelFlag, QString message);
|
||||||
void checkTag(QTextCursor &cursor, QString &message);
|
void checkTag(QTextCursor &cursor, QString &message);
|
||||||
void checkMention(QTextCursor &cursor, QString &message, QString &sender, UserLevelFlags userLevel);
|
void checkMention(QTextCursor &cursor, QString &message, const QString &userName, UserLevelFlags userLevel);
|
||||||
void checkWord(QTextCursor &cursor, QString &message);
|
void checkWord(QTextCursor &cursor, QString &message);
|
||||||
QString extractNextWord(QString &message, QString &rest);
|
QString extractNextWord(QString &message, QString &rest);
|
||||||
|
|
||||||
QColor otherUserColor = QColor(0, 65, 255); // dark blue
|
QColor otherUserColor = QColor(0, 65, 255); // dark blue
|
||||||
QColor serverMessageColor = QColor(0x85, 0x15, 0x15);
|
QColor serverMessageColor = QColor(0x85, 0x15, 0x15);
|
||||||
|
QColor linkColor;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void openLink(const QUrl &link);
|
void openLink(const QUrl &link);
|
||||||
void actMessageClicked();
|
void actMessageClicked();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ChatView(const TabSupervisor *_tabSupervisor,
|
ChatView(TabSupervisor *_tabSupervisor,
|
||||||
const UserlistProxy *_userlistProxy,
|
const UserlistProxy *_userlistProxy,
|
||||||
TabGame *_game,
|
TabGame *_game,
|
||||||
bool _showTimestamps,
|
bool _showTimestamps,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = nullptr);
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void appendHtml(const QString &html);
|
void appendHtml(const QString &html);
|
||||||
void virtual appendHtmlServerMessage(const QString &html,
|
void virtual appendHtmlServerMessage(const QString &html,
|
||||||
bool optionalIsBold = false,
|
bool optionalIsBold = false,
|
||||||
QString optionalFontColor = QString());
|
QString optionalFontColor = QString());
|
||||||
void appendMessage(QString message,
|
void appendMessage(QString message,
|
||||||
RoomMessageTypeFlags messageType = 0,
|
RoomMessageTypeFlags messageType = {},
|
||||||
QString sender = QString(),
|
const QString &userName = QString(),
|
||||||
UserLevelFlags userLevel = UserLevelFlags(),
|
UserLevelFlags userLevel = UserLevelFlags(),
|
||||||
QString UserPrivLevel = "NONE",
|
QString UserPrivLevel = "NONE",
|
||||||
bool playerBold = false);
|
bool playerBold = false);
|
||||||
void clearChat();
|
void clearChat();
|
||||||
|
void redactMessages(const QString &userName, int amount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void enterEvent(QEnterEvent *event);
|
||||||
|
#else
|
||||||
void enterEvent(QEvent *event);
|
void enterEvent(QEvent *event);
|
||||||
|
#endif
|
||||||
void leaveEvent(QEvent *event);
|
void leaveEvent(QEvent *event);
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
@@ -99,7 +119,7 @@ signals:
|
|||||||
void deleteCardInfoPopup(QString cardName);
|
void deleteCardInfoPopup(QString cardName);
|
||||||
void addMentionTag(QString mentionTag);
|
void addMentionTag(QString mentionTag);
|
||||||
void messageClickedSignal();
|
void messageClickedSignal();
|
||||||
void showMentionPopup(QString &sender);
|
void showMentionPopup(const QString &userName);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "counter_general.h"
|
#include "counter_general.h"
|
||||||
|
|
||||||
#include "abstractgraphicsitem.h"
|
#include "abstractgraphicsitem.h"
|
||||||
#include "pixmapgenerator.h"
|
#include "pixmapgenerator.h"
|
||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
GeneralCounter::GeneralCounter(Player *_player,
|
GeneralCounter::GeneralCounter(Player *_player,
|
||||||
@@ -10,8 +12,10 @@ GeneralCounter::GeneralCounter(Player *_player,
|
|||||||
int _radius,
|
int _radius,
|
||||||
int _value,
|
int _value,
|
||||||
bool useNameForShortcut,
|
bool useNameForShortcut,
|
||||||
QGraphicsItem *parent)
|
QGraphicsItem *parent,
|
||||||
: AbstractCounter(_player, _id, _name, true, _value, useNameForShortcut, parent), color(_color), radius(_radius)
|
QWidget *game)
|
||||||
|
: AbstractCounter(_player, _id, _name, true, _value, useNameForShortcut, parent, game), color(_color),
|
||||||
|
radius(_radius)
|
||||||
{
|
{
|
||||||
setCacheMode(DeviceCoordinateCache);
|
setCacheMode(DeviceCoordinateCache);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ public:
|
|||||||
int _radius,
|
int _radius,
|
||||||
int _value,
|
int _value,
|
||||||
bool useNameForShortcut = false,
|
bool useNameForShortcut = false,
|
||||||
QGraphicsItem *parent = 0);
|
QGraphicsItem *parent = nullptr,
|
||||||
|
QWidget *game = nullptr);
|
||||||
QRectF boundingRect() const;
|
QRectF boundingRect() const;
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||||
};
|
};
|
||||||
|
|||||||
71
cockatrice/src/customlineedit.cpp
Normal file
71
cockatrice/src/customlineedit.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "customlineedit.h"
|
||||||
|
|
||||||
|
#include "settingscache.h"
|
||||||
|
#include "shortcutssettings.h"
|
||||||
|
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
LineEditUnfocusable::LineEditUnfocusable(QWidget *parent) : QLineEdit(parent)
|
||||||
|
{
|
||||||
|
installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
LineEditUnfocusable::LineEditUnfocusable(const QString &contents, QWidget *parent) : QLineEdit(contents, parent)
|
||||||
|
{
|
||||||
|
installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LineEditUnfocusable::isUnfocusShortcut(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
QString modifier;
|
||||||
|
QString keyNoMod;
|
||||||
|
|
||||||
|
if (event->modifiers() & Qt::ShiftModifier)
|
||||||
|
modifier += "Shift+";
|
||||||
|
if (event->modifiers() & Qt::ControlModifier)
|
||||||
|
modifier += "Ctrl+";
|
||||||
|
if (event->modifiers() & Qt::AltModifier)
|
||||||
|
modifier += "Alt+";
|
||||||
|
if (event->modifiers() & Qt::MetaModifier)
|
||||||
|
modifier += "Meta+";
|
||||||
|
|
||||||
|
keyNoMod = QKeySequence(event->key()).toString();
|
||||||
|
|
||||||
|
QKeySequence key(modifier + keyNoMod);
|
||||||
|
QList<QKeySequence> unfocusShortcut = SettingsCache::instance().shortcuts().getShortcut("Textbox/unfocusTextBox");
|
||||||
|
|
||||||
|
for (const auto &unfocusKey : unfocusShortcut) {
|
||||||
|
if (key.matches(unfocusKey) == QKeySequence::ExactMatch)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEditUnfocusable::keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
if (isUnfocusShortcut(event)) {
|
||||||
|
clearFocus();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit::keyPressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LineEditUnfocusable::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::ShortcutOverride) {
|
||||||
|
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||||
|
|
||||||
|
if (isUnfocusShortcut(keyEvent)) {
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QLineEdit::eventFilter(watched, event);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user