mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-21 06:42:41 -08:00
Compare commits
448 Commits
2021-11-07
...
2024-12-22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d9e64ec73 | ||
|
|
5339be318e | ||
|
|
e1ba39c437 | ||
|
|
07ee271478 | ||
|
|
4823cce622 | ||
|
|
23099f7e8b | ||
|
|
5bdbd51fa8 | ||
|
|
a0e5871c6e | ||
|
|
3cf0904651 | ||
|
|
2bd06ff0fd | ||
|
|
6ea333d0f1 | ||
|
|
91d2485940 | ||
|
|
0d99b2bcf4 | ||
|
|
a54a424f84 | ||
|
|
3514699f5b | ||
|
|
d196988cab | ||
|
|
03aff83135 | ||
|
|
17e6bfaca6 | ||
|
|
90281262be | ||
|
|
5bbc118920 | ||
|
|
dde2f8b9ad | ||
|
|
d41aa30e10 | ||
|
|
231d0380a7 | ||
|
|
a5c509981b | ||
|
|
71b01e6110 | ||
|
|
c716f85962 | ||
|
|
245d51caea | ||
|
|
e588917f6c | ||
|
|
27e5d21b6b | ||
|
|
b894b75e6a | ||
|
|
116397cdb3 | ||
|
|
a6b5abf271 | ||
|
|
fd5a649246 | ||
|
|
e8e57989ba | ||
|
|
03db4ccce6 | ||
|
|
c9d5d5609c | ||
|
|
ac16206ddb | ||
|
|
5f8bcbd02d | ||
|
|
a0f74134bb | ||
|
|
0463a6fd70 | ||
|
|
a5de633c64 | ||
|
|
b2ad2acff3 | ||
|
|
4ee6ff73e0 | ||
|
|
628bdde939 | ||
|
|
e9b78c1c59 | ||
|
|
315cbc0925 | ||
|
|
69741d858c | ||
|
|
20d99a78b6 | ||
|
|
2d68393e07 | ||
|
|
8cb1470643 | ||
|
|
8d9b27bf47 | ||
|
|
0c5d9f1a7d | ||
|
|
a7d88c06c1 | ||
|
|
2735000fcf | ||
|
|
a39de270cd | ||
|
|
10f11213d3 | ||
|
|
3b49cbf73b | ||
|
|
e4cfe08113 | ||
|
|
fa02cb885c | ||
|
|
69b864fa02 | ||
|
|
b9ed9a6c0b | ||
|
|
5156495b47 | ||
|
|
b92047bc3f | ||
|
|
70559d32df | ||
|
|
bb84b75db9 | ||
|
|
f634177973 | ||
|
|
e33ff37c82 | ||
|
|
d2bc7f6ac0 | ||
|
|
5ef1ca06f5 | ||
|
|
1d8651bc00 | ||
|
|
17eabf2004 | ||
|
|
37bb1367db | ||
|
|
24b5dab456 | ||
|
|
c6bfc8b8ea | ||
|
|
f2b0fa164e | ||
|
|
0ca8bdb3a8 | ||
|
|
a8471f62bc | ||
|
|
5f1c03682f | ||
|
|
3255ed3ffb | ||
|
|
c51b54c0c5 | ||
|
|
a3f0807d47 | ||
|
|
27055944df | ||
|
|
7b1653034b | ||
|
|
39d8ca050f | ||
|
|
50274cb66d | ||
|
|
bd60a9fd2e | ||
|
|
83409c32c4 | ||
|
|
1bc92623dc | ||
|
|
f73196841a | ||
|
|
86a4b130ff | ||
|
|
f4e2f117c3 | ||
|
|
8ef92d26c5 | ||
|
|
c8336df49d | ||
|
|
c2fe3cda35 | ||
|
|
c54f47efbf | ||
|
|
3c40cc4b7d | ||
|
|
f0fb77bade | ||
|
|
e894e78346 | ||
|
|
dd04c610ec | ||
|
|
2e674efe50 | ||
|
|
4d394c31f9 | ||
|
|
11d58abbc3 | ||
|
|
5f4ad87a47 | ||
|
|
e43a21866c | ||
|
|
6652012f4c | ||
|
|
0c4e8ca290 | ||
|
|
230a2c5c62 | ||
|
|
590fb7f533 | ||
|
|
e8b88248f2 | ||
|
|
c6ba1b6a4e | ||
|
|
c4c52bd8c0 | ||
|
|
c633a792f5 | ||
|
|
8d5421d9da | ||
|
|
b041f4ace2 | ||
|
|
d26f96db9e | ||
|
|
fa999880ee | ||
|
|
d1e0f9dfc5 | ||
|
|
2d86938375 | ||
|
|
4865269a73 | ||
|
|
038ce3dcec | ||
|
|
43b997fe40 | ||
|
|
44e92f61ca | ||
|
|
b4bfa17cee | ||
|
|
500b694cc6 | ||
|
|
b998282304 | ||
|
|
b704216553 | ||
|
|
03ec02a749 | ||
|
|
248ea82573 | ||
|
|
bbe125beee | ||
|
|
95cd1c6f87 | ||
|
|
1c2107ae8f | ||
|
|
e826e17c6c | ||
|
|
b111f0921c | ||
|
|
090a48515c | ||
|
|
b8555d8c42 | ||
|
|
cf1f4f12a9 | ||
|
|
ef4413633a | ||
|
|
c5bb38e907 | ||
|
|
9f515fc804 | ||
|
|
245edcefdd | ||
|
|
153f73c308 | ||
|
|
315837b267 | ||
|
|
ea8da24215 | ||
|
|
1ab723ca64 | ||
|
|
f8bc6cf998 | ||
|
|
8687163cca | ||
|
|
e261e16d99 | ||
|
|
bdcd083eea | ||
|
|
c4bf9eb61c | ||
|
|
0994d10410 | ||
|
|
291c535edb | ||
|
|
f04702fdd1 | ||
|
|
b7fbc12ac0 | ||
|
|
e2ab8db958 | ||
|
|
34d70980e8 | ||
|
|
e45c4042fe | ||
|
|
ce8092318e | ||
|
|
c95cc1dd9d | ||
|
|
1f72877728 | ||
|
|
93b40343d9 | ||
|
|
ba10108207 | ||
|
|
c28f66d673 | ||
|
|
59f327f97a | ||
|
|
872c92a244 | ||
|
|
2303880b87 | ||
|
|
0e97cc1712 | ||
|
|
d550e42441 | ||
|
|
4279753030 | ||
|
|
2f6c018b7a | ||
|
|
be5d42baba | ||
|
|
f174614496 | ||
|
|
e8c7fba8b0 | ||
|
|
5c49283023 | ||
|
|
ad56b431a3 | ||
|
|
b0d8a33d5f | ||
|
|
1715bcb216 | ||
|
|
96caeaca72 | ||
|
|
c8723ae935 | ||
|
|
94e39c044c | ||
|
|
9776ea53c9 | ||
|
|
675d07dac0 | ||
|
|
1217820288 | ||
|
|
90e1a3cb76 | ||
|
|
7c1095ea50 | ||
|
|
203e916a07 | ||
|
|
7201e34b38 | ||
|
|
6d032c378f | ||
|
|
badd8952f5 | ||
|
|
7209eddb2d | ||
|
|
a7ffd43b29 | ||
|
|
724ba69483 | ||
|
|
1716801437 | ||
|
|
fa727524dc | ||
|
|
28f80e18a0 | ||
|
|
4acc8bfe80 | ||
|
|
9f86ed7887 | ||
|
|
cb18a55338 | ||
|
|
78a928464c | ||
|
|
07a8cd0a5f | ||
|
|
b73ef58567 | ||
|
|
519531f3a0 | ||
|
|
4b8e47d079 | ||
|
|
ed170f7e07 | ||
|
|
6bb559874c | ||
|
|
9cd68e25b3 | ||
|
|
72ac441598 | ||
|
|
f5fe56c85d | ||
|
|
d4fc1be2cc | ||
|
|
7b3617a273 | ||
|
|
3e8adae3de | ||
|
|
9943133d6d | ||
|
|
a5706a47af | ||
|
|
b3b911c64d | ||
|
|
05beb4fcaf | ||
|
|
324b50e381 | ||
|
|
186f4289e9 | ||
|
|
cb90a8356b | ||
|
|
e9c502ab32 | ||
|
|
f728520e97 | ||
|
|
c1b0d50237 | ||
|
|
b9cfc29059 | ||
|
|
6bf7c79891 | ||
|
|
2bd0e58354 | ||
|
|
ee674cb0cf | ||
|
|
dd1b354d48 | ||
|
|
d3e96f4a99 | ||
|
|
90e2eb3db9 | ||
|
|
102be6a350 | ||
|
|
be6152948c | ||
|
|
f14bf4b205 | ||
|
|
123ac2ca25 | ||
|
|
7216b976ec | ||
|
|
7fb698cfbf | ||
|
|
b0470ab678 | ||
|
|
0deb037035 | ||
|
|
064b362d60 | ||
|
|
6bbe228a84 | ||
|
|
a8ba8b6ab5 | ||
|
|
e850f6c2a5 | ||
|
|
e9eb7d6db1 | ||
|
|
56d21321d0 | ||
|
|
3888a74212 | ||
|
|
0035e29f9e | ||
|
|
90679d5669 | ||
|
|
ac5dc2578a | ||
|
|
671e6823be | ||
|
|
0d76662311 | ||
|
|
8dd59cf3cf | ||
|
|
332d25dc00 | ||
|
|
0fa81a77dc | ||
|
|
9a74d8f72d | ||
|
|
8c539351e3 | ||
|
|
e3552fc0ae | ||
|
|
ca308636c3 | ||
|
|
244cb847fb | ||
|
|
176c52daf2 | ||
|
|
ee3525ec64 | ||
|
|
adce921be7 | ||
|
|
20ceb1c284 | ||
|
|
db4364b8f8 | ||
|
|
48d6435e09 | ||
|
|
7c20e9ab34 | ||
|
|
cb52605928 | ||
|
|
bd3100dcda | ||
|
|
afb7c35cfd | ||
|
|
5b694a55d2 | ||
|
|
f750a4cd72 | ||
|
|
eddeaaf52a | ||
|
|
2b42bee424 | ||
|
|
b9706c0cc1 | ||
|
|
800b21b000 | ||
|
|
d1736a25bb | ||
|
|
f269e5fe58 | ||
|
|
45a5296013 | ||
|
|
5f0ab2a177 | ||
|
|
70ab02987a | ||
|
|
421da882d8 | ||
|
|
1a40102f71 | ||
|
|
1fbc10cd77 | ||
|
|
87462398d8 | ||
|
|
b33246b29f | ||
|
|
dbffe30f63 | ||
|
|
9ce450d0b0 | ||
|
|
f5f8acf1fd | ||
|
|
304ed3cd60 | ||
|
|
07248692ce | ||
|
|
cef99cba71 | ||
|
|
cab5f29b57 | ||
|
|
55a2f75d16 | ||
|
|
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 |
@@ -8,9 +8,11 @@ RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
|
|||||||
gtest \
|
gtest \
|
||||||
mariadb-libs \
|
mariadb-libs \
|
||||||
protobuf \
|
protobuf \
|
||||||
qt5-base \
|
qt6-base \
|
||||||
qt5-multimedia \
|
qt6-imageformats \
|
||||||
qt5-svg \
|
qt6-multimedia \
|
||||||
qt5-tools \
|
qt6-svg \
|
||||||
qt5-websockets \
|
qt6-tools \
|
||||||
|
qt6-translations \
|
||||||
|
qt6-websockets \
|
||||||
&& pacman --sync --clean --clean --noconfirm
|
&& pacman --sync --clean --clean --noconfirm
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:impish
|
FROM debian:11
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
@@ -17,6 +17,7 @@ RUN apt-get update && \
|
|||||||
libqt5svg5-dev \
|
libqt5svg5-dev \
|
||||||
libqt5websockets5-dev \
|
libqt5websockets5-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
|
qt5-image-formats-plugins \
|
||||||
qtmultimedia5-dev \
|
qtmultimedia5-dev \
|
||||||
qttools5-dev \
|
qttools5-dev \
|
||||||
qttools5-dev-tools \
|
qttools5-dev-tools \
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:hirsute
|
FROM debian:12
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
@@ -9,16 +9,19 @@ RUN apt-get update && \
|
|||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
git \
|
git \
|
||||||
|
libgl-dev \
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
libmariadb-dev-compat \
|
libmariadb-dev-compat \
|
||||||
libprotobuf-dev \
|
libprotobuf-dev \
|
||||||
libqt5multimedia5-plugins \
|
libqt6multimedia6 \
|
||||||
libqt5sql5-mysql \
|
libqt6sql6-mysql \
|
||||||
libqt5svg5-dev \
|
qt6-svg-dev \
|
||||||
libqt5websockets5-dev \
|
qt6-websockets-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
qtmultimedia5-dev \
|
qt6-image-formats-plugins \
|
||||||
qttools5-dev \
|
qt6-l10n-tools \
|
||||||
qttools5-dev-tools \
|
qt6-multimedia-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
FROM debian:buster
|
|
||||||
|
|
||||||
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-tools \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
FROM fedora:34
|
|
||||||
|
|
||||||
RUN dnf install -y \
|
|
||||||
@development-tools \
|
|
||||||
ccache \
|
|
||||||
cmake \
|
|
||||||
desktop-file-utils \
|
|
||||||
file \
|
|
||||||
gcc-c++ \
|
|
||||||
git \
|
|
||||||
hicolor-icon-theme \
|
|
||||||
libappstream-glib \
|
|
||||||
mariadb-devel \
|
|
||||||
protobuf-devel \
|
|
||||||
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
|
||||||
rpm-build \
|
|
||||||
sqlite-devel \
|
|
||||||
wget \
|
|
||||||
xz-devel \
|
|
||||||
zlib-devel \
|
|
||||||
&& dnf clean all
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
FROM fedora:35
|
|
||||||
|
|
||||||
RUN dnf install -y \
|
|
||||||
@development-tools \
|
|
||||||
ccache \
|
|
||||||
cmake \
|
|
||||||
desktop-file-utils \
|
|
||||||
file \
|
|
||||||
gcc-c++ \
|
|
||||||
git \
|
|
||||||
hicolor-icon-theme \
|
|
||||||
libappstream-glib \
|
|
||||||
mariadb-devel \
|
|
||||||
protobuf-devel \
|
|
||||||
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
|
||||||
rpm-build \
|
|
||||||
sqlite-devel \
|
|
||||||
wget \
|
|
||||||
xz-devel \
|
|
||||||
zlib-devel \
|
|
||||||
&& dnf clean all
|
|
||||||
15
.ci/Fedora40/Dockerfile
Normal file
15
.ci/Fedora40/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM fedora:40
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
gcc-c++ \
|
||||||
|
git \
|
||||||
|
mariadb-devel \
|
||||||
|
protobuf-devel \
|
||||||
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||||
|
qt6-qtimageformats \
|
||||||
|
rpm-build \
|
||||||
|
xz-devel \
|
||||||
|
zlib-devel \
|
||||||
|
&& dnf clean all
|
||||||
15
.ci/Fedora41/Dockerfile
Normal file
15
.ci/Fedora41/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM fedora:41
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
gcc-c++ \
|
||||||
|
git \
|
||||||
|
mariadb-devel \
|
||||||
|
protobuf-devel \
|
||||||
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||||
|
qt6-qtimageformats \
|
||||||
|
rpm-build \
|
||||||
|
xz-devel \
|
||||||
|
zlib-devel \
|
||||||
|
&& dnf clean all
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:focal
|
FROM ubuntu:20.04
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
@@ -18,6 +18,7 @@ RUN apt-get update && \
|
|||||||
libqt5websockets5-dev \
|
libqt5websockets5-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
qt5-default \
|
qt5-default \
|
||||||
|
qt5-image-formats-plugins \
|
||||||
qtmultimedia5-dev \
|
qtmultimedia5-dev \
|
||||||
qttools5-dev \
|
qttools5-dev \
|
||||||
qttools5-dev-tools \
|
qttools5-dev-tools \
|
||||||
27
.ci/Ubuntu22.04/Dockerfile
Normal file
27
.ci/Ubuntu22.04/Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
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-image-formats-plugins \
|
||||||
|
qt6-l10n-tools \
|
||||||
|
qt6-multimedia-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
27
.ci/Ubuntu24.04/Dockerfile
Normal file
27
.ci/Ubuntu24.04/Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
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 \
|
||||||
|
qt6-svg-dev \
|
||||||
|
qt6-websockets-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt6-image-formats-plugins \
|
||||||
|
qt6-l10n-tools \
|
||||||
|
qt6-multimedia-dev \
|
||||||
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
FROM ubuntu:bionic
|
|
||||||
|
|
||||||
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 \
|
|
||||||
qtmultimedia5-dev \
|
|
||||||
qttools5-dev \
|
|
||||||
qttools5-dev-tools \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
155
.ci/compile.sh
155
.ci/compile.sh
@@ -2,16 +2,26 @@
|
|||||||
|
|
||||||
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
# 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
|
# Read arguments
|
||||||
while [[ "$@" ]]; do
|
while [[ $# != 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
'--')
|
'--')
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
'--format')
|
|
||||||
CHECK_FORMAT=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--install')
|
'--install')
|
||||||
MAKE_INSTALL=1
|
MAKE_INSTALL=1
|
||||||
shift
|
shift
|
||||||
@@ -19,7 +29,7 @@ while [[ "$@" ]]; do
|
|||||||
'--package')
|
'--package')
|
||||||
MAKE_PACKAGE=1
|
MAKE_PACKAGE=1
|
||||||
shift
|
shift
|
||||||
if [[ $# != 0 && $1 != -* ]]; then
|
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||||
PACKAGE_TYPE="$1"
|
PACKAGE_TYPE="$1"
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
@@ -28,7 +38,7 @@ while [[ "$@" ]]; do
|
|||||||
shift
|
shift
|
||||||
if [[ $# == 0 ]]; then
|
if [[ $# == 0 ]]; then
|
||||||
echo "::error file=$0::--suffix expects an argument"
|
echo "::error file=$0::--suffix expects an argument"
|
||||||
exit 1
|
exit 3
|
||||||
fi
|
fi
|
||||||
PACKAGE_SUFFIX="$1"
|
PACKAGE_SUFFIX="$1"
|
||||||
shift
|
shift
|
||||||
@@ -49,94 +59,149 @@ while [[ "$@" ]]; do
|
|||||||
BUILDTYPE="Release"
|
BUILDTYPE="Release"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
*)
|
'--ccache')
|
||||||
if [[ $1 == -* ]]; then
|
USE_CCACHE=1
|
||||||
echo "::error file=$0::unrecognized option: $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
|
exit 3
|
||||||
fi
|
fi
|
||||||
BUILDTYPE="$1"
|
BUILD_DIR="$1"
|
||||||
shift
|
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
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# Check formatting using clang-format
|
|
||||||
if [[ $CHECK_FORMAT ]]; then
|
|
||||||
echo "::group::Run linter"
|
|
||||||
source ./.ci/lint.sh
|
|
||||||
echo "::endgroup::"
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
./servatrice/check_schema_version.sh
|
./servatrice/check_schema_version.sh
|
||||||
mkdir -p build
|
if [[ ! $BUILDTYPE ]]; then
|
||||||
cd build
|
BUILDTYPE=Release
|
||||||
|
|
||||||
if [[ ! $CMAKE_BUILD_PARALLEL_LEVEL ]]; then
|
|
||||||
CMAKE_BUILD_PARALLEL_LEVEL=2 # default machines have 2 cores
|
|
||||||
fi
|
fi
|
||||||
|
if [[ ! $BUILD_DIR ]]; then
|
||||||
|
BUILD_DIR="build"
|
||||||
|
fi
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
# Add cmake flags
|
# Add cmake flags
|
||||||
|
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||||
if [[ $MAKE_SERVER ]]; then
|
if [[ $MAKE_SERVER ]]; then
|
||||||
flags+=" -DWITH_SERVER=1"
|
flags+=("-DWITH_SERVER=1")
|
||||||
fi
|
fi
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
flags+=" -DTEST=1"
|
flags+=("-DTEST=1")
|
||||||
fi
|
fi
|
||||||
if [[ $BUILDTYPE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
flags+=" -DCMAKE_BUILD_TYPE=$BUILDTYPE"
|
flags+=("-DUSE_CCACHE=1")
|
||||||
|
if [[ $CCACHE_SIZE ]]; then
|
||||||
|
# note, this setting persists after running the script
|
||||||
|
ccache --max-size "$CCACHE_SIZE"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ $PACKAGE_TYPE ]]; then
|
if [[ $PACKAGE_TYPE ]]; then
|
||||||
flags+=" -DCPACK_GENERATOR=$PACKAGE_TYPE"
|
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
# Add cmake --build flags
|
||||||
# prepend ccache compiler binaries to path
|
buildflags=(--config "$BUILDTYPE")
|
||||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
if [[ $PARALLEL_COUNT ]]; then
|
||||||
# Add qt install location when using homebrew
|
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
|
||||||
flags+=" -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/"
|
# 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
|
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
|
# Compile
|
||||||
echo "::group::Show ccache stats"
|
if [[ $USE_CCACHE ]]; then
|
||||||
ccache --show-stats
|
echo "::group::Show ccache stats"
|
||||||
echo "::endgroup::"
|
ccachestatsverbose
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "::group::Configure cmake"
|
echo "::group::Configure cmake"
|
||||||
cmake --version
|
cmake --version
|
||||||
cmake .. $flags
|
cmake .. "${flags[@]}"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Build project"
|
echo "::group::Build project"
|
||||||
cmake --build .
|
if [[ $RUNNER_OS == Windows ]]; then
|
||||||
|
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||||
|
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
||||||
|
cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true
|
||||||
|
else
|
||||||
|
cmake --build . "${buildflags[@]}"
|
||||||
|
fi
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Show ccache stats again"
|
if [[ $USE_CCACHE ]]; then
|
||||||
ccache --show-stats
|
echo "::group::Show ccache stats again"
|
||||||
echo "::endgroup::"
|
ccachestatsverbose
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
echo "::group::Run tests"
|
echo "::group::Run tests"
|
||||||
cmake --build . --target test
|
ctest -C "$BUILDTYPE" --output-on-failure
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $MAKE_INSTALL ]]; then
|
if [[ $MAKE_INSTALL ]]; then
|
||||||
echo "::group::Install"
|
echo "::group::Install"
|
||||||
cmake --build . --target install
|
cmake --build . --target install --config "$BUILDTYPE"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $MAKE_PACKAGE ]]; then
|
if [[ $MAKE_PACKAGE ]]; then
|
||||||
echo "::group::Create package"
|
echo "::group::Create package"
|
||||||
cmake --build . --target package
|
|
||||||
|
if [[ $RUNNER_OS == macOS ]]; then
|
||||||
|
# Workaround https://github.com/actions/runner-images/issues/7522
|
||||||
|
echo "killing XProtectBehaviorService"; sudo pkill -9 XProtect >/dev/null || true;
|
||||||
|
echo "waiting for XProtectBehaviorService kill"; while pgrep "XProtect"; do sleep 3; done;
|
||||||
|
fi
|
||||||
|
cmake --build . --target package --config "$BUILDTYPE"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
if [[ $PACKAGE_SUFFIX ]]; then
|
if [[ $PACKAGE_SUFFIX ]]; then
|
||||||
echo "::group::Update package name"
|
echo "::group::Update package name"
|
||||||
../.ci/name_build.sh "$PACKAGE_SUFFIX"
|
cd ..
|
||||||
|
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -3,11 +3,15 @@
|
|||||||
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
# 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.
|
# 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
|
# --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
|
# --build builds the image from the Dockerfile in .ci/$NAME
|
||||||
# --save stores the image, if an image was loaded it will not be stored
|
# --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
|
# requires: docker
|
||||||
# uses env: NAME CACHE BUILD GET SAVE (correspond to args: <name> --set-cache <cache> --build --get --save)
|
# 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
|
# 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
|
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||||
export BUILD_SCRIPT=".ci/compile.sh"
|
export BUILD_SCRIPT=".ci/compile.sh"
|
||||||
@@ -18,7 +22,7 @@ image_cache="image"
|
|||||||
ccache_cache=".ccache"
|
ccache_cache=".ccache"
|
||||||
|
|
||||||
# Read arguments
|
# Read arguments
|
||||||
while [[ "$@" ]]; do
|
while [[ $# != 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
'--build')
|
'--build')
|
||||||
BUILD=1
|
BUILD=1
|
||||||
@@ -28,6 +32,10 @@ while [[ "$@" ]]; do
|
|||||||
GET=1
|
GET=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
'--interactive')
|
||||||
|
INTERACTIVE=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
'--save')
|
'--save')
|
||||||
SAVE=1
|
SAVE=1
|
||||||
shift
|
shift
|
||||||
@@ -36,12 +44,12 @@ while [[ "$@" ]]; do
|
|||||||
CACHE=$2
|
CACHE=$2
|
||||||
if ! [[ -d $CACHE ]]; then
|
if ! [[ -d $CACHE ]]; then
|
||||||
echo "could not find cache path: $CACHE" >&2
|
echo "could not find cache path: $CACHE" >&2
|
||||||
exit 3
|
return 3
|
||||||
fi
|
fi
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ $1 == -* ]]; then
|
if [[ ${1:0:1} == - ]]; then
|
||||||
echo "unrecognized option: $1"
|
echo "unrecognized option: $1"
|
||||||
return 3
|
return 3
|
||||||
fi
|
fi
|
||||||
@@ -67,27 +75,27 @@ fi
|
|||||||
|
|
||||||
if ! [[ $CACHE ]]; then
|
if ! [[ $CACHE ]]; then
|
||||||
echo "cache dir is not set!" >&2
|
echo "cache dir is not set!" >&2
|
||||||
else
|
CACHE="$(mktemp -d)"
|
||||||
if ! [[ -d $CACHE ]]; then
|
echo "set cache dir to $CACHE" >&2
|
||||||
echo "could not find cache dir: $CACHE" >&2
|
fi
|
||||||
mkdir -p $CACHE
|
if ! [[ -d $CACHE ]]; then
|
||||||
unset GET # the dir is empty
|
echo "could not find cache dir: $CACHE" >&2
|
||||||
fi
|
mkdir -p "$CACHE"
|
||||||
if [[ $GET || $SAVE ]]; then
|
unset GET # the dir is empty
|
||||||
img_dir="$CACHE/$image_cache"
|
fi
|
||||||
img_save="$img_dir/$IMAGE_NAME$save_extension"
|
if [[ $GET || $SAVE ]]; then
|
||||||
if ! [[ -d $img_dir ]]; then
|
img_dir="$CACHE/$image_cache"
|
||||||
echo "could not find image dir: $img_dir" >&2
|
img_save="$img_dir/$IMAGE_NAME$save_extension"
|
||||||
mkdir -p "$img_dir"
|
if ! [[ -d $img_dir ]]; then
|
||||||
fi
|
echo "could not find image dir: $img_dir" >&2
|
||||||
fi
|
mkdir -p "$img_dir"
|
||||||
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
|
fi
|
||||||
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
|
# Get the docker image from previously stored save
|
||||||
if [[ $GET ]]; then
|
if [[ $GET ]]; then
|
||||||
@@ -132,15 +140,26 @@ fi
|
|||||||
function RUN ()
|
function RUN ()
|
||||||
{
|
{
|
||||||
echo "running image:"
|
echo "running image:"
|
||||||
if docker images | grep "$IMAGE_NAME"; then
|
if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
|
||||||
args="--mount type=bind,source=$PWD,target=/src -w=/src"
|
local args=(--mount "type=bind,source=$PWD,target=/src")
|
||||||
|
args+=(--workdir "/src")
|
||||||
|
args+=(--user "$(id -u):$(id -g)")
|
||||||
if [[ $CCACHE_DIR ]]; then
|
if [[ $CCACHE_DIR ]]; then
|
||||||
args+=" --mount type=bind,source=$CCACHE_DIR,target=/.ccache -e CCACHE_DIR=/.ccache"
|
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
|
||||||
|
args+=(--env "CCACHE_DIR=/.ccache")
|
||||||
fi
|
fi
|
||||||
docker run $args $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS $@
|
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
|
||||||
return $?
|
return $?
|
||||||
else
|
else
|
||||||
echo "could not find docker image: $IMAGE_NAME" >&2
|
echo "could not find docker image: $IMAGE_NAME" >&2
|
||||||
return 3
|
return 3
|
||||||
fi
|
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
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ if ! git merge-base origin/master HEAD; then
|
|||||||
git fetch --unshallow
|
git fetch --unshallow
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check formatting using clangify
|
# Check formatting using format.sh
|
||||||
echo "Checking your code using clang-format..."
|
echo "Checking your code using clang-format/cmake-format..."
|
||||||
|
|
||||||
diff="$(./clangify.sh --diff --cf-version --branch origin/master)"
|
diff="$(./format.sh --diff --cmake --cf-version --branch origin/master)"
|
||||||
err=$?
|
err=$?
|
||||||
|
|
||||||
case $err in
|
case $err in
|
||||||
@@ -24,7 +24,7 @@ case $err in
|
|||||||
*** ***
|
*** ***
|
||||||
*** Your code does not comply with our style guide. ***
|
*** Your code does not comply with our style guide. ***
|
||||||
*** ***
|
*** ***
|
||||||
*** Please correct it or run the "clangify.sh" script. ***
|
*** Please correct it or run the "format.sh" script. ***
|
||||||
*** Then commit and push those changes to this branch. ***
|
*** Then commit and push those changes to this branch. ***
|
||||||
*** Check our CONTRIBUTING.md file for more details. ***
|
*** Check our CONTRIBUTING.md file for more details. ***
|
||||||
*** ***
|
*** ***
|
||||||
@@ -32,21 +32,23 @@ case $err in
|
|||||||
*** ***
|
*** ***
|
||||||
***********************************************************
|
***********************************************************
|
||||||
|
|
||||||
Used clang-format version:
|
Used version:
|
||||||
${diff%%
|
${diff%%
|
||||||
|
----------
|
||||||
*}
|
*}
|
||||||
|
|
||||||
The following changes should be made:
|
The following changes should be made:
|
||||||
${diff#*
|
${diff#*
|
||||||
|
----------
|
||||||
}
|
}
|
||||||
|
|
||||||
Exiting...
|
Exiting...
|
||||||
EOM
|
EOM
|
||||||
exit 2
|
exit 2
|
||||||
;;
|
;;
|
||||||
|
|
||||||
0)
|
0)
|
||||||
cat <<EOM
|
cat <<EOM
|
||||||
|
|
||||||
***********************************************************
|
***********************************************************
|
||||||
*** ***
|
*** ***
|
||||||
@@ -58,12 +60,10 @@ EOM
|
|||||||
|
|
||||||
Exiting...
|
Exiting...
|
||||||
EOM
|
EOM
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo ""
|
echo "Something went wrong in our formatting checks: format.sh returned $err" >&2
|
||||||
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
|
;;
|
||||||
echo ""
|
esac
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
# renames the file to [original name][SUFFIX].[original extension]
|
# renames the file to [original name][SUFFIX].[original extension]
|
||||||
# where SUFFIX is either available in the environment or as the first arg
|
# where SUFFIX is either available in the environment or as the first arg
|
||||||
# if MAKE_ZIP is set instead a zip is made
|
# if MAKE_ZIP is set instead a zip is made
|
||||||
# expected to be run in the build directory
|
# expected to be run in the build directory unless BUILD_DIR is set
|
||||||
builddir="."
|
# adds output to GITHUB_OUTPUT
|
||||||
|
builddir="${BUILD_DIR:=.}"
|
||||||
findrx="Cockatrice-*.*"
|
findrx="Cockatrice-*.*"
|
||||||
|
|
||||||
if [[ $1 ]]; then
|
if [[ $1 ]]; then
|
||||||
@@ -27,6 +28,7 @@ if [[ ! $file ]]; then
|
|||||||
echo "::error file=$0::could not find package"
|
echo "::error file=$0::could not find package"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
oldpwd="$PWD"
|
||||||
if ! cd "$path"; then
|
if ! cd "$path"; then
|
||||||
echo "::error file=$0::could not get file path"
|
echo "::error file=$0::could not get file path"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -45,6 +47,9 @@ else
|
|||||||
echo "renaming '$file' to '$filename'"
|
echo "renaming '$file' to '$filename'"
|
||||||
mv "$file" "$filename"
|
mv "$file" "$filename"
|
||||||
fi
|
fi
|
||||||
ls -l "$PWD/$filename"
|
|
||||||
echo "::set-output name=path::$PWD/$filename"
|
cd "$oldpwd"
|
||||||
echo "::set-output name=name::$filename"
|
relative_path="$path/$filename"
|
||||||
|
ls -l "$relative_path"
|
||||||
|
echo "path=$relative_path" >>"$GITHUB_OUTPUT"
|
||||||
|
echo "name=$filename" >>"$GITHUB_OUTPUT"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
# the releases are first made as drafts and will be vetted by a human
|
# the releases are first made as drafts and will be vetted by a human
|
||||||
# it just has to provide a template
|
# it just has to provide a template
|
||||||
# this requires the repo to be unshallowed
|
# this requires the repo to be unshallowed
|
||||||
|
# adds output to GITHUB_OUTPUT
|
||||||
template_path=".ci/release_template.md"
|
template_path=".ci/release_template.md"
|
||||||
body_path="/tmp/release.md"
|
body_path="/tmp/release.md"
|
||||||
beta_regex='beta'
|
beta_regex='beta'
|
||||||
@@ -22,22 +23,22 @@ fi
|
|||||||
|
|
||||||
# create title
|
# create title
|
||||||
if [[ $TAG =~ $beta_regex ]]; then
|
if [[ $TAG =~ $beta_regex ]]; then
|
||||||
echo "::set-output name=is_beta::yes"
|
echo "is_beta=yes" >>"$GITHUB_OUTPUT"
|
||||||
title="$TAG"
|
title="$TAG"
|
||||||
echo "creating beta release '$title'"
|
echo "creating beta release '$title'"
|
||||||
elif [[ ! $(cat CMakeLists.txt) =~ $name_regex ]]; then
|
elif [[ ! $(cat CMakeLists.txt) =~ $name_regex ]]; then
|
||||||
echo "::error file=$0::could not find releasename in CMakeLists.txt"
|
echo "::error file=$0::could not find releasename in CMakeLists.txt"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo "::set-output name=is_beta::no"
|
echo "is_beta=no" >>"$GITHUB_OUTPUT"
|
||||||
name="${BASH_REMATCH[1]}"
|
name="${BASH_REMATCH[1]}"
|
||||||
version="${TAG##*-}"
|
version="${TAG##*-}"
|
||||||
title="Cockatrice $version: $name"
|
title="Cockatrice $version: $name"
|
||||||
no_beta=1
|
no_beta=1
|
||||||
echo "::set-output name=friendly_name::$name"
|
echo "friendly_name=$name" >>"$GITHUB_OUTPUT"
|
||||||
echo "creating full release '$title'"
|
echo "creating full release '$title'"
|
||||||
fi
|
fi
|
||||||
echo "::set-output name=title::$title"
|
echo "title=$title" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# add release notes template
|
# add release notes template
|
||||||
if [[ $no_beta ]]; then
|
if [[ $no_beta ]]; then
|
||||||
@@ -60,9 +61,9 @@ fi
|
|||||||
all_tags="
|
all_tags="
|
||||||
$(git tag)" # tags are ordered alphabetically
|
$(git tag)" # tags are ordered alphabetically
|
||||||
before="${all_tags%%
|
before="${all_tags%%
|
||||||
$TAG*}" # strip line with current tag an all lines after it
|
"$TAG"*}" # strip line with current tag an all lines after it
|
||||||
# note the extra newlines are needed to always have a last line
|
# note the extra newlines are needed to always have a last line
|
||||||
if [[ $all_tags == $before ]]; then
|
if [[ $all_tags == "$before" ]]; then
|
||||||
echo "::warning file=$0::could not find current tag"
|
echo "::warning file=$0::could not find current tag"
|
||||||
else
|
else
|
||||||
while
|
while
|
||||||
@@ -74,7 +75,7 @@ else
|
|||||||
beta_list+=" $previous" # add to list of skipped betas
|
beta_list+=" $previous" # add to list of skipped betas
|
||||||
next_before="${before%
|
next_before="${before%
|
||||||
*}" # strip the last line
|
*}" # strip the last line
|
||||||
if [[ $next_before == $before ]]; then
|
if [[ $next_before == "$before" ]]; then
|
||||||
unset previous
|
unset previous
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -108,5 +109,5 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# write to file
|
# write to file
|
||||||
echo "::set-output name=body_path::$body_path"
|
echo "body_path=$body_path" >>"$GITHUB_OUTPUT"
|
||||||
echo "$body" >"$body_path"
|
echo "$body" >"$body_path"
|
||||||
|
|||||||
@@ -4,48 +4,49 @@
|
|||||||
git push -d origin --REPLACE-WITH-BETA-LIST--
|
git push -d origin --REPLACE-WITH-BETA-LIST--
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- This list of binaries should be updated every time the ci is changed to
|
<!-- This list of binaries should be updated every time the CI is changed to
|
||||||
include different targets -->
|
include different targets -->
|
||||||
<pre>
|
<pre>
|
||||||
<b>Pre-compiled binaries we serve:</b>
|
<b>Pre-compiled binaries we serve:</b>
|
||||||
- <kbd>Windows 7/8/10 (32-bit)</kbd></i>
|
- <kbd>Windows 10+</kbd>
|
||||||
- <kbd>Windows 7/8/10 (64-bit)</kbd></i>
|
- <kbd>Windows 7+</kbd>
|
||||||
- <kbd>macOS 10.14</kbd> ("Mojave")</i>
|
- <kbd>macOS 14+</kbd> ("Sonoma") / Apple M
|
||||||
- <kbd>macOS 10.15</kbd> ("Catalina")</i>
|
- <kbd>macOS 13+</kbd> ("Ventura") / Intel
|
||||||
- <kbd>macOS 11.0</kbd> ("Big Sur")</i>
|
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
|
||||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")</i>
|
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
|
||||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")</i>
|
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
|
||||||
- <kbd>Ubuntu 20.10</kbd> ("Groovy Gorilla")</i>
|
- <kbd>Debian 12</kbd> ("Bookworm")
|
||||||
- <kbd>Ubuntu 21.04</kbd> ("Hirsute Hippo")</i>
|
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||||
- <kbd>Debian 10</kbd> ("Buster")</i>
|
- <kbd>Fedora 41</kbd>
|
||||||
- <kbd>Fedora 33</kbd></i>
|
- <kbd>Fedora 40</kbd>
|
||||||
- <kbd>Fedora 34</kbd></i>
|
|
||||||
<kbd>We are also packaged in Arch Linux's official community repository, courtesy of @FFY00</kbd></i>
|
<i>We are also packaged in <kbd>Arch Linux</kbd>'s official "extra" repository, courtesy of @FFY00</i>
|
||||||
<kbd>General linux support is available via a flatpak package (Flathub)</kbd></i>
|
<i>General Linux support is available via a <kbd>flatpak</kbd> package (Flathub)</i>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
## General Notes
|
## General Notes
|
||||||
|
|
||||||
<!-- --REPLACE-WITH-RELEASE-TITLE-- should be placed here by the ci -->
|
|
||||||
We're pleased to announce the newest official release: <kbd>--REPLACE-WITH-RELEASE-TITLE--</kbd>
|
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.
|
We hope you enjoy the changes made! All improvements with their corresponding tickets since the last version of Cockatrice are listed in the changelog below.
|
||||||
|
|
||||||
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))
|
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 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**
|
For basic information related to the app and getting started, 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.
|
If you'd like to help and 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
|
## Upgrading Cockatrice
|
||||||
<!-- this optional section puts a warning banner for problems with updating
|
<!-- this optional section puts a warning banner for problems with updating
|
||||||
> ⚠️ **With this release, we no longer provide a ready-to-install binary for:**
|
> [!IMPORTANT]
|
||||||
|
> **With this release, we no longer provide a ready-to-install binary for:**
|
||||||
> --DEPRECATED-OS-HERE--
|
> --DEPRECATED-OS-HERE--
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- Run the internal software updater: <kbd>Help → Check for Client Updates</kbd>
|
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>)
|
Don't forget to update your card database right after! (<kbd>Help → Check for Card Updates...</kbd>)
|
||||||
|
|
||||||
@@ -62,14 +63,14 @@ Remove empty headers when done.
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Highlights of the release -->
|
<!-- Highlights of the release -->
|
||||||
### ⚠️ Important:
|
### 🔖 Highlights:
|
||||||
### ✨ New Features:
|
### ✨ New Features:
|
||||||
### 🐛 Fixed Bugs / Resolved issues:
|
### 🐛 Fixed Bugs / Resolved Issues:
|
||||||
|
|
||||||
<!-- Complete list of changes (foldable) -->
|
<!-- Complete list of changes (foldable) -->
|
||||||
<details>
|
<details>
|
||||||
<summary>
|
<summary>
|
||||||
📘 <b>Show all changes</b> (--REPLACE-WITH-COMMIT-COUNT-- commits)
|
<b>Show all changes</b> (--REPLACE-WITH-COMMIT-COUNT-- commits)
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
### User Interface
|
### User Interface
|
||||||
@@ -90,5 +91,6 @@ Remove empty headers when done.
|
|||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
<!-- Personalise this a bit! -->
|
<!-- 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.
|
It's 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. -->
|
<!-- We'd like to especially recognize @ZeldaZach, --ADD-CONTRIBUTORS-HERE-- for their help in preparing so many amazing new features for the user base. -->
|
||||||
|
|||||||
58
.ci/update_translation_source_strings.sh
Executable file
58
.ci/update_translation_source_strings.sh
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ci script to update translation files
|
||||||
|
# usage:
|
||||||
|
# $0 cockatrice/cockatrice_en@source.ts cockatrice/src common
|
||||||
|
# or
|
||||||
|
# FILE="cockatrice/cockatrice_en@source.ts"
|
||||||
|
# DIRS="cockatrice/src common"
|
||||||
|
# $0
|
||||||
|
# note: directories can't contain spaces
|
||||||
|
|
||||||
|
# check parameters
|
||||||
|
if [[ ! $FILE ]]; then
|
||||||
|
FILE="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
if [[ ! $FILE ]]; then
|
||||||
|
echo "no output file selected" >&2
|
||||||
|
exit 2;
|
||||||
|
fi
|
||||||
|
if [[ ! $DIRS ]]; then
|
||||||
|
DIRS="$*"
|
||||||
|
fi
|
||||||
|
if [[ ! $DIRS ]]; then
|
||||||
|
echo "no source directories selected to translate" >&2
|
||||||
|
exit 2;
|
||||||
|
fi
|
||||||
|
if [[ ! -e $FILE ]]; then
|
||||||
|
echo "output file does not exist at: $FILE" >&2
|
||||||
|
exit 3;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# print version
|
||||||
|
if ! lupdate -version; then
|
||||||
|
echo "failed to run lupdate" >&2
|
||||||
|
exit 4;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# run lupdate, duplicating the output in stderr and saving it
|
||||||
|
# for convenience we ignore that $DIRS will be split on spaces
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if ! got="$(lupdate $DIRS -ts "$FILE" | tee /dev/stderr)"; then
|
||||||
|
echo "failed to update $FILE with $DIRS" >&2
|
||||||
|
exit 4;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# trim output
|
||||||
|
# the line we are interested in is:
|
||||||
|
# Found xxx source text(s) (x new and xxx already existing)
|
||||||
|
output="${got##* source text(s) (}" # get stuff in between brackets
|
||||||
|
output="${output%%)*}" # trim everything after first )
|
||||||
|
if [[ $output == "$got" ]]; then
|
||||||
|
echo "could not parse generated output" >&2
|
||||||
|
exit 4;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# write output to ci environment file
|
||||||
|
echo "output=$output" >> "$GITHUB_OUTPUT"
|
||||||
14
.ci/update_translation_source_strings_template.md
Normal file
14
.ci/update_translation_source_strings_template.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Updated source strings for translations:
|
||||||
|
- {{ .cockatrice_output }} (Cockatrice)
|
||||||
|
- {{ .oracle_output }} (Oracle)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Last changes are based on commit {{ .commit }}.
|
||||||
|
|
||||||
|
---
|
||||||
|
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-push.yml`. Review [action runs][2].*<br>
|
||||||
|
*After merging, all changes to the source language are available for translation at [Transifex][1] shortly.*
|
||||||
|
|
||||||
|
[1]: https://app.transifex.com/cockatrice/cockatrice/
|
||||||
|
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
93
.github/CONTRIBUTING.md
vendored
93
.github/CONTRIBUTING.md
vendored
@@ -41,8 +41,8 @@ albeit slightly less active.
|
|||||||
|
|
||||||
We use a separate job on the CI to check your code for formatting issues. If
|
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.
|
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 "Run clangify" step to
|
It's the first job called "linter", you can click the "Check code formatting"
|
||||||
see the output of the test.
|
step to see the output of the test.
|
||||||
|
|
||||||
The message will look like this:
|
The message will look like this:
|
||||||
```
|
```
|
||||||
@@ -50,7 +50,7 @@ The message will look like this:
|
|||||||
*** ***
|
*** ***
|
||||||
*** Your code does not comply with our style guide. ***
|
*** Your code does not comply with our style guide. ***
|
||||||
*** ***
|
*** ***
|
||||||
*** Please correct it or run the "clangify.sh" script. ***
|
*** Please correct it or run the "format.sh" script. ***
|
||||||
*** Then commit and push those changes to this branch. ***
|
*** Then commit and push those changes to this branch. ***
|
||||||
*** Check our CONTRIBUTING.md file for more details. ***
|
*** Check our CONTRIBUTING.md file for more details. ***
|
||||||
*** ***
|
*** ***
|
||||||
@@ -81,9 +81,9 @@ 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
|
almost any environment. A special `.clang-format` configuration file is
|
||||||
included in the project and is used to format your code.
|
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
|
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 `./clangify.sh --help` to show a
|
format all files in your pr in one go. Use `./format.sh --help` to show a full
|
||||||
full help page.
|
help page.
|
||||||
|
|
||||||
To run clang-format on a single source file simply use the command
|
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 -i <filename>` to format it in place. (Some systems install
|
||||||
@@ -290,20 +290,21 @@ be included in the next release 👍
|
|||||||
|
|
||||||
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. CI updates the `*_en@source.ts files` regularly and creates a PR automatically;
|
||||||
3. Transifex picks up the new files from GitHub every 24 hours;
|
3. Maintainer verifies and merges the change;
|
||||||
4. Translators translate the new untranslated strings on Transifex;
|
4. Transifex picks up the new files from GitHub automatically;
|
||||||
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
5. Translators translate the new untranslated strings on Transifex;
|
||||||
|
6. 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
|
All user interface strings inside Cockatrice's source code must be written
|
||||||
in English(US).
|
in English (US).
|
||||||
Translations to other languages are managed using [Transifex](
|
Translations to other languages are managed using [Transifex](
|
||||||
https://www.transifex.com/projects/p/cockatrice/).
|
https://www.transifex.com/projects/p/cockatrice/).
|
||||||
|
|
||||||
Adding a new string to translate is as easy as adding the string in the
|
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
|
`tr("")` function, the string will be picked up as translatable automatically
|
||||||
and translated as needed.
|
and translated as needed.
|
||||||
For example, setting the text of a label in the way that the string
|
For example, setting the text of a label in the way that the string
|
||||||
`"My name is:"` can be translated:
|
`"My name is:"` can be translated:
|
||||||
@@ -312,7 +313,7 @@ nameLabel.setText(tr("My name is:"));
|
|||||||
```
|
```
|
||||||
|
|
||||||
To translate a string that would have plural forms you can add the amount to
|
To translate a string that would have plural forms you can add the amount to
|
||||||
the tr call, also you can add an extra string as a hint for translators:
|
the tr() call, also you can add an extra string as a hint for translators:
|
||||||
```c++
|
```c++
|
||||||
QString message = tr("Everyone draws %n cards", "pop up message", amount);
|
QString message = tr("Everyone draws %n cards", "pop up message", amount);
|
||||||
```
|
```
|
||||||
@@ -321,20 +322,46 @@ 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
|
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
|
string in the code, you don't need to take care of adding the new strings to
|
||||||
the translation files.
|
the translation files.<br>
|
||||||
Every few days, or when a lot of new strings have been added, someone from the
|
We have an automated process to update our language source files on a schedule
|
||||||
development team will take care of extracting all the new strings and adding
|
and provide the translators on Transifex with the new contents.<br>
|
||||||
them to the english translation files and making them available to translators
|
Maintainers can also manually trigger this on demand.
|
||||||
on Transifex.
|
|
||||||
|
|
||||||
### Maintaining Translations (for maintainers) ###
|
### Maintaining Translations (for maintainers) ###
|
||||||
|
|
||||||
When new translatable strings have been added to the code, a maintainer should
|
When new translatable strings have been added to the code, a maintainer has to
|
||||||
make them available to translators on Transifex. Every few days, or when a lot
|
make them available to translators on Transifex.
|
||||||
of new strings have been added, a maintainer should take care of extracting all
|
|
||||||
the new strings and add them to the english translation files.
|
|
||||||
|
|
||||||
To update the english translation files, re-run cmake enabling the appropriate
|
To help with that, we have an automated CI workflow, that regularly looks at the
|
||||||
|
code in the master branch, extracts all strings and updates dedicated source string
|
||||||
|
files with any changes. These updates are not commited right away, the CI creates a
|
||||||
|
PR for reviewing instead.<br>
|
||||||
|
After approval, our translation tool automatically picks the changes up and deploys
|
||||||
|
them to our translators. Be mindful when merging only a few changes!
|
||||||
|
|
||||||
|
Once a release is planned, or when a lot of strings have been added or changed, a
|
||||||
|
maintainer can manually trigger a CI run to extract all strings on demand.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Manually trigger CI run (Workflow Dispatch)</b></summary>
|
||||||
|
|
||||||
|
Maintainers can always request the CI to run on demand if it's required.
|
||||||
|
|
||||||
|
Go to the `Actions` tab and select our dedicated translation workflow:
|
||||||
|
https://github.com/Cockatrice/Cockatrice/actions/workflows/translations.yml
|
||||||
|
|
||||||
|
You see a "This workflow has a workflow_dispatch event trigger." hint at the top of
|
||||||
|
the list.<br>
|
||||||
|
Select `Run workflow` on the right and trigger a run from master branch.
|
||||||
|
|
||||||
|
The CI will now check for changed strings and create a PR if there are any updates.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>Manually update source strings locally</b></summary>
|
||||||
|
|
||||||
|
To update the english source files for translation, re-run cmake enabling the appropriate
|
||||||
parameter and then run make:
|
parameter and then run make:
|
||||||
```sh
|
```sh
|
||||||
cd cockatrice/build
|
cd cockatrice/build
|
||||||
@@ -344,24 +371,26 @@ 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
|
||||||
cmake .. -DUPDATE_TRANSLATIONS=OFF
|
cmake .. -DUPDATE_TRANSLATIONS=OFF
|
||||||
```
|
```
|
||||||
Now you are ready to propose your change.
|
Now you are ready to commit your changes and open a PR.
|
||||||
|
|
||||||
Once your change gets merged, Transifex will pick up the modified files
|
</details>
|
||||||
automatically (checked every 24 hours) and update the interface where
|
|
||||||
translators will be able to translate the new strings.
|
Once the changes get merged, Transifex will pick up the modified files
|
||||||
|
automatically (checked every few hours) and update their online editor where
|
||||||
|
translators will be able to translate the new strings right in the browser.
|
||||||
|
|
||||||
### Releasing Translations (for maintainers) ###
|
### Releasing Translations (for maintainers) ###
|
||||||
|
|
||||||
|
|||||||
49
.github/dependabot.yml
vendored
Normal file
49
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Configuration options: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# # Enable version updates for git submodules
|
||||||
|
# Not yet possible to bump only on tags or releases, see:
|
||||||
|
# https://github.com/dependabot/dependabot-core/issues/1639
|
||||||
|
# https://github.com/dependabot/dependabot-core/issues/2192
|
||||||
|
# Alternative: Action that updates submodule and can be manually run on demand (workflow_dispatch)
|
||||||
|
# - package-ecosystem: "gitsubmodule"
|
||||||
|
# # Look for `.gitmodules` in the `root` directory
|
||||||
|
# directory: "/"
|
||||||
|
# # Check for updates once a month
|
||||||
|
# schedule:
|
||||||
|
# interval: "monthly"
|
||||||
|
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||||
|
# open-pull-requests-limit: 1
|
||||||
|
|
||||||
|
# # Enable version updates for Docker
|
||||||
|
# Not yet possible to bump from one LTS version to the next and skip others, see:
|
||||||
|
# https://github.com/dependabot/dependabot-core/issues/2247
|
||||||
|
# - package-ecosystem: "docker"
|
||||||
|
# # Look for a `Dockerfile` in the `root` directory
|
||||||
|
# directory: "/"
|
||||||
|
# # Check for updates once a week
|
||||||
|
# schedule:
|
||||||
|
# interval: "weekly"
|
||||||
|
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||||
|
# open-pull-requests-limit: 1
|
||||||
|
|
||||||
|
# Enable version updates for GitHub Actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
# Directory must be set to "/" to check for workflow files in .github/workflows
|
||||||
|
directory: "/"
|
||||||
|
# Check for updates to GitHub Actions once a week
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
# Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||||
|
open-pull-requests-limit: 2
|
||||||
|
|
||||||
|
# # Enable version updates for npm
|
||||||
|
# - package-ecosystem: "npm"
|
||||||
|
# # Look for `package.json` and `lock` files in the `webclient` subdirectory
|
||||||
|
# directory: "/webclient"
|
||||||
|
# # Check the npm registry for updates once a week
|
||||||
|
# schedule:
|
||||||
|
# interval: "weekly"
|
||||||
|
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||||
|
# open-pull-requests-limit: 5
|
||||||
408
.github/workflows/ci-builds.yml
vendored
408
.github/workflows/ci-builds.yml
vendored
@@ -1,408 +0,0 @@
|
|||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- 'webclient/**'
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- 'webclient/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
configure:
|
|
||||||
name: Configure
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
tag: ${{steps.configure.outputs.tag}}
|
|
||||||
sha: ${{steps.configure.outputs.sha}}
|
|
||||||
upload_url: ${{steps.create_release.outputs.upload_url}}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Cancel previous runs
|
|
||||||
uses: styfle/cancel-workflow-action@0.6.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 "::set-output name=tag::$tag"
|
|
||||||
else # push to branch
|
|
||||||
sha="$GITHUB_SHA"
|
|
||||||
fi
|
|
||||||
echo "::set-output name=sha::$sha"
|
|
||||||
|
|
||||||
- name: Checkout
|
|
||||||
if: steps.configure.outputs.tag != null
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Prepare release paramaters
|
|
||||||
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
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
|
||||||
with:
|
|
||||||
tag_name: ${{github.ref}}
|
|
||||||
release_name: ${{steps.prepare.outputs.title}}
|
|
||||||
body_path: ${{steps.prepare.outputs.body_path}}
|
|
||||||
draft: true
|
|
||||||
prerelease: ${{steps.prepare.outputs.is_beta == 'yes'}}
|
|
||||||
|
|
||||||
build-linux:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# these names correspond to the files in .ci/$distro
|
|
||||||
include:
|
|
||||||
- distro: UbuntuImpish
|
|
||||||
package: DEB
|
|
||||||
|
|
||||||
- distro: UbuntuHirsute
|
|
||||||
package: DEB
|
|
||||||
test: skip
|
|
||||||
|
|
||||||
- distro: UbuntuFocal
|
|
||||||
package: DEB
|
|
||||||
test: skip # UbuntuFocal has a broken qt for debug builds
|
|
||||||
|
|
||||||
- distro: UbuntuBionic
|
|
||||||
package: DEB
|
|
||||||
|
|
||||||
- distro: ArchLinux
|
|
||||||
package: skip # we are packaged in arch already
|
|
||||||
allow-failure: yes
|
|
||||||
|
|
||||||
- distro: DebianBuster
|
|
||||||
package: DEB
|
|
||||||
|
|
||||||
- distro: Fedora35
|
|
||||||
package: RPM
|
|
||||||
|
|
||||||
- distro: Fedora34
|
|
||||||
package: RPM
|
|
||||||
test: skip # gtest does not compile for some reason
|
|
||||||
|
|
||||||
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?
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Get cache timestamp
|
|
||||||
id: cache_timestamp
|
|
||||||
shell: bash
|
|
||||||
run: echo "::set-output name=timestamp::$(date -u '+%Y%m%d%H%M%S')"
|
|
||||||
|
|
||||||
- name: Restore cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
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
|
|
||||||
run: |
|
|
||||||
source .ci/docker.sh
|
|
||||||
RUN --server --debug --test
|
|
||||||
|
|
||||||
- name: Build release package
|
|
||||||
id: package
|
|
||||||
if: matrix.package != 'skip'
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
suffix: '-${{matrix.distro}}'
|
|
||||||
type: '${{matrix.package}}'
|
|
||||||
run: |
|
|
||||||
source .ci/docker.sh
|
|
||||||
RUN --server --release --package "$type" --suffix "$suffix"
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
if: matrix.package != 'skip'
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: ${{matrix.distro}}-package
|
|
||||||
path: ./build/${{steps.package.outputs.name}}
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload to release
|
|
||||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
|
||||||
with:
|
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
|
||||||
asset_path: ./build/${{steps.package.outputs.name}}
|
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
build-macos:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
target:
|
|
||||||
- Debug
|
|
||||||
- 10.14_Mojave
|
|
||||||
- 10.15_Catalina
|
|
||||||
- 11_Big_Sur
|
|
||||||
include:
|
|
||||||
- target: Debug # tests only
|
|
||||||
os: macos-latest
|
|
||||||
xcode: 12.1
|
|
||||||
type: Debug
|
|
||||||
do_tests: 0 # tests do not work yet on mac
|
|
||||||
make_package: false
|
|
||||||
|
|
||||||
- target: 10.14_Mojave
|
|
||||||
os: macos-10.15 # runs on Catalina
|
|
||||||
xcode: 10.3 # allows compatibility with macOS 10.14
|
|
||||||
type: Release
|
|
||||||
do_tests: 0
|
|
||||||
make_package: true
|
|
||||||
|
|
||||||
- target: 10.15_Catalina
|
|
||||||
os: macos-10.15
|
|
||||||
xcode: 12.1
|
|
||||||
type: Release
|
|
||||||
do_tests: 0
|
|
||||||
make_package: true
|
|
||||||
|
|
||||||
- target: 11_Big_Sur
|
|
||||||
os: macos-11
|
|
||||||
xcode: 12.5.1
|
|
||||||
type: Release
|
|
||||||
do_tests: 0
|
|
||||||
make_package: true
|
|
||||||
|
|
||||||
name: macOS ${{matrix.target}}
|
|
||||||
|
|
||||||
needs: configure
|
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
|
|
||||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
|
||||||
|
|
||||||
env:
|
|
||||||
CCACHE_DIR: ~/.ccache
|
|
||||||
DEVELOPER_DIR:
|
|
||||||
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install dependencies using homebrew
|
|
||||||
shell: bash
|
|
||||||
# cmake cannot find the mysql connector
|
|
||||||
# neither of these works: mariadb-connector-c mysql-connector-c++
|
|
||||||
run: brew install ccache protobuf
|
|
||||||
|
|
||||||
- name: Install QT using homebrew
|
|
||||||
id: brew_install_qt
|
|
||||||
continue-on-error: true
|
|
||||||
shell: bash
|
|
||||||
run: brew install qt@5 --force-bottle
|
|
||||||
|
|
||||||
- name: Install QT using actions
|
|
||||||
if: steps.brew_install_qt.outcome != 'success'
|
|
||||||
uses: jurplel/install-qt-action@v2
|
|
||||||
|
|
||||||
- name: Get ccache timestamp
|
|
||||||
id: ccache_timestamp
|
|
||||||
shell: bash
|
|
||||||
run: echo "::set-output name=timestamp::$(date -u '+%Y%m%d%H%M%S')"
|
|
||||||
|
|
||||||
- name: Restore ccache cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
env:
|
|
||||||
timestamp: ${{steps.ccache_timestamp.outputs.timestamp}}
|
|
||||||
with:
|
|
||||||
path: ${{env.CCACHE_DIR}}
|
|
||||||
key: ${{runner.os}}-xcode-${{matrix.xcode}}-ccache-${{env.timestamp}}
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-xcode-${{matrix.xcode}}-ccache-
|
|
||||||
|
|
||||||
- name: Build on Xcode ${{matrix.xcode}}
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
CMAKE_BUILD_PARALLEL_LEVEL: 3 # mac machines actually have 3 cores
|
|
||||||
run: .ci/compile.sh ${{matrix.type}} --server
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
if: matrix.do_tests == 1
|
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: cmake --build . --target test
|
|
||||||
|
|
||||||
- name: Package for ${{matrix.target}}
|
|
||||||
id: package
|
|
||||||
if: matrix.make_package
|
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: |
|
|
||||||
cmake --build . --target package
|
|
||||||
../.ci/name_build.sh "-macOS-${{matrix.target}}"
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
if: matrix.make_package
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: macOS-${{matrix.target}}-xcode-${{matrix.xcode}}-dmg
|
|
||||||
path: ${{steps.package.outputs.path}}
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload to release
|
|
||||||
if: matrix.make_package && needs.configure.outputs.tag != null
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
|
||||||
with:
|
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
|
||||||
asset_path: ${{steps.package.outputs.path}}
|
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
arch:
|
|
||||||
- 64
|
|
||||||
- 32
|
|
||||||
include:
|
|
||||||
- arch: 64
|
|
||||||
triplet: x64
|
|
||||||
cmake: x64
|
|
||||||
append: _64
|
|
||||||
|
|
||||||
- arch: 32
|
|
||||||
triplet: x86
|
|
||||||
cmake: Win32
|
|
||||||
|
|
||||||
name: Windows ${{matrix.arch}}
|
|
||||||
|
|
||||||
needs: configure
|
|
||||||
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
env:
|
|
||||||
QT_VERSION: '5.15.2'
|
|
||||||
QT_ARCH: msvc2019${{matrix.append}}
|
|
||||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Add msbuild to PATH
|
|
||||||
id: add-msbuild
|
|
||||||
uses: microsoft/setup-msbuild@v1.0.2
|
|
||||||
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Restore Qt ${{env.QT_VERSION}} ${{matrix.arch}}-bit from cache
|
|
||||||
id: cache-qt
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
key: ${{runner.os}}-QtCache-${{env.QT_VERSION}}-${{matrix.arch}}
|
|
||||||
path: ${{runner.workspace}}/Qt
|
|
||||||
|
|
||||||
- name: Install ${{matrix.arch}}-bit Qt
|
|
||||||
uses: jurplel/install-qt-action@v2
|
|
||||||
with:
|
|
||||||
cached: ${{steps.cache-qt.outputs.cache-hit}}
|
|
||||||
version: ${{env.QT_VERSION}}
|
|
||||||
arch: win${{matrix.arch}}_${{env.QT_ARCH}}
|
|
||||||
|
|
||||||
- name: Restore or setup vcpkg
|
|
||||||
uses: lukka/run-vcpkg@v6
|
|
||||||
with:
|
|
||||||
vcpkgArguments: '@${{github.workspace}}/vcpkg.txt'
|
|
||||||
vcpkgDirectory: ${{github.workspace}}/vcpkg
|
|
||||||
appendedCacheKey: ${{hashFiles('**/vcpkg.txt')}}
|
|
||||||
vcpkgTriplet: ${{matrix.triplet}}-windows
|
|
||||||
|
|
||||||
- name: Configure Cockatrice ${{matrix.arch}}-bit
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
export QTDIR="${{runner.workspace}}/Qt/${{env.QT_VERSION}}/${{env.QT_ARCH}}"
|
|
||||||
cmake .. -G "${{env.CMAKE_GENERATOR}}" -A "${{matrix.cmake}}" -DCMAKE_BUILD_TYPE="Release" -DWITH_SERVER=1 -DTEST=1
|
|
||||||
|
|
||||||
- name: Build Cockatrice ${{matrix.arch}}-bit
|
|
||||||
id: package
|
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: |
|
|
||||||
cmake --build . --target package --config Release
|
|
||||||
../.ci/name_build.sh "-win${{matrix.arch}}"
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: ctest -T Test -C Release
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: Windows-${{matrix.arch}}bit-installer
|
|
||||||
path: ./build/${{steps.package.outputs.name}}
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload to release
|
|
||||||
if: needs.configure.outputs.tag != null
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
|
||||||
with:
|
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
|
||||||
asset_path: ./build/${{steps.package.outputs.name}}
|
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
358
.github/workflows/desktop-build.yml
vendored
Normal file
358
.github/workflows/desktop-build.yml
vendored
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
name: Build Desktop
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- '.github/workflows/translations-*.yml'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- '.github/workflows/translations-*.yml'
|
||||||
|
|
||||||
|
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on master)
|
||||||
|
concurrency:
|
||||||
|
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
|
||||||
|
cancel-in-progress: ${{ github.ref_name != 'master' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
configure:
|
||||||
|
name: Configure
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
tag: ${{steps.configure.outputs.tag}}
|
||||||
|
sha: ${{steps.configure.outputs.sha}}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- 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@v4
|
||||||
|
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$version"
|
||||||
|
include:
|
||||||
|
- distro: Arch
|
||||||
|
package: skip # We are packaged in Arch already
|
||||||
|
allow-failure: yes
|
||||||
|
|
||||||
|
- distro: Debian
|
||||||
|
version: 11
|
||||||
|
package: DEB
|
||||||
|
test: skip # Running tests on all distros is superfluous
|
||||||
|
|
||||||
|
- distro: Debian
|
||||||
|
version: 12
|
||||||
|
package: DEB
|
||||||
|
|
||||||
|
- distro: Fedora
|
||||||
|
version: 40
|
||||||
|
package: RPM
|
||||||
|
test: skip # Running tests on all distros is superfluous
|
||||||
|
|
||||||
|
- distro: Fedora
|
||||||
|
version: 41
|
||||||
|
package: RPM
|
||||||
|
|
||||||
|
- distro: Ubuntu
|
||||||
|
version: 20.04
|
||||||
|
package: DEB
|
||||||
|
test: skip # Ubuntu 20.04 has a broken Qt for debug builds
|
||||||
|
|
||||||
|
- distro: Ubuntu
|
||||||
|
version: 22.04
|
||||||
|
package: DEB
|
||||||
|
test: skip # Running tests on all distros is superfluous
|
||||||
|
|
||||||
|
- distro: Ubuntu
|
||||||
|
version: 24.04
|
||||||
|
package: DEB
|
||||||
|
|
||||||
|
name: ${{matrix.distro}} ${{matrix.version}}
|
||||||
|
needs: configure
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
|
env:
|
||||||
|
NAME: ${{matrix.distro}}${{matrix.version}}
|
||||||
|
CACHE: /tmp/${{matrix.distro}}${{matrix.version}}-cache # ${{runner.temp}} does not work?
|
||||||
|
# Cache size over the entire repo is 10Gi:
|
||||||
|
# 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@v4
|
||||||
|
|
||||||
|
- name: Generate 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@v4
|
||||||
|
env:
|
||||||
|
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
||||||
|
with:
|
||||||
|
path: ${{env.CACHE}}
|
||||||
|
key: docker-${{matrix.distro}}${{matrix.version}}-cache-${{env.timestamp}}
|
||||||
|
restore-keys: |
|
||||||
|
docker-${{matrix.distro}}${{matrix.version}}-cache-
|
||||||
|
|
||||||
|
- name: Build ${{matrix.distro}} ${{matrix.version}} Docker image
|
||||||
|
shell: bash
|
||||||
|
run: source .ci/docker.sh --build
|
||||||
|
|
||||||
|
- name: Build debug and test
|
||||||
|
if: matrix.test != 'skip'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
source .ci/docker.sh
|
||||||
|
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
|
||||||
|
|
||||||
|
- name: Build release package
|
||||||
|
id: build
|
||||||
|
if: matrix.package != 'skip'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
BUILD_DIR: build
|
||||||
|
SUFFIX: '-${{matrix.distro}}${{matrix.version}}'
|
||||||
|
type: '${{matrix.package}}'
|
||||||
|
run: |
|
||||||
|
source .ci/docker.sh
|
||||||
|
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
|
||||||
|
--ccache "$CCACHE_SIZE" --parallel 4
|
||||||
|
.ci/name_build.sh
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: matrix.package != 'skip'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{matrix.distro}}${{matrix.version}}-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: 13
|
||||||
|
soc: Intel
|
||||||
|
os: macos-13
|
||||||
|
xcode: "14.3.1"
|
||||||
|
type: Release
|
||||||
|
core_count: 4
|
||||||
|
make_package: 1
|
||||||
|
|
||||||
|
- target: 14
|
||||||
|
soc: Apple
|
||||||
|
os: macos-14
|
||||||
|
xcode: "15.4"
|
||||||
|
type: Release
|
||||||
|
core_count: 3
|
||||||
|
make_package: 1
|
||||||
|
|
||||||
|
- target: 14
|
||||||
|
soc: Apple
|
||||||
|
os: macos-14
|
||||||
|
xcode: "15.4"
|
||||||
|
type: Debug
|
||||||
|
core_count: 3
|
||||||
|
|
||||||
|
name: macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Install dependencies using Homebrew
|
||||||
|
shell: bash
|
||||||
|
# CMake cannot find the MySQL connector
|
||||||
|
# Neither of these works: mariadb-connector-c mysql-connector-c++
|
||||||
|
env:
|
||||||
|
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||||
|
run: |
|
||||||
|
brew update
|
||||||
|
brew install protobuf qt --force-bottle
|
||||||
|
|
||||||
|
- name: Build on Xcode ${{matrix.xcode}}
|
||||||
|
shell: bash
|
||||||
|
id: build
|
||||||
|
env:
|
||||||
|
BUILDTYPE: '${{matrix.type}}'
|
||||||
|
MAKE_TEST: 1
|
||||||
|
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||||
|
PACKAGE_SUFFIX: '-macOS${{matrix.target}}_${{matrix.soc}}'
|
||||||
|
# macOS runner have 3 cores usually - only the macos-13 image has 4:
|
||||||
|
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
||||||
|
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
|
||||||
|
run: .ci/compile.sh --server --parallel ${{matrix.core_count}}
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
if: matrix.make_package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-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: 7
|
||||||
|
qt_version: 5.15.*
|
||||||
|
qt_arch: msvc2019_64
|
||||||
|
|
||||||
|
- target: 10
|
||||||
|
qt_version: 6.6.*
|
||||||
|
qt_arch: msvc2019_64
|
||||||
|
qt_modules: "qtimageformats qtmultimedia qtwebsockets"
|
||||||
|
|
||||||
|
name: Windows ${{matrix.target}}
|
||||||
|
needs: configure
|
||||||
|
runs-on: windows-2022
|
||||||
|
env:
|
||||||
|
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
id: add-msbuild
|
||||||
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
with:
|
||||||
|
msbuild-architecture: x64
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Qt ${{matrix.qt_version}}
|
||||||
|
uses: jurplel/install-qt-action@v4
|
||||||
|
with:
|
||||||
|
cache: true
|
||||||
|
setup-python: false
|
||||||
|
version: ${{matrix.qt_version}}
|
||||||
|
arch: win64_${{matrix.qt_arch}}
|
||||||
|
tools: ${{matrix.qt_tools}}
|
||||||
|
modules: ${{matrix.qt_modules}}
|
||||||
|
|
||||||
|
- name: Run vcpkg
|
||||||
|
uses: lukka/run-vcpkg@v11
|
||||||
|
with:
|
||||||
|
runVcpkgInstall: true
|
||||||
|
doNotCache: false
|
||||||
|
env:
|
||||||
|
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
|
||||||
|
VCPKG_DISABLE_METRICS: 1
|
||||||
|
|
||||||
|
- name: Build Cockatrice
|
||||||
|
id: build
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
PACKAGE_SUFFIX: '-Win${{matrix.target}}'
|
||||||
|
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||||
|
CMAKE_GENERATOR_PLATFORM: 'x64'
|
||||||
|
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win64_${{matrix.qt_arch}}'
|
||||||
|
# No need for --parallel flag, MTT is added in the compile script to let cmake/msbuild manage core count,
|
||||||
|
# project and process parallelism: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||||
|
run: .ci/compile.sh --server --release --test --package
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Windows${{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"
|
||||||
@@ -2,28 +2,28 @@ name: Code Style (C++)
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- 'webclient/**'
|
- 'webclient/**'
|
||||||
|
- '.github/workflows/web-*.yml'
|
||||||
|
- '.github/workflows/translations-*.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
clang-format:
|
format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 20 # should be enough to find merge base
|
fetch-depth: 20 # should be enough to find merge base
|
||||||
|
|
||||||
- name: Install clang-format
|
- name: Install dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y --no-install-recommends clang-format
|
sudo apt-get install -y --no-install-recommends clang-format cmake-format
|
||||||
|
|
||||||
- name: Run clangify
|
- name: Check code formatting
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./.ci/lint_cpp.sh
|
run: ./.ci/lint_cpp.sh
|
||||||
72
.github/workflows/translations-pull.yml
vendored
Normal file
72
.github/workflows/translations-pull.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: Update Translations
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
# runs in the middle of each month starting a quarter (UTC) = two weeks after new strings are built
|
||||||
|
- cron: '0 0 15 1,4,7,10 *'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/translations-pull.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
translations:
|
||||||
|
# Do not run the scheduled workflow on forks
|
||||||
|
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||||
|
|
||||||
|
name: Pull languages
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Pull translated strings from Transifex
|
||||||
|
uses: transifex/cli-action@v2
|
||||||
|
with:
|
||||||
|
# used config file: https://github.com/Cockatrice/Cockatrice/blob/master/.tx/config
|
||||||
|
# https://github.com/transifex/cli#pulling-files-from-transifex
|
||||||
|
token: ${{ secrets.TX_TOKEN }}
|
||||||
|
args: pull --force --all
|
||||||
|
|
||||||
|
- name: Create pull request
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
id: create_pr
|
||||||
|
uses: peter-evans/create-pull-request@v7
|
||||||
|
with:
|
||||||
|
add-paths: |
|
||||||
|
cockatrice/translations/*.ts
|
||||||
|
oracle/translations/*.ts
|
||||||
|
webclient/public/locales/*/translation.json
|
||||||
|
commit-message: Update translation files
|
||||||
|
# author is the owner of the commit
|
||||||
|
author: github-actions <github-actions@github.com>
|
||||||
|
branch: ci-update_translations
|
||||||
|
delete-branch: true
|
||||||
|
title: 'Update translations'
|
||||||
|
body: |
|
||||||
|
Pulled all translated strings from [Transifex][1].
|
||||||
|
|
||||||
|
---
|
||||||
|
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br>
|
||||||
|
*After merging, all new languages and translations are available in the next build.*
|
||||||
|
|
||||||
|
[1]: https://app.transifex.com/cockatrice/cockatrice/
|
||||||
|
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster
|
||||||
|
labels: |
|
||||||
|
CI
|
||||||
|
Translation
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
- name: PR Status
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||||
|
run: |
|
||||||
|
if [[ "$STATUS" == "none" ]]; then
|
||||||
|
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY
|
||||||
87
.github/workflows/translations-push.yml
vendored
Normal file
87
.github/workflows/translations-push.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
name: Update Translation Source
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
# runs at the start of each quarter (UTC)
|
||||||
|
- cron: '0 0 1 1,4,7,10 *'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/translations-push.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
translations:
|
||||||
|
# Do not run the scheduled workflow on forks
|
||||||
|
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||||
|
|
||||||
|
name: Push strings
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install lupdate
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --no-install-recommends qttools5-dev-tools
|
||||||
|
|
||||||
|
- name: Update Cockatrice translation source
|
||||||
|
id: cockatrice
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
FILE: 'cockatrice/cockatrice_en@source.ts'
|
||||||
|
DIRS: 'cockatrice/src common'
|
||||||
|
run: .ci/update_translation_source_strings.sh
|
||||||
|
|
||||||
|
- name: Update Oracle translation source
|
||||||
|
id: oracle
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
FILE: 'oracle/oracle_en@source.ts'
|
||||||
|
DIRS: 'oracle/src'
|
||||||
|
run: .ci/update_translation_source_strings.sh
|
||||||
|
|
||||||
|
- name: Render template
|
||||||
|
id: template
|
||||||
|
uses: chuhlomin/render-template@v1
|
||||||
|
with:
|
||||||
|
template: .ci/update_translation_source_strings_template.md
|
||||||
|
vars: |
|
||||||
|
cockatrice_output: ${{ steps.cockatrice.outputs.output }}
|
||||||
|
oracle_output: ${{ steps.oracle.outputs.output }}
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Create pull request
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
id: create_pr
|
||||||
|
uses: peter-evans/create-pull-request@v7
|
||||||
|
with:
|
||||||
|
add-paths: |
|
||||||
|
cockatrice/cockatrice_en@source.ts
|
||||||
|
oracle/oracle_en@source.ts
|
||||||
|
commit-message: Update translation source strings
|
||||||
|
# author is the owner of the commit
|
||||||
|
author: github-actions <github-actions@github.com>
|
||||||
|
branch: ci-update_translation_source
|
||||||
|
delete-branch: true
|
||||||
|
title: 'Update source strings'
|
||||||
|
body: ${{ steps.template.outputs.result }}
|
||||||
|
labels: |
|
||||||
|
CI
|
||||||
|
Translation
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
- name: PR Status
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||||
|
run: |
|
||||||
|
if [[ "$STATUS" == "none" ]]; then
|
||||||
|
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
|
||||||
|
else
|
||||||
|
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
|
||||||
|
fi
|
||||||
|
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY
|
||||||
52
.github/workflows/web-build.yml
vendored
Normal file
52
.github/workflows/web-build.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
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@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
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,7 +6,10 @@ mysql.cnf
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.idea/
|
.idea/
|
||||||
*.aps
|
*.aps
|
||||||
cmake-build-debug/
|
cmake-build-debug*
|
||||||
preferences
|
preferences
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
.vs/
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
.cache
|
||||||
|
.gdb_history
|
||||||
|
|||||||
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
|
||||||
27
.tx/config
27
.tx/config
@@ -1,13 +1,26 @@
|
|||||||
[main]
|
[main]
|
||||||
host = https://www.transifex.com
|
host = https://app.transifex.com
|
||||||
|
|
||||||
[cockatrice.cockatrice]
|
[o:cockatrice:p:cockatrice:r:cockatrice-cockatrice-en-source-ts--master]
|
||||||
|
resource_name = Cockatrice
|
||||||
|
source_lang = en
|
||||||
|
source_file = cockatrice/cockatrice_en@source.ts
|
||||||
file_filter = cockatrice/translations/cockatrice_<lang>.ts
|
file_filter = cockatrice/translations/cockatrice_<lang>.ts
|
||||||
source_file = cockatrice/translations/cockatrice_en.ts
|
type = QT
|
||||||
source_lang = en
|
minimum_perc = 10
|
||||||
|
|
||||||
[cockatrice.oracle]
|
[o:cockatrice:p:cockatrice:r:oracle-oracle-en-source-ts--master]
|
||||||
|
resource_name = Oracle
|
||||||
|
source_lang = en
|
||||||
|
source_file = oracle/oracle_en@source.ts
|
||||||
file_filter = oracle/translations/oracle_<lang>.ts
|
file_filter = oracle/translations/oracle_<lang>.ts
|
||||||
source_file = oracle/translations/oracle_en.ts
|
type = QT
|
||||||
source_lang = en
|
minimum_perc = 10
|
||||||
|
|
||||||
|
[o:cockatrice:p:cockatrice:r:webclient-src-i18n-default-json--master]
|
||||||
|
resource_name = Webclient
|
||||||
|
source_lang = en
|
||||||
|
source_file = webclient/src/i18n-default.json
|
||||||
|
file_filter = webclient/public/locales/<lang>/translation.json
|
||||||
|
type = KEYVALUEJSON
|
||||||
|
minimum_perc = 10
|
||||||
|
|||||||
442
CMakeLists.txt
442
CMakeLists.txt
@@ -5,58 +5,95 @@
|
|||||||
# 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.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
# Early detect ccache
|
||||||
|
option(USE_CCACHE "Cache the build results with ccache" ON)
|
||||||
|
# Treat warnings as errors (Debug builds only)
|
||||||
|
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||||
|
# Check for translation updates
|
||||||
|
option(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
||||||
|
# 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
|
|
||||||
OPTION(USE_CCACHE "Cache the build results with ccache" ON)
|
|
||||||
if(USE_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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# Use vcpkg toolchain on Windows
|
# Use vcpkg toolchain on Windows
|
||||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
set(CMAKE_TOOLCHAIN_FILE
|
||||||
CACHE STRING "Vcpkg toolchain file")
|
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||||
# Qt path set by user or env var
|
CACHE STRING "Vcpkg toolchain file"
|
||||||
if (QTDIR OR DEFINED ENV{QTDIR} OR DEFINED ENV{QTDIR32} OR DEFINED ENV{QTDIR64})
|
)
|
||||||
else()
|
# Qt path set by user or env var
|
||||||
set(QTDIR "" CACHE PATH "Path to Qt (e.g. C:/Qt/5.7/msvc2015_64)")
|
if(QTDIR
|
||||||
message(WARNING "QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/5.7/msvc2015_64)")
|
OR DEFINED ENV{QTDIR}
|
||||||
endif()
|
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.8.1)
|
project("Cockatrice" VERSION 2.10.0)
|
||||||
|
|
||||||
# Set release name if not provided via env/cmake var
|
# Set release name if not provided via env/cmake var
|
||||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||||
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
set(GIT_TAG_RELEASENAME "Rings of the Wild")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Use c++11 for all targets
|
# Use c++20 for all targets
|
||||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
set(CMAKE_CXX_STANDARD
|
||||||
|
20
|
||||||
|
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}")
|
||||||
|
|
||||||
include(getversion)
|
include(getversion)
|
||||||
|
|
||||||
@@ -65,152 +102,154 @@ 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)
|
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
|
||||||
|
|
||||||
# Force ccache usage if available
|
# Force ccache usage if available
|
||||||
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
|
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
|
||||||
if(RULE_LAUNCH_COMPILE)
|
if(RULE_LAUNCH_COMPILE)
|
||||||
MESSAGE(STATUS "Force enabling CCache usage under macOS")
|
message(STATUS "Force enabling CCache usage under macOS")
|
||||||
# Set up wrapper scripts
|
# Set up wrapper scripts
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-c.in launch-c)
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-cxx.in launch-cxx)
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
|
||||||
execute_process(COMMAND chmod a+rx
|
execute_process(COMMAND chmod a+rx "${CMAKE_BINARY_DIR}/launch-c" "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
"${CMAKE_BINARY_DIR}/launch-c"
|
|
||||||
"${CMAKE_BINARY_DIR}/launch-cxx")
|
|
||||||
|
|
||||||
# Set Xcode project attributes to route compilation through our scripts
|
# Set Xcode project attributes to route compilation through our scripts
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
|
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
|
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
|
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
|
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()
|
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)
|
elseif(WIN32)
|
||||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
|
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: Maximum optimization, disable warning C4251
|
# Visual Studio: Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 ")
|
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc")
|
||||||
# Generate complete debugging information
|
# Visual Studio: Maximum Optimization, Multi-threaded DLL
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
||||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
# Visual Studio: No Optimization, Multi-threaded Debug DLL, Debug Symbols
|
||||||
# linux/gcc, bsd/gcc, windows/mingw
|
set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd /Zi")
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
add_compile_definitions(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING)
|
||||||
if(WARNING_AS_ERROR)
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
|
# linux/gcc, bsd/gcc, windows/mingw
|
||||||
else()
|
include(CheckCXXCompilerFlag)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
||||||
|
if(WARNING_AS_ERROR)
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20")
|
||||||
|
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 -Wno-unused-parameter")
|
||||||
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")
|
|
||||||
if(WARNING_AS_ERROR)
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror")
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
|
|
||||||
endif()
|
|
||||||
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_PACKAGE(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
# Find Qt5
|
# Determine 32 or 64 bit build
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(_lib_suffix 64)
|
set(_lib_suffix 64)
|
||||||
else()
|
else()
|
||||||
set(_lib_suffix 32)
|
set(_lib_suffix 32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DEFINED QTDIR${_lib_suffix})
|
if(DEFINED QTDIR${_lib_suffix})
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
|
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
|
||||||
elseif(DEFINED QTDIR)
|
elseif(DEFINED QTDIR)
|
||||||
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
|
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
|
||||||
elseif(DEFINED ENV{QTDIR${_lib_suffix}})
|
elseif(DEFINED ENV{QTDIR${_lib_suffix}})
|
||||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
|
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
|
||||||
elseif(DEFINED ENV{QTDIR})
|
elseif(DEFINED ENV{QTDIR})
|
||||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
FIND_PACKAGE(Qt5Core 5.5.0 REQUIRED)
|
message(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
||||||
|
|
||||||
IF(Qt5Core_FOUND)
|
include(FindQtRuntime)
|
||||||
MESSAGE(STATUS "Found Qt ${Qt5Core_VERSION_STRING}")
|
|
||||||
|
|
||||||
# FIX: Qt was built with -reduce-relocations
|
|
||||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
|
||||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# guess plugins and libraries directory
|
|
||||||
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()
|
|
||||||
|
|
||||||
# Check for translation updates
|
|
||||||
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
|
||||||
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
|
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC TRUE)
|
set(CMAKE_AUTOMOC TRUE)
|
||||||
|
|
||||||
# Find other needed libraries
|
# Find other needed libraries
|
||||||
FIND_PACKAGE(Protobuf REQUIRED)
|
find_package(Protobuf CONFIG)
|
||||||
IF(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
if(NOT Protobuf_FOUND)
|
||||||
MESSAGE(FATAL_ERROR "No protoc command found!")
|
find_package(Protobuf REQUIRED)
|
||||||
ELSE()
|
endif()
|
||||||
MESSAGE(STATUS "Protoc version ${Protobuf_VERSION} found!")
|
|
||||||
ENDIF()
|
if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||||
|
message(FATAL_ERROR "No protoc command found!")
|
||||||
|
endif()
|
||||||
|
|
||||||
#Find OpenSSL
|
#Find OpenSSL
|
||||||
IF(WIN32)
|
if(WIN32)
|
||||||
FIND_PACKAGE(Win32SslRuntime)
|
find_package(OpenSSL REQUIRED)
|
||||||
ENDIF()
|
if(OPENSSL_FOUND)
|
||||||
|
include_directories(${OPENSSL_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
|
||||||
|
)
|
||||||
|
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")
|
||||||
@@ -220,82 +259,95 @@ 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")
|
||||||
|
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script")
|
||||||
|
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
|
||||||
|
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, qt6-qtimageformats")
|
||||||
|
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, qt6-image-formats-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_PLATFORM}" MATCHES "(x64)")
|
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 dbconverter (default on)
|
|
||||||
option(WITH_DBCONVERTER "build dbconverter" ON)
|
|
||||||
if(WITH_DBCONVERTER)
|
if(WITH_DBCONVERTER)
|
||||||
add_subdirectory(dbconverter)
|
add_subdirectory(dbconverter)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
set(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile tests (default off)
|
|
||||||
option(TEST "build tests" OFF)
|
|
||||||
if(TEST)
|
if(TEST)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(tests)
|
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()
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -5,10 +5,10 @@
|
|||||||
<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>
|
||||||
<a href="#run">Run</a> <b>|</b>
|
<a href="#run">Run</a> <b>|</b>
|
||||||
<a href="#license-">License</a>
|
<a href="#license-">License</a>
|
||||||
</p>
|
</p>
|
||||||
@@ -40,9 +40,9 @@ Downloads are available for full releases and the current beta version in develo
|
|||||||
- 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://discord.gg/3Z9yzmA) [](https://gitter.im/Cockatrice/Cockatrice)
|
# Get Involved [](https://discord.gg/3Z9yzmA)
|
||||||
|
|
||||||
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>
|
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project, contributors or fellow users of the app. 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>
|
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).
|
||||||
@@ -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,18 +65,14 @@ 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://transifex.com/cockatrice/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, Oracle and Webatrice to your language or just adjust single wordings right from within your browser by visiting our [Transifex project page](https://transifex.com/cockatrice/cockatrice/).<br>
|
||||||
|
|
||||||
| Cockatrice | Oracle |
|
|
||||||
|:-:|:-:|
|
|
||||||
| [](https://www.transifex.com/projects/p/cockatrice/) | [](https://www.transifex.com/projects/p/cockatrice/) |
|
|
||||||
|
|
||||||
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://github.com/Cockatrice/Cockatrice/actions/workflows/ci-builds.yml?query=branch%3Amaster+event%3Apush)
|
# 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 can be found 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)**
|
||||||
|
|
||||||
@@ -117,6 +111,7 @@ 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
|
||||||
|
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
|
|||||||
55
cmake/CMakeDMGSetup.script
Normal file
55
cmake/CMakeDMGSetup.script
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
on run argv
|
||||||
|
set image_name to item 1 of argv
|
||||||
|
|
||||||
|
tell application "Finder"
|
||||||
|
tell disk image_name
|
||||||
|
|
||||||
|
-- wait for the image to finish mounting
|
||||||
|
set open_attempts to 0
|
||||||
|
repeat while open_attempts < 4
|
||||||
|
try
|
||||||
|
open
|
||||||
|
delay 1
|
||||||
|
set open_attempts to 5
|
||||||
|
close
|
||||||
|
on error errStr number errorNumber
|
||||||
|
set open_attempts to open_attempts + 1
|
||||||
|
delay 10
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
delay 5
|
||||||
|
|
||||||
|
-- open the image the first time and save a DS_Store with just
|
||||||
|
-- background and icon setup
|
||||||
|
open
|
||||||
|
set current view of container window to icon view
|
||||||
|
set theViewOptions to the icon view options of container window
|
||||||
|
set background picture of theViewOptions to file ".background:background.tif"
|
||||||
|
set arrangement of theViewOptions to not arranged
|
||||||
|
set icon size of theViewOptions to 128
|
||||||
|
delay 5
|
||||||
|
close
|
||||||
|
|
||||||
|
-- next setup the position of the app and Applications symlink
|
||||||
|
-- plus hide all the window decoration
|
||||||
|
open
|
||||||
|
update without registering applications
|
||||||
|
tell container window
|
||||||
|
set sidebar width to 0
|
||||||
|
set statusbar visible to false
|
||||||
|
set toolbar visible to false
|
||||||
|
set the bounds to { 400, 100, 1400, 922 }
|
||||||
|
set position of item "Cockatrice.app" to { 139, 214 }
|
||||||
|
set position of item "Oracle.app" to { 139, 414 }
|
||||||
|
set position of item "Servatrice.app" to { 139, 614 }
|
||||||
|
set position of item "dbconverter.app" to { 1400, 1400 }
|
||||||
|
set position of item "Applications" to { 861, 414 }
|
||||||
|
end tell
|
||||||
|
update without registering applications
|
||||||
|
delay 5
|
||||||
|
close
|
||||||
|
|
||||||
|
end tell
|
||||||
|
delay 1
|
||||||
|
end tell
|
||||||
|
end run
|
||||||
@@ -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 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,77 +0,0 @@
|
|||||||
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
|
||||||
# will be needed by Qt in order to access https urls.
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
# Get standard installation paths for OpenSSL under Windows
|
|
||||||
|
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
|
||||||
|
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
# target win64
|
|
||||||
set(_OPENSSL_ROOT_HINTS
|
|
||||||
${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"
|
|
||||||
"${_programfiles}/OpenSSL-Win64"
|
|
||||||
"C:/OpenSSL-Win64/"
|
|
||||||
)
|
|
||||||
unset(_programfiles)
|
|
||||||
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
# target win32
|
|
||||||
set(_OPENSSL_ROOT_HINTS
|
|
||||||
${OPENSSL_ROOT_DIR}
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-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/x86-windows/bin"
|
|
||||||
"${_programfiles}/OpenSSL"
|
|
||||||
"${_programfiles}/OpenSSL-Win32"
|
|
||||||
"C:/OpenSSL/"
|
|
||||||
"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
|
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
# target win64
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1-x64.dll libcrypto.dll libeay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1-x64.dll libssl.dll ssleay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
# target win32
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1.dll libcrypto.dll libeay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1.dll libssl.dll ssleay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
|
||||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
@@ -235,6 +235,13 @@ ${If} $PortableMode = 0
|
|||||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||||
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
||||||
IntFmt $0 "0x%08X" $0
|
IntFmt $0 "0x%08X" $0
|
||||||
|
|
||||||
|
; Enable Windows User-Mode Dumps
|
||||||
|
; https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpFolder" "%LOCALAPPDATA%\CrashDumps\Cockatrice"
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpCount" "5"
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpType" "2"
|
||||||
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayIcon" "$INSTDIR\cockatrice.exe"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayIcon" "$INSTDIR\cockatrice.exe"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayName" "Cockatrice"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayName" "Cockatrice"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayVersion" "@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayVersion" "@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@"
|
||||||
@@ -248,20 +255,20 @@ ${If} $PortableMode = 0
|
|||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
|
||||||
|
|
||||||
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
|
IfFileExists "$INSTDIR\vc_redist.x86.exe" VcRedist86Exists PastVcRedist86Check
|
||||||
VcRedist86Exists:
|
VcRedist86Exists:
|
||||||
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
|
ExecWait '"$INSTDIR\vc_redist.x86.exe" /passive /norestart'
|
||||||
DetailPrint "Wait 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\vc_redist.x86.exe"
|
||||||
PastVcRedist86Check:
|
PastVcRedist86Check:
|
||||||
|
|
||||||
IfFileExists "$INSTDIR\vcredist_x64.exe" VcRedist64Exists PastVcRedist64Check
|
IfFileExists "$INSTDIR\vc_redist.x64.exe" VcRedist64Exists PastVcRedist64Check
|
||||||
VcRedist64Exists:
|
VcRedist64Exists:
|
||||||
ExecWait '"$INSTDIR\vcredist_x64.exe" /passive /norestart'
|
ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart'
|
||||||
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
||||||
Sleep 3000
|
Sleep 3000
|
||||||
Delete "$INSTDIR\vcredist_x64.exe"
|
Delete "$INSTDIR\vc_redist.x64.exe"
|
||||||
PastVcRedist64Check:
|
PastVcRedist64Check:
|
||||||
|
|
||||||
${Else}
|
${Else}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
)
|
||||||
|
|||||||
BIN
cmake/dmgBackground.tif
Normal file
BIN
cmake/dmgBackground.tif
Normal file
Binary file not shown.
@@ -1,154 +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
|
||||||
|
"${GIT_COM_DATE}"
|
||||||
|
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
|
||||||
# set release name from env var
|
)
|
||||||
set(PROJECT_VERSION_RELEASENAME "${GIT_TAG_RELEASENAME}" PARENT_SCOPE)
|
elseif(${GIT_TAG_TYPE} STREQUAL "Release")
|
||||||
endif()
|
set(PROJECT_VERSION_LABEL
|
||||||
|
""
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
# set release name from env var
|
||||||
|
set(PROJECT_VERSION_RELEASENAME
|
||||||
|
"${GIT_TAG_RELEASENAME}"
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@@ -163,16 +196,16 @@ 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})")
|
||||||
@@ -180,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}")
|
||||||
|
|
||||||
|
|||||||
@@ -2,284 +2,414 @@
|
|||||||
#
|
#
|
||||||
# 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/abstractcounter.cpp
|
src/game/cards/abstract_card_drag_item.cpp
|
||||||
src/counter_general.cpp
|
src/game/cards/abstract_card_item.cpp
|
||||||
src/dlg_creategame.cpp
|
src/client/game_logic/abstract_client.cpp
|
||||||
src/dlg_filter_games.cpp
|
src/game/board/abstract_counter.cpp
|
||||||
src/dlg_connect.cpp
|
src/game/board/abstract_graphics_item.cpp
|
||||||
src/dlg_create_token.cpp
|
src/game/board/arrow_item.cpp
|
||||||
src/dlg_edit_avatar.cpp
|
src/game/board/arrow_target.cpp
|
||||||
src/dlg_edit_password.cpp
|
src/game/cards/card_database.cpp
|
||||||
src/dlg_edit_tokens.cpp
|
src/game/cards/card_database_manager.cpp
|
||||||
src/dlg_edit_user.cpp
|
src/game/cards/card_database_model.cpp
|
||||||
src/dlg_forgotpasswordrequest.cpp
|
src/game/cards/card_database_parser/card_database_parser.cpp
|
||||||
src/dlg_forgotpasswordreset.cpp
|
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
|
||||||
src/dlg_forgotpasswordchallenge.cpp
|
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
|
||||||
src/dlg_manage_sets.cpp
|
src/game/cards/card_drag_item.cpp
|
||||||
src/dlg_register.cpp
|
src/game/filters/filter_card.cpp
|
||||||
src/dlg_tip_of_the_day.cpp
|
src/client/ui/widgets/cards/card_info_frame_widget.cpp
|
||||||
src/tip_of_the_day.cpp
|
src/client/ui/widgets/cards/card_info_picture_widget.cpp
|
||||||
src/dlg_update.cpp
|
src/client/ui/widgets/cards/card_info_text_widget.cpp
|
||||||
src/dlg_viewlog.cpp
|
src/client/ui/widgets/cards/card_info_display_widget.cpp
|
||||||
src/abstractclient.cpp
|
src/client/ui/widgets/cards/card_size_widget.cpp
|
||||||
src/remoteclient.cpp
|
src/game/cards/card_item.cpp
|
||||||
|
src/game/cards/card_list.cpp
|
||||||
|
src/game/zones/card_zone.cpp
|
||||||
|
src/server/chat_view/chat_view.cpp
|
||||||
|
src/game/board/counter_general.cpp
|
||||||
|
src/deck/custom_line_edit.cpp
|
||||||
|
src/deck/deck_loader.cpp
|
||||||
|
src/deck/deck_list_model.cpp
|
||||||
|
src/deck/deck_stats_interface.cpp
|
||||||
|
src/deck/deck_view.cpp
|
||||||
|
src/dialogs/dlg_connect.cpp
|
||||||
|
src/dialogs/dlg_create_token.cpp
|
||||||
|
src/dialogs/dlg_create_game.cpp
|
||||||
|
src/dialogs/dlg_edit_avatar.cpp
|
||||||
|
src/dialogs/dlg_edit_password.cpp
|
||||||
|
src/dialogs/dlg_edit_tokens.cpp
|
||||||
|
src/dialogs/dlg_edit_user.cpp
|
||||||
|
src/dialogs/dlg_filter_games.cpp
|
||||||
|
src/dialogs/dlg_forgot_password_challenge.cpp
|
||||||
|
src/dialogs/dlg_forgot_password_request.cpp
|
||||||
|
src/dialogs/dlg_forgot_password_reset.cpp
|
||||||
|
src/dialogs/dlg_load_deck_from_clipboard.cpp
|
||||||
|
src/dialogs/dlg_load_remote_deck.cpp
|
||||||
|
src/dialogs/dlg_manage_sets.cpp
|
||||||
|
src/dialogs/dlg_move_top_cards_until.cpp
|
||||||
|
src/dialogs/dlg_register.cpp
|
||||||
|
src/dialogs/dlg_roll_dice.cpp
|
||||||
|
src/dialogs/dlg_settings.cpp
|
||||||
|
src/dialogs/dlg_tip_of_the_day.cpp
|
||||||
|
src/dialogs/dlg_update.cpp
|
||||||
|
src/dialogs/dlg_view_log.cpp
|
||||||
|
src/game/filters/filter_string.cpp
|
||||||
|
src/game/filters/filter_builder.cpp
|
||||||
|
src/game/filters/filter_tree.cpp
|
||||||
|
src/game/filters/filter_tree_model.cpp
|
||||||
|
src/client/ui/layouts/flow_layout.cpp
|
||||||
|
src/client/ui/layouts/horizontal_flow_layout.cpp
|
||||||
|
src/client/ui/layouts/vertical_flow_layout.cpp
|
||||||
|
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
|
||||||
|
src/game/game_scene.cpp
|
||||||
|
src/game/game_selector.cpp
|
||||||
|
src/game/games_model.cpp
|
||||||
|
src/game/game_view.cpp
|
||||||
|
src/client/get_text_with_max.cpp
|
||||||
|
src/game/hand_counter.cpp
|
||||||
|
src/server/handle_public_servers.cpp
|
||||||
|
src/game/zones/hand_zone.cpp
|
||||||
|
src/client/game_logic/key_signals.cpp
|
||||||
|
src/client/ui/line_edit_completer.cpp
|
||||||
|
src/server/local_client.cpp
|
||||||
|
src/server/local_server.cpp
|
||||||
|
src/server/local_server_interface.cpp
|
||||||
|
src/utility/logger.cpp
|
||||||
|
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
|
||||||
|
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
||||||
|
src/client/ui/widgets/general/display/labeled_input.cpp
|
||||||
|
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
|
||||||
|
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
|
||||||
|
src/client/ui/widgets/general/display/shadow_background_label.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/window_main.cpp
|
src/server/message_log_widget.cpp
|
||||||
src/gamesmodel.cpp
|
src/client/ui/layouts/overlap_layout.cpp
|
||||||
src/player.cpp
|
src/client/ui/widgets/general/layout_containers/overlap_widget.cpp
|
||||||
src/playertarget.cpp
|
src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||||
src/cardzone.cpp
|
src/server/pending_command.cpp
|
||||||
src/selectzone.cpp
|
src/game/phase.cpp
|
||||||
src/cardlist.cpp
|
src/client/ui/phases_toolbar.cpp
|
||||||
src/abstractcarditem.cpp
|
src/client/ui/picture_loader.cpp
|
||||||
src/carditem.cpp
|
src/game/zones/pile_zone.cpp
|
||||||
src/tablezone.cpp
|
src/client/ui/pixel_map_generator.cpp
|
||||||
src/handzone.cpp
|
src/game/player/player.cpp
|
||||||
src/handcounter.cpp
|
src/game/player/player_list_widget.cpp
|
||||||
src/carddatabase.cpp
|
src/game/player/player_target.cpp
|
||||||
src/keysignals.cpp
|
src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp
|
||||||
src/gameview.cpp
|
src/client/ui/widgets/printing_selector/card_amount_widget.cpp
|
||||||
src/gameselector.cpp
|
src/client/ui/widgets/printing_selector/printing_selector.cpp
|
||||||
src/decklistmodel.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp
|
||||||
src/deck_loader.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
|
||||||
src/dlg_load_deck_from_clipboard.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
|
||||||
src/dlg_load_remote_deck.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
|
||||||
src/cardinfowidget.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
|
||||||
src/cardframe.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_view_options_toolbar_widget.cpp
|
||||||
src/cardinfopicture.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_view_options_widget.cpp
|
||||||
src/cardinfotext.cpp
|
src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
|
||||||
src/filterbuilder.cpp
|
src/client/network/release_channel.cpp
|
||||||
src/cardfilter.cpp
|
src/server/remote/remote_client.cpp
|
||||||
src/filtertreemodel.cpp
|
src/server/remote/remote_decklist_tree_widget.cpp
|
||||||
src/filtertree.cpp
|
src/server/remote/remote_replay_list_tree_widget.cpp
|
||||||
src/messagelogwidget.cpp
|
src/client/network/replay_timeline_widget.cpp
|
||||||
src/zoneviewzone.cpp
|
src/game/zones/select_zone.cpp
|
||||||
src/zoneviewwidget.cpp
|
src/utility/sequence_edit.cpp
|
||||||
src/pilezone.cpp
|
src/client/network/sets_model.cpp
|
||||||
src/stackzone.cpp
|
src/settings/card_database_settings.cpp
|
||||||
src/carddragitem.cpp
|
src/settings/download_settings.cpp
|
||||||
src/carddatabasemodel.cpp
|
src/settings/game_filters_settings.cpp
|
||||||
src/setsmodel.cpp
|
src/settings/layouts_settings.cpp
|
||||||
src/abstractgraphicsitem.cpp
|
src/settings/message_settings.cpp
|
||||||
src/abstractcarddragitem.cpp
|
src/settings/servers_settings.cpp
|
||||||
src/dlg_settings.cpp
|
src/settings/settings_manager.cpp
|
||||||
src/phasestoolbar.cpp
|
src/settings/cache_settings.cpp
|
||||||
src/gamescene.cpp
|
src/settings/shortcuts_settings.cpp
|
||||||
src/arrowitem.cpp
|
src/settings/shortcut_treeview.cpp
|
||||||
src/arrowtarget.cpp
|
src/client/sound_engine.cpp
|
||||||
src/tab.cpp
|
src/client/network/spoiler_background_updater.cpp
|
||||||
src/tab_server.cpp
|
src/game/zones/stack_zone.cpp
|
||||||
src/tab_room.cpp
|
src/client/tabs/tab.cpp
|
||||||
src/tab_message.cpp
|
src/client/tabs/tab_account.cpp
|
||||||
src/tab_game.cpp
|
src/client/tabs/tab_admin.cpp
|
||||||
src/tab_deck_storage.cpp
|
src/client/tabs/tab_deck_editor.cpp
|
||||||
src/tab_replays.cpp
|
src/client/tabs/tab_deck_storage.cpp
|
||||||
src/tab_supervisor.cpp
|
src/client/tabs/tab_game.cpp
|
||||||
src/tab_admin.cpp
|
src/client/tabs/tab_logs.cpp
|
||||||
src/tab_account.cpp
|
src/client/tabs/tab_message.cpp
|
||||||
src/tab_deck_editor.cpp
|
src/client/tabs/tab_replays.cpp
|
||||||
src/tab_logs.cpp
|
src/client/tabs/tab_room.cpp
|
||||||
src/replay_timeline_widget.cpp
|
src/client/tabs/tab_server.cpp
|
||||||
src/deckstats_interface.cpp
|
src/client/tabs/tab_supervisor.cpp
|
||||||
src/tappedout_interface.cpp
|
src/game/zones/table_zone.cpp
|
||||||
src/chatview/chatview.cpp
|
src/client/tapped_out_interface.cpp
|
||||||
src/userlist.cpp
|
src/client/ui/theme_manager.cpp
|
||||||
src/userinfobox.cpp
|
src/client/ui/tip_of_the_day.cpp
|
||||||
src/user_context_menu.cpp
|
src/client/translate_counter_name.cpp
|
||||||
src/remotedecklist_treewidget.cpp
|
src/client/update_downloader.cpp
|
||||||
src/remotereplaylist_treewidget.cpp
|
src/server/user/user_context_menu.cpp
|
||||||
src/deckview.cpp
|
src/server/user/user_info_connection.cpp
|
||||||
src/playerlistwidget.cpp
|
src/server/user/user_info_box.cpp
|
||||||
src/pixmapgenerator.cpp
|
src/server/user/user_list.cpp
|
||||||
src/settingscache.cpp
|
src/client/ui/window_main.cpp
|
||||||
src/thememanager.cpp
|
src/game/zones/view_zone_widget.cpp
|
||||||
src/localserver.cpp
|
src/game/zones/view_zone.cpp
|
||||||
src/localserverinterface.cpp
|
|
||||||
src/localclient.cpp
|
|
||||||
src/soundengine.cpp
|
|
||||||
src/pending_command.cpp
|
|
||||||
src/pictureloader.cpp
|
|
||||||
src/shortcutssettings.cpp
|
|
||||||
src/sequenceEdit/sequenceedit.cpp
|
|
||||||
src/lineeditcompleter.cpp
|
|
||||||
src/settings/settingsmanager.cpp
|
|
||||||
src/settings/carddatabasesettings.cpp
|
|
||||||
src/settings/serverssettings.cpp
|
|
||||||
src/settings/messagesettings.cpp
|
|
||||||
src/settings/gamefilterssettings.cpp
|
|
||||||
src/settings/layoutssettings.cpp
|
|
||||||
src/settings/downloadsettings.cpp
|
|
||||||
src/update_downloader.cpp
|
|
||||||
src/logger.cpp
|
|
||||||
src/releasechannel.cpp
|
|
||||||
src/userconnection_information.cpp
|
|
||||||
src/spoilerbackgroundupdater.cpp
|
|
||||||
src/handle_public_servers.cpp
|
|
||||||
src/carddbparser/carddatabaseparser.cpp
|
|
||||||
src/carddbparser/cockatricexml3.cpp
|
|
||||||
src/carddbparser/cockatricexml4.cpp
|
|
||||||
src/filter_string.cpp
|
|
||||||
src/phase.cpp
|
|
||||||
src/customlineedit.cpp
|
|
||||||
src/translatecountername.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|styles)/.*[^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/*.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(OPENSSL_FOUND)
|
||||||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
install(FILES ${OPENSSL_INCLUDE_DIRS} 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>
|
||||||
@@ -353,10 +351,10 @@
|
|||||||
<file>resources/tips/images/cockatrice_wiki.png</file>
|
<file>resources/tips/images/cockatrice_wiki.png</file>
|
||||||
<file>resources/tips/images/coin_flip.png</file>
|
<file>resources/tips/images/coin_flip.png</file>
|
||||||
<file>resources/tips/images/counter_expression.png</file>
|
<file>resources/tips/images/counter_expression.png</file>
|
||||||
|
<file>resources/tips/images/discord.png</file>
|
||||||
<file>resources/tips/images/face_down.png</file>
|
<file>resources/tips/images/face_down.png</file>
|
||||||
<file>resources/tips/images/filter_games.png</file>
|
<file>resources/tips/images/filter_games.png</file>
|
||||||
<file>resources/tips/images/github_logo.png</file>
|
<file>resources/tips/images/github_logo.png</file>
|
||||||
<file>resources/tips/images/gitter.png</file>
|
|
||||||
<file>resources/tips/images/setpt.png</file>
|
<file>resources/tips/images/setpt.png</file>
|
||||||
<file>resources/tips/images/shortcuts.png</file>
|
<file>resources/tips/images/shortcuts.png</file>
|
||||||
<file>resources/tips/images/themes.png</file>
|
<file>resources/tips/images/themes.png</file>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
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 |
@@ -1,6 +1,7 @@
|
|||||||
## Syntax Help
|
## Search Syntax Help
|
||||||
-----
|
-----
|
||||||
The search bar recognizes a set of special commands similar to some other card databases. Here is a list with examples. Each entry can be clicked to test the query and has a small explanation. Note that all searches are case insensitive.
|
The search bar recognizes a set of special commands similar to some other card databases.<br>
|
||||||
|
In this list of examples below, each entry has an explanation and can be clicked to test the query. Note that all searches are case insensitive.
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Name:</dt>
|
<dt>Name:</dt>
|
||||||
<dd>[birds of paradise](#birds of paradise) <small>(Any card name containing the words birds, of, and paradise)</small></dd>
|
<dd>[birds of paradise](#birds of paradise) <small>(Any card name containing the words birds, of, and paradise)</small></dd>
|
||||||
@@ -46,8 +47,7 @@ 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>Negate:</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>
|
||||||
|
|||||||
BIN
cockatrice/resources/tips/images/discord.png
Normal file
BIN
cockatrice/resources/tips/images/discord.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -7,9 +7,9 @@
|
|||||||
</tip>
|
</tip>
|
||||||
<tip>
|
<tip>
|
||||||
<title>Suggesting New Tips</title>
|
<title>Suggesting New Tips</title>
|
||||||
<text>You can suggest new Tips of the Day by reaching out to the development team on <a href="https://gitter.im/cockatrice/cockatrice">Gitter</a>!</text>
|
<text>You can suggest new Tips of the Day by reaching out to the development team on <a href="https://discord.gg/3Z9yzmA">Discord</a>!</text>
|
||||||
<image>gitter.png</image>
|
<image>discord.png</image>
|
||||||
<date>2018-03-01</date>
|
<date>2023-10-18</date>
|
||||||
</tip>
|
</tip>
|
||||||
<tip>
|
<tip>
|
||||||
<title>Reporting Bugs</title>
|
<title>Reporting Bugs</title>
|
||||||
|
|||||||
@@ -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,60 +0,0 @@
|
|||||||
#include "cardinfopicture.h"
|
|
||||||
|
|
||||||
#include "carditem.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "pictureloader.h"
|
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true)
|
|
||||||
{
|
|
||||||
setMinimumHeight(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfoPicture::setCard(CardInfoPtr card)
|
|
||||||
{
|
|
||||||
if (info) {
|
|
||||||
disconnect(info.data(), nullptr, this, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
info = card;
|
|
||||||
|
|
||||||
if (info) {
|
|
||||||
connect(info.data(), SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePixmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfoPicture::resizeEvent(QResizeEvent *)
|
|
||||||
{
|
|
||||||
updatePixmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfoPicture::updatePixmap()
|
|
||||||
{
|
|
||||||
pixmapDirty = true;
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfoPicture::loadPixmap()
|
|
||||||
{
|
|
||||||
if (info)
|
|
||||||
PictureLoader::getPixmap(resizedPixmap, info, size());
|
|
||||||
else
|
|
||||||
PictureLoader::getCardBackPixmap(resizedPixmap, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfoPicture::paintEvent(QPaintEvent *)
|
|
||||||
{
|
|
||||||
if (width() == 0 || height() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pixmapDirty)
|
|
||||||
loadPixmap();
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
style()->drawItemPixmap(&painter, rect(), Qt::AlignHCenter, resizedPixmap);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef CARDINFOPICTURE_H
|
|
||||||
#define CARDINFOPICTURE_H
|
|
||||||
|
|
||||||
#include "carddatabase.h"
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class AbstractCardItem;
|
|
||||||
|
|
||||||
class CardInfoPicture : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
private:
|
|
||||||
CardInfoPtr info;
|
|
||||||
QPixmap resizedPixmap;
|
|
||||||
bool pixmapDirty;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CardInfoPicture(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void resizeEvent(QResizeEvent *event);
|
|
||||||
void paintEvent(QPaintEvent *);
|
|
||||||
void loadPixmap();
|
|
||||||
public slots:
|
|
||||||
void setCard(CardInfoPtr card);
|
|
||||||
void updatePixmap();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#include "cardlist.h"
|
|
||||||
|
|
||||||
#include "carddatabase.h"
|
|
||||||
#include "carditem.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
CardList::CardList(bool _contentsKnown) : QList<CardItem *>(), contentsKnown(_contentsKnown)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CardItem *CardList::findCard(const int id, const bool remove, int *position)
|
|
||||||
{
|
|
||||||
if (!contentsKnown) {
|
|
||||||
if (empty())
|
|
||||||
return 0;
|
|
||||||
CardItem *temp = at(0);
|
|
||||||
if (remove)
|
|
||||||
removeAt(0);
|
|
||||||
if (position)
|
|
||||||
*position = id;
|
|
||||||
return temp;
|
|
||||||
} else
|
|
||||||
for (int i = 0; i < size(); i++) {
|
|
||||||
CardItem *temp = at(i);
|
|
||||||
if (temp->getId() == id) {
|
|
||||||
if (remove)
|
|
||||||
removeAt(i);
|
|
||||||
if (position)
|
|
||||||
*position = i;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CardList::compareFunctor
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit compareFunctor(int _flags) : flags(_flags)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
inline bool operator()(CardItem *a, CardItem *b) const
|
|
||||||
{
|
|
||||||
if (flags & SortByType) {
|
|
||||||
QString t1 = a->getInfo() ? a->getInfo()->getMainCardType() : QString();
|
|
||||||
QString t2 = b->getInfo() ? b->getInfo()->getMainCardType() : QString();
|
|
||||||
if ((t1 == t2) && (flags & SortByName))
|
|
||||||
return a->getName() < b->getName();
|
|
||||||
return t1 < t2;
|
|
||||||
} else
|
|
||||||
return a->getName() < b->getName();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void CardList::sort(int flags)
|
|
||||||
{
|
|
||||||
compareFunctor cf(flags);
|
|
||||||
std::sort(begin(), end(), cf);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef CARDLIST_H
|
|
||||||
#define CARDLIST_H
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
class CardItem;
|
|
||||||
|
|
||||||
class CardList : public QList<CardItem *>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
class compareFunctor;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool contentsKnown;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum SortFlags
|
|
||||||
{
|
|
||||||
SortByName = 1,
|
|
||||||
SortByType = 2
|
|
||||||
};
|
|
||||||
CardList(bool _contentsKnown);
|
|
||||||
CardItem *findCard(const int id, const bool remove, int *position = NULL);
|
|
||||||
bool getContentsKnown() const
|
|
||||||
{
|
|
||||||
return contentsKnown;
|
|
||||||
}
|
|
||||||
void sort(int flags = SortByName);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "abstractclient.h"
|
#include "abstract_client.h"
|
||||||
|
|
||||||
#include "client_metatypes.h"
|
#include "../../server/pending_command.h"
|
||||||
#include "featureset.h"
|
#include "featureset.h"
|
||||||
#include "get_pb_extension.h"
|
#include "get_pb_extension.h"
|
||||||
#include "pb/commands.pb.h"
|
#include "pb/commands.pb.h"
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
#include "pb/event_user_left.pb.h"
|
#include "pb/event_user_left.pb.h"
|
||||||
#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 <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");
|
||||||
@@ -47,11 +47,12 @@ 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);
|
||||||
|
|
||||||
connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
|
connect(this, &AbstractClient::sigQueuePendingCommand, this, &AbstractClient::queuePendingCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractClient::~AbstractClient()
|
AbstractClient::~AbstractClient()
|
||||||
@@ -40,6 +40,7 @@ enum ClientStatus
|
|||||||
StatusRequestingForgotPassword,
|
StatusRequestingForgotPassword,
|
||||||
StatusSubmitForgotPasswordReset,
|
StatusSubmitForgotPasswordReset,
|
||||||
StatusSubmitForgotPasswordChallenge,
|
StatusSubmitForgotPasswordChallenge,
|
||||||
|
StatusGettingPasswordSalt,
|
||||||
};
|
};
|
||||||
|
|
||||||
class AbstractClient : public QObject
|
class AbstractClient : public QObject
|
||||||
@@ -87,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()
|
||||||
{
|
{
|
||||||
@@ -107,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,4 +1,4 @@
|
|||||||
#include "keysignals.h"
|
#include "key_signals.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
@@ -60,6 +60,11 @@ bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event)
|
|||||||
if (kevent->modifiers() & Qt::ShiftModifier)
|
if (kevent->modifiers() & Qt::ShiftModifier)
|
||||||
emit onShiftS();
|
emit onShiftS();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Qt::Key_C:
|
||||||
|
if (kevent->modifiers() & Qt::ControlModifier)
|
||||||
|
emit onCtrlC();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -20,6 +20,7 @@ signals:
|
|||||||
void onCtrlAltLBracket();
|
void onCtrlAltLBracket();
|
||||||
void onCtrlAltRBracket();
|
void onCtrlAltRBracket();
|
||||||
void onShiftS();
|
void onShiftS();
|
||||||
|
void onCtrlC();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool eventFilter(QObject *, QEvent *event);
|
virtual bool eventFilter(QObject *, QEvent *event);
|
||||||
32
cockatrice/src/client/get_text_with_max.cpp
Normal file
32
cockatrice/src/client/get_text_with_max.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "get_text_with_max.h"
|
||||||
|
|
||||||
|
QString getTextWithMax(QWidget *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &label,
|
||||||
|
QLineEdit::EchoMode mode,
|
||||||
|
const QString &text,
|
||||||
|
bool *ok,
|
||||||
|
int max,
|
||||||
|
Qt::WindowFlags flags,
|
||||||
|
Qt::InputMethodHints inputMethodHints)
|
||||||
|
{
|
||||||
|
auto *dialog = new QInputDialog(parent, flags);
|
||||||
|
dialog->setWindowTitle(title);
|
||||||
|
dialog->setLabelText(label);
|
||||||
|
dialog->setTextValue(text);
|
||||||
|
dialog->setTextEchoMode(mode);
|
||||||
|
dialog->setInputMethodHints(inputMethodHints);
|
||||||
|
|
||||||
|
// find the qlineedit that this dialog holds, there should be only one
|
||||||
|
dialog->findChild<QLineEdit *>()->setMaxLength(max);
|
||||||
|
|
||||||
|
const int ret = dialog->exec();
|
||||||
|
if (ok != nullptr) {
|
||||||
|
*ok = !!ret;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
return dialog->textValue();
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
cockatrice/src/client/get_text_with_max.h
Normal file
23
cockatrice/src/client/get_text_with_max.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// custom QInputDialog::getText implementation that allows configuration of the max length
|
||||||
|
#ifndef GETTEXTWITHMAX_H
|
||||||
|
#define GETTEXTWITHMAX_H
|
||||||
|
|
||||||
|
#include "trice_limits.h"
|
||||||
|
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
|
QString getTextWithMax(QWidget *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &label,
|
||||||
|
QLineEdit::EchoMode echo = QLineEdit::Normal,
|
||||||
|
const QString &text = QString(),
|
||||||
|
bool *ok = nullptr,
|
||||||
|
int max = MAX_NAME_LENGTH,
|
||||||
|
Qt::WindowFlags flags = Qt::WindowFlags(),
|
||||||
|
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||||
|
static inline QString getTextWithMax(QWidget *parent, const QString &title, const QString &label, int max)
|
||||||
|
{
|
||||||
|
return getTextWithMax(parent, title, label, QLineEdit::Normal, QString(), nullptr, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GETTEXTWITHMAX_H
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "releasechannel.h"
|
#include "release_channel.h"
|
||||||
|
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
|
||||||
@@ -23,10 +23,9 @@
|
|||||||
|
|
||||||
int ReleaseChannel::sharedIndex = 0;
|
int ReleaseChannel::sharedIndex = 0;
|
||||||
|
|
||||||
ReleaseChannel::ReleaseChannel() : response(nullptr), lastRelease(nullptr)
|
ReleaseChannel::ReleaseChannel() : netMan(new QNetworkAccessManager(this)), response(nullptr), lastRelease(nullptr)
|
||||||
{
|
{
|
||||||
index = sharedIndex++;
|
index = sharedIndex++;
|
||||||
netMan = new QNetworkAccessManager(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseChannel::~ReleaseChannel()
|
ReleaseChannel::~ReleaseChannel()
|
||||||
@@ -39,11 +38,11 @@ void ReleaseChannel::checkForUpdates()
|
|||||||
QString releaseChannelUrl = getReleaseChannelUrl();
|
QString releaseChannelUrl = getReleaseChannelUrl();
|
||||||
qDebug() << "Searching for updates on the channel: " << releaseChannelUrl;
|
qDebug() << "Searching for updates on the channel: " << releaseChannelUrl;
|
||||||
response = netMan->get(QNetworkRequest(releaseChannelUrl));
|
response = netMan->get(QNetworkRequest(releaseChannelUrl));
|
||||||
connect(response, SIGNAL(finished()), this, SLOT(releaseListFinished()));
|
connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Different release channel checking functions for different operating systems
|
// Different release channel checking functions for different operating systems
|
||||||
#if defined(Q_OS_OSX)
|
#if defined(Q_OS_MACOS)
|
||||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||||
{
|
{
|
||||||
static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
|
static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
|
||||||
@@ -63,9 +62,14 @@ bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
|||||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||||
{
|
{
|
||||||
#if Q_PROCESSOR_WORDSIZE == 4
|
#if Q_PROCESSOR_WORDSIZE == 4
|
||||||
return fileName.contains("win32");
|
return fileName.contains("32bit");
|
||||||
#elif Q_PROCESSOR_WORDSIZE == 8
|
#elif Q_PROCESSOR_WORDSIZE == 8
|
||||||
return fileName.contains("win64");
|
const QString &version = QSysInfo::productVersion();
|
||||||
|
if (version.startsWith("7") || version.startsWith("8")) {
|
||||||
|
return fileName.contains("Win7");
|
||||||
|
} else {
|
||||||
|
return fileName.contains("Win10");
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
@@ -154,7 +158,7 @@ void StableReleaseChannel::releaseListFinished()
|
|||||||
QString url = QString(STABLETAG_URL) + tagName;
|
QString url = QString(STABLETAG_URL) + tagName;
|
||||||
qDebug() << "Searching for commit hash corresponding to stable channel tag: " << tagName;
|
qDebug() << "Searching for commit hash corresponding to stable channel tag: " << tagName;
|
||||||
response = netMan->get(QNetworkRequest(url));
|
response = netMan->get(QNetworkRequest(url));
|
||||||
connect(response, SIGNAL(finished()), this, SLOT(tagListFinished()));
|
connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StableReleaseChannel::tagListFinished()
|
void StableReleaseChannel::tagListFinished()
|
||||||
@@ -256,7 +260,7 @@ void BetaReleaseChannel::releaseListFinished()
|
|||||||
|
|
||||||
qDebug() << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
|
qDebug() << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
|
||||||
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
|
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
|
||||||
connect(response, SIGNAL(finished()), this, SLOT(fileListFinished()));
|
connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BetaReleaseChannel::fileListFinished()
|
void BetaReleaseChannel::fileListFinished()
|
||||||
@@ -78,7 +78,7 @@ class ReleaseChannel : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ReleaseChannel();
|
explicit ReleaseChannel();
|
||||||
~ReleaseChannel() override;
|
~ReleaseChannel() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -117,7 +117,7 @@ class StableReleaseChannel : public ReleaseChannel
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
StableReleaseChannel() = default;
|
explicit StableReleaseChannel() = default;
|
||||||
~StableReleaseChannel() override = default;
|
~StableReleaseChannel() override = default;
|
||||||
|
|
||||||
QString getManualDownloadUrl() const override;
|
QString getManualDownloadUrl() const override;
|
||||||
193
cockatrice/src/client/network/replay_timeline_widget.cpp
Normal file
193
cockatrice/src/client/network/replay_timeline_widget.cpp
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
#include "replay_timeline_widget.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
|
||||||
|
: QWidget(parent), maxBinValue(1), maxTime(1), timeScaleFactor(1.0), currentVisualTime(0), currentProcessedTime(0),
|
||||||
|
currentEvent(0)
|
||||||
|
{
|
||||||
|
replayTimer = new QTimer(this);
|
||||||
|
connect(replayTimer, &QTimer::timeout, this, &ReplayTimelineWidget::replayTimerTimeout);
|
||||||
|
|
||||||
|
rewindBufferingTimer = new QTimer(this);
|
||||||
|
rewindBufferingTimer->setSingleShot(true);
|
||||||
|
connect(rewindBufferingTimer, &QTimer::timeout, this, &ReplayTimelineWidget::processRewind);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
|
||||||
|
{
|
||||||
|
replayTimeline = _replayTimeline;
|
||||||
|
histogram.clear();
|
||||||
|
int binEndTime = BIN_LENGTH - 1;
|
||||||
|
int binValue = 0;
|
||||||
|
for (int i : replayTimeline) {
|
||||||
|
if (i > binEndTime) {
|
||||||
|
histogram.append(binValue);
|
||||||
|
if (binValue > maxBinValue)
|
||||||
|
maxBinValue = binValue;
|
||||||
|
while (i > binEndTime + BIN_LENGTH) {
|
||||||
|
histogram.append(0);
|
||||||
|
binEndTime += BIN_LENGTH;
|
||||||
|
}
|
||||||
|
binValue = 1;
|
||||||
|
binEndTime += BIN_LENGTH;
|
||||||
|
} else
|
||||||
|
++binValue;
|
||||||
|
}
|
||||||
|
histogram.append(binValue);
|
||||||
|
if (!replayTimeline.isEmpty())
|
||||||
|
maxTime = replayTimeline.last();
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.drawRect(0, 0, width() - 1, height() - 1);
|
||||||
|
|
||||||
|
qreal binWidth = (qreal)width() / histogram.size();
|
||||||
|
QPainterPath path;
|
||||||
|
path.moveTo(0, height() - 1);
|
||||||
|
for (int i = 0; i < histogram.size(); ++i)
|
||||||
|
path.lineTo(qRound(i * binWidth), (height() - 1) * (1.0 - (qreal)histogram[i] / maxBinValue));
|
||||||
|
path.lineTo(width() - 1, height() - 1);
|
||||||
|
path.lineTo(0, height() - 1);
|
||||||
|
painter.fillPath(path, Qt::black);
|
||||||
|
|
||||||
|
const QColor barColor = QColor::fromHsv(120, 255, 255, 100);
|
||||||
|
quint64 w = (quint64)(width() - 1) * (quint64)currentVisualTime / maxTime;
|
||||||
|
painter.fillRect(0, 0, static_cast<int>(w), height() - 1, barColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->position().x() / width());
|
||||||
|
#else
|
||||||
|
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->x() / width());
|
||||||
|
#endif
|
||||||
|
// don't buffer rewinds from clicks, since clicks usually don't happen fast enough to require buffering
|
||||||
|
skipToTime(newTime, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::skipToTime(int newTime, bool doRewindBuffering)
|
||||||
|
{
|
||||||
|
// check boundary conditions
|
||||||
|
if (newTime < 0) {
|
||||||
|
newTime = 0;
|
||||||
|
}
|
||||||
|
if (newTime > maxTime) {
|
||||||
|
newTime = maxTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
newTime -= newTime % TIMER_INTERVAL_MS; // Time should always be a multiple of the interval
|
||||||
|
|
||||||
|
const bool isBackwardsSkip = newTime < currentProcessedTime;
|
||||||
|
currentVisualTime = newTime;
|
||||||
|
|
||||||
|
if (isBackwardsSkip) {
|
||||||
|
handleBackwardsSkip(doRewindBuffering);
|
||||||
|
} else {
|
||||||
|
processNewEvents(FORWARD_SKIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @param doRewindBuffering When true, if multiple backward skips are made in quick succession, only a single rewind
|
||||||
|
/// is processed at the end. When false, the backwards skip will always cause an immediate rewind
|
||||||
|
void ReplayTimelineWidget::handleBackwardsSkip(bool doRewindBuffering)
|
||||||
|
{
|
||||||
|
if (doRewindBuffering) {
|
||||||
|
// We use a one-shot timer to implement the rewind buffering.
|
||||||
|
// The rewind only happens once the timer runs out.
|
||||||
|
// If another backwards skip happens, the timer will just get reset instead of rewinding.
|
||||||
|
rewindBufferingTimer->stop();
|
||||||
|
rewindBufferingTimer->start(SettingsCache::instance().getRewindBufferingMs());
|
||||||
|
} else {
|
||||||
|
// otherwise, process the rewind immediately
|
||||||
|
processRewind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::processRewind()
|
||||||
|
{
|
||||||
|
// stop any queued-up rewinds
|
||||||
|
rewindBufferingTimer->stop();
|
||||||
|
|
||||||
|
// process the rewind
|
||||||
|
currentEvent = 0;
|
||||||
|
emit rewound();
|
||||||
|
processNewEvents(BACKWARD_SKIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ReplayTimelineWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
return {-1, 50};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ReplayTimelineWidget::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return {400, 50};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::replayTimerTimeout()
|
||||||
|
{
|
||||||
|
currentVisualTime += TIMER_INTERVAL_MS;
|
||||||
|
|
||||||
|
processNewEvents(NORMAL_PLAYBACK);
|
||||||
|
|
||||||
|
if (!(currentVisualTime % 1000))
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes all unprocessed events up to the current time.
|
||||||
|
void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode)
|
||||||
|
{
|
||||||
|
currentProcessedTime = currentVisualTime;
|
||||||
|
|
||||||
|
while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentProcessedTime)) {
|
||||||
|
Player::EventProcessingOptions options;
|
||||||
|
|
||||||
|
// backwards skip => always skip reveal windows
|
||||||
|
// forwards skip => skip reveal windows that don't happen within a big skip of the target
|
||||||
|
if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS)
|
||||||
|
options |= Player::EventProcessingOption::SKIP_REVEAL_WINDOW;
|
||||||
|
|
||||||
|
// backwards skip => always skip tap animation
|
||||||
|
if (playbackMode == BACKWARD_SKIP)
|
||||||
|
options |= Player::EventProcessingOption::SKIP_TAP_ANIMATION;
|
||||||
|
|
||||||
|
emit processNextEvent(options);
|
||||||
|
++currentEvent;
|
||||||
|
}
|
||||||
|
if (currentEvent == replayTimeline.size()) {
|
||||||
|
emit replayFinished();
|
||||||
|
replayTimer->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::setTimeScaleFactor(qreal _timeScaleFactor)
|
||||||
|
{
|
||||||
|
timeScaleFactor = _timeScaleFactor;
|
||||||
|
replayTimer->setInterval(static_cast<int>(TIMER_INTERVAL_MS / timeScaleFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::startReplay()
|
||||||
|
{
|
||||||
|
replayTimer->start(static_cast<int>(TIMER_INTERVAL_MS / timeScaleFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::stopReplay()
|
||||||
|
{
|
||||||
|
replayTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplayTimelineWidget::skipByAmount(int amount)
|
||||||
|
{
|
||||||
|
skipToTime(currentVisualTime + amount, amount < 0);
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef REPLAY_TIMELINE_WIDGET
|
#ifndef REPLAY_TIMELINE_WIDGET
|
||||||
#define REPLAY_TIMELINE_WIDGET
|
#define REPLAY_TIMELINE_WIDGET
|
||||||
|
|
||||||
|
#include "../../game/player/player.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -12,23 +14,44 @@ class ReplayTimelineWidget : public QWidget
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
void processNextEvent();
|
void processNextEvent(Player::EventProcessingOptions options);
|
||||||
void replayFinished();
|
void replayFinished();
|
||||||
void rewound();
|
void rewound();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum PlaybackMode
|
||||||
|
{
|
||||||
|
NORMAL_PLAYBACK,
|
||||||
|
FORWARD_SKIP,
|
||||||
|
BACKWARD_SKIP
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr int TIMER_INTERVAL_MS = 200;
|
||||||
|
static constexpr int BIN_LENGTH = 5000;
|
||||||
|
|
||||||
QTimer *replayTimer;
|
QTimer *replayTimer;
|
||||||
|
QTimer *rewindBufferingTimer;
|
||||||
QList<int> replayTimeline;
|
QList<int> replayTimeline;
|
||||||
QList<int> histogram;
|
QList<int> histogram;
|
||||||
static const int binLength;
|
|
||||||
int maxBinValue, maxTime;
|
int maxBinValue, maxTime;
|
||||||
qreal timeScaleFactor;
|
qreal timeScaleFactor;
|
||||||
int currentTime;
|
int currentVisualTime; // time currently displayed by the timeline
|
||||||
|
int currentProcessedTime; // time that events are currently processed up to. Could differ from visual time due to
|
||||||
|
// rewind buffering
|
||||||
int currentEvent;
|
int currentEvent;
|
||||||
|
|
||||||
|
void skipToTime(int newTime, bool doRewindBuffering);
|
||||||
|
void handleBackwardsSkip(bool doRewindBuffering);
|
||||||
|
void processRewind();
|
||||||
|
void processNewEvents(PlaybackMode playbackMode);
|
||||||
private slots:
|
private slots:
|
||||||
void replayTimerTimeout();
|
void replayTimerTimeout();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr int SMALL_SKIP_MS = 1000;
|
||||||
|
static constexpr int BIG_SKIP_MS = 10000;
|
||||||
|
static constexpr qreal FAST_FORWARD_SCALE_FACTOR = 10.0;
|
||||||
|
|
||||||
explicit ReplayTimelineWidget(QWidget *parent = nullptr);
|
explicit ReplayTimelineWidget(QWidget *parent = nullptr);
|
||||||
void setTimeline(const QList<int> &_replayTimeline);
|
void setTimeline(const QList<int> &_replayTimeline);
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
@@ -41,6 +64,7 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void startReplay();
|
void startReplay();
|
||||||
void stopReplay();
|
void stopReplay();
|
||||||
|
void skipByAmount(int amount); // use a negative amount to skip backwards
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "setsmodel.h"
|
#include "sets_model.h"
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(parent), sets(_db->getSetList())
|
SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(parent), sets(_db->getSetList())
|
||||||
{
|
{
|
||||||
@@ -193,6 +195,13 @@ void SetsModel::swapRows(int oldRow, int newRow)
|
|||||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetsModel::restoreOriginalOrder()
|
||||||
|
{
|
||||||
|
int numRows = rowCount();
|
||||||
|
sets.defaultSort();
|
||||||
|
emit dataChanged(index(0, 0), index(numRows - 1, columnCount() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
void SetsModel::sort(int column, Qt::SortOrder order)
|
void SetsModel::sort(int column, Qt::SortOrder order)
|
||||||
{
|
{
|
||||||
QMultiMap<QString, CardSetPtr> setMap;
|
QMultiMap<QString, CardSetPtr> setMap;
|
||||||
@@ -274,9 +283,15 @@ bool SetsDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex &source
|
|||||||
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
||||||
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
||||||
|
|
||||||
return (sourceModel()->data(typeIndex).toString().contains(filterRegExp()) ||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||||
sourceModel()->data(nameIndex).toString().contains(filterRegExp()) ||
|
const auto filter = filterRegularExpression();
|
||||||
sourceModel()->data(shortNameIndex).toString().contains(filterRegExp()));
|
#else
|
||||||
|
const auto filter = filterRegExp();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (sourceModel()->data(typeIndex).toString().contains(filter) ||
|
||||||
|
sourceModel()->data(nameIndex).toString().contains(filter) ||
|
||||||
|
sourceModel()->data(shortNameIndex).toString().contains(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef SETSMODEL_H
|
#ifndef SETSMODEL_H
|
||||||
#define SETSMODEL_H
|
#define SETSMODEL_H
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "../../game/cards/card_database.h"
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
@@ -49,7 +49,8 @@ public:
|
|||||||
LongNameCol,
|
LongNameCol,
|
||||||
ShortNameCol,
|
ShortNameCol,
|
||||||
SetTypeCol,
|
SetTypeCol,
|
||||||
ReleaseDateCol
|
ReleaseDateCol,
|
||||||
|
PriorityCol
|
||||||
};
|
};
|
||||||
enum Role
|
enum Role
|
||||||
{
|
{
|
||||||
@@ -80,6 +81,7 @@ public:
|
|||||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||||
void save(CardDatabase *db);
|
void save(CardDatabase *db);
|
||||||
void restore(CardDatabase *db);
|
void restore(CardDatabase *db);
|
||||||
|
void restoreOriginalOrder();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SetsDisplayModel : public QSortFilterProxyModel
|
class SetsDisplayModel : public QSortFilterProxyModel
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#include "spoilerbackgroundupdater.h"
|
#include "spoiler_background_updater.h"
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "../../game/cards/card_database.h"
|
||||||
#include "main.h"
|
#include "../../game/cards/card_database_manager.h"
|
||||||
#include "settingscache.h"
|
#include "../../main.h"
|
||||||
#include "window_main.h"
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../ui/window_main.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
@@ -44,10 +45,10 @@ void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults)
|
|||||||
|
|
||||||
if (saveResults) {
|
if (saveResults) {
|
||||||
// This will write out to the file (used for spoiler.xml)
|
// This will write out to the file (used for spoiler.xml)
|
||||||
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSpoilersFile()));
|
connect(reply, &QNetworkReply::finished, this, &SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile);
|
||||||
} else {
|
} else {
|
||||||
// This will check the status (used to see if we're in spoiler season or not)
|
// This will check the status (used to see if we're in spoiler season or not)
|
||||||
connect(reply, SIGNAL(finished()), this, SLOT(actCheckIfSpoilerSeasonEnabled()));
|
connect(reply, &QNetworkReply::finished, this, &SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
|
|||||||
emit spoilerCheckerDone();
|
emit spoilerCheckerDone();
|
||||||
} else {
|
} else {
|
||||||
if (trayIcon) {
|
if (trayIcon) {
|
||||||
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + errorCode);
|
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Spoiler download failed with reason" << errorCode;
|
qDebug() << "Spoiler download failed with reason" << errorCode;
|
||||||
@@ -159,7 +160,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
|||||||
|
|
||||||
// Data written, so reload the card database
|
// Data written, so reload the card database
|
||||||
qDebug() << "Spoiler Service Data Written";
|
qDebug() << "Spoiler Service Data Written";
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
|
||||||
|
|
||||||
// If the user has notifications enabled, let them know
|
// If the user has notifications enabled, let them know
|
||||||
// when the database was last updated
|
// when the database was last updated
|
||||||
@@ -172,7 +173,11 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
|||||||
timeStamp.chop(6); // Remove " (UTC)"
|
timeStamp.chop(6); // Remove " (UTC)"
|
||||||
|
|
||||||
auto utcTime = QLocale().toDateTime(timeStamp, "ddd, MMM dd yyyy, hh:mm:ss");
|
auto utcTime = QLocale().toDateTime(timeStamp, "ddd, MMM dd yyyy, hh:mm:ss");
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
|
||||||
|
utcTime.setTimeZone(QTimeZone::UTC);
|
||||||
|
#else
|
||||||
utcTime.setTimeSpec(Qt::UTC);
|
utcTime.setTimeSpec(Qt::UTC);
|
||||||
|
#endif
|
||||||
|
|
||||||
QString localTime = utcTime.toLocalTime().toString("MMM d, hh:mm");
|
QString localTime = utcTime.toLocalTime().toString("MMM d, hh:mm");
|
||||||
|
|
||||||
158
cockatrice/src/client/sound_engine.cpp
Normal file
158
cockatrice/src/client/sound_engine.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include "sound_engine.h"
|
||||||
|
|
||||||
|
#include "../settings/cache_settings.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMediaPlayer>
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
#include <QAudioOutput>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_THEME_NAME "Default"
|
||||||
|
#define TEST_SOUND_FILENAME "player_join"
|
||||||
|
|
||||||
|
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), player(nullptr)
|
||||||
|
{
|
||||||
|
ensureThemeDirectoryExists();
|
||||||
|
connect(&SettingsCache::instance(), &SettingsCache::soundThemeChanged, this, &SoundEngine::themeChangedSlot);
|
||||||
|
connect(&SettingsCache::instance(), &SettingsCache::soundEnabledChanged, this, &SoundEngine::soundEnabledChanged);
|
||||||
|
|
||||||
|
soundEnabledChanged();
|
||||||
|
themeChangedSlot();
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundEngine::~SoundEngine()
|
||||||
|
{
|
||||||
|
if (player) {
|
||||||
|
player->deleteLater();
|
||||||
|
player = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundEngine::soundEnabledChanged()
|
||||||
|
{
|
||||||
|
if (SettingsCache::instance().getSoundEnabled()) {
|
||||||
|
qDebug() << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
|
||||||
|
if (!player) {
|
||||||
|
player = new QMediaPlayer;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
auto qAudioOutput = new QAudioOutput;
|
||||||
|
player->setAudioOutput(qAudioOutput);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "SoundEngine: disabling sound";
|
||||||
|
if (player) {
|
||||||
|
player->stop();
|
||||||
|
player->deleteLater();
|
||||||
|
player = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundEngine::playSound(const QString &fileName)
|
||||||
|
{
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!audioData.contains(fileName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->stop();
|
||||||
|
int volumeSliderValue = SettingsCache::instance().getMasterVolume();
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
player->audioOutput()->setVolume(qreal(volumeSliderValue) / 100);
|
||||||
|
player->setSource(QUrl::fromLocalFile(audioData[fileName]));
|
||||||
|
#else
|
||||||
|
player->setVolume(volumeSliderValue);
|
||||||
|
player->setMedia(QUrl::fromLocalFile(audioData[fileName]));
|
||||||
|
#endif
|
||||||
|
player->play();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundEngine::testSound()
|
||||||
|
{
|
||||||
|
playSound(TEST_SOUND_FILENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundEngine::ensureThemeDirectoryExists()
|
||||||
|
{
|
||||||
|
if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
|
||||||
|
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
|
||||||
|
qDebug() << "Sounds theme name not set, setting default value";
|
||||||
|
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringMap &SoundEngine::getAvailableThemes()
|
||||||
|
{
|
||||||
|
QDir dir;
|
||||||
|
availableThemes.clear();
|
||||||
|
|
||||||
|
// load themes from user profile dir
|
||||||
|
|
||||||
|
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
|
||||||
|
|
||||||
|
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
||||||
|
if (!availableThemes.contains(themeName))
|
||||||
|
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load themes from cockatrice system dir
|
||||||
|
dir.setPath(qApp->applicationDirPath() +
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
"/../Resources/sounds"
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
"/sounds"
|
||||||
|
#else // linux
|
||||||
|
"/../share/cockatrice/sounds"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
||||||
|
if (!availableThemes.contains(themeName))
|
||||||
|
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return availableThemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundEngine::themeChangedSlot()
|
||||||
|
{
|
||||||
|
QString themeName = SettingsCache::instance().getSoundThemeName();
|
||||||
|
qDebug() << "Sound theme changed:" << themeName;
|
||||||
|
|
||||||
|
QDir dir = getAvailableThemes().value(themeName);
|
||||||
|
|
||||||
|
audioData.clear();
|
||||||
|
|
||||||
|
static const QStringList extensions = {".wav", ".mp3", ".ogg"};
|
||||||
|
static const QStringList fileNames = {
|
||||||
|
// Phases
|
||||||
|
"untap_step", "upkeep_step", "draw_step", "main_1", "start_combat", "attack_step", "block_step", "damage_step",
|
||||||
|
"end_combat", "main_2", "end_step",
|
||||||
|
// Game Actions
|
||||||
|
"draw_card", "play_card", "tap_card", "untap_card", "shuffle", "roll_dice", "life_change",
|
||||||
|
// Player
|
||||||
|
"player_join", "player_leave", "player_disconnect", "player_reconnect", "player_concede",
|
||||||
|
// Spectator
|
||||||
|
"spectator_join", "spectator_leave",
|
||||||
|
// Buddy
|
||||||
|
"buddy_join", "buddy_leave",
|
||||||
|
// Chat & UI
|
||||||
|
"chat_mention", "all_mention", "private_message"};
|
||||||
|
|
||||||
|
for (const QString &extension : extensions) {
|
||||||
|
for (const QString &name : fileNames) {
|
||||||
|
QFile file(dir.filePath(name + extension));
|
||||||
|
if (file.exists()) {
|
||||||
|
audioData.insert(name, file.fileName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
soundEnabledChanged();
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef SOUNDENGINE_H
|
#ifndef SOUNDENGINE_H
|
||||||
#define SOUNDENGINE_H
|
#define SOUNDENGINE_H
|
||||||
|
|
||||||
#include <QDir>
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QMediaPlayer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
@@ -15,16 +15,15 @@ class SoundEngine : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SoundEngine(QObject *parent = nullptr);
|
explicit SoundEngine(QObject *parent = nullptr);
|
||||||
~SoundEngine();
|
~SoundEngine() override;
|
||||||
void playSound(QString fileName);
|
void playSound(const QString &fileName);
|
||||||
QStringMap &getAvailableThemes();
|
QStringMap &getAvailableThemes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<QString, QByteArray> audioData;
|
|
||||||
QBuffer *inputBuffer;
|
|
||||||
QAudioOutput *player;
|
|
||||||
QStringMap availableThemes;
|
QStringMap availableThemes;
|
||||||
|
QMap<QString, QString> audioData;
|
||||||
|
QMediaPlayer *player;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ensureThemeDirectoryExists();
|
void ensureThemeDirectoryExists();
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
|
||||||
#include "cardinfowidget.h"
|
#include "../ui/widgets/cards/card_info_display_widget.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopWidget>
|
#include <QScreen>
|
||||||
|
|
||||||
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
|
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
|
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
|
||||||
{
|
{
|
||||||
@@ -17,10 +18,11 @@ void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName)
|
|||||||
infoPopup->deleteLater();
|
infoPopup->deleteLater();
|
||||||
}
|
}
|
||||||
currentCardName = cardName;
|
currentCardName = cardName;
|
||||||
infoPopup = new CardInfoWidget(
|
infoPopup = new CardInfoDisplayWidget(
|
||||||
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
|
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
|
||||||
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
|
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
QRect screenRect = qApp->desktop()->screenGeometry(this);
|
|
||||||
|
auto screenRect = qApp->primaryScreen()->geometry();
|
||||||
infoPopup->move(qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2,
|
infoPopup->move(qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2,
|
||||||
screenRect.left() + screenRect.width() - infoPopup->width())),
|
screenRect.left() + screenRect.width() - infoPopup->width())),
|
||||||
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2,
|
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2,
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
class QMenu;
|
class QMenu;
|
||||||
class TabSupervisor;
|
class TabSupervisor;
|
||||||
class CardInfoWidget;
|
class CardInfoDisplayWidget;
|
||||||
|
|
||||||
class Tab : public QMainWindow
|
class Tab : public QMainWindow
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ protected slots:
|
|||||||
private:
|
private:
|
||||||
QString currentCardName;
|
QString currentCardName;
|
||||||
bool contentsChanged;
|
bool contentsChanged;
|
||||||
CardInfoWidget *infoPopup;
|
CardInfoDisplayWidget *infoPopup;
|
||||||
QList<QMenu *> tabMenus;
|
QList<QMenu *> tabMenus;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
#include "tab_account.h"
|
#include "tab_account.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../deck/custom_line_edit.h"
|
||||||
#include "customlineedit.h"
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../server/user/user_info_box.h"
|
||||||
|
#include "../../server/user/user_list.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
|
#include "../sound_engine.h"
|
||||||
#include "pb/event_add_to_list.pb.h"
|
#include "pb/event_add_to_list.pb.h"
|
||||||
#include "pb/event_remove_from_list.pb.h"
|
#include "pb/event_remove_from_list.pb.h"
|
||||||
#include "pb/event_user_joined.pb.h"
|
#include "pb/event_user_joined.pb.h"
|
||||||
#include "pb/event_user_left.pb.h"
|
#include "pb/event_user_left.pb.h"
|
||||||
#include "pb/response_list_users.pb.h"
|
#include "pb/response_list_users.pb.h"
|
||||||
#include "pb/session_commands.pb.h"
|
#include "pb/session_commands.pb.h"
|
||||||
#include "pending_command.h"
|
#include "trice_limits.h"
|
||||||
#include "soundengine.h"
|
|
||||||
#include "userinfobox.h"
|
|
||||||
#include "userlist.h"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
@@ -29,29 +30,22 @@ TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor,
|
|||||||
userInfoBox = new UserInfoBox(client, true);
|
userInfoBox = new UserInfoBox(client, true);
|
||||||
userInfoBox->updateInfo(userInfo);
|
userInfoBox->updateInfo(userInfo);
|
||||||
|
|
||||||
connect(allUsersList, SIGNAL(openMessageDialog(const QString &, bool)), this,
|
connect(allUsersList, &UserList::openMessageDialog, this, &TabUserLists::openMessageDialog);
|
||||||
SIGNAL(openMessageDialog(const QString &, bool)));
|
connect(buddyList, &UserList::openMessageDialog, this, &TabUserLists::openMessageDialog);
|
||||||
connect(buddyList, SIGNAL(openMessageDialog(const QString &, bool)), this,
|
connect(ignoreList, &UserList::openMessageDialog, this, &TabUserLists::openMessageDialog);
|
||||||
SIGNAL(openMessageDialog(const QString &, bool)));
|
|
||||||
connect(ignoreList, SIGNAL(openMessageDialog(const QString &, bool)), this,
|
|
||||||
SIGNAL(openMessageDialog(const QString &, bool)));
|
|
||||||
|
|
||||||
connect(client, SIGNAL(userJoinedEventReceived(const Event_UserJoined &)), this,
|
connect(client, &AbstractClient::userJoinedEventReceived, this, &TabUserLists::processUserJoinedEvent);
|
||||||
SLOT(processUserJoinedEvent(const Event_UserJoined &)));
|
connect(client, &AbstractClient::userLeftEventReceived, this, &TabUserLists::processUserLeftEvent);
|
||||||
connect(client, SIGNAL(userLeftEventReceived(const Event_UserLeft &)), this,
|
connect(client, &AbstractClient::buddyListReceived, this, &TabUserLists::buddyListReceived);
|
||||||
SLOT(processUserLeftEvent(const Event_UserLeft &)));
|
connect(client, &AbstractClient::ignoreListReceived, this, &TabUserLists::ignoreListReceived);
|
||||||
connect(client, SIGNAL(buddyListReceived(const QList<ServerInfo_User> &)), this,
|
connect(client, &AbstractClient::addToListEventReceived, this, &TabUserLists::processAddToListEvent);
|
||||||
SLOT(buddyListReceived(const QList<ServerInfo_User> &)));
|
connect(client, &AbstractClient::removeFromListEventReceived, this, &TabUserLists::processRemoveFromListEvent);
|
||||||
connect(client, SIGNAL(ignoreListReceived(const QList<ServerInfo_User> &)), this,
|
|
||||||
SLOT(ignoreListReceived(const QList<ServerInfo_User> &)));
|
|
||||||
connect(client, SIGNAL(addToListEventReceived(const Event_AddToList &)), this,
|
|
||||||
SLOT(processAddToListEvent(const Event_AddToList &)));
|
|
||||||
connect(client, SIGNAL(removeFromListEventReceived(const Event_RemoveFromList &)), this,
|
|
||||||
SLOT(processRemoveFromListEvent(const Event_RemoveFromList &)));
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(Command_ListUsers());
|
PendingCommand *pend = client->prepareSessionCommand(Command_ListUsers());
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
connect(pend,
|
||||||
SLOT(processListUsersResponse(const Response &)));
|
static_cast<void (PendingCommand::*)(const Response &, const CommandContainer &, const QVariant &)>(
|
||||||
|
&PendingCommand::finished),
|
||||||
|
this, &TabUserLists::processListUsersResponse);
|
||||||
client->sendCommand(pend);
|
client->sendCommand(pend);
|
||||||
|
|
||||||
QVBoxLayout *vbox = new QVBoxLayout;
|
QVBoxLayout *vbox = new QVBoxLayout;
|
||||||
@@ -60,19 +54,21 @@ TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor,
|
|||||||
|
|
||||||
QHBoxLayout *addToBuddyList = new QHBoxLayout;
|
QHBoxLayout *addToBuddyList = new QHBoxLayout;
|
||||||
addBuddyEdit = new LineEditUnfocusable;
|
addBuddyEdit = new LineEditUnfocusable;
|
||||||
|
addBuddyEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||||
addBuddyEdit->setPlaceholderText(tr("Add to Buddy List"));
|
addBuddyEdit->setPlaceholderText(tr("Add to Buddy List"));
|
||||||
connect(addBuddyEdit, SIGNAL(returnPressed()), this, SLOT(addToBuddyList()));
|
connect(addBuddyEdit, &LineEditUnfocusable::returnPressed, this, &TabUserLists::addToBuddyList);
|
||||||
QPushButton *addBuddyButton = new QPushButton("Add");
|
QPushButton *addBuddyButton = new QPushButton("Add");
|
||||||
connect(addBuddyButton, SIGNAL(clicked()), this, SLOT(addToBuddyList()));
|
connect(addBuddyButton, &QPushButton::clicked, this, &TabUserLists::addToBuddyList);
|
||||||
addToBuddyList->addWidget(addBuddyEdit);
|
addToBuddyList->addWidget(addBuddyEdit);
|
||||||
addToBuddyList->addWidget(addBuddyButton);
|
addToBuddyList->addWidget(addBuddyButton);
|
||||||
|
|
||||||
QHBoxLayout *addToIgnoreList = new QHBoxLayout;
|
QHBoxLayout *addToIgnoreList = new QHBoxLayout;
|
||||||
addIgnoreEdit = new LineEditUnfocusable;
|
addIgnoreEdit = new LineEditUnfocusable;
|
||||||
|
addIgnoreEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||||
addIgnoreEdit->setPlaceholderText(tr("Add to Ignore List"));
|
addIgnoreEdit->setPlaceholderText(tr("Add to Ignore List"));
|
||||||
connect(addIgnoreEdit, SIGNAL(returnPressed()), this, SLOT(addToIgnoreList()));
|
connect(addIgnoreEdit, &LineEditUnfocusable::returnPressed, this, &TabUserLists::addToIgnoreList);
|
||||||
QPushButton *addIgnoreButton = new QPushButton("Add");
|
QPushButton *addIgnoreButton = new QPushButton("Add");
|
||||||
connect(addIgnoreButton, SIGNAL(clicked()), this, SLOT(addToIgnoreList()));
|
connect(addIgnoreButton, &QPushButton::clicked, this, &TabUserLists::addToIgnoreList);
|
||||||
addToIgnoreList->addWidget(addIgnoreEdit);
|
addToIgnoreList->addWidget(addIgnoreEdit);
|
||||||
addToIgnoreList->addWidget(addIgnoreButton);
|
addToIgnoreList->addWidget(addIgnoreButton);
|
||||||
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "tab_admin.h"
|
#include "tab_admin.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../game_logic/abstract_client.h"
|
||||||
#include "pb/admin_commands.pb.h"
|
#include "pb/admin_commands.pb.h"
|
||||||
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
@@ -18,6 +19,7 @@ ShutdownDialog::ShutdownDialog(QWidget *parent) : QDialog(parent)
|
|||||||
{
|
{
|
||||||
QLabel *reasonLabel = new QLabel(tr("&Reason for shutdown:"));
|
QLabel *reasonLabel = new QLabel(tr("&Reason for shutdown:"));
|
||||||
reasonEdit = new QLineEdit;
|
reasonEdit = new QLineEdit;
|
||||||
|
reasonEdit->setMaxLength(MAX_TEXT_LENGTH);
|
||||||
reasonLabel->setBuddy(reasonEdit);
|
reasonLabel->setBuddy(reasonEdit);
|
||||||
QLabel *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):"));
|
QLabel *minutesLabel = new QLabel(tr("&Time until shutdown (minutes):"));
|
||||||
minutesEdit = new QSpinBox;
|
minutesEdit = new QSpinBox;
|
||||||
@@ -27,8 +29,8 @@ ShutdownDialog::ShutdownDialog(QWidget *parent) : QDialog(parent)
|
|||||||
minutesEdit->setMaximum(999);
|
minutesEdit->setMaximum(999);
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(buttonBox, &QDialogButtonBox::accepted, this, &ShutdownDialog::accept);
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, &QDialogButtonBox::accepted, this, &ShutdownDialog::reject);
|
||||||
|
|
||||||
QGridLayout *mainLayout = new QGridLayout;
|
QGridLayout *mainLayout = new QGridLayout;
|
||||||
mainLayout->addWidget(reasonLabel, 0, 0);
|
mainLayout->addWidget(reasonLabel, 0, 0);
|
||||||
@@ -55,11 +57,11 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool
|
|||||||
: Tab(_tabSupervisor, parent), locked(true), client(_client), fullAdmin(_fullAdmin)
|
: Tab(_tabSupervisor, parent), locked(true), client(_client), fullAdmin(_fullAdmin)
|
||||||
{
|
{
|
||||||
updateServerMessageButton = new QPushButton;
|
updateServerMessageButton = new QPushButton;
|
||||||
connect(updateServerMessageButton, SIGNAL(clicked()), this, SLOT(actUpdateServerMessage()));
|
connect(updateServerMessageButton, &QPushButton::clicked, this, &TabAdmin::actUpdateServerMessage);
|
||||||
shutdownServerButton = new QPushButton;
|
shutdownServerButton = new QPushButton;
|
||||||
connect(shutdownServerButton, SIGNAL(clicked()), this, SLOT(actShutdownServer()));
|
connect(shutdownServerButton, &QPushButton::clicked, this, &TabAdmin::actShutdownServer);
|
||||||
reloadConfigButton = new QPushButton;
|
reloadConfigButton = new QPushButton;
|
||||||
connect(reloadConfigButton, SIGNAL(clicked()), this, SLOT(actReloadConfig()));
|
connect(reloadConfigButton, &QPushButton::clicked, this, &TabAdmin::actReloadConfig);
|
||||||
|
|
||||||
QVBoxLayout *vbox = new QVBoxLayout;
|
QVBoxLayout *vbox = new QVBoxLayout;
|
||||||
vbox->addWidget(updateServerMessageButton);
|
vbox->addWidget(updateServerMessageButton);
|
||||||
@@ -72,10 +74,10 @@ TabAdmin::TabAdmin(TabSupervisor *_tabSupervisor, AbstractClient *_client, bool
|
|||||||
adminGroupBox->setEnabled(false);
|
adminGroupBox->setEnabled(false);
|
||||||
|
|
||||||
unlockButton = new QPushButton;
|
unlockButton = new QPushButton;
|
||||||
connect(unlockButton, SIGNAL(clicked()), this, SLOT(actUnlock()));
|
connect(unlockButton, &QPushButton::clicked, this, &TabAdmin::actUnlock);
|
||||||
lockButton = new QPushButton;
|
lockButton = new QPushButton;
|
||||||
lockButton->setEnabled(false);
|
lockButton->setEnabled(false);
|
||||||
connect(lockButton, SIGNAL(clicked()), this, SLOT(actLock()));
|
connect(lockButton, &QPushButton::clicked, this, &TabAdmin::actLock);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(adminGroupBox);
|
mainLayout->addWidget(adminGroupBox);
|
||||||
@@ -1,22 +1,25 @@
|
|||||||
#include "tab_deck_editor.h"
|
#include "tab_deck_editor.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../client/game_logic/abstract_client.h"
|
||||||
#include "carddatabasemodel.h"
|
#include "../../client/tapped_out_interface.h"
|
||||||
#include "cardframe.h"
|
#include "../../client/ui/widgets/cards/card_info_frame_widget.h"
|
||||||
#include "decklistmodel.h"
|
#include "../../deck/deck_list_model.h"
|
||||||
#include "deckstats_interface.h"
|
#include "../../deck/deck_stats_interface.h"
|
||||||
#include "dlg_load_deck_from_clipboard.h"
|
#include "../../dialogs/dlg_load_deck_from_clipboard.h"
|
||||||
#include "filterbuilder.h"
|
#include "../../game/cards/card_database_manager.h"
|
||||||
#include "filtertreemodel.h"
|
#include "../../game/cards/card_database_model.h"
|
||||||
#include "main.h"
|
#include "../../game/filters/filter_builder.h"
|
||||||
|
#include "../../game/filters/filter_tree_model.h"
|
||||||
|
#include "../../main.h"
|
||||||
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../ui/picture_loader.h"
|
||||||
|
#include "../ui/pixel_map_generator.h"
|
||||||
|
#include "../ui/widgets/printing_selector/printing_selector.h"
|
||||||
#include "pb/command_deck_upload.pb.h"
|
#include "pb/command_deck_upload.pb.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "pictureloader.h"
|
|
||||||
#include "pixmapgenerator.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
#include "tappedout_interface.h"
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@@ -47,13 +50,6 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
void SearchLineEdit::keyPressEvent(QKeyEvent *event)
|
|
||||||
{
|
|
||||||
if (treeView && ((event->key() == Qt::Key_Up) || (event->key() == Qt::Key_Down)))
|
|
||||||
QCoreApplication::sendEvent(treeView, event);
|
|
||||||
LineEditUnfocusable::keyPressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabDeckEditor::createDeckDock()
|
void TabDeckEditor::createDeckDock()
|
||||||
{
|
{
|
||||||
deckModel = new DeckListModel(this);
|
deckModel = new DeckListModel(this);
|
||||||
@@ -67,9 +63,13 @@ void TabDeckEditor::createDeckDock()
|
|||||||
deckView->sortByColumn(1, Qt::AscendingOrder);
|
deckView->sortByColumn(1, Qt::AscendingOrder);
|
||||||
deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||||
deckView->installEventFilter(&deckViewKeySignals);
|
deckView->installEventFilter(&deckViewKeySignals);
|
||||||
|
deckView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
||||||
SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
|
SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
|
||||||
|
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
||||||
|
SLOT(updatePrintingSelectorDeckView(const QModelIndex &, const QModelIndex &)));
|
||||||
connect(deckView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actSwapCard()));
|
connect(deckView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actSwapCard()));
|
||||||
|
connect(deckView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(decklistCustomMenu(QPoint)));
|
||||||
connect(&deckViewKeySignals, SIGNAL(onShiftS()), this, SLOT(actSwapCard()));
|
connect(&deckViewKeySignals, SIGNAL(onShiftS()), this, SLOT(actSwapCard()));
|
||||||
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
|
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
|
||||||
connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement()));
|
connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement()));
|
||||||
@@ -81,6 +81,7 @@ void TabDeckEditor::createDeckDock()
|
|||||||
nameLabel = new QLabel();
|
nameLabel = new QLabel();
|
||||||
nameLabel->setObjectName("nameLabel");
|
nameLabel->setObjectName("nameLabel");
|
||||||
nameEdit = new LineEditUnfocusable;
|
nameEdit = new LineEditUnfocusable;
|
||||||
|
nameEdit->setMaxLength(MAX_NAME_LENGTH);
|
||||||
nameEdit->setObjectName("nameEdit");
|
nameEdit->setObjectName("nameEdit");
|
||||||
nameLabel->setBuddy(nameEdit);
|
nameLabel->setBuddy(nameEdit);
|
||||||
connect(nameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateName(const QString &)));
|
connect(nameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateName(const QString &)));
|
||||||
@@ -160,7 +161,6 @@ void TabDeckEditor::createDeckDock()
|
|||||||
deckDock = new QDockWidget(this);
|
deckDock = new QDockWidget(this);
|
||||||
deckDock->setObjectName("deckDock");
|
deckDock->setObjectName("deckDock");
|
||||||
|
|
||||||
deckDock->setMinimumSize(QSize(200, 41));
|
|
||||||
deckDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
deckDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||||
deckDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
deckDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
||||||
QDockWidget::DockWidgetMovable);
|
QDockWidget::DockWidgetMovable);
|
||||||
@@ -175,7 +175,7 @@ void TabDeckEditor::createDeckDock()
|
|||||||
|
|
||||||
void TabDeckEditor::createCardInfoDock()
|
void TabDeckEditor::createCardInfoDock()
|
||||||
{
|
{
|
||||||
cardInfo = new CardFrame();
|
cardInfo = new CardInfoFrameWidget();
|
||||||
cardInfo->setObjectName("cardInfo");
|
cardInfo->setObjectName("cardInfo");
|
||||||
auto *cardInfoFrame = new QVBoxLayout;
|
auto *cardInfoFrame = new QVBoxLayout;
|
||||||
cardInfoFrame->setObjectName("cardInfoFrame");
|
cardInfoFrame->setObjectName("cardInfoFrame");
|
||||||
@@ -184,7 +184,6 @@ void TabDeckEditor::createCardInfoDock()
|
|||||||
cardInfoDock = new QDockWidget(this);
|
cardInfoDock = new QDockWidget(this);
|
||||||
cardInfoDock->setObjectName("cardInfoDock");
|
cardInfoDock->setObjectName("cardInfoDock");
|
||||||
|
|
||||||
cardInfoDock->setMinimumSize(QSize(200, 41));
|
|
||||||
cardInfoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
cardInfoDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||||
cardInfoDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
cardInfoDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
||||||
QDockWidget::DockWidgetMovable);
|
QDockWidget::DockWidgetMovable);
|
||||||
@@ -259,6 +258,32 @@ void TabDeckEditor::createFiltersDock()
|
|||||||
connect(filterDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool)));
|
connect(filterDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::createPrintingSelectorDock()
|
||||||
|
{
|
||||||
|
printingSelector = new PrintingSelector(this, this, deckModel, deckView);
|
||||||
|
printingSelector->setObjectName("printingSelector");
|
||||||
|
auto *printingSelectorFrame = new QVBoxLayout;
|
||||||
|
printingSelectorFrame->setObjectName("printingSelectorFrame");
|
||||||
|
printingSelectorFrame->addWidget(printingSelector);
|
||||||
|
|
||||||
|
printingSelectorDock = new QDockWidget(this);
|
||||||
|
printingSelectorDock->setObjectName("printingSelectorDock");
|
||||||
|
|
||||||
|
printingSelectorDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||||
|
printingSelectorDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
|
||||||
|
QDockWidget::DockWidgetMovable);
|
||||||
|
auto *printingSelectorDockContents = new QWidget();
|
||||||
|
printingSelectorDockContents->setObjectName("printingSelectorDockContents");
|
||||||
|
printingSelectorDockContents->setLayout(printingSelectorFrame);
|
||||||
|
printingSelectorDock->setWidget(printingSelectorDockContents);
|
||||||
|
|
||||||
|
printingSelectorDock->installEventFilter(this);
|
||||||
|
connect(printingSelectorDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool)));
|
||||||
|
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, printingSelectorDock);
|
||||||
|
printingSelectorDock->setFloating(false);
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::createMenus()
|
void TabDeckEditor::createMenus()
|
||||||
{
|
{
|
||||||
aNewDeck = new QAction(QString(), this);
|
aNewDeck = new QAction(QString(), this);
|
||||||
@@ -337,6 +362,7 @@ void TabDeckEditor::createMenus()
|
|||||||
cardInfoDockMenu = viewMenu->addMenu(QString());
|
cardInfoDockMenu = viewMenu->addMenu(QString());
|
||||||
deckDockMenu = viewMenu->addMenu(QString());
|
deckDockMenu = viewMenu->addMenu(QString());
|
||||||
filterDockMenu = viewMenu->addMenu(QString());
|
filterDockMenu = viewMenu->addMenu(QString());
|
||||||
|
printingSelectorDockMenu = viewMenu->addMenu(QString());
|
||||||
|
|
||||||
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
|
aCardInfoDockVisible = cardInfoDockMenu->addAction(QString());
|
||||||
aCardInfoDockVisible->setCheckable(true);
|
aCardInfoDockVisible->setCheckable(true);
|
||||||
@@ -359,6 +385,13 @@ void TabDeckEditor::createMenus()
|
|||||||
aFilterDockFloating->setCheckable(true);
|
aFilterDockFloating->setCheckable(true);
|
||||||
connect(aFilterDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
|
connect(aFilterDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
|
||||||
|
|
||||||
|
aPrintingSelectorDockVisible = printingSelectorDockMenu->addAction(QString());
|
||||||
|
aPrintingSelectorDockVisible->setCheckable(true);
|
||||||
|
connect(aPrintingSelectorDockVisible, SIGNAL(triggered()), this, SLOT(dockVisibleTriggered()));
|
||||||
|
aPrintingSelectorDockFloating = printingSelectorDockMenu->addAction(QString());
|
||||||
|
aPrintingSelectorDockFloating->setCheckable(true);
|
||||||
|
connect(aPrintingSelectorDockFloating, SIGNAL(triggered()), this, SLOT(dockFloatingTriggered()));
|
||||||
|
|
||||||
viewMenu->addSeparator();
|
viewMenu->addSeparator();
|
||||||
|
|
||||||
aResetLayout = viewMenu->addAction(QString());
|
aResetLayout = viewMenu->addAction(QString());
|
||||||
@@ -374,7 +407,7 @@ void TabDeckEditor::createCentralFrame()
|
|||||||
{
|
{
|
||||||
searchEdit = new SearchLineEdit;
|
searchEdit = new SearchLineEdit;
|
||||||
searchEdit->setObjectName("searchEdit");
|
searchEdit->setObjectName("searchEdit");
|
||||||
searchEdit->setPlaceholderText(tr("Search by card name"));
|
searchEdit->setPlaceholderText(tr("Search by card name (or search expressions)"));
|
||||||
searchEdit->setClearButtonEnabled(true);
|
searchEdit->setClearButtonEnabled(true);
|
||||||
searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition);
|
searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition);
|
||||||
auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition);
|
auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition);
|
||||||
@@ -392,9 +425,10 @@ void TabDeckEditor::createCentralFrame()
|
|||||||
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
|
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
|
||||||
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
|
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
|
||||||
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
|
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
|
||||||
|
connect(&searchKeySignals, SIGNAL(onCtrlC()), this, SLOT(copyDatabaseCellContents()));
|
||||||
connect(help, &QAction::triggered, this, &TabDeckEditor::showSearchSyntaxHelp);
|
connect(help, &QAction::triggered, this, &TabDeckEditor::showSearchSyntaxHelp);
|
||||||
|
|
||||||
databaseModel = new CardDatabaseModel(db, true, this);
|
databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this);
|
||||||
databaseModel->setObjectName("databaseModel");
|
databaseModel->setObjectName("databaseModel");
|
||||||
databaseDisplayModel = new CardDatabaseDisplayModel(this);
|
databaseDisplayModel = new CardDatabaseDisplayModel(this);
|
||||||
databaseDisplayModel->setSourceModel(databaseModel);
|
databaseDisplayModel->setSourceModel(databaseModel);
|
||||||
@@ -413,6 +447,8 @@ void TabDeckEditor::createCentralFrame()
|
|||||||
connect(databaseView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(databaseCustomMenu(QPoint)));
|
connect(databaseView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(databaseCustomMenu(QPoint)));
|
||||||
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
||||||
SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
|
SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
|
||||||
|
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
|
||||||
|
SLOT(updatePrintingSelectorDatabase(const QModelIndex &, const QModelIndex &)));
|
||||||
connect(databaseView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actAddCard()));
|
connect(databaseView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actAddCard()));
|
||||||
|
|
||||||
QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState();
|
QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState();
|
||||||
@@ -452,6 +488,7 @@ void TabDeckEditor::createCentralFrame()
|
|||||||
centralWidget = new QWidget(this);
|
centralWidget = new QWidget(this);
|
||||||
centralWidget->setObjectName("centralWidget");
|
centralWidget->setObjectName("centralWidget");
|
||||||
centralWidget->setLayout(centralFrame);
|
centralWidget->setLayout(centralFrame);
|
||||||
|
centralWidget->setMaximumSize(900, 5000);
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(centralWidget);
|
||||||
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
|
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
|
||||||
}
|
}
|
||||||
@@ -462,11 +499,14 @@ void TabDeckEditor::databaseCustomMenu(QPoint point)
|
|||||||
const CardInfoPtr info = currentCardInfo();
|
const CardInfoPtr info = currentCardInfo();
|
||||||
|
|
||||||
// add to deck and sideboard options
|
// add to deck and sideboard options
|
||||||
QAction *addToDeck, *addToSideboard;
|
QAction *addToDeck, *addToSideboard, *selectPrinting;
|
||||||
addToDeck = menu.addAction(tr("Add to Deck"));
|
addToDeck = menu.addAction(tr("Add to Deck"));
|
||||||
addToSideboard = menu.addAction(tr("Add to Sideboard"));
|
addToSideboard = menu.addAction(tr("Add to Sideboard"));
|
||||||
|
selectPrinting = menu.addAction(tr("Select Printing"));
|
||||||
|
|
||||||
connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard()));
|
connect(addToDeck, SIGNAL(triggered()), this, SLOT(actAddCard()));
|
||||||
connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
|
connect(addToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
|
||||||
|
connect(selectPrinting, &QAction::triggered, this, [this, info] { this->showPrintingSelector(); });
|
||||||
|
|
||||||
// filling out the related cards submenu
|
// filling out the related cards submenu
|
||||||
auto *relatedMenu = new QMenu(tr("Show Related cards"));
|
auto *relatedMenu = new QMenu(tr("Show Related cards"));
|
||||||
@@ -485,36 +525,58 @@ void TabDeckEditor::databaseCustomMenu(QPoint point)
|
|||||||
menu.exec(databaseView->mapToGlobal(point));
|
menu.exec(databaseView->mapToGlobal(point));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::decklistCustomMenu(QPoint point)
|
||||||
|
{
|
||||||
|
QMenu menu;
|
||||||
|
const CardInfoPtr info = cardInfo->getInfo();
|
||||||
|
|
||||||
|
QAction *selectPrinting = menu.addAction(tr("Select Printing"));
|
||||||
|
|
||||||
|
connect(selectPrinting, &QAction::triggered, this, &TabDeckEditor::showPrintingSelector);
|
||||||
|
|
||||||
|
menu.exec(deckView->mapToGlobal(point));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::showPrintingSelector()
|
||||||
|
{
|
||||||
|
printingSelector->setCard(cardInfo->getInfo(), DECK_ZONE_MAIN);
|
||||||
|
printingSelector->updateDisplay();
|
||||||
|
aPrintingSelectorDockVisible->setChecked(true);
|
||||||
|
printingSelectorDock->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::restartLayout()
|
void TabDeckEditor::restartLayout()
|
||||||
{
|
{
|
||||||
deckDock->setVisible(true);
|
deckDock->setVisible(true);
|
||||||
cardInfoDock->setVisible(true);
|
cardInfoDock->setVisible(true);
|
||||||
filterDock->setVisible(true);
|
filterDock->setVisible(true);
|
||||||
|
printingSelectorDock->setVisible(false);
|
||||||
|
|
||||||
deckDock->setFloating(false);
|
deckDock->setFloating(false);
|
||||||
cardInfoDock->setFloating(false);
|
cardInfoDock->setFloating(false);
|
||||||
filterDock->setFloating(false);
|
filterDock->setFloating(false);
|
||||||
|
printingSelectorDock->setFloating(false);
|
||||||
|
|
||||||
aCardInfoDockVisible->setChecked(true);
|
aCardInfoDockVisible->setChecked(true);
|
||||||
aDeckDockVisible->setChecked(true);
|
aDeckDockVisible->setChecked(true);
|
||||||
aFilterDockVisible->setChecked(true);
|
aFilterDockVisible->setChecked(true);
|
||||||
|
aPrintingSelectorDockVisible->setChecked(false);
|
||||||
|
|
||||||
aCardInfoDockFloating->setChecked(false);
|
aCardInfoDockFloating->setChecked(false);
|
||||||
aDeckDockFloating->setChecked(false);
|
aDeckDockFloating->setChecked(false);
|
||||||
aFilterDockFloating->setChecked(false);
|
aFilterDockFloating->setChecked(false);
|
||||||
|
aPrintingSelectorDockFloating->setChecked(false);
|
||||||
|
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), deckDock);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), deckDock);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), cardInfoDock);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), cardInfoDock);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), filterDock);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), filterDock);
|
||||||
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), printingSelectorDock);
|
||||||
|
|
||||||
splitDockWidget(cardInfoDock, deckDock, Qt::Horizontal);
|
splitDockWidget(cardInfoDock, printingSelectorDock, Qt::Horizontal);
|
||||||
|
splitDockWidget(printingSelectorDock, deckDock, Qt::Horizontal);
|
||||||
|
splitDockWidget(cardInfoDock, printingSelectorDock, Qt::Horizontal);
|
||||||
splitDockWidget(cardInfoDock, filterDock, Qt::Vertical);
|
splitDockWidget(cardInfoDock, filterDock, Qt::Vertical);
|
||||||
|
|
||||||
deckDock->setMinimumWidth(360);
|
|
||||||
deckDock->setMaximumWidth(360);
|
|
||||||
|
|
||||||
cardInfoDock->setMinimumSize(250, 360);
|
|
||||||
cardInfoDock->setMaximumSize(250, 360);
|
|
||||||
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
|
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,6 +590,11 @@ void TabDeckEditor::freeDocksSize()
|
|||||||
|
|
||||||
filterDock->setMinimumSize(100, 100);
|
filterDock->setMinimumSize(100, 100);
|
||||||
filterDock->setMaximumSize(5000, 5000);
|
filterDock->setMaximumSize(5000, 5000);
|
||||||
|
|
||||||
|
printingSelectorDock->setMinimumSize(525, 100);
|
||||||
|
printingSelectorDock->setMaximumSize(5000, 5000);
|
||||||
|
|
||||||
|
centralWidget->setMaximumSize(900, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::refreshShortcuts()
|
void TabDeckEditor::refreshShortcuts()
|
||||||
@@ -559,20 +626,28 @@ void TabDeckEditor::refreshShortcuts()
|
|||||||
void TabDeckEditor::loadLayout()
|
void TabDeckEditor::loadLayout()
|
||||||
{
|
{
|
||||||
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
LayoutsSettings &layouts = SettingsCache::instance().layouts();
|
||||||
restoreState(layouts.getDeckEditorLayoutState());
|
auto &layoutState = layouts.getDeckEditorLayoutState();
|
||||||
restoreGeometry(layouts.getDeckEditorGeometry());
|
if (layoutState.isNull()) {
|
||||||
|
restartLayout();
|
||||||
|
} else {
|
||||||
|
restoreState(layoutState);
|
||||||
|
restoreGeometry(layouts.getDeckEditorGeometry());
|
||||||
|
}
|
||||||
|
|
||||||
aCardInfoDockVisible->setChecked(cardInfoDock->isVisible());
|
aCardInfoDockVisible->setChecked(cardInfoDock->isVisible());
|
||||||
aFilterDockVisible->setChecked(filterDock->isVisible());
|
aFilterDockVisible->setChecked(filterDock->isVisible());
|
||||||
aDeckDockVisible->setChecked(deckDock->isVisible());
|
aDeckDockVisible->setChecked(deckDock->isVisible());
|
||||||
|
aPrintingSelectorDockVisible->setChecked(printingSelectorDock->isVisible());
|
||||||
|
|
||||||
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
|
aCardInfoDockFloating->setEnabled(aCardInfoDockVisible->isChecked());
|
||||||
aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked());
|
aDeckDockFloating->setEnabled(aDeckDockVisible->isChecked());
|
||||||
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
|
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
|
||||||
|
aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked());
|
||||||
|
|
||||||
aCardInfoDockFloating->setChecked(cardInfoDock->isFloating());
|
aCardInfoDockFloating->setChecked(cardInfoDock->isFloating());
|
||||||
aFilterDockFloating->setChecked(filterDock->isFloating());
|
aFilterDockFloating->setChecked(filterDock->isFloating());
|
||||||
aDeckDockFloating->setChecked(deckDock->isFloating());
|
aDeckDockFloating->setChecked(deckDock->isFloating());
|
||||||
|
aPrintingSelectorDockFloating->setChecked(printingSelectorDock->isFloating());
|
||||||
|
|
||||||
cardInfoDock->setMinimumSize(layouts.getDeckEditorCardSize());
|
cardInfoDock->setMinimumSize(layouts.getDeckEditorCardSize());
|
||||||
cardInfoDock->setMaximumSize(layouts.getDeckEditorCardSize());
|
cardInfoDock->setMaximumSize(layouts.getDeckEditorCardSize());
|
||||||
@@ -583,6 +658,9 @@ void TabDeckEditor::loadLayout()
|
|||||||
deckDock->setMinimumSize(layouts.getDeckEditorDeckSize());
|
deckDock->setMinimumSize(layouts.getDeckEditorDeckSize());
|
||||||
deckDock->setMaximumSize(layouts.getDeckEditorDeckSize());
|
deckDock->setMaximumSize(layouts.getDeckEditorDeckSize());
|
||||||
|
|
||||||
|
printingSelectorDock->setMinimumSize(layouts.getDeckEditorPrintingSelectorSize());
|
||||||
|
printingSelectorDock->setMaximumSize(layouts.getDeckEditorPrintingSelectorSize());
|
||||||
|
|
||||||
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
|
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +676,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||||||
createDeckDock();
|
createDeckDock();
|
||||||
createCardInfoDock();
|
createCardInfoDock();
|
||||||
createFiltersDock();
|
createFiltersDock();
|
||||||
|
createPrintingSelectorDock();
|
||||||
|
|
||||||
this->installEventFilter(this);
|
this->installEventFilter(this);
|
||||||
|
|
||||||
@@ -605,7 +684,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||||||
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
|
|
||||||
QTimer::singleShot(0, this, SLOT(loadLayout()));
|
loadLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
TabDeckEditor::~TabDeckEditor()
|
TabDeckEditor::~TabDeckEditor()
|
||||||
@@ -657,11 +736,13 @@ void TabDeckEditor::retranslateUi()
|
|||||||
cardInfoDock->setWindowTitle(tr("Card Info"));
|
cardInfoDock->setWindowTitle(tr("Card Info"));
|
||||||
deckDock->setWindowTitle(tr("Deck"));
|
deckDock->setWindowTitle(tr("Deck"));
|
||||||
filterDock->setWindowTitle(tr("Filters"));
|
filterDock->setWindowTitle(tr("Filters"));
|
||||||
|
printingSelectorDock->setWindowTitle(tr("Printing Selector"));
|
||||||
|
|
||||||
viewMenu->setTitle(tr("&View"));
|
viewMenu->setTitle(tr("&View"));
|
||||||
cardInfoDockMenu->setTitle(tr("Card Info"));
|
cardInfoDockMenu->setTitle(tr("Card Info"));
|
||||||
deckDockMenu->setTitle(tr("Deck"));
|
deckDockMenu->setTitle(tr("Deck"));
|
||||||
filterDockMenu->setTitle(tr("Filters"));
|
filterDockMenu->setTitle(tr("Filters"));
|
||||||
|
printingSelectorDockMenu->setTitle(tr("Printing"));
|
||||||
|
|
||||||
aCardInfoDockVisible->setText(tr("Visible"));
|
aCardInfoDockVisible->setText(tr("Visible"));
|
||||||
aCardInfoDockFloating->setText(tr("Floating"));
|
aCardInfoDockFloating->setText(tr("Floating"));
|
||||||
@@ -672,6 +753,9 @@ void TabDeckEditor::retranslateUi()
|
|||||||
aFilterDockVisible->setText(tr("Visible"));
|
aFilterDockVisible->setText(tr("Visible"));
|
||||||
aFilterDockFloating->setText(tr("Floating"));
|
aFilterDockFloating->setText(tr("Floating"));
|
||||||
|
|
||||||
|
aPrintingSelectorDockVisible->setText(tr("Visible"));
|
||||||
|
aPrintingSelectorDockFloating->setText(tr("Floating"));
|
||||||
|
|
||||||
aResetLayout->setText(tr("Reset layout"));
|
aResetLayout->setText(tr("Reset layout"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,6 +781,11 @@ void TabDeckEditor::updateComments()
|
|||||||
setSaveStatus(true);
|
setSaveStatus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::updateCardInfo(CardInfoPtr _card)
|
||||||
|
{
|
||||||
|
cardInfo->setCard(_card);
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
void TabDeckEditor::updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
||||||
{
|
{
|
||||||
cardInfo->setCard(current.sibling(current.row(), 0).data().toString());
|
cardInfo->setCard(current.sibling(current.row(), 0).data().toString());
|
||||||
@@ -706,8 +795,47 @@ void TabDeckEditor::updateCardInfoRight(const QModelIndex ¤t, const QModel
|
|||||||
{
|
{
|
||||||
if (!current.isValid())
|
if (!current.isValid())
|
||||||
return;
|
return;
|
||||||
if (!current.model()->hasChildren(current.sibling(current.row(), 0)))
|
if (!current.model()->hasChildren(current.sibling(current.row(), 0))) {
|
||||||
cardInfo->setCard(current.sibling(current.row(), 1).data().toString());
|
cardInfo->setCard(current.sibling(current.row(), 1).data().toString(),
|
||||||
|
current.sibling(current.row(), 4).data().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::updatePrintingSelectorDatabase(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
||||||
|
{
|
||||||
|
const QString cardName = current.sibling(current.row(), 0).data().toString();
|
||||||
|
const QString cardProviderID = CardDatabaseManager::getInstance()->getPreferredPrintingProviderIdForCard(cardName);
|
||||||
|
|
||||||
|
if (!current.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current.model()->hasChildren(current.sibling(current.row(), 0))) {
|
||||||
|
printingSelector->setCard(
|
||||||
|
CardDatabaseManager::getInstance()->getCardByNameAndProviderId(cardName, cardProviderID), DECK_ZONE_MAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::updatePrintingSelectorDeckView(const QModelIndex ¤t, const QModelIndex & /*previous*/)
|
||||||
|
{
|
||||||
|
const QString cardName = current.sibling(current.row(), 1).data().toString();
|
||||||
|
const QString cardProviderID = current.sibling(current.row(), 4).data().toString();
|
||||||
|
const QModelIndex gparent = current.parent().parent();
|
||||||
|
|
||||||
|
if (!gparent.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString zoneName = gparent.sibling(gparent.row(), 1).data(Qt::EditRole).toString();
|
||||||
|
|
||||||
|
if (!current.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current.model()->hasChildren(current.sibling(current.row(), 0))) {
|
||||||
|
printingSelector->setCard(
|
||||||
|
CardDatabaseManager::getInstance()->getCardByNameAndProviderId(cardName, cardProviderID), zoneName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::updateSearch(const QString &search)
|
void TabDeckEditor::updateSearch(const QString &search)
|
||||||
@@ -728,9 +856,7 @@ bool TabDeckEditor::confirmClose()
|
|||||||
{
|
{
|
||||||
if (modified) {
|
if (modified) {
|
||||||
tabSupervisor->setCurrentWidget(this);
|
tabSupervisor->setCurrentWidget(this);
|
||||||
QMessageBox::StandardButton ret = QMessageBox::warning(
|
int ret = createSaveConfirmationWindow()->exec();
|
||||||
this, tr("Are you sure?"), tr("The decklist has been modified.\nDo you want to save the changes?"),
|
|
||||||
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
||||||
if (ret == QMessageBox::Save)
|
if (ret == QMessageBox::Save)
|
||||||
return actSaveDeck();
|
return actSaveDeck();
|
||||||
else if (ret == QMessageBox::Cancel)
|
else if (ret == QMessageBox::Cancel)
|
||||||
@@ -747,8 +873,16 @@ void TabDeckEditor::closeRequest()
|
|||||||
|
|
||||||
void TabDeckEditor::actNewDeck()
|
void TabDeckEditor::actNewDeck()
|
||||||
{
|
{
|
||||||
if (!confirmClose())
|
auto deckOpenLocation = confirmOpen(false);
|
||||||
|
|
||||||
|
if (deckOpenLocation == CANCELLED) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deckOpenLocation == NEW_TAB) {
|
||||||
|
emit openDeckEditor(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
deckModel->cleanList();
|
deckModel->cleanList();
|
||||||
nameEdit->setText(QString());
|
nameEdit->setText(QString());
|
||||||
@@ -760,8 +894,11 @@ void TabDeckEditor::actNewDeck()
|
|||||||
|
|
||||||
void TabDeckEditor::actLoadDeck()
|
void TabDeckEditor::actLoadDeck()
|
||||||
{
|
{
|
||||||
if (!confirmClose())
|
auto deckOpenLocation = confirmOpen();
|
||||||
|
|
||||||
|
if (deckOpenLocation == CANCELLED) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QFileDialog dialog(this, tr("Load deck"));
|
QFileDialog dialog(this, tr("Load deck"));
|
||||||
dialog.setDirectory(SettingsCache::instance().getDeckPath());
|
dialog.setDirectory(SettingsCache::instance().getDeckPath());
|
||||||
@@ -774,8 +911,12 @@ void TabDeckEditor::actLoadDeck()
|
|||||||
|
|
||||||
auto *l = new DeckLoader;
|
auto *l = new DeckLoader;
|
||||||
if (l->loadFromFile(fileName, fmt)) {
|
if (l->loadFromFile(fileName, fmt)) {
|
||||||
setSaveStatus(false);
|
if (deckOpenLocation == NEW_TAB) {
|
||||||
setDeck(l);
|
emit openDeckEditor(l);
|
||||||
|
} else {
|
||||||
|
setSaveStatus(false);
|
||||||
|
setDeck(l);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
delete l;
|
delete l;
|
||||||
setSaveStatus(true);
|
setSaveStatus(true);
|
||||||
@@ -793,9 +934,15 @@ bool TabDeckEditor::actSaveDeck()
|
|||||||
{
|
{
|
||||||
DeckLoader *const deck = deckModel->getDeckList();
|
DeckLoader *const deck = deckModel->getDeckList();
|
||||||
if (deck->getLastRemoteDeckId() != -1) {
|
if (deck->getLastRemoteDeckId() != -1) {
|
||||||
|
QString deckString = deck->writeToString_Native();
|
||||||
|
if (deckString.length() > MAX_FILE_LENGTH) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Command_DeckUpload cmd;
|
Command_DeckUpload cmd;
|
||||||
cmd.set_deck_id(static_cast<google::protobuf::uint32>(deck->getLastRemoteDeckId()));
|
cmd.set_deck_id(static_cast<google::protobuf::uint32>(deck->getLastRemoteDeckId()));
|
||||||
cmd.set_deck_list(deck->writeToString_Native().toStdString());
|
cmd.set_deck_list(deckString.toStdString());
|
||||||
|
|
||||||
PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd);
|
PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
||||||
@@ -841,15 +988,23 @@ bool TabDeckEditor::actSaveDeckAs()
|
|||||||
|
|
||||||
void TabDeckEditor::actLoadDeckFromClipboard()
|
void TabDeckEditor::actLoadDeckFromClipboard()
|
||||||
{
|
{
|
||||||
if (!confirmClose())
|
auto deckOpenLocation = confirmOpen();
|
||||||
|
|
||||||
|
if (deckOpenLocation == CANCELLED) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DlgLoadDeckFromClipboard dlg(this);
|
DlgLoadDeckFromClipboard dlg(this);
|
||||||
if (!dlg.exec())
|
if (!dlg.exec())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setDeck(dlg.getDeckList());
|
if (deckOpenLocation == NEW_TAB) {
|
||||||
setModified(true);
|
emit openDeckEditor(dlg.getDeckList());
|
||||||
|
} else {
|
||||||
|
setDeck(dlg.getDeckList());
|
||||||
|
setModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
setSaveStatus(true);
|
setSaveStatus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,6 +1098,79 @@ void TabDeckEditor::recursiveExpand(const QModelIndex &index)
|
|||||||
deckView->expand(index);
|
deckView->expand(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Displays the save confirmation dialogue that is shown before loading a deck, if required. Takes into
|
||||||
|
* account the `openDeckInNewTab` settting.
|
||||||
|
*
|
||||||
|
* @param openInSameTabIfBlank Open the deck in the same tab instead of a new tab if the current tab is completely
|
||||||
|
* blank. Only relevant when the `openDeckInNewTab` setting is enabled.
|
||||||
|
*
|
||||||
|
* @returns An enum that indicates if and where to load the deck
|
||||||
|
*/
|
||||||
|
TabDeckEditor::DeckOpenLocation TabDeckEditor::confirmOpen(const bool openInSameTabIfBlank)
|
||||||
|
{
|
||||||
|
// handle `openDeckInNewTab` setting
|
||||||
|
if (SettingsCache::instance().getOpenDeckInNewTab()) {
|
||||||
|
if (openInSameTabIfBlank && isBlankNewDeck()) {
|
||||||
|
return SAME_TAB;
|
||||||
|
} else {
|
||||||
|
return NEW_TAB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// early return if deck is unmodified
|
||||||
|
if (!modified) {
|
||||||
|
return SAME_TAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the save confirmation dialogue
|
||||||
|
tabSupervisor->setCurrentWidget(this);
|
||||||
|
|
||||||
|
QMessageBox *msgBox = createSaveConfirmationWindow();
|
||||||
|
QPushButton *newTabButton = msgBox->addButton(tr("Open in new tab"), QMessageBox::ApplyRole);
|
||||||
|
|
||||||
|
int ret = msgBox->exec();
|
||||||
|
|
||||||
|
// `exec()` returns an opaque value if a non-standard button was clicked.
|
||||||
|
// Directly check if newTabButton was clicked before switching over the standard buttons.
|
||||||
|
if (msgBox->clickedButton() == newTabButton) {
|
||||||
|
return NEW_TAB;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Save:
|
||||||
|
return actSaveDeck() ? SAME_TAB : CANCELLED;
|
||||||
|
case QMessageBox::Discard:
|
||||||
|
return SAME_TAB;
|
||||||
|
default:
|
||||||
|
return CANCELLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates the base save confirmation dialogue box.
|
||||||
|
*
|
||||||
|
* @returns A QMessageBox that can be further modified
|
||||||
|
*/
|
||||||
|
QMessageBox *TabDeckEditor::createSaveConfirmationWindow()
|
||||||
|
{
|
||||||
|
QMessageBox *msgBox = new QMessageBox(this);
|
||||||
|
msgBox->setIcon(QMessageBox::Warning);
|
||||||
|
msgBox->setWindowTitle(tr("Are you sure?"));
|
||||||
|
msgBox->setText(tr("The decklist has been modified.\nDo you want to save the changes?"));
|
||||||
|
msgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||||
|
return msgBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if this tab is a blank newly opened tab, as if it was just created with the `New Deck` action.
|
||||||
|
*/
|
||||||
|
bool TabDeckEditor::isBlankNewDeck() const
|
||||||
|
{
|
||||||
|
DeckLoader *const deck = deckModel->getDeckList();
|
||||||
|
return !modified && deck->getLastFileName().isEmpty() && deck->getLastRemoteDeckId() == -1;
|
||||||
|
}
|
||||||
|
|
||||||
CardInfoPtr TabDeckEditor::currentCardInfo() const
|
CardInfoPtr TabDeckEditor::currentCardInfo() const
|
||||||
{
|
{
|
||||||
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
|
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
|
||||||
@@ -952,7 +1180,7 @@ CardInfoPtr TabDeckEditor::currentCardInfo() const
|
|||||||
|
|
||||||
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
|
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
|
||||||
|
|
||||||
return db->getCard(cardName);
|
return CardDatabaseManager::getInstance()->getCard(cardName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::addCardHelper(QString zoneName)
|
void TabDeckEditor::addCardHelper(QString zoneName)
|
||||||
@@ -963,7 +1191,7 @@ void TabDeckEditor::addCardHelper(QString zoneName)
|
|||||||
if (info->getIsToken())
|
if (info->getIsToken())
|
||||||
zoneName = DECK_ZONE_TOKENS;
|
zoneName = DECK_ZONE_TOKENS;
|
||||||
|
|
||||||
QModelIndex newCardIndex = deckModel->addCard(info->getName(), zoneName);
|
QModelIndex newCardIndex = deckModel->addPreferredPrintingCard(info->getName(), zoneName, false);
|
||||||
recursiveExpand(newCardIndex);
|
recursiveExpand(newCardIndex);
|
||||||
deckView->setCurrentIndex(newCardIndex);
|
deckView->setCurrentIndex(newCardIndex);
|
||||||
setModified(true);
|
setModified(true);
|
||||||
@@ -976,6 +1204,7 @@ void TabDeckEditor::actSwapCard()
|
|||||||
if (!currentIndex.isValid())
|
if (!currentIndex.isValid())
|
||||||
return;
|
return;
|
||||||
const QString cardName = currentIndex.sibling(currentIndex.row(), 1).data().toString();
|
const QString cardName = currentIndex.sibling(currentIndex.row(), 1).data().toString();
|
||||||
|
const QString cardProviderID = currentIndex.sibling(currentIndex.row(), 4).data().toString();
|
||||||
const QModelIndex gparent = currentIndex.parent().parent();
|
const QModelIndex gparent = currentIndex.parent().parent();
|
||||||
|
|
||||||
if (!gparent.isValid())
|
if (!gparent.isValid())
|
||||||
@@ -985,8 +1214,10 @@ void TabDeckEditor::actSwapCard()
|
|||||||
actDecrement();
|
actDecrement();
|
||||||
const QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN;
|
const QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN;
|
||||||
|
|
||||||
// Third argument (true) says create the card no mater what, even if not in DB
|
// Third argument (true) says create the card no matter what, even if not in DB
|
||||||
QModelIndex newCardIndex = deckModel->addCard(cardName, otherZoneName, true);
|
QModelIndex newCardIndex = deckModel->addCard(
|
||||||
|
cardName, CardDatabaseManager::getInstance()->getSpecificSetForCard(cardName, cardProviderID), otherZoneName,
|
||||||
|
true);
|
||||||
recursiveExpand(newCardIndex);
|
recursiveExpand(newCardIndex);
|
||||||
|
|
||||||
setModified(true);
|
setModified(true);
|
||||||
@@ -1060,6 +1291,12 @@ void TabDeckEditor::actDecrementCardFromSideboard()
|
|||||||
decrementCardHelper(DECK_ZONE_SIDE);
|
decrementCardHelper(DECK_ZONE_SIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabDeckEditor::copyDatabaseCellContents()
|
||||||
|
{
|
||||||
|
auto _data = databaseView->selectionModel()->currentIndex().data();
|
||||||
|
QApplication::clipboard()->setText(_data.toString());
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actIncrement()
|
void TabDeckEditor::actIncrement()
|
||||||
{
|
{
|
||||||
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
const QModelIndex ¤tIndex = deckView->selectionModel()->currentIndex();
|
||||||
@@ -1083,7 +1320,8 @@ void TabDeckEditor::setDeck(DeckLoader *_deck)
|
|||||||
deckView->expandAll();
|
deckView->expandAll();
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|
||||||
PictureLoader::cacheCardPixmaps(db->getCards(deckModel->getDeckList()->getCardList()));
|
PictureLoader::cacheCardPixmaps(
|
||||||
|
CardDatabaseManager::getInstance()->getCards(deckModel->getDeckList()->getCardList()));
|
||||||
deckView->expandAll();
|
deckView->expandAll();
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|
||||||
@@ -1140,6 +1378,9 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e)
|
|||||||
} else if (o == filterDock) {
|
} else if (o == filterDock) {
|
||||||
aFilterDockVisible->setChecked(false);
|
aFilterDockVisible->setChecked(false);
|
||||||
aFilterDockFloating->setEnabled(false);
|
aFilterDockFloating->setEnabled(false);
|
||||||
|
} else if (o == printingSelectorDock) {
|
||||||
|
aPrintingSelectorDockVisible->setChecked(false);
|
||||||
|
aPrintingSelectorDockFloating->setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o == this && e->type() == QEvent::Hide) {
|
if (o == this && e->type() == QEvent::Hide) {
|
||||||
@@ -1149,6 +1390,7 @@ bool TabDeckEditor::eventFilter(QObject *o, QEvent *e)
|
|||||||
layouts.setDeckEditorCardSize(cardInfoDock->size());
|
layouts.setDeckEditorCardSize(cardInfoDock->size());
|
||||||
layouts.setDeckEditorFilterSize(filterDock->size());
|
layouts.setDeckEditorFilterSize(filterDock->size());
|
||||||
layouts.setDeckEditorDeckSize(deckDock->size());
|
layouts.setDeckEditorDeckSize(deckDock->size());
|
||||||
|
layouts.setDeckEditorPrintingSelectorSize(printingSelectorDock->size());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1173,6 +1415,12 @@ void TabDeckEditor::dockVisibleTriggered()
|
|||||||
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
|
aFilterDockFloating->setEnabled(aFilterDockVisible->isChecked());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (o == aPrintingSelectorDockVisible) {
|
||||||
|
printingSelectorDock->setVisible(aPrintingSelectorDockVisible->isChecked());
|
||||||
|
aPrintingSelectorDockFloating->setEnabled(aPrintingSelectorDockVisible->isChecked());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::dockFloatingTriggered()
|
void TabDeckEditor::dockFloatingTriggered()
|
||||||
@@ -1192,6 +1440,11 @@ void TabDeckEditor::dockFloatingTriggered()
|
|||||||
filterDock->setFloating(aFilterDockFloating->isChecked());
|
filterDock->setFloating(aFilterDockFloating->isChecked());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (o == aPrintingSelectorDockFloating) {
|
||||||
|
printingSelectorDock->setFloating(aPrintingSelectorDockFloating->isChecked());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::dockTopLevelChanged(bool topLevel)
|
void TabDeckEditor::dockTopLevelChanged(bool topLevel)
|
||||||
@@ -1211,6 +1464,11 @@ void TabDeckEditor::dockTopLevelChanged(bool topLevel)
|
|||||||
aFilterDockFloating->setChecked(topLevel);
|
aFilterDockFloating->setChecked(topLevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (o == printingSelectorDock) {
|
||||||
|
aPrintingSelectorDockFloating->setChecked(topLevel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::saveDbHeaderState()
|
void TabDeckEditor::saveDbHeaderState()
|
||||||
@@ -1261,6 +1519,6 @@ void TabDeckEditor::showSearchSyntaxHelp()
|
|||||||
browser->document()->setDefaultStyleSheet(sheet);
|
browser->document()->setDefaultStyleSheet(sheet);
|
||||||
|
|
||||||
browser->setHtml(text);
|
browser->setHtml(text);
|
||||||
connect(browser, &QTextBrowser::anchorClicked, [=](const QUrl &link) { searchEdit->setText(link.fragment()); });
|
connect(browser, &QTextBrowser::anchorClicked, [this](const QUrl &link) { searchEdit->setText(link.fragment()); });
|
||||||
browser->show();
|
browser->show();
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#ifndef WINDOW_DECKEDITOR_H
|
#ifndef WINDOW_DECKEDITOR_H
|
||||||
#define WINDOW_DECKEDITOR_H
|
#define WINDOW_DECKEDITOR_H
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "../../deck/custom_line_edit.h"
|
||||||
#include "customlineedit.h"
|
#include "../../game/cards/card_database.h"
|
||||||
#include "keysignals.h"
|
#include "../game_logic/key_signals.h"
|
||||||
|
#include "../ui/widgets/printing_selector/printing_selector.h"
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
@@ -14,7 +15,7 @@ class CardDatabaseDisplayModel;
|
|||||||
class DeckListModel;
|
class DeckListModel;
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
|
|
||||||
class CardFrame;
|
class CardInfoFrameWidget;
|
||||||
class QTextEdit;
|
class QTextEdit;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class DeckLoader;
|
class DeckLoader;
|
||||||
@@ -22,29 +23,12 @@ class Response;
|
|||||||
class FilterTreeModel;
|
class FilterTreeModel;
|
||||||
class FilterBuilder;
|
class FilterBuilder;
|
||||||
class QGroupBox;
|
class QGroupBox;
|
||||||
|
class QMessageBox;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QDockWidget;
|
class QDockWidget;
|
||||||
|
|
||||||
class SearchLineEdit : public LineEditUnfocusable
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
QTreeView *treeView;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SearchLineEdit() : LineEditUnfocusable(), treeView(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void setTreeView(QTreeView *_treeView)
|
|
||||||
{
|
|
||||||
treeView = _treeView;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TabDeckEditor : public Tab
|
class TabDeckEditor : public Tab
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -54,8 +38,11 @@ private slots:
|
|||||||
void updateHash();
|
void updateHash();
|
||||||
void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous);
|
void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous);
|
void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
void updatePrintingSelectorDatabase(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
void updatePrintingSelectorDeckView(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
void updateSearch(const QString &search);
|
void updateSearch(const QString &search);
|
||||||
void databaseCustomMenu(QPoint point);
|
void databaseCustomMenu(QPoint point);
|
||||||
|
void decklistCustomMenu(QPoint point);
|
||||||
|
|
||||||
void actNewDeck();
|
void actNewDeck();
|
||||||
void actLoadDeck();
|
void actLoadDeck();
|
||||||
@@ -80,6 +67,7 @@ private slots:
|
|||||||
void actDecrement();
|
void actDecrement();
|
||||||
void actDecrementCard();
|
void actDecrementCard();
|
||||||
void actDecrementCardFromSideboard();
|
void actDecrementCardFromSideboard();
|
||||||
|
void copyDatabaseCellContents();
|
||||||
|
|
||||||
void saveDeckRemoteFinished(const Response &r);
|
void saveDeckRemoteFinished(const Response &r);
|
||||||
void filterViewCustomContextMenu(const QPoint &point);
|
void filterViewCustomContextMenu(const QPoint &point);
|
||||||
@@ -99,6 +87,20 @@ private slots:
|
|||||||
void showSearchSyntaxHelp();
|
void showSearchSyntaxHelp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Which tab to open the new deck in
|
||||||
|
*/
|
||||||
|
enum DeckOpenLocation
|
||||||
|
{
|
||||||
|
CANCELLED,
|
||||||
|
SAME_TAB,
|
||||||
|
NEW_TAB
|
||||||
|
};
|
||||||
|
|
||||||
|
DeckOpenLocation confirmOpen(const bool openInSameTabIfBlank = true);
|
||||||
|
QMessageBox *createSaveConfirmationWindow();
|
||||||
|
|
||||||
|
bool isBlankNewDeck() const;
|
||||||
CardInfoPtr currentCardInfo() const;
|
CardInfoPtr currentCardInfo() const;
|
||||||
void addCardHelper(QString zoneName);
|
void addCardHelper(QString zoneName);
|
||||||
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
||||||
@@ -112,7 +114,8 @@ private:
|
|||||||
|
|
||||||
QTreeView *deckView;
|
QTreeView *deckView;
|
||||||
KeySignals deckViewKeySignals;
|
KeySignals deckViewKeySignals;
|
||||||
CardFrame *cardInfo;
|
CardInfoFrameWidget *cardInfo;
|
||||||
|
PrintingSelector *printingSelector;
|
||||||
SearchLineEdit *searchEdit;
|
SearchLineEdit *searchEdit;
|
||||||
KeySignals searchKeySignals;
|
KeySignals searchKeySignals;
|
||||||
|
|
||||||
@@ -127,8 +130,8 @@ private:
|
|||||||
KeySignals filterViewKeySignals;
|
KeySignals filterViewKeySignals;
|
||||||
QWidget *filterBox;
|
QWidget *filterBox;
|
||||||
|
|
||||||
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *analyzeDeckMenu,
|
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *printingSelectorDockMenu,
|
||||||
*saveDeckToClipboardMenu;
|
*analyzeDeckMenu, *saveDeckToClipboardMenu;
|
||||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard,
|
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard,
|
||||||
*aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout,
|
*aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout,
|
||||||
*aClose;
|
*aClose;
|
||||||
@@ -136,7 +139,7 @@ private:
|
|||||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
||||||
QAction *aResetLayout;
|
QAction *aResetLayout;
|
||||||
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating, *aFilterDockVisible,
|
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating, *aFilterDockVisible,
|
||||||
*aFilterDockFloating;
|
*aFilterDockFloating, *aPrintingSelectorDockVisible, *aPrintingSelectorDockFloating;
|
||||||
|
|
||||||
bool modified;
|
bool modified;
|
||||||
QVBoxLayout *centralFrame;
|
QVBoxLayout *centralFrame;
|
||||||
@@ -144,6 +147,7 @@ private:
|
|||||||
QDockWidget *cardInfoDock;
|
QDockWidget *cardInfoDock;
|
||||||
QDockWidget *deckDock;
|
QDockWidget *deckDock;
|
||||||
QDockWidget *filterDock;
|
QDockWidget *filterDock;
|
||||||
|
QDockWidget *printingSelectorDock;
|
||||||
QWidget *centralWidget;
|
QWidget *centralWidget;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -157,12 +161,16 @@ public:
|
|||||||
void createDeckDock();
|
void createDeckDock();
|
||||||
void createCardInfoDock();
|
void createCardInfoDock();
|
||||||
void createFiltersDock();
|
void createFiltersDock();
|
||||||
|
void createPrintingSelectorDock();
|
||||||
void createMenus();
|
void createMenus();
|
||||||
void createCentralFrame();
|
void createCentralFrame();
|
||||||
|
void updateCardInfo(CardInfoPtr _card);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void closeRequest() override;
|
void closeRequest() override;
|
||||||
|
void showPrintingSelector();
|
||||||
signals:
|
signals:
|
||||||
|
void openDeckEditor(const DeckLoader *deckLoader);
|
||||||
void deckEditorClosing(TabDeckEditor *tab);
|
void deckEditorClosing(TabDeckEditor *tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
#include "tab_deck_storage.h"
|
#include "tab_deck_storage.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../deck/deck_loader.h"
|
||||||
#include "deck_loader.h"
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../server/remote/remote_decklist_tree_widget.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
|
#include "../get_text_with_max.h"
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
#include "pb/command_deck_del.pb.h"
|
#include "pb/command_deck_del.pb.h"
|
||||||
#include "pb/command_deck_del_dir.pb.h"
|
#include "pb/command_deck_del_dir.pb.h"
|
||||||
@@ -11,12 +15,10 @@
|
|||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pb/response_deck_download.pb.h"
|
#include "pb/response_deck_download.pb.h"
|
||||||
#include "pb/response_deck_upload.pb.h"
|
#include "pb/response_deck_upload.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "remotedecklist_treewidget.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
#include <QFileSystemModel>
|
#include <QFileSystemModel>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@@ -127,6 +129,24 @@ void TabDeckStorage::retranslateUi()
|
|||||||
aDeleteRemoteDeck->setText(tr("Delete"));
|
aDeleteRemoteDeck->setText(tr("Delete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString TabDeckStorage::getTargetPath() const
|
||||||
|
{
|
||||||
|
RemoteDeckList_TreeModel::Node *curRight = serverDirView->getCurrentItem();
|
||||||
|
if (curRight == nullptr)
|
||||||
|
return {};
|
||||||
|
auto *dir = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight);
|
||||||
|
if (dir == nullptr) {
|
||||||
|
dir = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight->getParent());
|
||||||
|
if (dir != nullptr) {
|
||||||
|
return dir->getPath();
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return dir->getPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TabDeckStorage::actOpenLocalDeck()
|
void TabDeckStorage::actOpenLocalDeck()
|
||||||
{
|
{
|
||||||
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
||||||
@@ -146,35 +166,45 @@ void TabDeckStorage::actUpload()
|
|||||||
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
||||||
if (localDirModel->isDir(curLeft))
|
if (localDirModel->isDir(curLeft))
|
||||||
return;
|
return;
|
||||||
|
QString targetPath = getTargetPath();
|
||||||
|
if (targetPath.length() > MAX_NAME_LENGTH) {
|
||||||
|
qCritical() << "target path to upload to is too long" << targetPath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString filePath = localDirModel->filePath(curLeft);
|
QString filePath = localDirModel->filePath(curLeft);
|
||||||
QFile deckFile(filePath);
|
QFile deckFile(filePath);
|
||||||
QFileInfo deckFileInfo(deckFile);
|
QFileInfo deckFileInfo(deckFile);
|
||||||
|
|
||||||
|
QString deckString;
|
||||||
DeckLoader deck;
|
DeckLoader deck;
|
||||||
if (!deck.loadFromFile(filePath, DeckLoader::CockatriceFormat))
|
bool error = !deck.loadFromFile(filePath, DeckLoader::CockatriceFormat);
|
||||||
|
if (!error) {
|
||||||
|
deckString = deck.writeToString_Native();
|
||||||
|
error = deckString.length() > MAX_FILE_LENGTH;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Invalid deck file"));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (deck.getName().isEmpty()) {
|
if (deck.getName().isEmpty()) {
|
||||||
bool ok;
|
bool ok;
|
||||||
QString deckName = QInputDialog::getText(this, tr("Enter deck name"),
|
QString deckName =
|
||||||
tr("This decklist does not have a name.\nPlease enter a name:"),
|
getTextWithMax(this, tr("Enter deck name"), tr("This decklist does not have a name.\nPlease enter a name:"),
|
||||||
QLineEdit::Normal, deckFileInfo.completeBaseName(), &ok);
|
QLineEdit::Normal, deckFileInfo.completeBaseName(), &ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return;
|
return;
|
||||||
if (deckName.isEmpty())
|
if (deckName.isEmpty())
|
||||||
deckName = tr("Unnamed deck");
|
deckName = tr("Unnamed deck");
|
||||||
deck.setName(deckName);
|
deck.setName(deckName);
|
||||||
|
} else {
|
||||||
|
deck.setName(deck.getName().left(MAX_NAME_LENGTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString targetPath;
|
|
||||||
RemoteDeckList_TreeModel::Node *curRight = serverDirView->getCurrentItem();
|
|
||||||
if (!curRight)
|
|
||||||
return;
|
|
||||||
if (!dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight))
|
|
||||||
curRight = curRight->getParent();
|
|
||||||
targetPath = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight)->getPath();
|
|
||||||
|
|
||||||
Command_DeckUpload cmd;
|
Command_DeckUpload cmd;
|
||||||
cmd.set_path(targetPath.toStdString());
|
cmd.set_path(targetPath.toStdString());
|
||||||
cmd.set_deck_list(deck.writeToString_Native().toStdString());
|
cmd.set_deck_list(deckString.toStdString());
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
||||||
@@ -184,8 +214,11 @@ void TabDeckStorage::actUpload()
|
|||||||
|
|
||||||
void TabDeckStorage::uploadFinished(const Response &r, const CommandContainer &commandContainer)
|
void TabDeckStorage::uploadFinished(const Response &r, const CommandContainer &commandContainer)
|
||||||
{
|
{
|
||||||
if (r.response_code() != Response::RespOk)
|
if (r.response_code() != Response::RespOk) {
|
||||||
|
qCritical() << "failed to upload deck:" << r.response_code();
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to upload deck to server"));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const Response_DeckUpload &resp = r.GetExtension(Response_DeckUpload::ext);
|
const Response_DeckUpload &resp = r.GetExtension(Response_DeckUpload::ext);
|
||||||
const Command_DeckUpload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckUpload::ext);
|
const Command_DeckUpload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckUpload::ext);
|
||||||
@@ -282,7 +315,13 @@ void TabDeckStorage::downloadFinished(const Response &r,
|
|||||||
|
|
||||||
void TabDeckStorage::actNewFolder()
|
void TabDeckStorage::actNewFolder()
|
||||||
{
|
{
|
||||||
QString folderName = QInputDialog::getText(this, tr("New folder"), tr("Name of new folder:"));
|
QString targetPath = getTargetPath();
|
||||||
|
int max_length = MAX_NAME_LENGTH - targetPath.length() - 1; // generated length would be path + / + name
|
||||||
|
|
||||||
|
if (max_length < 1) // can't create path that's short enough
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString folderName = getTextWithMax(this, tr("New folder"), tr("Name of new folder:"), max_length);
|
||||||
if (folderName.isEmpty())
|
if (folderName.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -291,15 +330,6 @@ void TabDeckStorage::actNewFolder()
|
|||||||
std::string folder = folderName.toStdString();
|
std::string folder = folderName.toStdString();
|
||||||
std::replace(folder.begin(), folder.end(), '/', '-');
|
std::replace(folder.begin(), folder.end(), '/', '-');
|
||||||
|
|
||||||
QString targetPath;
|
|
||||||
RemoteDeckList_TreeModel::Node *curRight = serverDirView->getCurrentItem();
|
|
||||||
if (!curRight)
|
|
||||||
return;
|
|
||||||
if (!dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight))
|
|
||||||
curRight = curRight->getParent();
|
|
||||||
RemoteDeckList_TreeModel::DirectoryNode *dir = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight);
|
|
||||||
targetPath = dir->getPath();
|
|
||||||
|
|
||||||
Command_DeckNewDir cmd;
|
Command_DeckNewDir cmd;
|
||||||
cmd.set_path(targetPath.toStdString());
|
cmd.set_path(targetPath.toStdString());
|
||||||
cmd.set_dir_name(folder);
|
cmd.set_dir_name(folder);
|
||||||
@@ -328,15 +358,19 @@ void TabDeckStorage::actDeleteRemoteDeck()
|
|||||||
return;
|
return;
|
||||||
RemoteDeckList_TreeModel::DirectoryNode *dir = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight);
|
RemoteDeckList_TreeModel::DirectoryNode *dir = dynamic_cast<RemoteDeckList_TreeModel::DirectoryNode *>(curRight);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
QString path = dir->getPath();
|
QString targetPath = dir->getPath();
|
||||||
if (path.isEmpty())
|
if (targetPath.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
if (targetPath.length() > MAX_NAME_LENGTH) {
|
||||||
|
qCritical() << "target path to delete is too long" << targetPath;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (QMessageBox::warning(this, tr("Delete remote folder"),
|
if (QMessageBox::warning(this, tr("Delete remote folder"),
|
||||||
tr("Are you sure you want to delete \"%1\"?").arg(path),
|
tr("Are you sure you want to delete \"%1\"?").arg(targetPath),
|
||||||
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
||||||
return;
|
return;
|
||||||
Command_DeckDelDir cmd;
|
Command_DeckDelDir cmd;
|
||||||
cmd.set_path(path.toStdString());
|
cmd.set_path(targetPath.toStdString());
|
||||||
pend = client->prepareSessionCommand(cmd);
|
pend = client->prepareSessionCommand(cmd);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
||||||
SLOT(deleteFolderFinished(Response, CommandContainer)));
|
SLOT(deleteFolderFinished(Response, CommandContainer)));
|
||||||
@@ -27,6 +27,7 @@ private:
|
|||||||
QGroupBox *leftGroupBox, *rightGroupBox;
|
QGroupBox *leftGroupBox, *rightGroupBox;
|
||||||
|
|
||||||
QAction *aOpenLocalDeck, *aUpload, *aDeleteLocalDeck, *aOpenRemoteDeck, *aDownload, *aNewFolder, *aDeleteRemoteDeck;
|
QAction *aOpenLocalDeck, *aUpload, *aDeleteLocalDeck, *aOpenRemoteDeck, *aDownload, *aNewFolder, *aDeleteRemoteDeck;
|
||||||
|
QString getTargetPath() const;
|
||||||
private slots:
|
private slots:
|
||||||
void actOpenLocalDeck();
|
void actOpenLocalDeck();
|
||||||
|
|
||||||
@@ -1,21 +1,32 @@
|
|||||||
#include "tab_game.h"
|
#include "tab_game.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../client/ui/widgets/cards/card_info_frame_widget.h"
|
||||||
#include "arrowitem.h"
|
#include "../../deck/deck_loader.h"
|
||||||
#include "carddatabase.h"
|
#include "../../deck/deck_view.h"
|
||||||
#include "cardframe.h"
|
#include "../../dialogs/dlg_create_game.h"
|
||||||
#include "carditem.h"
|
#include "../../dialogs/dlg_load_remote_deck.h"
|
||||||
#include "deck_loader.h"
|
#include "../../dialogs/dlg_manage_sets.h"
|
||||||
#include "deckview.h"
|
#include "../../game/board/arrow_item.h"
|
||||||
#include "dlg_creategame.h"
|
#include "../../game/cards/card_database.h"
|
||||||
#include "dlg_load_remote_deck.h"
|
#include "../../game/cards/card_database_manager.h"
|
||||||
#include "dlg_manage_sets.h"
|
#include "../../game/cards/card_item.h"
|
||||||
#include "gamescene.h"
|
#include "../../game/game_scene.h"
|
||||||
#include "gameview.h"
|
#include "../../game/game_view.h"
|
||||||
|
#include "../../game/player/player.h"
|
||||||
|
#include "../../game/player/player_list_widget.h"
|
||||||
|
#include "../../game/zones/view_zone.h"
|
||||||
|
#include "../../game/zones/view_zone_widget.h"
|
||||||
|
#include "../../main.h"
|
||||||
|
#include "../../server/message_log_widget.h"
|
||||||
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
|
#include "../network/replay_timeline_widget.h"
|
||||||
|
#include "../ui/line_edit_completer.h"
|
||||||
|
#include "../ui/phases_toolbar.h"
|
||||||
|
#include "../ui/picture_loader.h"
|
||||||
|
#include "../ui/window_main.h"
|
||||||
#include "get_pb_extension.h"
|
#include "get_pb_extension.h"
|
||||||
#include "lineeditcompleter.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "messagelogwidget.h"
|
|
||||||
#include "pb/command_concede.pb.h"
|
#include "pb/command_concede.pb.h"
|
||||||
#include "pb/command_deck_select.pb.h"
|
#include "pb/command_deck_select.pb.h"
|
||||||
#include "pb/command_delete_arrow.pb.h"
|
#include "pb/command_delete_arrow.pb.h"
|
||||||
@@ -45,17 +56,8 @@
|
|||||||
#include "pb/game_event_container.pb.h"
|
#include "pb/game_event_container.pb.h"
|
||||||
#include "pb/game_replay.pb.h"
|
#include "pb/game_replay.pb.h"
|
||||||
#include "pb/response_deck_download.pb.h"
|
#include "pb/response_deck_download.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "phasestoolbar.h"
|
|
||||||
#include "pictureloader.h"
|
|
||||||
#include "player.h"
|
|
||||||
#include "playerlistwidget.h"
|
|
||||||
#include "replay_timeline_widget.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
#include "window_main.h"
|
#include "trice_limits.h"
|
||||||
#include "zoneviewwidget.h"
|
|
||||||
#include "zoneviewzone.h"
|
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
@@ -254,7 +256,25 @@ void TabGame::refreshShortcuts()
|
|||||||
aResetLayout->setShortcuts(shortcuts.getShortcut("Player/aResetLayout"));
|
aResetLayout->setShortcuts(shortcuts.getShortcut("Player/aResetLayout"));
|
||||||
}
|
}
|
||||||
if (aFocusChat) {
|
if (aFocusChat) {
|
||||||
aFocusChat->setShortcuts(shortcuts.getShortcut("tab_game/aFocusChat"));
|
aFocusChat->setShortcuts(shortcuts.getShortcut("Player/aFocusChat"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipForward) {
|
||||||
|
aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipBackward) {
|
||||||
|
aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipForwardBig) {
|
||||||
|
aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig"));
|
||||||
|
}
|
||||||
|
if (aReplaySkipBackwardBig) {
|
||||||
|
aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig"));
|
||||||
|
}
|
||||||
|
if (replayPlayButton) {
|
||||||
|
replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton"));
|
||||||
|
}
|
||||||
|
if (replayFastForwardButton) {
|
||||||
|
replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,14 +288,21 @@ void DeckViewContainer::loadLocalDeck()
|
|||||||
|
|
||||||
QString fileName = dialog.selectedFiles().at(0);
|
QString fileName = dialog.selectedFiles().at(0);
|
||||||
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
|
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
|
||||||
|
QString deckString;
|
||||||
DeckLoader deck;
|
DeckLoader deck;
|
||||||
if (!deck.loadFromFile(fileName, fmt)) {
|
|
||||||
|
bool error = !deck.loadFromFile(fileName, fmt);
|
||||||
|
if (!error) {
|
||||||
|
deckString = deck.writeToString_Native();
|
||||||
|
error = deckString.length() > MAX_FILE_LENGTH;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
QMessageBox::critical(this, tr("Error"), tr("The selected file could not be loaded."));
|
QMessageBox::critical(this, tr("Error"), tr("The selected file could not be loaded."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command_DeckSelect cmd;
|
Command_DeckSelect cmd;
|
||||||
cmd.set_deck(deck.writeToString_Native().toStdString());
|
cmd.set_deck(deckString.toStdString());
|
||||||
PendingCommand *pend = parentGame->prepareGameCommand(cmd);
|
PendingCommand *pend = parentGame->prepareGameCommand(cmd);
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
|
||||||
SLOT(deckSelectFinished(const Response &)));
|
SLOT(deckSelectFinished(const Response &)));
|
||||||
@@ -299,7 +326,8 @@ void DeckViewContainer::deckSelectFinished(const Response &r)
|
|||||||
{
|
{
|
||||||
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
|
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
|
||||||
DeckLoader newDeck(QString::fromStdString(resp.deck()));
|
DeckLoader newDeck(QString::fromStdString(resp.deck()));
|
||||||
PictureLoader::cacheCardPixmaps(db->getCards(newDeck.getCardList()));
|
// TODO CHANGE THIS TO BE SELECTED BY UUID
|
||||||
|
PictureLoader::cacheCardPixmaps(CardDatabaseManager::getInstance()->getCards(newDeck.getCardList()));
|
||||||
setDeck(newDeck);
|
setDeck(newDeck);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +442,9 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
|||||||
: Tab(_tabSupervisor), clients(_clients), gameInfo(event.game_info()), roomGameTypes(_roomGameTypes),
|
: Tab(_tabSupervisor), clients(_clients), gameInfo(event.game_info()), roomGameTypes(_roomGameTypes),
|
||||||
hostId(event.host_id()), localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()),
|
hostId(event.host_id()), localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()),
|
||||||
spectator(event.spectator()), judge(event.judge()), gameStateKnown(false), resuming(event.resuming()),
|
spectator(event.spectator()), judge(event.judge()), gameStateKnown(false), resuming(event.resuming()),
|
||||||
currentPhase(-1), activeCard(nullptr), gameClosed(false), replay(nullptr), replayDock(nullptr)
|
currentPhase(-1), activeCard(nullptr), gameClosed(false), replay(nullptr), replayPlayButton(nullptr),
|
||||||
|
replayFastForwardButton(nullptr), aReplaySkipForward(nullptr), aReplaySkipBackward(nullptr),
|
||||||
|
aReplaySkipForwardBig(nullptr), aReplaySkipBackwardBig(nullptr), replayDock(nullptr)
|
||||||
{
|
{
|
||||||
// THIS CTOR IS USED ON GAMES
|
// THIS CTOR IS USED ON GAMES
|
||||||
gameInfo.set_started(false);
|
gameInfo.set_started(false);
|
||||||
@@ -568,7 +598,7 @@ void TabGame::retranslateUi()
|
|||||||
|
|
||||||
aResetLayout->setText(tr("Reset layout"));
|
aResetLayout->setText(tr("Reset layout"));
|
||||||
|
|
||||||
cardInfo->retranslateUi();
|
cardInfoFrameWidget->retranslateUi();
|
||||||
|
|
||||||
QMapIterator<int, Player *> i(players);
|
QMapIterator<int, Player *> i(players);
|
||||||
while (i.hasNext())
|
while (i.hasNext())
|
||||||
@@ -585,39 +615,40 @@ void TabGame::closeRequest()
|
|||||||
actLeaveGame();
|
actLeaveGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayNextEvent()
|
void TabGame::replayNextEvent(Player::EventProcessingOptions options)
|
||||||
{
|
{
|
||||||
processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), nullptr);
|
processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), nullptr, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayFinished()
|
void TabGame::replayFinished()
|
||||||
{
|
{
|
||||||
replayStartButton->setEnabled(true);
|
replayPlayButton->setChecked(false);
|
||||||
replayPauseButton->setEnabled(false);
|
|
||||||
replayFastForwardButton->setEnabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayStartButtonClicked()
|
void TabGame::replayPlayButtonToggled(bool checked)
|
||||||
{
|
{
|
||||||
replayStartButton->setEnabled(false);
|
if (checked) { // start replay
|
||||||
replayPauseButton->setEnabled(true);
|
timelineWidget->startReplay();
|
||||||
replayFastForwardButton->setEnabled(true);
|
} else { // pause replay
|
||||||
|
timelineWidget->stopReplay();
|
||||||
timelineWidget->startReplay();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void TabGame::replayPauseButtonClicked()
|
|
||||||
{
|
|
||||||
replayStartButton->setEnabled(true);
|
|
||||||
replayPauseButton->setEnabled(false);
|
|
||||||
replayFastForwardButton->setEnabled(false);
|
|
||||||
|
|
||||||
timelineWidget->stopReplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayFastForwardButtonToggled(bool checked)
|
void TabGame::replayFastForwardButtonToggled(bool checked)
|
||||||
{
|
{
|
||||||
timelineWidget->setTimeScaleFactor(checked ? 10.0 : 1.0);
|
timelineWidget->setTimeScaleFactor(checked ? ReplayTimelineWidget::FAST_FORWARD_SCALE_FACTOR : 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles everything that needs to be reset when doing a replay rewind.
|
||||||
|
*/
|
||||||
|
void TabGame::replayRewind()
|
||||||
|
{
|
||||||
|
// reset chat log
|
||||||
|
messageLog->clearChat();
|
||||||
|
|
||||||
|
// reset phase markers
|
||||||
|
setActivePhase(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::incrementGameTime()
|
void TabGame::incrementGameTime()
|
||||||
@@ -831,7 +862,9 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
|
|||||||
return newPlayer;
|
return newPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::processGameEventContainer(const GameEventContainer &cont, AbstractClient *client)
|
void TabGame::processGameEventContainer(const GameEventContainer &cont,
|
||||||
|
AbstractClient *client,
|
||||||
|
Player::EventProcessingOptions options)
|
||||||
{
|
{
|
||||||
const GameEventContext &context = cont.context();
|
const GameEventContext &context = cont.context();
|
||||||
messageLog->containerProcessingStarted(context);
|
messageLog->containerProcessingStarted(context);
|
||||||
@@ -906,7 +939,7 @@ void TabGame::processGameEventContainer(const GameEventContainer &cont, Abstract
|
|||||||
qDebug() << "unhandled game event: invalid player id";
|
qDebug() << "unhandled game event: invalid player id";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
player->processGameEvent(eventType, event, context);
|
player->processGameEvent(eventType, event, context, options);
|
||||||
emitUserEvent();
|
emitUserEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -978,7 +1011,7 @@ PendingCommand *TabGame::prepareGameCommand(const QList<const ::google::protobuf
|
|||||||
return new PendingCommand(cont);
|
return new PendingCommand(cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::startGame(bool resuming)
|
void TabGame::startGame(bool _resuming)
|
||||||
{
|
{
|
||||||
currentPhase = -1;
|
currentPhase = -1;
|
||||||
|
|
||||||
@@ -991,7 +1024,7 @@ void TabGame::startGame(bool resuming)
|
|||||||
|
|
||||||
mainWidget->setCurrentWidget(gamePlayAreaWidget);
|
mainWidget->setCurrentWidget(gamePlayAreaWidget);
|
||||||
|
|
||||||
if (!resuming) {
|
if (!_resuming) {
|
||||||
QMapIterator<int, Player *> playerIterator(players);
|
QMapIterator<int, Player *> playerIterator(players);
|
||||||
while (playerIterator.hasNext())
|
while (playerIterator.hasNext())
|
||||||
playerIterator.next().value()->setGameStarted();
|
playerIterator.next().value()->setGameStarted();
|
||||||
@@ -1079,7 +1112,8 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event,
|
|||||||
DeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
|
DeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
|
||||||
if (playerInfo.has_deck_list()) {
|
if (playerInfo.has_deck_list()) {
|
||||||
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
|
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
|
||||||
PictureLoader::cacheCardPixmaps(db->getCards(newDeck.getCardList()));
|
PictureLoader::cacheCardPixmaps(
|
||||||
|
CardDatabaseManager::getInstance()->getCards(newDeck.getCardList()));
|
||||||
deckViewContainer->setDeck(newDeck);
|
deckViewContainer->setDeck(newDeck);
|
||||||
player->setDeck(newDeck);
|
player->setDeck(newDeck);
|
||||||
}
|
}
|
||||||
@@ -1346,7 +1380,7 @@ void TabGame::eventSetActivePhase(const Event_SetActivePhase &event,
|
|||||||
|
|
||||||
void TabGame::newCardAdded(AbstractCardItem *card)
|
void TabGame::newCardAdded(AbstractCardItem *card)
|
||||||
{
|
{
|
||||||
connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *)));
|
connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfoFrameWidget, SLOT(setCard(AbstractCardItem *)));
|
||||||
connect(card, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
connect(card, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
||||||
connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
||||||
connect(card, SIGNAL(cardShiftClicked(QString)), this, SLOT(linkCardToChat(QString)));
|
connect(card, SIGNAL(cardShiftClicked(QString)), this, SLOT(linkCardToChat(QString)));
|
||||||
@@ -1696,32 +1730,55 @@ void TabGame::createPlayAreaWidget(bool bReplay)
|
|||||||
|
|
||||||
void TabGame::createReplayDock()
|
void TabGame::createReplayDock()
|
||||||
{
|
{
|
||||||
|
// timeline widget
|
||||||
timelineWidget = new ReplayTimelineWidget;
|
timelineWidget = new ReplayTimelineWidget;
|
||||||
timelineWidget->setTimeline(replayTimeline);
|
timelineWidget->setTimeline(replayTimeline);
|
||||||
connect(timelineWidget, SIGNAL(processNextEvent()), this, SLOT(replayNextEvent()));
|
connect(timelineWidget, SIGNAL(processNextEvent(Player::EventProcessingOptions)), this,
|
||||||
|
SLOT(replayNextEvent(Player::EventProcessingOptions)));
|
||||||
connect(timelineWidget, SIGNAL(replayFinished()), this, SLOT(replayFinished()));
|
connect(timelineWidget, SIGNAL(replayFinished()), this, SLOT(replayFinished()));
|
||||||
connect(timelineWidget, &ReplayTimelineWidget::rewound, messageLog, &ChatView::clearChat);
|
connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &TabGame::replayRewind);
|
||||||
|
|
||||||
|
// timeline skip shortcuts
|
||||||
|
aReplaySkipForward = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipForward);
|
||||||
|
connect(aReplaySkipForward, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipBackward = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipBackward);
|
||||||
|
connect(aReplaySkipBackward, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipForwardBig = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipForwardBig);
|
||||||
|
connect(aReplaySkipForwardBig, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||||
|
|
||||||
|
aReplaySkipBackwardBig = new QAction(timelineWidget);
|
||||||
|
timelineWidget->addAction(aReplaySkipBackwardBig);
|
||||||
|
connect(aReplaySkipBackwardBig, &QAction::triggered, this,
|
||||||
|
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
replayPlayButton = new QToolButton;
|
||||||
|
replayPlayButton->setIconSize(QSize(32, 32));
|
||||||
|
QIcon playButtonIcon = QIcon();
|
||||||
|
playButtonIcon.addPixmap(QPixmap("theme:replay/start"), QIcon::Normal, QIcon::Off);
|
||||||
|
playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On);
|
||||||
|
replayPlayButton->setIcon(playButtonIcon);
|
||||||
|
replayPlayButton->setCheckable(true);
|
||||||
|
connect(replayPlayButton, SIGNAL(toggled(bool)), this, SLOT(replayPlayButtonToggled(bool)));
|
||||||
|
|
||||||
replayStartButton = new QToolButton;
|
|
||||||
replayStartButton->setIconSize(QSize(32, 32));
|
|
||||||
replayStartButton->setIcon(QPixmap("theme:replay/start"));
|
|
||||||
connect(replayStartButton, SIGNAL(clicked()), this, SLOT(replayStartButtonClicked()));
|
|
||||||
replayPauseButton = new QToolButton;
|
|
||||||
replayPauseButton->setIconSize(QSize(32, 32));
|
|
||||||
replayPauseButton->setEnabled(false);
|
|
||||||
replayPauseButton->setIcon(QPixmap("theme:replay/pause"));
|
|
||||||
connect(replayPauseButton, SIGNAL(clicked()), this, SLOT(replayPauseButtonClicked()));
|
|
||||||
replayFastForwardButton = new QToolButton;
|
replayFastForwardButton = new QToolButton;
|
||||||
replayFastForwardButton->setIconSize(QSize(32, 32));
|
replayFastForwardButton->setIconSize(QSize(32, 32));
|
||||||
replayFastForwardButton->setEnabled(false);
|
|
||||||
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
|
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
|
||||||
replayFastForwardButton->setCheckable(true);
|
replayFastForwardButton->setCheckable(true);
|
||||||
connect(replayFastForwardButton, SIGNAL(toggled(bool)), this, SLOT(replayFastForwardButtonToggled(bool)));
|
connect(replayFastForwardButton, SIGNAL(toggled(bool)), this, SLOT(replayFastForwardButtonToggled(bool)));
|
||||||
|
|
||||||
|
// putting everything together
|
||||||
replayControlLayout = new QHBoxLayout;
|
replayControlLayout = new QHBoxLayout;
|
||||||
replayControlLayout->addWidget(timelineWidget, 10);
|
replayControlLayout->addWidget(timelineWidget, 10);
|
||||||
replayControlLayout->addWidget(replayStartButton);
|
replayControlLayout->addWidget(replayPlayButton);
|
||||||
replayControlLayout->addWidget(replayPauseButton);
|
|
||||||
replayControlLayout->addWidget(replayFastForwardButton);
|
replayControlLayout->addWidget(replayFastForwardButton);
|
||||||
|
|
||||||
replayControlWidget = new QWidget();
|
replayControlWidget = new QWidget();
|
||||||
@@ -1750,20 +1807,20 @@ void TabGame::createDeckViewContainerWidget(bool bReplay)
|
|||||||
deckViewContainerWidget->setLayout(deckViewContainerLayout);
|
deckViewContainerWidget->setLayout(deckViewContainerLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::viewCardInfo(const QString &cardName)
|
void TabGame::viewCardInfo(const QString &cardName, const QString &providerId) const
|
||||||
{
|
{
|
||||||
cardInfo->setCard(cardName);
|
cardInfoFrameWidget->setCard(cardName, providerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::createCardInfoDock(bool bReplay)
|
void TabGame::createCardInfoDock(bool bReplay)
|
||||||
{
|
{
|
||||||
Q_UNUSED(bReplay);
|
Q_UNUSED(bReplay);
|
||||||
|
|
||||||
cardInfo = new CardFrame();
|
cardInfoFrameWidget = new CardInfoFrameWidget();
|
||||||
cardHInfoLayout = new QHBoxLayout;
|
cardHInfoLayout = new QHBoxLayout;
|
||||||
cardVInfoLayout = new QVBoxLayout;
|
cardVInfoLayout = new QVBoxLayout;
|
||||||
cardVInfoLayout->setContentsMargins(0, 0, 0, 0);
|
cardVInfoLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
cardVInfoLayout->addWidget(cardInfo);
|
cardVInfoLayout->addWidget(cardInfoFrameWidget);
|
||||||
cardVInfoLayout->addLayout(cardHInfoLayout);
|
cardVInfoLayout->addLayout(cardHInfoLayout);
|
||||||
|
|
||||||
cardBoxLayoutWidget = new QWidget;
|
cardBoxLayoutWidget = new QWidget;
|
||||||
@@ -1805,7 +1862,7 @@ void TabGame::createPlayerListDock(bool bReplay)
|
|||||||
void TabGame::createMessageDock(bool bReplay)
|
void TabGame::createMessageDock(bool bReplay)
|
||||||
{
|
{
|
||||||
messageLog = new MessageLogWidget(tabSupervisor, tabSupervisor, this);
|
messageLog = new MessageLogWidget(tabSupervisor, tabSupervisor, this);
|
||||||
connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfo, SLOT(setCard(QString)));
|
connect(messageLog, SIGNAL(cardNameHovered(QString)), cardInfoFrameWidget, SLOT(setCard(QString)));
|
||||||
connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
connect(messageLog, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
||||||
connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
connect(messageLog, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
||||||
|
|
||||||
@@ -1823,6 +1880,7 @@ void TabGame::createMessageDock(bool bReplay)
|
|||||||
|
|
||||||
sayLabel = new QLabel;
|
sayLabel = new QLabel;
|
||||||
sayEdit = new LineEditCompleter;
|
sayEdit = new LineEditCompleter;
|
||||||
|
sayEdit->setMaxLength(MAX_TEXT_LENGTH);
|
||||||
sayLabel->setBuddy(sayEdit);
|
sayLabel->setBuddy(sayEdit);
|
||||||
completer = new QCompleter(autocompleteUserList, sayEdit);
|
completer = new QCompleter(autocompleteUserList, sayEdit);
|
||||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
#ifndef TAB_GAME_H
|
#ifndef TAB_GAME_H
|
||||||
#define TAB_GAME_H
|
#define TAB_GAME_H
|
||||||
|
|
||||||
|
#include "../../client/tearoff_menu.h"
|
||||||
|
#include "../../game/player/player.h"
|
||||||
#include "pb/event_leave.pb.h"
|
#include "pb/event_leave.pb.h"
|
||||||
#include "pb/serverinfo_game.pb.h"
|
#include "pb/serverinfo_game.pb.h"
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
#include "tearoffmenu.h"
|
|
||||||
|
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@@ -15,7 +16,7 @@ class CardDatabase;
|
|||||||
class GameView;
|
class GameView;
|
||||||
class DeckView;
|
class DeckView;
|
||||||
class GameScene;
|
class GameScene;
|
||||||
class CardFrame;
|
class CardInfoFrameWidget;
|
||||||
class MessageLogWidget;
|
class MessageLogWidget;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
@@ -47,7 +48,6 @@ class Event_Ping;
|
|||||||
class Event_GameSay;
|
class Event_GameSay;
|
||||||
class Event_Kicked;
|
class Event_Kicked;
|
||||||
class Event_ReverseTurn;
|
class Event_ReverseTurn;
|
||||||
class Player;
|
|
||||||
class CardZone;
|
class CardZone;
|
||||||
class AbstractCardItem;
|
class AbstractCardItem;
|
||||||
class CardItem;
|
class CardItem;
|
||||||
@@ -146,9 +146,10 @@ private:
|
|||||||
int currentReplayStep;
|
int currentReplayStep;
|
||||||
QList<int> replayTimeline;
|
QList<int> replayTimeline;
|
||||||
ReplayTimelineWidget *timelineWidget;
|
ReplayTimelineWidget *timelineWidget;
|
||||||
QToolButton *replayStartButton, *replayPauseButton, *replayFastForwardButton;
|
QToolButton *replayPlayButton, *replayFastForwardButton;
|
||||||
|
QAction *aReplaySkipForward, *aReplaySkipBackward, *aReplaySkipForwardBig, *aReplaySkipBackwardBig;
|
||||||
|
|
||||||
CardFrame *cardInfo;
|
CardInfoFrameWidget *cardInfoFrameWidget;
|
||||||
PlayerListWidget *playerListWidget;
|
PlayerListWidget *playerListWidget;
|
||||||
QLabel *timeElapsedLabel;
|
QLabel *timeElapsedLabel;
|
||||||
MessageLogWidget *messageLog;
|
MessageLogWidget *messageLog;
|
||||||
@@ -218,11 +219,11 @@ signals:
|
|||||||
void openDeckEditor(const DeckLoader *deck);
|
void openDeckEditor(const DeckLoader *deck);
|
||||||
void notIdle();
|
void notIdle();
|
||||||
private slots:
|
private slots:
|
||||||
void replayNextEvent();
|
void replayNextEvent(Player::EventProcessingOptions options);
|
||||||
void replayFinished();
|
void replayFinished();
|
||||||
void replayStartButtonClicked();
|
void replayPlayButtonToggled(bool checked);
|
||||||
void replayPauseButtonClicked();
|
|
||||||
void replayFastForwardButtonToggled(bool checked);
|
void replayFastForwardButtonToggled(bool checked);
|
||||||
|
void replayRewind();
|
||||||
|
|
||||||
void incrementGameTime();
|
void incrementGameTime();
|
||||||
void adminLockChanged(bool lock);
|
void adminLockChanged(bool lock);
|
||||||
@@ -304,13 +305,15 @@ public:
|
|||||||
return activeCard;
|
return activeCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processGameEventContainer(const GameEventContainer &cont, AbstractClient *client);
|
void processGameEventContainer(const GameEventContainer &cont,
|
||||||
|
AbstractClient *client,
|
||||||
|
Player::EventProcessingOptions options);
|
||||||
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
|
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
|
||||||
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
|
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
|
||||||
public slots:
|
public slots:
|
||||||
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
||||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
||||||
void viewCardInfo(const QString &cardName);
|
void viewCardInfo(const QString &cardName, const QString &providerId = "") const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "tab_logs.h"
|
#include "tab_logs.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../deck/custom_line_edit.h"
|
||||||
#include "customlineedit.h"
|
#include "../../dialogs/dlg_manage_sets.h"
|
||||||
#include "dlg_manage_sets.h"
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
#include "pb/moderator_commands.pb.h"
|
#include "pb/moderator_commands.pb.h"
|
||||||
#include "pb/response_viewlog_history.pb.h"
|
#include "pb/response_viewlog_history.pb.h"
|
||||||
#include "pending_command.h"
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
@@ -88,7 +89,7 @@ void TabLog::getClicked()
|
|||||||
if (maximumResults->value() == 0)
|
if (maximumResults->value() == 0)
|
||||||
maximumResults->setValue(1000);
|
maximumResults->setValue(1000);
|
||||||
|
|
||||||
int dateRange;
|
int dateRange = 0;
|
||||||
if (lastHour->isChecked())
|
if (lastHour->isChecked())
|
||||||
dateRange = 1;
|
dateRange = 1;
|
||||||
|
|
||||||
@@ -146,21 +147,25 @@ void TabLog::clearClicked()
|
|||||||
|
|
||||||
void TabLog::createDock()
|
void TabLog::createDock()
|
||||||
{
|
{
|
||||||
|
|
||||||
labelFindUserName = new QLabel(tr("Username: "));
|
labelFindUserName = new QLabel(tr("Username: "));
|
||||||
findUsername = new LineEditUnfocusable("");
|
findUsername = new LineEditUnfocusable("");
|
||||||
|
findUsername->setMaxLength(MAX_NAME_LENGTH);
|
||||||
findUsername->setAlignment(Qt::AlignCenter);
|
findUsername->setAlignment(Qt::AlignCenter);
|
||||||
labelFindIPAddress = new QLabel(tr("IP Address: "));
|
labelFindIPAddress = new QLabel(tr("IP Address: "));
|
||||||
findIPAddress = new LineEditUnfocusable("");
|
findIPAddress = new LineEditUnfocusable("");
|
||||||
|
findIPAddress->setMaxLength(MAX_NAME_LENGTH);
|
||||||
findIPAddress->setAlignment(Qt::AlignCenter);
|
findIPAddress->setAlignment(Qt::AlignCenter);
|
||||||
labelFindGameName = new QLabel(tr("Game Name: "));
|
labelFindGameName = new QLabel(tr("Game Name: "));
|
||||||
findGameName = new LineEditUnfocusable("");
|
findGameName = new LineEditUnfocusable("");
|
||||||
|
findGameName->setMaxLength(MAX_NAME_LENGTH);
|
||||||
findGameName->setAlignment(Qt::AlignCenter);
|
findGameName->setAlignment(Qt::AlignCenter);
|
||||||
labelFindGameID = new QLabel(tr("GameID: "));
|
labelFindGameID = new QLabel(tr("GameID: "));
|
||||||
findGameID = new LineEditUnfocusable("");
|
findGameID = new LineEditUnfocusable("");
|
||||||
|
findGameID->setMaxLength(MAX_NAME_LENGTH);
|
||||||
findGameID->setAlignment(Qt::AlignCenter);
|
findGameID->setAlignment(Qt::AlignCenter);
|
||||||
labelMessage = new QLabel(tr("Message: "));
|
labelMessage = new QLabel(tr("Message: "));
|
||||||
findMessage = new LineEditUnfocusable("");
|
findMessage = new LineEditUnfocusable("");
|
||||||
|
findMessage->setMaxLength(MAX_TEXT_LENGTH);
|
||||||
findMessage->setAlignment(Qt::AlignCenter);
|
findMessage->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
mainRoom = new QCheckBox(tr("Main Room"));
|
mainRoom = new QCheckBox(tr("Main Room"));
|
||||||
@@ -202,7 +207,8 @@ void TabLog::createDock()
|
|||||||
|
|
||||||
criteriaGroupBox = new QGroupBox(tr("Filters"));
|
criteriaGroupBox = new QGroupBox(tr("Filters"));
|
||||||
criteriaGroupBox->setLayout(criteriaGrid);
|
criteriaGroupBox->setLayout(criteriaGrid);
|
||||||
criteriaGroupBox->setFixedSize(500, 300);
|
criteriaGroupBox->setMaximumSize(500, 300);
|
||||||
|
criteriaGroupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
|
||||||
locationGrid = new QGridLayout;
|
locationGrid = new QGridLayout;
|
||||||
locationGrid->addWidget(mainRoom, 0, 0);
|
locationGrid->addWidget(mainRoom, 0, 0);
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
#include "tab_message.h"
|
#include "tab_message.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../deck/custom_line_edit.h"
|
||||||
#include "chatview/chatview.h"
|
#include "../../main.h"
|
||||||
#include "customlineedit.h"
|
#include "../../server/chat_view/chat_view.h"
|
||||||
#include "main.h"
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
|
#include "../sound_engine.h"
|
||||||
#include "pb/event_user_message.pb.h"
|
#include "pb/event_user_message.pb.h"
|
||||||
#include "pb/serverinfo_user.pb.h"
|
#include "pb/serverinfo_user.pb.h"
|
||||||
#include "pb/session_commands.pb.h"
|
#include "pb/session_commands.pb.h"
|
||||||
#include "pending_command.h"
|
#include "trice_limits.h"
|
||||||
#include "settingscache.h"
|
|
||||||
#include "soundengine.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -29,6 +30,7 @@ TabMessage::TabMessage(TabSupervisor *_tabSupervisor,
|
|||||||
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
connect(chatView, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString)));
|
||||||
connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString)));
|
connect(chatView, SIGNAL(addMentionTag(QString)), this, SLOT(addMentionTag(QString)));
|
||||||
sayEdit = new LineEditUnfocusable;
|
sayEdit = new LineEditUnfocusable;
|
||||||
|
sayEdit->setMaxLength(MAX_TEXT_LENGTH);
|
||||||
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
|
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
|
||||||
|
|
||||||
QVBoxLayout *vbox = new QVBoxLayout;
|
QVBoxLayout *vbox = new QVBoxLayout;
|
||||||
@@ -157,7 +159,7 @@ void TabMessage::showSystemPopup(const Event_UserMessage &event)
|
|||||||
void TabMessage::messageClicked()
|
void TabMessage::messageClicked()
|
||||||
{
|
{
|
||||||
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
|
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
|
||||||
QApplication::setActiveWindow(this);
|
activateWindow();
|
||||||
emit maximizeClient();
|
emit maximizeClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "tab_replays.h"
|
#include "tab_replays.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../server/remote/remote_replay_list_tree_widget.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../game_logic/abstract_client.h"
|
||||||
#include "pb/command_replay_delete_match.pb.h"
|
#include "pb/command_replay_delete_match.pb.h"
|
||||||
#include "pb/command_replay_download.pb.h"
|
#include "pb/command_replay_download.pb.h"
|
||||||
#include "pb/command_replay_modify_match.pb.h"
|
#include "pb/command_replay_modify_match.pb.h"
|
||||||
@@ -8,9 +11,6 @@
|
|||||||
#include "pb/game_replay.pb.h"
|
#include "pb/game_replay.pb.h"
|
||||||
#include "pb/response.pb.h"
|
#include "pb/response.pb.h"
|
||||||
#include "pb/response_replay_download.pb.h"
|
#include "pb/response_replay_download.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "remotereplaylist_treewidget.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include "tab_game.h"
|
#include "tab_game.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@@ -134,11 +134,11 @@ void TabReplays::actOpenLocalReplay()
|
|||||||
QFile f(filePath);
|
QFile f(filePath);
|
||||||
if (!f.open(QIODevice::ReadOnly))
|
if (!f.open(QIODevice::ReadOnly))
|
||||||
return;
|
return;
|
||||||
QByteArray data = f.readAll();
|
QByteArray _data = f.readAll();
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
GameReplay *replay = new GameReplay;
|
GameReplay *replay = new GameReplay;
|
||||||
replay->ParseFromArray(data.data(), data.size());
|
replay->ParseFromArray(_data.data(), _data.size());
|
||||||
|
|
||||||
emit openReplay(replay);
|
emit openReplay(replay);
|
||||||
}
|
}
|
||||||
@@ -146,6 +146,9 @@ void TabReplays::actOpenLocalReplay()
|
|||||||
void TabReplays::actDeleteLocalReplay()
|
void TabReplays::actDeleteLocalReplay()
|
||||||
{
|
{
|
||||||
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
QModelIndex curLeft = localDirView->selectionModel()->currentIndex();
|
||||||
|
if (!curLeft.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
if (QMessageBox::warning(this, tr("Delete local file"),
|
if (QMessageBox::warning(this, tr("Delete local file"),
|
||||||
tr("Are you sure you want to delete \"%1\"?").arg(localDirModel->fileName(curLeft)),
|
tr("Are you sure you want to delete \"%1\"?").arg(localDirModel->fileName(curLeft)),
|
||||||
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
||||||
@@ -223,10 +226,10 @@ void TabReplays::downloadFinished(const Response &r,
|
|||||||
const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
|
const Response_ReplayDownload &resp = r.GetExtension(Response_ReplayDownload::ext);
|
||||||
QString filePath = extraData.toString();
|
QString filePath = extraData.toString();
|
||||||
|
|
||||||
const std::string &data = resp.replay_data();
|
const std::string &_data = resp.replay_data();
|
||||||
QFile f(filePath);
|
QFile f(filePath);
|
||||||
f.open(QIODevice::WriteOnly);
|
f.open(QIODevice::WriteOnly);
|
||||||
f.write((const char *)data.data(), data.size());
|
f.write((const char *)_data.data(), _data.size());
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
#include "tab_room.h"
|
#include "tab_room.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../client/game_logic/abstract_client.h"
|
||||||
#include "chatview/chatview.h"
|
#include "../../dialogs/dlg_settings.h"
|
||||||
#include "dlg_settings.h"
|
#include "../../game/game_selector.h"
|
||||||
#include "gameselector.h"
|
#include "../../main.h"
|
||||||
|
#include "../../server/chat_view/chat_view.h"
|
||||||
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../server/user/user_list.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
#include "get_pb_extension.h"
|
#include "get_pb_extension.h"
|
||||||
#include "main.h"
|
|
||||||
#include "pb/event_join_room.pb.h"
|
#include "pb/event_join_room.pb.h"
|
||||||
#include "pb/event_leave_room.pb.h"
|
#include "pb/event_leave_room.pb.h"
|
||||||
#include "pb/event_list_games.pb.h"
|
#include "pb/event_list_games.pb.h"
|
||||||
@@ -13,11 +16,9 @@
|
|||||||
#include "pb/event_room_say.pb.h"
|
#include "pb/event_room_say.pb.h"
|
||||||
#include "pb/room_commands.pb.h"
|
#include "pb/room_commands.pb.h"
|
||||||
#include "pb/serverinfo_room.pb.h"
|
#include "pb/serverinfo_room.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include "tab_account.h"
|
#include "tab_account.h"
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
#include "userlist.h"
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
@@ -51,7 +52,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
|
|||||||
SIGNAL(openMessageDialog(const QString &, bool)));
|
SIGNAL(openMessageDialog(const QString &, bool)));
|
||||||
|
|
||||||
chatView = new ChatView(tabSupervisor, tabSupervisor, nullptr, true, this);
|
chatView = new ChatView(tabSupervisor, tabSupervisor, nullptr, true, this);
|
||||||
connect(chatView, SIGNAL(showMentionPopup(QString &)), this, SLOT(actShowMentionPopup(QString &)));
|
connect(chatView, SIGNAL(showMentionPopup(const QString &)), this, SLOT(actShowMentionPopup(const QString &)));
|
||||||
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab()));
|
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab()));
|
||||||
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
||||||
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
||||||
@@ -60,6 +61,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
|
|||||||
connect(&SettingsCache::instance(), SIGNAL(chatMentionCompleterChanged()), this, SLOT(actCompleterChanged()));
|
connect(&SettingsCache::instance(), SIGNAL(chatMentionCompleterChanged()), this, SLOT(actCompleterChanged()));
|
||||||
sayLabel = new QLabel;
|
sayLabel = new QLabel;
|
||||||
sayEdit = new LineEditCompleter;
|
sayEdit = new LineEditCompleter;
|
||||||
|
sayEdit->setMaxLength(MAX_TEXT_LENGTH);
|
||||||
sayLabel->setBuddy(sayEdit);
|
sayLabel->setBuddy(sayEdit);
|
||||||
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
|
connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(sendMessage()));
|
||||||
|
|
||||||
@@ -153,12 +155,12 @@ void TabRoom::retranslateUi()
|
|||||||
|
|
||||||
void TabRoom::focusTab()
|
void TabRoom::focusTab()
|
||||||
{
|
{
|
||||||
QApplication::setActiveWindow(this);
|
activateWindow();
|
||||||
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
|
tabSupervisor->setCurrentIndex(tabSupervisor->indexOf(this));
|
||||||
emit maximizeClient();
|
emit maximizeClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabRoom::actShowMentionPopup(QString &sender)
|
void TabRoom::actShowMentionPopup(const QString &sender)
|
||||||
{
|
{
|
||||||
this->actShowPopup(sender + tr(" mentioned you."));
|
this->actShowPopup(sender + tr(" mentioned you."));
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef TAB_ROOM_H
|
#ifndef TAB_ROOM_H
|
||||||
#define TAB_ROOM_H
|
#define TAB_ROOM_H
|
||||||
|
|
||||||
#include "lineeditcompleter.h"
|
#include "../ui/line_edit_completer.h"
|
||||||
#include "tab.h"
|
#include "tab.h"
|
||||||
|
|
||||||
#include <QFocusEvent>
|
#include <QFocusEvent>
|
||||||
@@ -75,7 +75,7 @@ private slots:
|
|||||||
void actOpenChatSettings();
|
void actOpenChatSettings();
|
||||||
void addMentionTag(QString mentionTag);
|
void addMentionTag(QString mentionTag);
|
||||||
void focusTab();
|
void focusTab();
|
||||||
void actShowMentionPopup(QString &sender);
|
void actShowMentionPopup(const QString &sender);
|
||||||
void actShowPopup(const QString &message);
|
void actShowPopup(const QString &message);
|
||||||
void actCompleterChanged();
|
void actCompleterChanged();
|
||||||
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
#include "tab_server.h"
|
#include "tab_server.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../client/game_logic/abstract_client.h"
|
||||||
|
#include "../../server/pending_command.h"
|
||||||
|
#include "../../server/user/user_list.h"
|
||||||
#include "pb/event_list_rooms.pb.h"
|
#include "pb/event_list_rooms.pb.h"
|
||||||
#include "pb/event_server_message.pb.h"
|
#include "pb/event_server_message.pb.h"
|
||||||
#include "pb/response_join_room.pb.h"
|
#include "pb/response_join_room.pb.h"
|
||||||
#include "pb/session_commands.pb.h"
|
#include "pb/session_commands.pb.h"
|
||||||
#include "pending_command.h"
|
|
||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
#include "userlist.h"
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "tab_supervisor.h"
|
#include "tab_supervisor.h"
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "../../client/game_logic/abstract_client.h"
|
||||||
#include "main.h"
|
#include "../../main.h"
|
||||||
|
#include "../../server/user/user_list.h"
|
||||||
|
#include "../../settings/cache_settings.h"
|
||||||
|
#include "../ui/pixel_map_generator.h"
|
||||||
#include "pb/event_game_joined.pb.h"
|
#include "pb/event_game_joined.pb.h"
|
||||||
#include "pb/event_notify_user.pb.h"
|
#include "pb/event_notify_user.pb.h"
|
||||||
#include "pb/event_user_message.pb.h"
|
#include "pb/event_user_message.pb.h"
|
||||||
@@ -11,8 +14,6 @@
|
|||||||
#include "pb/room_event.pb.h"
|
#include "pb/room_event.pb.h"
|
||||||
#include "pb/serverinfo_room.pb.h"
|
#include "pb/serverinfo_room.pb.h"
|
||||||
#include "pb/serverinfo_user.pb.h"
|
#include "pb/serverinfo_user.pb.h"
|
||||||
#include "pixmapgenerator.h"
|
|
||||||
#include "settingscache.h"
|
|
||||||
#include "tab_account.h"
|
#include "tab_account.h"
|
||||||
#include "tab_admin.h"
|
#include "tab_admin.h"
|
||||||
#include "tab_deck_editor.h"
|
#include "tab_deck_editor.h"
|
||||||
@@ -23,7 +24,6 @@
|
|||||||
#include "tab_replays.h"
|
#include "tab_replays.h"
|
||||||
#include "tab_room.h"
|
#include "tab_room.h"
|
||||||
#include "tab_server.h"
|
#include "tab_server.h"
|
||||||
#include "userlist.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -58,7 +58,11 @@ QSize CloseButton::sizeHint() const
|
|||||||
return QSize(width, height);
|
return QSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void CloseButton::enterEvent(QEnterEvent *event)
|
||||||
|
#else
|
||||||
void CloseButton::enterEvent(QEvent *event)
|
void CloseButton::enterEvent(QEvent *event)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
QAbstractButton::enterEvent(event);
|
QAbstractButton::enterEvent(event);
|
||||||
@@ -74,7 +78,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
|
|||||||
{
|
{
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
QStyleOption opt;
|
QStyleOption opt;
|
||||||
opt.init(this);
|
opt.initFrom(this);
|
||||||
opt.state |= QStyle::State_AutoRaise;
|
opt.state |= QStyle::State_AutoRaise;
|
||||||
if (isEnabled() && underMouse() && !isChecked() && !isDown())
|
if (isEnabled() && underMouse() && !isChecked() && !isDown())
|
||||||
opt.state |= QStyle::State_Raised;
|
opt.state |= QStyle::State_Raised;
|
||||||
@@ -438,7 +442,7 @@ void TabSupervisor::replayLeft(TabGame *tab)
|
|||||||
if (tab == currentWidget())
|
if (tab == currentWidget())
|
||||||
emit setMenu();
|
emit setMenu();
|
||||||
|
|
||||||
replayTabs.removeAt(replayTabs.indexOf(tab));
|
replayTabs.removeOne(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus)
|
TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus)
|
||||||
@@ -492,6 +496,7 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
|
|||||||
if (deckToOpen)
|
if (deckToOpen)
|
||||||
tab->setDeck(new DeckLoader(*deckToOpen));
|
tab->setDeck(new DeckLoader(*deckToOpen));
|
||||||
connect(tab, SIGNAL(deckEditorClosing(TabDeckEditor *)), this, SLOT(deckEditorClosed(TabDeckEditor *)));
|
connect(tab, SIGNAL(deckEditorClosing(TabDeckEditor *)), this, SLOT(deckEditorClosed(TabDeckEditor *)));
|
||||||
|
connect(tab, SIGNAL(openDeckEditor(const DeckLoader *)), this, SLOT(addDeckEditorTab(const DeckLoader *)));
|
||||||
int tabIndex = myAddTab(tab);
|
int tabIndex = myAddTab(tab);
|
||||||
addCloseButtonToTab(tab, tabIndex);
|
addCloseButtonToTab(tab, tabIndex);
|
||||||
deckEditorTabs.append(tab);
|
deckEditorTabs.append(tab);
|
||||||
@@ -504,7 +509,7 @@ void TabSupervisor::deckEditorClosed(TabDeckEditor *tab)
|
|||||||
if (tab == currentWidget())
|
if (tab == currentWidget())
|
||||||
emit setMenu();
|
emit setMenu();
|
||||||
|
|
||||||
deckEditorTabs.removeAt(deckEditorTabs.indexOf(tab));
|
deckEditorTabs.removeOne(tab);
|
||||||
removeTab(indexOf(tab));
|
removeTab(indexOf(tab));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +542,7 @@ void TabSupervisor::processGameEventContainer(const GameEventContainer &cont)
|
|||||||
{
|
{
|
||||||
TabGame *tab = gameTabs.value(cont.game_id());
|
TabGame *tab = gameTabs.value(cont.game_id());
|
||||||
if (tab)
|
if (tab)
|
||||||
tab->processGameEventContainer(cont, qobject_cast<AbstractClient *>(sender()));
|
tab->processGameEventContainer(cont, qobject_cast<AbstractClient *>(sender()), {});
|
||||||
else
|
else
|
||||||
qDebug() << "gameEvent: invalid gameId";
|
qDebug() << "gameEvent: invalid gameId";
|
||||||
}
|
}
|
||||||
@@ -683,12 +688,12 @@ void TabSupervisor::processNotifyUserEvent(const Event_NotifyUser &event)
|
|||||||
|
|
||||||
bool TabSupervisor::isOwnUserRegistered() const
|
bool TabSupervisor::isOwnUserRegistered() const
|
||||||
{
|
{
|
||||||
return static_cast<bool>(getUserInfo()->user_level() & ServerInfo_User::IsRegistered);
|
return userInfo != nullptr && (userInfo->user_level() & ServerInfo_User::IsRegistered) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TabSupervisor::getOwnUsername() const
|
QString TabSupervisor::getOwnUsername() const
|
||||||
{
|
{
|
||||||
return userInfo ? QString::fromStdString(userInfo->name()) : QString();
|
return userInfo != nullptr ? QString::fromStdString(userInfo->name()) : QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabSupervisor::isUserBuddy(const QString &userName) const
|
bool TabSupervisor::isUserBuddy(const QString &userName) const
|
||||||
@@ -725,9 +730,22 @@ const ServerInfo_User *TabSupervisor::getOnlineUser(const QString &userName) con
|
|||||||
|
|
||||||
for (i = userList.begin(); i != userList.end(); ++i)
|
for (i = userList.begin(); i != userList.end(); ++i)
|
||||||
if (i.key().toLower() == userNameToMatchLower) {
|
if (i.key().toLower() == userNameToMatchLower) {
|
||||||
const ServerInfo_User &userInfo = i.value()->getUserInfo();
|
const ServerInfo_User &_userInfo = i.value()->getUserInfo();
|
||||||
return &userInfo;
|
return &_userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool TabSupervisor::switchToGameTabIfAlreadyExists(const int gameId)
|
||||||
|
{
|
||||||
|
bool isGameTabExists = false;
|
||||||
|
if (gameTabs.contains(gameId)) {
|
||||||
|
isGameTabExists = true;
|
||||||
|
TabGame *tabGame = gameTabs[gameId];
|
||||||
|
const int gameTabIndex = indexOf(tabGame);
|
||||||
|
setCurrentIndex(gameTabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isGameTabExists;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user