mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-21 14:50:26 -08:00
Compare commits
345 Commits
2022-05-09
...
2024-12-21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -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,25 +0,0 @@
|
|||||||
FROM debian:10
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
build-essential \
|
|
||||||
ccache \
|
|
||||||
clang-format \
|
|
||||||
cmake \
|
|
||||||
file \
|
|
||||||
g++ \
|
|
||||||
git \
|
|
||||||
liblzma-dev \
|
|
||||||
libmariadb-dev-compat \
|
|
||||||
libprotobuf-dev \
|
|
||||||
libqt5multimedia5-plugins \
|
|
||||||
libqt5sql5-mysql \
|
|
||||||
libqt5svg5-dev \
|
|
||||||
libqt5websockets5-dev \
|
|
||||||
protobuf-compiler \
|
|
||||||
qt5-default \
|
|
||||||
qtbase5-dev \
|
|
||||||
qtmultimedia5-dev \
|
|
||||||
qttools5-dev \
|
|
||||||
qttools5-dev-tools \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
@@ -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:impish
|
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,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
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM fedora:36
|
FROM fedora:40
|
||||||
|
|
||||||
RUN dnf install -y \
|
RUN dnf install -y \
|
||||||
ccache \
|
ccache \
|
||||||
@@ -7,7 +7,8 @@ RUN dnf install -y \
|
|||||||
git \
|
git \
|
||||||
mariadb-devel \
|
mariadb-devel \
|
||||||
protobuf-devel \
|
protobuf-devel \
|
||||||
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets,qt5compat}-devel \
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||||
|
qt6-qtimageformats \
|
||||||
rpm-build \
|
rpm-build \
|
||||||
xz-devel \
|
xz-devel \
|
||||||
zlib-devel \
|
zlib-devel \
|
||||||
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 \
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:jammy
|
FROM ubuntu:22.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 \
|
||||||
@@ -13,12 +13,12 @@ RUN apt-get update && \
|
|||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
libmariadb-dev-compat \
|
libmariadb-dev-compat \
|
||||||
libprotobuf-dev \
|
libprotobuf-dev \
|
||||||
libqt6core5compat6-dev \
|
|
||||||
libqt6multimedia6 \
|
libqt6multimedia6 \
|
||||||
libqt6sql6-mysql \
|
libqt6sql6-mysql \
|
||||||
libqt6svg6-dev \
|
libqt6svg6-dev \
|
||||||
libqt6websockets6-dev \
|
libqt6websockets6-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
|
qt6-image-formats-plugins \
|
||||||
qt6-l10n-tools \
|
qt6-l10n-tools \
|
||||||
qt6-multimedia-dev \
|
qt6-multimedia-dev \
|
||||||
qt6-tools-dev \
|
qt6-tools-dev \
|
||||||
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/*
|
|
||||||
@@ -127,7 +127,7 @@ fi
|
|||||||
# Add cmake --build flags
|
# Add cmake --build flags
|
||||||
buildflags=(--config "$BUILDTYPE")
|
buildflags=(--config "$BUILDTYPE")
|
||||||
if [[ $PARALLEL_COUNT ]]; then
|
if [[ $PARALLEL_COUNT ]]; then
|
||||||
if [[ $(cmake --build /not_a_dir --parallel |& head -1) =~ parallel ]]; then
|
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
|
||||||
# workaround for bionic having an old cmake
|
# workaround for bionic having an old cmake
|
||||||
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
||||||
buildflags+=(-- -j "$PARALLEL_COUNT")
|
buildflags+=(-- -j "$PARALLEL_COUNT")
|
||||||
@@ -160,7 +160,13 @@ cmake .. "${flags[@]}"
|
|||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Build project"
|
echo "::group::Build project"
|
||||||
cmake --build . "${buildflags[@]}"
|
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::"
|
||||||
|
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
@@ -171,7 +177,7 @@ fi
|
|||||||
|
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
echo "::group::Run tests"
|
echo "::group::Run tests"
|
||||||
ctest -C "$BUILDTYPE"
|
ctest -C "$BUILDTYPE" --output-on-failure
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -183,6 +189,12 @@ fi
|
|||||||
|
|
||||||
if [[ $MAKE_PACKAGE ]]; then
|
if [[ $MAKE_PACKAGE ]]; then
|
||||||
echo "::group::Create package"
|
echo "::group::Create 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"
|
cmake --build . --target package --config "$BUILDTYPE"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Read arguments
|
|
||||||
while [[ $# != 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
'--')
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--arch')
|
|
||||||
shift
|
|
||||||
if [[ $# == 0 ]]; then
|
|
||||||
echo "::error file=$0::--arch expects an argument"
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
OS_ARCH="$1"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "::error file=$0::unrecognized option: $1"
|
|
||||||
exit 3
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
OPEN_SSL_VERSION="1.1.1n"
|
|
||||||
DEST_PATH="C:\OpenSSL-Win$OS_ARCH"
|
|
||||||
|
|
||||||
curl -JLSs "https://github.com/CristiFati/Prebuilt-Binaries/raw/master/OpenSSL/v1.1.1/OpenSSL-$OPEN_SSL_VERSION-Win-pc0$OS_ARCH.zip" -o OpenSSL.zip
|
|
||||||
unzip -q "OpenSSL.zip"
|
|
||||||
rm "OpenSSL.zip"
|
|
||||||
mv "OpenSSL\OpenSSL\\$OPEN_SSL_VERSION" "$DEST_PATH"
|
|
||||||
rm -r "OpenSSL"
|
|
||||||
echo "Installed OpenSSL v$OPEN_SSL_VERSION to $DEST_PATH"
|
|
||||||
@@ -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,12 +32,14 @@ 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...
|
||||||
@@ -62,8 +64,6 @@ EOM
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
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
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
# 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 unless BUILD_DIR is set
|
# expected to be run in the build directory unless BUILD_DIR is set
|
||||||
|
# adds output to GITHUB_OUTPUT
|
||||||
builddir="${BUILD_DIR:=.}"
|
builddir="${BUILD_DIR:=.}"
|
||||||
findrx="Cockatrice-*.*"
|
findrx="Cockatrice-*.*"
|
||||||
|
|
||||||
@@ -50,5 +51,5 @@ fi
|
|||||||
cd "$oldpwd"
|
cd "$oldpwd"
|
||||||
relative_path="$path/$filename"
|
relative_path="$path/$filename"
|
||||||
ls -l "$relative_path"
|
ls -l "$relative_path"
|
||||||
echo "::set-output name=path::$relative_path"
|
echo "path=$relative_path" >>"$GITHUB_OUTPUT"
|
||||||
echo "::set-output name=name::$filename"
|
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,50 +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/11 (32-bit)</kbd>
|
- <kbd>Windows 10+</kbd>
|
||||||
- <kbd>Windows 7/8/10/11 (64-bit)</kbd>
|
- <kbd>Windows 7+</kbd>
|
||||||
- <kbd>macOS 10.14</kbd> ("Mojave")
|
- <kbd>macOS 14+</kbd> ("Sonoma") / Apple M
|
||||||
- <kbd>macOS 10.15</kbd> ("Catalina")
|
- <kbd>macOS 13+</kbd> ("Ventura") / Intel
|
||||||
- <kbd>macOS 11.0</kbd> ("Big Sur")
|
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
|
||||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")
|
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
|
||||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")
|
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
|
||||||
- <kbd>Ubuntu 21.10</kbd> ("Impish Indri")
|
- <kbd>Debian 12</kbd> ("Bookworm")
|
||||||
- <kbd>Ubuntu 22.04</kbd> ("Jammy Jellyfish")
|
|
||||||
- <kbd>Debian 10</kbd> ("Buster")
|
|
||||||
- <kbd>Debian 11</kbd> ("Bullseye")
|
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||||
- <kbd>Fedora 34</kbd>
|
- <kbd>Fedora 41</kbd>
|
||||||
- <kbd>Fedora 35</kbd>
|
- <kbd>Fedora 40</kbd>
|
||||||
- <kbd>Fedora 36</kbd>
|
|
||||||
<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>)
|
||||||
|
|
||||||
@@ -64,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
|
||||||
@@ -92,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
|
||||||
@@ -102,5 +102,8 @@
|
|||||||
"decisions. See the documentation for more information."
|
"decisions. See the documentation for more information."
|
||||||
],
|
],
|
||||||
"layout_passes": {}
|
"layout_passes": {}
|
||||||
|
},
|
||||||
|
"markup": {
|
||||||
|
"enable_markup": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
85
.github/CONTRIBUTING.md
vendored
85
.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@source.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
|
||||||
@@ -357,11 +384,13 @@ 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
|
||||||
338
.github/workflows/desktop-build.yml
vendored
338
.github/workflows/desktop-build.yml
vendored
@@ -8,6 +8,7 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
- 'webclient/**'
|
- 'webclient/**'
|
||||||
- '.github/workflows/web-*.yml'
|
- '.github/workflows/web-*.yml'
|
||||||
|
- '.github/workflows/translations-*.yml'
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
pull_request:
|
pull_request:
|
||||||
@@ -15,6 +16,12 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
- 'webclient/**'
|
- 'webclient/**'
|
||||||
- '.github/workflows/web-*.yml'
|
- '.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:
|
jobs:
|
||||||
configure:
|
configure:
|
||||||
@@ -23,33 +30,27 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
tag: ${{steps.configure.outputs.tag}}
|
tag: ${{steps.configure.outputs.tag}}
|
||||||
sha: ${{steps.configure.outputs.sha}}
|
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
|
|
||||||
|
|
||||||
|
steps:
|
||||||
- name: Configure
|
- name: Configure
|
||||||
id: configure
|
id: configure
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
tag_regex='^refs/tags/'
|
tag_regex='^refs/tags/'
|
||||||
if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request
|
if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request
|
||||||
sha="${{github.event.pull_request.head.sha}}"
|
sha="${{github.event.pull_request.head.sha}}"
|
||||||
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
|
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
|
||||||
sha="$GITHUB_SHA"
|
sha="$GITHUB_SHA"
|
||||||
tag="${GITHUB_REF/refs\/tags\//}"
|
tag="${GITHUB_REF/refs\/tags\//}"
|
||||||
echo "::set-output name=tag::$tag"
|
echo "tag=$tag" >>"$GITHUB_OUTPUT"
|
||||||
else # push to branch
|
else # push to branch
|
||||||
sha="$GITHUB_SHA"
|
sha="$GITHUB_SHA"
|
||||||
fi
|
fi
|
||||||
echo "::set-output name=sha::$sha"
|
echo "sha=$sha" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
if: steps.configure.outputs.tag != null
|
if: steps.configure.outputs.tag != null
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -64,178 +65,166 @@ jobs:
|
|||||||
- name: Create release
|
- name: Create release
|
||||||
if: steps.configure.outputs.tag != null
|
if: steps.configure.outputs.tag != null
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GH_TOKEN: ${{github.token}}
|
||||||
with:
|
tag_name: ${{steps.configure.outputs.tag}}
|
||||||
tag_name: ${{github.ref}}
|
target: ${{steps.configure.outputs.sha}}
|
||||||
release_name: ${{steps.prepare.outputs.title}}
|
release_name: ${{steps.prepare.outputs.title}}
|
||||||
body_path: ${{steps.prepare.outputs.body_path}}
|
body_path: ${{steps.prepare.outputs.body_path}}
|
||||||
draft: true
|
prerelease: ${{steps.prepare.outputs.is_beta}}
|
||||||
prerelease: ${{steps.prepare.outputs.is_beta == 'yes'}}
|
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:
|
build-linux:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# these names correspond to the files in .ci/$distro
|
# These names correspond to the files in ".ci/$distro$version"
|
||||||
include:
|
include:
|
||||||
- distro: ArchLinux
|
- distro: Arch
|
||||||
package: skip # we are packaged in arch already
|
package: skip # We are packaged in Arch already
|
||||||
allow-failure: yes
|
allow-failure: yes
|
||||||
|
|
||||||
- distro: Debian10
|
- distro: Debian
|
||||||
|
version: 11
|
||||||
package: DEB
|
package: DEB
|
||||||
test: skip # running tests on all distros is superfluous
|
test: skip # Running tests on all distros is superfluous
|
||||||
|
|
||||||
- distro: Debian11
|
- distro: Debian
|
||||||
|
version: 12
|
||||||
package: DEB
|
package: DEB
|
||||||
|
|
||||||
- distro: Fedora34
|
- distro: Fedora
|
||||||
|
version: 40
|
||||||
package: RPM
|
package: RPM
|
||||||
test: skip # gtest does not compile for some reason
|
test: skip # Running tests on all distros is superfluous
|
||||||
|
|
||||||
- distro: Fedora35
|
- distro: Fedora
|
||||||
package: RPM
|
version: 41
|
||||||
test: skip
|
|
||||||
|
|
||||||
- distro: Fedora36
|
|
||||||
package: RPM
|
package: RPM
|
||||||
|
|
||||||
- distro: UbuntuBionic
|
- 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
|
package: DEB
|
||||||
|
|
||||||
- distro: UbuntuFocal
|
name: ${{matrix.distro}} ${{matrix.version}}
|
||||||
package: DEB
|
|
||||||
test: skip # UbuntuFocal has a broken qt for debug builds
|
|
||||||
|
|
||||||
- distro: UbuntuImpish
|
|
||||||
package: DEB
|
|
||||||
test: skip
|
|
||||||
|
|
||||||
- distro: UbuntuJammy
|
|
||||||
package: DEB
|
|
||||||
|
|
||||||
name: ${{matrix.distro}}
|
|
||||||
needs: configure
|
needs: configure
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
env:
|
env:
|
||||||
NAME: ${{matrix.distro}}
|
NAME: ${{matrix.distro}}${{matrix.version}}
|
||||||
CACHE: /tmp/${{matrix.distro}}-cache # ${{runner.temp}} does not work?
|
CACHE: /tmp/${{matrix.distro}}${{matrix.version}}-cache # ${{runner.temp}} does not work?
|
||||||
# cache size over the entire repo is 10Gi link:
|
# 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
|
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||||
CCACHE_SIZE: 200M
|
CCACHE_SIZE: 200M
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get cache timestamp
|
- name: Generate cache timestamp
|
||||||
id: cache_timestamp
|
id: cache_timestamp
|
||||||
shell: bash
|
shell: bash
|
||||||
run: echo "::set-output name=timestamp::$(date -u '+%Y%m%d%H%M%S')"
|
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Restore cache
|
- name: Restore cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
env:
|
env:
|
||||||
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
||||||
with:
|
with:
|
||||||
path: ${{env.CACHE}}
|
path: ${{env.CACHE}}
|
||||||
key: docker-${{matrix.distro}}-cache-${{env.timestamp}}
|
key: docker-${{matrix.distro}}${{matrix.version}}-cache-${{env.timestamp}}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
docker-${{matrix.distro}}-cache-
|
docker-${{matrix.distro}}${{matrix.version}}-cache-
|
||||||
|
|
||||||
- name: Build ${{matrix.distro}} Docker image
|
- name: Build ${{matrix.distro}} ${{matrix.version}} Docker image
|
||||||
shell: bash
|
shell: bash
|
||||||
run: source .ci/docker.sh --build
|
run: source .ci/docker.sh --build
|
||||||
|
|
||||||
- name: Build debug and test
|
- name: Build debug and test
|
||||||
if: matrix.test != 'skip'
|
if: matrix.test != 'skip'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
|
||||||
distro: '${{matrix.distro}}'
|
|
||||||
run: |
|
run: |
|
||||||
source .ci/docker.sh
|
source .ci/docker.sh
|
||||||
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 2
|
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
|
||||||
|
|
||||||
- name: Build release package
|
- name: Build release package
|
||||||
id: package
|
id: build
|
||||||
if: matrix.package != 'skip'
|
if: matrix.package != 'skip'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
suffix: '-${{matrix.distro}}'
|
BUILD_DIR: build
|
||||||
|
SUFFIX: '-${{matrix.distro}}${{matrix.version}}'
|
||||||
type: '${{matrix.package}}'
|
type: '${{matrix.package}}'
|
||||||
distro: '${{matrix.distro}}'
|
|
||||||
run: |
|
run: |
|
||||||
source .ci/docker.sh
|
source .ci/docker.sh
|
||||||
RUN --server --release --package "$type" --suffix "$suffix" \
|
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
|
||||||
--ccache "$CCACHE_SIZE" --parallel 2
|
--ccache "$CCACHE_SIZE" --parallel 4
|
||||||
|
.ci/name_build.sh
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
if: matrix.package != 'skip'
|
if: matrix.package != 'skip'
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{matrix.distro}}-package
|
name: ${{matrix.distro}}${{matrix.version}}-package
|
||||||
path: ${{steps.package.outputs.path}}
|
path: ${{steps.build.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
uses: actions/upload-release-asset@v1
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GH_TOKEN: ${{github.token}}
|
||||||
with:
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
asset_path: ${{steps.package.outputs.path}}
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- target: Debug # tests only
|
- target: 13
|
||||||
os: macos-latest
|
soc: Intel
|
||||||
xcode: 12.5.1
|
os: macos-13
|
||||||
qt_version: 6
|
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
|
type: Debug
|
||||||
do_tests: 1
|
core_count: 3
|
||||||
|
|
||||||
- target: 10.14_Mojave
|
name: macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
||||||
os: macos-10.15 # runs on Catalina
|
|
||||||
xcode: 10.3 # allows compatibility with macOS 10.14
|
|
||||||
qt_version: 5
|
|
||||||
type: Release
|
|
||||||
# do_tests: 1 # tests do not work on qt5?
|
|
||||||
make_package: 1
|
|
||||||
|
|
||||||
- target: 10.15_Catalina
|
|
||||||
os: macos-10.15
|
|
||||||
xcode: 12.4
|
|
||||||
qt_version: 6
|
|
||||||
type: Release
|
|
||||||
do_tests: 1
|
|
||||||
make_package: 1
|
|
||||||
|
|
||||||
- target: 11_Big_Sur
|
|
||||||
os: macos-11
|
|
||||||
xcode: 13.2
|
|
||||||
qt_version: 6
|
|
||||||
type: Release
|
|
||||||
do_tests: 1
|
|
||||||
make_package: 1
|
|
||||||
|
|
||||||
# - target: 12_Monterey
|
|
||||||
# os: macos-12
|
|
||||||
# xcode: 13.3
|
|
||||||
# qt_version: 6
|
|
||||||
# type: Release
|
|
||||||
# do_tests: 1
|
|
||||||
# make_package: 1
|
|
||||||
|
|
||||||
name: macOS ${{matrix.target}}
|
|
||||||
needs: configure
|
needs: configure
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
@@ -245,140 +234,125 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install dependencies using homebrew
|
- name: Install dependencies using Homebrew
|
||||||
shell: bash
|
shell: bash
|
||||||
# cmake cannot find the mysql connector
|
# CMake cannot find the MySQL connector
|
||||||
# neither of these works: mariadb-connector-c mysql-connector-c++
|
# Neither of these works: mariadb-connector-c mysql-connector-c++
|
||||||
env:
|
env:
|
||||||
qt_version: 'qt@${{matrix.qt_version}}'
|
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||||
run: |
|
run: |
|
||||||
brew update
|
brew update
|
||||||
brew install protobuf
|
brew install protobuf qt --force-bottle
|
||||||
brew install "$qt_version" --force-bottle
|
|
||||||
|
|
||||||
- name: Build on Xcode ${{matrix.xcode}}
|
- name: Build on Xcode ${{matrix.xcode}}
|
||||||
shell: bash
|
shell: bash
|
||||||
id: build
|
id: build
|
||||||
env:
|
env:
|
||||||
BUILDTYPE: '${{matrix.type}}'
|
BUILDTYPE: '${{matrix.type}}'
|
||||||
MAKE_TEST: '${{matrix.do_tests}}'
|
MAKE_TEST: 1
|
||||||
MAKE_PACKAGE: '${{matrix.make_package}}'
|
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||||
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
|
PACKAGE_SUFFIX: '-macOS${{matrix.target}}_${{matrix.soc}}'
|
||||||
# set QTDIR to find qt5, qt6 can be found without this
|
# macOS runner have 3 cores usually - only the macos-13 image has 4:
|
||||||
QTDIR: '/usr/local/opt/qt5'
|
# 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
|
||||||
# Mac machines actually have 3 cores
|
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
|
||||||
run: .ci/compile.sh --server --parallel 3
|
run: .ci/compile.sh --server --parallel ${{matrix.core_count}}
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
if: matrix.make_package
|
if: matrix.make_package
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: macOS-${{matrix.target}}-dmg
|
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-dmg
|
||||||
path: ${{steps.build.outputs.path}}
|
path: ${{steps.build.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: matrix.make_package && needs.configure.outputs.tag != null
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
uses: actions/upload-release-asset@v1
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GH_TOKEN: ${{github.token}}
|
||||||
with:
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
|
||||||
asset_path: ${{steps.build.outputs.path}}
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
asset_name: ${{steps.build.outputs.name}}
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
asset_content_type: application/octet-stream
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: 32
|
- target: 7
|
||||||
vcpkg_default_triplet: x86
|
qt_version: 5.15.*
|
||||||
qt_version: '5.15.2'
|
|
||||||
cmake_generator_platform: Win32
|
|
||||||
qt_arch: msvc2019
|
|
||||||
- arch: 64
|
|
||||||
vcpkg_default_triplet: x64
|
|
||||||
qt_version: '6.3.0'
|
|
||||||
cmake_generator_platform: x64
|
|
||||||
qt_arch: msvc2019_64
|
qt_arch: msvc2019_64
|
||||||
qt_modules: "qt5compat qtmultimedia qtwebsockets"
|
|
||||||
|
|
||||||
name: Windows (${{matrix.arch}}-bit)
|
- target: 10
|
||||||
|
qt_version: 6.6.*
|
||||||
|
qt_arch: msvc2019_64
|
||||||
|
qt_modules: "qtimageformats qtmultimedia qtwebsockets"
|
||||||
|
|
||||||
|
name: Windows ${{matrix.target}}
|
||||||
needs: configure
|
needs: configure
|
||||||
runs-on: windows-2019
|
runs-on: windows-2022
|
||||||
env:
|
env:
|
||||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
id: add-msbuild
|
id: add-msbuild
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
with:
|
||||||
|
msbuild-architecture: x64
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Restore Qt ${{matrix.qt_version}} (${{matrix.arch}}-bit) from cache
|
- name: Install Qt ${{matrix.qt_version}}
|
||||||
id: cache-qt
|
uses: jurplel/install-qt-action@v4
|
||||||
uses: actions/cache@v1 # Intentionally v1, based on jurplel documentation
|
|
||||||
with:
|
with:
|
||||||
key: ${{runner.os}}-QtCache-${{matrix.qt_version}}-${{matrix.arch}}
|
cache: true
|
||||||
path: '${{github.workspace}}/../Qt'
|
setup-python: false
|
||||||
|
|
||||||
- name: Install Qt ${{matrix.qt_version}} (${{matrix.arch}}-bit)
|
|
||||||
uses: jurplel/install-qt-action@v3
|
|
||||||
with:
|
|
||||||
cached: ${{steps.cache-qt.outputs.cache-hit}}
|
|
||||||
version: ${{matrix.qt_version}}
|
version: ${{matrix.qt_version}}
|
||||||
arch: win${{matrix.arch}}_${{matrix.qt_arch}}
|
arch: win64_${{matrix.qt_arch}}
|
||||||
|
tools: ${{matrix.qt_tools}}
|
||||||
modules: ${{matrix.qt_modules}}
|
modules: ${{matrix.qt_modules}}
|
||||||
|
|
||||||
- name: Run vcpkg
|
- name: Run vcpkg
|
||||||
uses: lukka/run-vcpkg@v10.2
|
uses: lukka/run-vcpkg@v11
|
||||||
with:
|
with:
|
||||||
runVcpkgInstall: true
|
runVcpkgInstall: true
|
||||||
appendedCacheKey: ${{matrix.arch}}-bit
|
doNotCache: false
|
||||||
env:
|
env:
|
||||||
VCPKG_DEFAULT_TRIPLET: '${{matrix.vcpkg_default_triplet}}-windows'
|
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
|
||||||
VCPKG_DISABLE_METRICS: 1
|
VCPKG_DISABLE_METRICS: 1
|
||||||
|
|
||||||
- name: Install OpenSSL (${{matrix.arch}}-bit)
|
- name: Build Cockatrice
|
||||||
shell: bash
|
|
||||||
run: .ci/download_openssl.sh --arch ${{matrix.arch}}
|
|
||||||
|
|
||||||
- name: Build Cockatrice (${{matrix.arch}}-bit)
|
|
||||||
id: build
|
id: build
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
PACKAGE_SUFFIX: '-win${{matrix.arch}}'
|
PACKAGE_SUFFIX: '-Win${{matrix.target}}'
|
||||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||||
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake_generator_platform}}'
|
CMAKE_GENERATOR_PLATFORM: 'x64'
|
||||||
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win${{matrix.arch}}_${{matrix.qt_arch}}'
|
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win64_${{matrix.qt_arch}}'
|
||||||
run: .ci/compile.sh --server --release --test --package --parallel 2
|
# 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/
|
||||||
- name: Setup tmate session
|
run: .ci/compile.sh --server --release --test --package
|
||||||
if: ${{ failure() }}
|
|
||||||
uses: mxschmitt/action-tmate@v3
|
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Windows-${{matrix.arch}}bit-installer
|
name: Windows${{matrix.target}}-installer
|
||||||
path: ${{steps.build.outputs.path}}
|
path: ${{steps.build.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: needs.configure.outputs.tag != null
|
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||||
uses: actions/upload-release-asset@v1
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GH_TOKEN: ${{github.token}}
|
||||||
with:
|
tag_name: ${{needs.configure.outputs.tag}}
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
|
||||||
asset_path: ${{steps.build.outputs.path}}
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
asset_name: ${{steps.build.outputs.name}}
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
asset_content_type: application/octet-stream
|
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||||
|
|||||||
13
.github/workflows/desktop-lint.yml
vendored
13
.github/workflows/desktop-lint.yml
vendored
@@ -6,23 +6,24 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
- 'webclient/**'
|
- 'webclient/**'
|
||||||
- '.github/workflows/web-*.yml'
|
- '.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
|
||||||
66
.github/workflows/translations.yml
vendored
66
.github/workflows/translations.yml
vendored
@@ -1,66 +0,0 @@
|
|||||||
name: Update translation source
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
# runs once per month
|
|
||||||
- cron: '0 0 1 * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
translations:
|
|
||||||
# Do not run the scheduled workflow on forks
|
|
||||||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Install lupdate
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends qttools5-dev-tools
|
|
||||||
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Update cockatrice translations
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
shopt -s globstar # globstar is needed for recursive **
|
|
||||||
lupdate -version
|
|
||||||
echo "reading the following source files:"
|
|
||||||
# note: there are three strings to translate in common right now
|
|
||||||
echo {cockatrice,common}/**/*.{cpp,h}
|
|
||||||
echo "$(echo {cockatrice,common}/**/*.{cpp,h} | wc -w) files total"
|
|
||||||
lupdate {cockatrice,common}/**/*.{cpp,h} -ts cockatrice/translations/cockatrice_en@source.ts
|
|
||||||
|
|
||||||
- name: Update oracle translations
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
shopt -s globstar # globstar is needed for recursive **
|
|
||||||
lupdate -version
|
|
||||||
echo "reading the following source files:"
|
|
||||||
echo oracle/**/*.{cpp,h}
|
|
||||||
echo "$(echo oracle/**/*.{cpp,h} | wc -w) files total"
|
|
||||||
lupdate oracle/**/*.{cpp,h} -ts oracle/translations/oracle_en@source.ts
|
|
||||||
|
|
||||||
- name: Check for updates
|
|
||||||
id: check
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set +e # do not fail, just save the exit state
|
|
||||||
git diff --exit-code
|
|
||||||
echo "::set-output name=deploy::$?"
|
|
||||||
|
|
||||||
- name: Commit changes
|
|
||||||
if: steps.check.outputs.deploy == '1'
|
|
||||||
shell: bash
|
|
||||||
working-directory: ${{env.OUTPUT_PATH}}
|
|
||||||
run: |
|
|
||||||
git config user.name github-actions
|
|
||||||
git config user.email github-actions@github.com
|
|
||||||
git add cockatrice/translations/cockatrice_en@source.ts oracle/translations/oracle_en@source.ts
|
|
||||||
git commit -m "Automated translation update ( $GITHUB_SHA )"
|
|
||||||
git push
|
|
||||||
deploy_commit=$(git rev-parse HEAD)
|
|
||||||
echo "Created commit: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$deploy_commit"
|
|
||||||
7
.github/workflows/web-build.yml
vendored
7
.github/workflows/web-build.yml
vendored
@@ -28,15 +28,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node_version:
|
node_version:
|
||||||
- 12
|
- 16
|
||||||
- lts/*
|
- lts/*
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{matrix.node_version}}
|
node-version: ${{matrix.node_version}}
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -50,4 +50,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Test app
|
- name: Test app
|
||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/web-lint.yml
vendored
4
.github/workflows/web-lint.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: 'webclient/package-lock.json'
|
cache-dependency-path: 'webclient/package-lock.json'
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,3 +11,5 @@ preferences
|
|||||||
compile_commands.json
|
compile_commands.json
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.cache
|
||||||
|
.gdb_history
|
||||||
|
|||||||
27
.tx/config
27
.tx/config
@@ -1,13 +1,26 @@
|
|||||||
[main]
|
[main]
|
||||||
host = https://www.transifex.com
|
host = https://app.transifex.com
|
||||||
|
|
||||||
[cockatrice.cockatrice-translations-cockatrice-en-source-ts--master]
|
[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@source.ts
|
type = QT
|
||||||
source_lang = en
|
minimum_perc = 10
|
||||||
|
|
||||||
[cockatrice.oracle-translations-oracle-en-source-ts--master]
|
[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@source.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
|
||||||
|
|||||||
401
CMakeLists.txt
401
CMakeLists.txt
@@ -27,44 +27,65 @@ 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()
|
||||||
|
|
||||||
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++17 for all targets
|
# Use c++20 for all targets
|
||||||
set(CMAKE_CXX_STANDARD 17 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
|
||||||
@@ -81,130 +102,150 @@ 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("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
||||||
configure_file("${COCKATRICE_CMAKE_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()
|
||||||
|
|
||||||
# Define proper compilation flags
|
# Define proper compilation flags
|
||||||
IF(MSVC)
|
if(MSVC)
|
||||||
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
|
# Visual Studio: Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
|
||||||
SET(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive-")
|
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()
|
||||||
IF(APPLE)
|
else()
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
|
# other: osx/llvm, bsd/llvm
|
||||||
ENDIF()
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
||||||
|
if(WARNING_AS_ERROR)
|
||||||
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)
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter")
|
||||||
|
else()
|
||||||
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
|
||||||
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
|
endif()
|
||||||
IF(CXX_HAS_WARNING_${FLAG})
|
endif()
|
||||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
|
|
||||||
ENDIF()
|
|
||||||
ENDFOREACH()
|
|
||||||
ELSE()
|
|
||||||
# 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)
|
||||||
|
|
||||||
# Determine 32 or 64 bit build
|
# 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()
|
||||||
|
|
||||||
MESSAGE(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
message(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
||||||
|
|
||||||
include(FindQtRuntime)
|
include(FindQtRuntime)
|
||||||
|
|
||||||
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 "Found Protobuf ${Protobuf_VERSION} at: ${Protobuf_LIBRARIES}")
|
|
||||||
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 <zach@cockatrice.us>")
|
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
|
||||||
@@ -218,95 +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_MAIN_COMPONENT "cockatrice")
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||||
IF(Qt6_FOUND)
|
if(Qt6_FOUND)
|
||||||
SET(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins")
|
||||||
ELSEIF(Qt5_FOUND)
|
elseif(Qt5_FOUND)
|
||||||
SET(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
||||||
ENDIF()
|
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()
|
|
||||||
set(CPACK_GENERATOR DEB)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
|
||||||
IF(Qt6_FOUND)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins")
|
|
||||||
ELSEIF(Qt5_FOUND)
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
|
||||||
ENDIF()
|
|
||||||
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")
|
||||||
"${COCKATRICE_CMAKE_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)
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
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()
|
||||||
|
|
||||||
if(TEST)
|
if(TEST)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Qt6Found AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
|
if(Qt6_FOUND AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
|
||||||
# Qt6.3+ requires project finalization to support translations
|
# Qt6.3+ requires project finalization to support translations
|
||||||
qt6_finalize_project()
|
qt6_finalize_project()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -5,7 +5,7 @@
|
|||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
|
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
|
||||||
<a href="#download-">Download</a> <b>|</b>
|
<a href="#download-">Download</a> <b>|</b>
|
||||||
<a href="#get-involved--">Get Involved</a> <b>|</b>
|
<a href="#get-involved-">Get Involved</a> <b>|</b>
|
||||||
<a href="#community-resources">Community</a> <b>|</b>
|
<a href="#community-resources">Community</a> <b>|</b>
|
||||||
<a href="#translations-">Translations</a> <b>|</b>
|
<a href="#translations-">Translations</a> <b>|</b>
|
||||||
<a href="#build--">Build</a> <b>|</b>
|
<a href="#build--">Build</a> <b>|</b>
|
||||||
@@ -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,13 +65,9 @@ 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>
|
||||||
|
|
||||||
|
|||||||
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,7 +1,13 @@
|
|||||||
# Find a compatible Qt version Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, WITH_DBCONVERTER, FORCE_USE_QT5 Optional
|
# Find a compatible Qt version
|
||||||
# Input: QT6_DIR -- Hint as to where Qt6 lives on the system Optional Input: QT5_DIR -- Hint as to where Qt5 lives on
|
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, WITH_DBCONVERTER, FORCE_USE_QT5
|
||||||
# the system Output: COCKATRICE_QT_VERSION_NAME -- Example values: Qt5, Qt6 Outputs: SERVATRICE_QT_MODULES,
|
# Optional Input: QT6_DIR -- Hint as to where Qt6 lives on the system
|
||||||
# COCKATRICE_QT_MODULES, ORACLE_QT_MODULES, DBCONVERTER_QT_MODULES, TEST_QT_MODULES
|
# 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)
|
set(REQUIRED_QT_COMPONENTS Core)
|
||||||
if(WITH_SERVER)
|
if(WITH_SERVER)
|
||||||
@@ -15,8 +21,8 @@ if(WITH_CLIENT)
|
|||||||
Network
|
Network
|
||||||
PrintSupport
|
PrintSupport
|
||||||
Svg
|
Svg
|
||||||
Widgets
|
|
||||||
WebSockets
|
WebSockets
|
||||||
|
Widgets
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
if(WITH_ORACLE)
|
if(WITH_ORACLE)
|
||||||
@@ -35,27 +41,24 @@ set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_CO
|
|||||||
list(REMOVE_DUPLICATES REQUIRED_QT_COMPONENTS)
|
list(REMOVE_DUPLICATES REQUIRED_QT_COMPONENTS)
|
||||||
|
|
||||||
if(NOT FORCE_USE_QT5)
|
if(NOT FORCE_USE_QT5)
|
||||||
# Core5Compat is Qt6 Only, Linguist is now a component in Qt6 instead of an external package
|
# Linguist is now a component in Qt6 instead of an external package
|
||||||
find_package(
|
find_package(
|
||||||
Qt6 6.2.3
|
Qt6 6.2.3
|
||||||
COMPONENTS Core5Compat ${REQUIRED_QT_COMPONENTS}
|
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
|
||||||
OPTIONAL_COMPONENTS Linguist
|
|
||||||
QUIET HINTS ${Qt6_DIR}
|
QUIET HINTS ${Qt6_DIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
if(Qt6_FOUND)
|
if(Qt6_FOUND)
|
||||||
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
||||||
|
|
||||||
if(Qt6LinguistTools_FOUND)
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
||||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
if(QT6_LRELEASE_INDEX EQUAL -1)
|
||||||
if(QT6_LRELEASE_INDEX EQUAL -1)
|
message(WARNING "Qt6 lrelease not found.")
|
||||||
message(WARNING "Qt6 lrelease not found.")
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
||||||
if(QT6_LUPDATE_INDEX EQUAL -1)
|
if(QT6_LUPDATE_INDEX EQUAL -1)
|
||||||
message(WARNING "Qt6 lupdate not found.")
|
message(WARNING "Qt6 lupdate not found.")
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
find_package(
|
find_package(
|
||||||
@@ -110,10 +113,5 @@ string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" COCKATRICE_Q
|
|||||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" ORACLE_QT_MODULES "${_ORACLE_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" DB_CONVERTER_QT_MODULES "${_DBCONVERTER_NEEDED}")
|
||||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}")
|
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}")
|
||||||
if(Qt6_FOUND)
|
|
||||||
list(APPEND SERVATRICE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
|
||||||
list(APPEND COCKATRICE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
|
||||||
list(APPEND ORACLE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")
|
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ if(WIN32)
|
|||||||
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)
|
||||||
@@ -22,10 +23,13 @@ if(WIN32)
|
|||||||
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})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VCREDISTRUNTIME_FOUND)
|
if(VCREDISTRUNTIME_FOUND)
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
# Find the OpenSSL runtime libraries (.dll) for Windows that will be needed by Qt in order to access https urls.
|
|
||||||
if(NOT DEFINED WIN32 OR NOT ${WIN32})
|
|
||||||
message(STATUS "Non-Windows device trying to execute FindWin32SslRuntime, skipping")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
|
||||||
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
|
||||||
set(_OPENSSL_ROOT_PATHS "$ENV{VCPKG_PACKAGES_DIR}/x64-windows/bin" "C:/OpenSSL-Win64/bin" "C:/OpenSSL-Win64"
|
|
||||||
"C:/Tools/vcpkg/installed/x64-windows/bin" "${_programfiles}/OpenSSL-Win64"
|
|
||||||
)
|
|
||||||
unset(_programfiles)
|
|
||||||
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
|
||||||
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
|
||||||
set(_OPENSSL_ROOT_PATHS
|
|
||||||
"$ENV{VCPKG_PACKAGES_DIR}/x86-windows/bin"
|
|
||||||
"C:/OpenSSL-Win32/bin"
|
|
||||||
"C:/OpenSSL-Win32"
|
|
||||||
"C:/OpenSSL"
|
|
||||||
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
|
||||||
"${_programfiles}/OpenSSL"
|
|
||||||
"${_programfiles}/OpenSSL-Win32"
|
|
||||||
)
|
|
||||||
unset(_programfiles)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
message(STATUS "Looking for OpenSSL @ $ENV{CMAKE_GENERATOR_PLATFORM} in ${_OPENSSL_ROOT_PATHS}")
|
|
||||||
if("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
|
||||||
find_file(
|
|
||||||
WIN32SSLRUNTIME_LIBEAY
|
|
||||||
NAMES libcrypto-1_1-x64.dll libcrypto.dll
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
find_file(
|
|
||||||
WIN32SSLRUNTIME_SSLEAY
|
|
||||||
NAMES libssl-1_1-x64.dll libssl.dll
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
elseif("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
|
||||||
find_file(
|
|
||||||
WIN32SSLRUNTIME_LIBEAY
|
|
||||||
NAMES libcrypto-1_1.dll libcrypto.dll
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
find_file(
|
|
||||||
WIN32SSLRUNTIME_SSLEAY
|
|
||||||
NAMES libssl-1_1.dll libssl.dll
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
|
||||||
set(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
|
||||||
set(WIN32SSLRUNTIME_FOUND "YES")
|
|
||||||
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
|
||||||
else()
|
|
||||||
set(WIN32SSLRUNTIME_FOUND "NO")
|
|
||||||
message(
|
|
||||||
WARNING
|
|
||||||
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
mark_as_advanced(WIN32SSLRUNTIME_LIBEAY WIN32SSLRUNTIME_SSLEAY)
|
|
||||||
@@ -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}
|
||||||
|
|||||||
BIN
cmake/dmgBackground.tif
Normal file
BIN
cmake/dmgBackground.tif
Normal file
Binary file not shown.
@@ -19,7 +19,7 @@ function(get_commit_id)
|
|||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
set(PROJECT_VERSION_LABEL
|
set(PROJECT_VERSION_LABEL
|
||||||
"custom(${GIT_COM_ID})"
|
"custom-${GIT_COM_ID}"
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
endfunction()
|
endfunction()
|
||||||
@@ -71,7 +71,9 @@ function(get_tag_name commit)
|
|||||||
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: YYYY-MM-DD-Release-MAJ.MIN.PATCH YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X
|
# Extract information from tag:
|
||||||
|
# YYYY-MM-DD-Release-MAJ.MIN.PATCH
|
||||||
|
# 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}")
|
||||||
|
|
||||||
@@ -131,8 +133,10 @@ function(get_tag_name commit)
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Label 7 = Stable release 8 = Dev release, first beta so only "beta" attached 9 = Dev release, subsequent beta so
|
# Label
|
||||||
# "beta.N" attached (N>=2)
|
# 7 = Stable release
|
||||||
|
# 8 = Dev release, first beta so only "beta" attached
|
||||||
|
# 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)
|
||||||
|
|||||||
14
cmakeify.sh
14
cmakeify.sh
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# go to the project root directory, this file should be located in the project root directory
|
|
||||||
cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with special links etc.
|
|
||||||
|
|
||||||
# CMake-Format
|
|
||||||
cmake_format_cmd="cmake-format"
|
|
||||||
|
|
||||||
if ! hash $cmake_format_cmd 2>/dev/null; then
|
|
||||||
echo "could not find $cmake_format_cmd, skipping" >&2
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
$cmake_format_cmd -i cmake/*.cmake */CMakeLists.txt CMakeLists.txt
|
|
||||||
@@ -5,127 +5,156 @@
|
|||||||
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
|
|
||||||
set(cockatrice_SOURCES
|
set(cockatrice_SOURCES
|
||||||
src/abstractcarddragitem.cpp
|
src/game/cards/abstract_card_drag_item.cpp
|
||||||
src/abstractcarditem.cpp
|
src/game/cards/abstract_card_item.cpp
|
||||||
src/abstractclient.cpp
|
src/client/game_logic/abstract_client.cpp
|
||||||
src/abstractcounter.cpp
|
src/game/board/abstract_counter.cpp
|
||||||
src/abstractgraphicsitem.cpp
|
src/game/board/abstract_graphics_item.cpp
|
||||||
src/arrowitem.cpp
|
src/game/board/arrow_item.cpp
|
||||||
src/arrowtarget.cpp
|
src/game/board/arrow_target.cpp
|
||||||
src/carddatabase.cpp
|
src/game/cards/card_database.cpp
|
||||||
src/carddatabasemodel.cpp
|
src/game/cards/card_database_manager.cpp
|
||||||
src/carddbparser/carddatabaseparser.cpp
|
src/game/cards/card_database_model.cpp
|
||||||
src/carddbparser/cockatricexml3.cpp
|
src/game/cards/card_database_parser/card_database_parser.cpp
|
||||||
src/carddbparser/cockatricexml4.cpp
|
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
|
||||||
src/carddragitem.cpp
|
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
|
||||||
src/cardfilter.cpp
|
src/game/cards/card_drag_item.cpp
|
||||||
src/cardframe.cpp
|
src/game/filters/filter_card.cpp
|
||||||
src/cardinfopicture.cpp
|
src/client/ui/widgets/cards/card_info_frame_widget.cpp
|
||||||
src/cardinfotext.cpp
|
src/client/ui/widgets/cards/card_info_picture_widget.cpp
|
||||||
src/cardinfowidget.cpp
|
src/client/ui/widgets/cards/card_info_text_widget.cpp
|
||||||
src/carditem.cpp
|
src/client/ui/widgets/cards/card_info_display_widget.cpp
|
||||||
src/cardlist.cpp
|
src/client/ui/widgets/cards/card_size_widget.cpp
|
||||||
src/cardzone.cpp
|
src/game/cards/card_item.cpp
|
||||||
src/chatview/chatview.cpp
|
src/game/cards/card_list.cpp
|
||||||
src/counter_general.cpp
|
src/game/zones/card_zone.cpp
|
||||||
src/customlineedit.cpp
|
src/server/chat_view/chat_view.cpp
|
||||||
src/deck_loader.cpp
|
src/game/board/counter_general.cpp
|
||||||
src/decklistmodel.cpp
|
src/deck/custom_line_edit.cpp
|
||||||
src/deckstats_interface.cpp
|
src/deck/deck_loader.cpp
|
||||||
src/deckview.cpp
|
src/deck/deck_list_model.cpp
|
||||||
src/dlg_connect.cpp
|
src/deck/deck_stats_interface.cpp
|
||||||
src/dlg_create_token.cpp
|
src/deck/deck_view.cpp
|
||||||
src/dlg_creategame.cpp
|
src/dialogs/dlg_connect.cpp
|
||||||
src/dlg_edit_avatar.cpp
|
src/dialogs/dlg_create_token.cpp
|
||||||
src/dlg_edit_password.cpp
|
src/dialogs/dlg_create_game.cpp
|
||||||
src/dlg_edit_tokens.cpp
|
src/dialogs/dlg_edit_avatar.cpp
|
||||||
src/dlg_edit_user.cpp
|
src/dialogs/dlg_edit_password.cpp
|
||||||
src/dlg_filter_games.cpp
|
src/dialogs/dlg_edit_tokens.cpp
|
||||||
src/dlg_forgotpasswordchallenge.cpp
|
src/dialogs/dlg_edit_user.cpp
|
||||||
src/dlg_forgotpasswordrequest.cpp
|
src/dialogs/dlg_filter_games.cpp
|
||||||
src/dlg_forgotpasswordreset.cpp
|
src/dialogs/dlg_forgot_password_challenge.cpp
|
||||||
src/dlg_load_deck_from_clipboard.cpp
|
src/dialogs/dlg_forgot_password_request.cpp
|
||||||
src/dlg_load_remote_deck.cpp
|
src/dialogs/dlg_forgot_password_reset.cpp
|
||||||
src/dlg_manage_sets.cpp
|
src/dialogs/dlg_load_deck_from_clipboard.cpp
|
||||||
src/dlg_register.cpp
|
src/dialogs/dlg_load_remote_deck.cpp
|
||||||
src/dlg_settings.cpp
|
src/dialogs/dlg_manage_sets.cpp
|
||||||
src/dlg_tip_of_the_day.cpp
|
src/dialogs/dlg_move_top_cards_until.cpp
|
||||||
src/dlg_update.cpp
|
src/dialogs/dlg_register.cpp
|
||||||
src/dlg_viewlog.cpp
|
src/dialogs/dlg_roll_dice.cpp
|
||||||
src/filter_string.cpp
|
src/dialogs/dlg_settings.cpp
|
||||||
src/filterbuilder.cpp
|
src/dialogs/dlg_tip_of_the_day.cpp
|
||||||
src/filtertree.cpp
|
src/dialogs/dlg_update.cpp
|
||||||
src/filtertreemodel.cpp
|
src/dialogs/dlg_view_log.cpp
|
||||||
src/gamescene.cpp
|
src/game/filters/filter_string.cpp
|
||||||
src/gameselector.cpp
|
src/game/filters/filter_builder.cpp
|
||||||
src/gamesmodel.cpp
|
src/game/filters/filter_tree.cpp
|
||||||
src/gameview.cpp
|
src/game/filters/filter_tree_model.cpp
|
||||||
src/gettextwithmax.cpp
|
src/client/ui/layouts/flow_layout.cpp
|
||||||
src/handcounter.cpp
|
src/client/ui/layouts/horizontal_flow_layout.cpp
|
||||||
src/handle_public_servers.cpp
|
src/client/ui/layouts/vertical_flow_layout.cpp
|
||||||
src/handzone.cpp
|
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
|
||||||
src/keysignals.cpp
|
src/game/game_scene.cpp
|
||||||
src/lineeditcompleter.cpp
|
src/game/game_selector.cpp
|
||||||
src/localclient.cpp
|
src/game/games_model.cpp
|
||||||
src/localserver.cpp
|
src/game/game_view.cpp
|
||||||
src/localserverinterface.cpp
|
src/client/get_text_with_max.cpp
|
||||||
src/logger.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/messagelogwidget.cpp
|
src/server/message_log_widget.cpp
|
||||||
src/pending_command.cpp
|
src/client/ui/layouts/overlap_layout.cpp
|
||||||
src/phase.cpp
|
src/client/ui/widgets/general/layout_containers/overlap_widget.cpp
|
||||||
src/phasestoolbar.cpp
|
src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||||
src/pictureloader.cpp
|
src/server/pending_command.cpp
|
||||||
src/pilezone.cpp
|
src/game/phase.cpp
|
||||||
src/pixmapgenerator.cpp
|
src/client/ui/phases_toolbar.cpp
|
||||||
src/player.cpp
|
src/client/ui/picture_loader.cpp
|
||||||
src/playerlistwidget.cpp
|
src/game/zones/pile_zone.cpp
|
||||||
src/playertarget.cpp
|
src/client/ui/pixel_map_generator.cpp
|
||||||
src/releasechannel.cpp
|
src/game/player/player.cpp
|
||||||
src/remoteclient.cpp
|
src/game/player/player_list_widget.cpp
|
||||||
src/remotedecklist_treewidget.cpp
|
src/game/player/player_target.cpp
|
||||||
src/remotereplaylist_treewidget.cpp
|
src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp
|
||||||
src/replay_timeline_widget.cpp
|
src/client/ui/widgets/printing_selector/card_amount_widget.cpp
|
||||||
src/selectzone.cpp
|
src/client/ui/widgets/printing_selector/printing_selector.cpp
|
||||||
src/sequenceEdit/sequenceedit.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp
|
||||||
src/setsmodel.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
|
||||||
src/settings/carddatabasesettings.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
|
||||||
src/settings/downloadsettings.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
|
||||||
src/settings/gamefilterssettings.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
|
||||||
src/settings/layoutssettings.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_view_options_toolbar_widget.cpp
|
||||||
src/settings/messagesettings.cpp
|
src/client/ui/widgets/printing_selector/printing_selector_view_options_widget.cpp
|
||||||
src/settings/serverssettings.cpp
|
src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
|
||||||
src/settings/settingsmanager.cpp
|
src/client/network/release_channel.cpp
|
||||||
src/settingscache.cpp
|
src/server/remote/remote_client.cpp
|
||||||
src/shortcutssettings.cpp
|
src/server/remote/remote_decklist_tree_widget.cpp
|
||||||
src/soundengine.cpp
|
src/server/remote/remote_replay_list_tree_widget.cpp
|
||||||
src/spoilerbackgroundupdater.cpp
|
src/client/network/replay_timeline_widget.cpp
|
||||||
src/stackzone.cpp
|
src/game/zones/select_zone.cpp
|
||||||
src/tab.cpp
|
src/utility/sequence_edit.cpp
|
||||||
src/tab_account.cpp
|
src/client/network/sets_model.cpp
|
||||||
src/tab_admin.cpp
|
src/settings/card_database_settings.cpp
|
||||||
src/tab_deck_editor.cpp
|
src/settings/download_settings.cpp
|
||||||
src/tab_deck_storage.cpp
|
src/settings/game_filters_settings.cpp
|
||||||
src/tab_game.cpp
|
src/settings/layouts_settings.cpp
|
||||||
src/tab_logs.cpp
|
src/settings/message_settings.cpp
|
||||||
src/tab_message.cpp
|
src/settings/servers_settings.cpp
|
||||||
src/tab_replays.cpp
|
src/settings/settings_manager.cpp
|
||||||
src/tab_room.cpp
|
src/settings/cache_settings.cpp
|
||||||
src/tab_server.cpp
|
src/settings/shortcuts_settings.cpp
|
||||||
src/tab_supervisor.cpp
|
src/settings/shortcut_treeview.cpp
|
||||||
src/tablezone.cpp
|
src/client/sound_engine.cpp
|
||||||
src/tappedout_interface.cpp
|
src/client/network/spoiler_background_updater.cpp
|
||||||
src/thememanager.cpp
|
src/game/zones/stack_zone.cpp
|
||||||
src/tip_of_the_day.cpp
|
src/client/tabs/tab.cpp
|
||||||
src/translatecountername.cpp
|
src/client/tabs/tab_account.cpp
|
||||||
src/update_downloader.cpp
|
src/client/tabs/tab_admin.cpp
|
||||||
src/user_context_menu.cpp
|
src/client/tabs/tab_deck_editor.cpp
|
||||||
src/userconnection_information.cpp
|
src/client/tabs/tab_deck_storage.cpp
|
||||||
src/userinfobox.cpp
|
src/client/tabs/tab_game.cpp
|
||||||
src/userlist.cpp
|
src/client/tabs/tab_logs.cpp
|
||||||
src/window_main.cpp
|
src/client/tabs/tab_message.cpp
|
||||||
src/zoneviewwidget.cpp
|
src/client/tabs/tab_replays.cpp
|
||||||
src/zoneviewzone.cpp
|
src/client/tabs/tab_room.cpp
|
||||||
|
src/client/tabs/tab_server.cpp
|
||||||
|
src/client/tabs/tab_supervisor.cpp
|
||||||
|
src/game/zones/table_zone.cpp
|
||||||
|
src/client/tapped_out_interface.cpp
|
||||||
|
src/client/ui/theme_manager.cpp
|
||||||
|
src/client/ui/tip_of_the_day.cpp
|
||||||
|
src/client/translate_counter_name.cpp
|
||||||
|
src/client/update_downloader.cpp
|
||||||
|
src/server/user/user_context_menu.cpp
|
||||||
|
src/server/user/user_info_connection.cpp
|
||||||
|
src/server/user/user_info_box.cpp
|
||||||
|
src/server/user/user_list.cpp
|
||||||
|
src/client/ui/window_main.cpp
|
||||||
|
src/game/zones/view_zone_widget.cpp
|
||||||
|
src/game/zones/view_zone.cpp
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -311,15 +340,9 @@ if(WIN32)
|
|||||||
PATTERN "audio/qtaudio_wasapi.dll"
|
PATTERN "audio/qtaudio_wasapi.dll"
|
||||||
PATTERN "audio/qtaudio_windows.dll"
|
PATTERN "audio/qtaudio_windows.dll"
|
||||||
PATTERN "iconengines/qsvgicon.dll"
|
PATTERN "iconengines/qsvgicon.dll"
|
||||||
PATTERN "imageformats/qgif.dll"
|
PATTERN "imageformats/*.dll"
|
||||||
PATTERN "imageformats/qicns.dll"
|
PATTERN "mediaservice/dsengine.dll"
|
||||||
PATTERN "imageformats/qico.dll"
|
PATTERN "mediaservice/wmfengine.dll"
|
||||||
PATTERN "imageformats/qjpeg.dll"
|
|
||||||
PATTERN "imageformats/qsvg.dll"
|
|
||||||
PATTERN "imageformats/qtga.dll"
|
|
||||||
PATTERN "imageformats/qtiff.dll"
|
|
||||||
PATTERN "imageformats/qwbmp.dll"
|
|
||||||
PATTERN "imageformats/qwebp.dll"
|
|
||||||
PATTERN "platforms/qdirect2d.dll"
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
PATTERN "platforms/qminimal.dll"
|
PATTERN "platforms/qminimal.dll"
|
||||||
PATTERN "platforms/qoffscreen.dll"
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
@@ -355,13 +378,13 @@ Data = Resources\")
|
|||||||
COMPONENT Runtime
|
COMPONENT Runtime
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32SSLRUNTIME_FOUND)
|
if(OPENSSL_FOUND)
|
||||||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
install(FILES ${OPENSSL_INCLUDE_DIRS} DESTINATION ./)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Qt6LinguistTools_FOUND)
|
if(Qt6_FOUND AND Qt6LinguistTools_FOUND)
|
||||||
# Qt6 Translations happen after the executable is built up
|
#Qt6 Translations happen after the executable is built up
|
||||||
if(UPDATE_TRANSLATIONS)
|
if(UPDATE_TRANSLATIONS)
|
||||||
qt6_add_translations(
|
qt6_add_translations(
|
||||||
cockatrice
|
cockatrice
|
||||||
|
|||||||
@@ -351,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.
@@ -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>
|
||||||
|
|||||||
@@ -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,7 +18,6 @@
|
|||||||
#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>
|
||||||
|
|
||||||
@@ -53,7 +52,7 @@ AbstractClient::AbstractClient(QObject *parent)
|
|||||||
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()
|
||||||
@@ -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);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "gettextwithmax.h"
|
#include "get_text_with_max.h"
|
||||||
|
|
||||||
QString getTextWithMax(QWidget *parent,
|
QString getTextWithMax(QWidget *parent,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#ifndef GETTEXTWITHMAX_H
|
#ifndef GETTEXTWITHMAX_H
|
||||||
#define GETTEXTWITHMAX_H
|
#define GETTEXTWITHMAX_H
|
||||||
|
|
||||||
#include "stringsizes.h"
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "releasechannel.h"
|
#include "release_channel.h"
|
||||||
|
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
|
||||||
@@ -38,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+)");
|
||||||
@@ -62,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
|
||||||
@@ -153,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()
|
||||||
@@ -255,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()
|
||||||
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,4 @@
|
|||||||
#include "setsmodel.h"
|
#include "sets_model.h"
|
||||||
|
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
@@ -195,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;
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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";
|
||||||
const auto reloadOk = QtConcurrent::run([] { db->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();
|
||||||
|
}
|
||||||
@@ -15,9 +15,9 @@ 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:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#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>
|
||||||
@@ -18,7 +18,7 @@ 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);
|
||||||
|
|
||||||
@@ -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,18 +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 "stringsizes.h"
|
|
||||||
#include "userinfobox.h"
|
|
||||||
#include "userlist.h"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
@@ -30,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;
|
||||||
@@ -63,9 +56,9 @@ TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor,
|
|||||||
addBuddyEdit = new LineEditUnfocusable;
|
addBuddyEdit = new LineEditUnfocusable;
|
||||||
addBuddyEdit->setMaxLength(MAX_NAME_LENGTH);
|
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);
|
||||||
|
|
||||||
@@ -73,9 +66,9 @@ TabUserLists::TabUserLists(TabSupervisor *_tabSupervisor,
|
|||||||
addIgnoreEdit = new LineEditUnfocusable;
|
addIgnoreEdit = new LineEditUnfocusable;
|
||||||
addIgnoreEdit->setMaxLength(MAX_NAME_LENGTH);
|
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,8 +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 "stringsizes.h"
|
#include "trice_limits.h"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
@@ -29,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);
|
||||||
@@ -57,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);
|
||||||
@@ -74,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,23 +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 "stringsizes.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>
|
||||||
@@ -48,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);
|
||||||
@@ -68,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()));
|
||||||
@@ -162,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);
|
||||||
@@ -177,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");
|
||||||
@@ -186,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);
|
||||||
@@ -261,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);
|
||||||
@@ -339,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);
|
||||||
@@ -361,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());
|
||||||
@@ -376,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);
|
||||||
@@ -394,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);
|
||||||
@@ -415,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();
|
||||||
@@ -454,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);
|
||||||
}
|
}
|
||||||
@@ -464,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"));
|
||||||
@@ -487,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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,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()
|
||||||
@@ -572,14 +637,17 @@ void TabDeckEditor::loadLayout()
|
|||||||
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());
|
||||||
@@ -590,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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,6 +676,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
|||||||
createDeckDock();
|
createDeckDock();
|
||||||
createCardInfoDock();
|
createCardInfoDock();
|
||||||
createFiltersDock();
|
createFiltersDock();
|
||||||
|
createPrintingSelectorDock();
|
||||||
|
|
||||||
this->installEventFilter(this);
|
this->installEventFilter(this);
|
||||||
|
|
||||||
@@ -664,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"));
|
||||||
@@ -679,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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,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());
|
||||||
@@ -713,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)
|
||||||
@@ -735,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)
|
||||||
@@ -754,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());
|
||||||
@@ -767,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());
|
||||||
@@ -781,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);
|
||||||
@@ -854,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -956,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();
|
||||||
@@ -965,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)
|
||||||
@@ -976,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);
|
||||||
@@ -989,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())
|
||||||
@@ -998,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);
|
||||||
@@ -1073,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();
|
||||||
@@ -1096,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);
|
||||||
|
|
||||||
@@ -1153,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) {
|
||||||
@@ -1162,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;
|
||||||
}
|
}
|
||||||
@@ -1186,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()
|
||||||
@@ -1205,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)
|
||||||
@@ -1224,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()
|
||||||
@@ -1274,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,9 +1,12 @@
|
|||||||
#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 "gettextwithmax.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"
|
||||||
#include "pb/command_deck_download.pb.h"
|
#include "pb/command_deck_download.pb.h"
|
||||||
@@ -12,9 +15,6 @@
|
|||||||
#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>
|
||||||
@@ -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,18 +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 "stringsizes.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>
|
||||||
@@ -255,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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,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);
|
||||||
@@ -576,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())
|
||||||
@@ -593,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()
|
||||||
@@ -839,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);
|
||||||
@@ -914,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -986,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;
|
||||||
|
|
||||||
@@ -999,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();
|
||||||
@@ -1087,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);
|
||||||
}
|
}
|
||||||
@@ -1354,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)));
|
||||||
@@ -1704,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();
|
||||||
@@ -1758,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;
|
||||||
@@ -1813,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)));
|
||||||
|
|
||||||
@@ -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,12 +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 "stringsizes.h"
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
@@ -89,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;
|
||||||
|
|
||||||
@@ -1,16 +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 "stringsizes.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -159,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,12 +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 "stringsizes.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>
|
||||||
@@ -155,7 +155,7 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -496,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);
|
||||||
@@ -541,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";
|
||||||
}
|
}
|
||||||
@@ -687,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
|
||||||
@@ -729,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;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef TAB_SUPERVISOR_H
|
#ifndef TAB_SUPERVISOR_H
|
||||||
#define TAB_SUPERVISOR_H
|
#define TAB_SUPERVISOR_H
|
||||||
|
|
||||||
#include "chatview/userlistProxy.h"
|
#include "../../deck/deck_loader.h"
|
||||||
#include "deck_loader.h"
|
#include "../../server/chat_view/user_list_proxy.h"
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QCommonStyle>
|
#include <QCommonStyle>
|
||||||
@@ -120,6 +120,7 @@ public:
|
|||||||
bool isUserBuddy(const QString &userName) const;
|
bool isUserBuddy(const QString &userName) const;
|
||||||
bool isUserIgnored(const QString &userName) const;
|
bool isUserIgnored(const QString &userName) const;
|
||||||
const ServerInfo_User *getOnlineUser(const QString &userName) const;
|
const ServerInfo_User *getOnlineUser(const QString &userName) const;
|
||||||
|
bool switchToGameTabIfAlreadyExists(const int gameId);
|
||||||
void actShowPopup(const QString &message);
|
void actShowPopup(const QString &message);
|
||||||
signals:
|
signals:
|
||||||
void setMenu(const QList<QMenu *> &newMenuList = QList<QMenu *>());
|
void setMenu(const QList<QMenu *> &newMenuList = QList<QMenu *>());
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "tappedout_interface.h"
|
#include "tapped_out_interface.h"
|
||||||
|
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QRegExp>
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
@@ -15,13 +14,13 @@ TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *par
|
|||||||
: QObject(parent), cardDatabase(_cardDatabase)
|
: QObject(parent), cardDatabase(_cardDatabase)
|
||||||
{
|
{
|
||||||
manager = new QNetworkAccessManager(this);
|
manager = new QNetworkAccessManager(this);
|
||||||
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
connect(manager, &QNetworkAccessManager::finished, this, &TappedOutInterface::queryFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
QMessageBox::critical(0, tr("Error"), reply->errorString());
|
QMessageBox::critical(nullptr, tr("Error"), reply->errorString());
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
deleteLater();
|
deleteLater();
|
||||||
return;
|
return;
|
||||||
@@ -42,26 +41,26 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
|||||||
* from the html. Css pseudo selector for errors: $("div.alert-danger > ul > li")
|
* from the html. Css pseudo selector for errors: $("div.alert-danger > ul > li")
|
||||||
*/
|
*/
|
||||||
QString data(reply->readAll());
|
QString data(reply->readAll());
|
||||||
QString errorMessage = tr("Unable to analyze the deck.");
|
QStringList errorMessageList = {tr("Unable to analyze the deck.")};
|
||||||
|
|
||||||
QRegExp rx("<div class=\"alert alert-danger.*<ul>(.*)</ul>");
|
static const QRegularExpression rx("<div class=\"alert alert-danger.*?<ul>(.*?)</ul>");
|
||||||
rx.setMinimal(true);
|
auto match = rx.match(data);
|
||||||
int found = rx.indexIn(data);
|
if (match.hasMatch()) {
|
||||||
if (found >= 0) {
|
QString errors = match.captured(1);
|
||||||
QString errors = rx.cap(1);
|
static const QRegularExpression rx2("<li>(.*?)</li>");
|
||||||
QRegExp rx2("<li>(.*)</li>");
|
static const QRegularExpression rxremove("<[^>]*>");
|
||||||
rx2.setMinimal(true);
|
auto matchIterator = rx2.globalMatch(errors);
|
||||||
|
while (matchIterator.hasNext()) {
|
||||||
int captures = rx2.captureCount();
|
auto match2 = matchIterator.next();
|
||||||
for (int i = 1; i <= captures; i++) {
|
errorMessageList.append(match2.captured(1).remove(rxremove).simplified());
|
||||||
errorMessage += QString("\n") + rx2.cap(i).remove(QRegularExpression("<[^>]*>")).simplified();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString errorMessage = errorMessageList.join("\n");
|
||||||
qDebug() << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size() << "message"
|
qDebug() << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size() << "message"
|
||||||
<< errorMessage;
|
<< errorMessage;
|
||||||
|
|
||||||
QMessageBox::critical(0, tr("Error"), errorMessage);
|
QMessageBox::critical(nullptr, tr("Error"), errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef TAPPEDOUT_INTERFACE_H
|
#ifndef TAPPEDOUT_INTERFACE_H
|
||||||
#define TAPPEDOUT_INTERFACE_H
|
#define TAPPEDOUT_INTERFACE_H
|
||||||
|
|
||||||
#include "carddatabase.h"
|
#include "../game/cards/card_database.h"
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -1,29 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "settingscache.h"
|
#include "../settings/cache_settings.h"
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
class TearOffMenu : public QMenu
|
class TearOffMenu : public QMenu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TearOffMenu(const QString &title, QWidget *parent = nullptr) : QMenu(title, parent)
|
explicit TearOffMenu(const QString &title, QWidget *parent = nullptr) : QMenu(title, parent)
|
||||||
{
|
{
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
||||||
[=](bool state) { setTearOffEnabled(state); });
|
[this](const bool state) { setTearOffEnabled(state); });
|
||||||
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
||||||
}
|
}
|
||||||
|
|
||||||
TearOffMenu(QWidget *parent = nullptr) : QMenu(parent)
|
explicit TearOffMenu(QWidget *parent = nullptr) : QMenu(parent)
|
||||||
{
|
{
|
||||||
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
connect(&SettingsCache::instance(), &SettingsCache::useTearOffMenusChanged, this,
|
||||||
[=](bool state) { setTearOffEnabled(state); });
|
[this](const bool state) { setTearOffEnabled(state); });
|
||||||
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
setTearOffEnabled(SettingsCache::instance().getUseTearOffMenus());
|
||||||
}
|
}
|
||||||
|
|
||||||
TearOffMenu *addTearOffMenu(const QString &title)
|
TearOffMenu *addTearOffMenu(const QString &title)
|
||||||
{
|
{
|
||||||
TearOffMenu *menu = new TearOffMenu(title, this);
|
auto *menu = new TearOffMenu(title, this);
|
||||||
addMenu(menu);
|
addMenu(menu);
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "translatecountername.h"
|
#include "translate_counter_name.h"
|
||||||
|
|
||||||
const QMap<QString, QString> TranslateCounterName::translated = {
|
const QMap<QString, QString> TranslateCounterName::translated = {
|
||||||
{"life", QT_TRANSLATE_NOOP("TranslateCounterName", "Life")},
|
{"life", QT_TRANSLATE_NOOP("TranslateCounterName", "Life")},
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user