diff --git a/.ci/Debian11/Dockerfile b/.ci/Debian11/Dockerfile
deleted file mode 100644
index b994863bf..000000000
--- a/.ci/Debian11/Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-FROM debian:11
-
-RUN apt-get update && \
- DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
- build-essential \
- ccache \
- clang-format \
- cmake \
- file \
- g++ \
- git \
- liblzma-dev \
- libmariadb-dev-compat \
- libprotobuf-dev \
- libqt5multimedia5-plugins \
- libqt5sql5-mysql \
- libqt5svg5-dev \
- libqt5websockets5-dev \
- ninja-build \
- protobuf-compiler \
- qt5-image-formats-plugins \
- qtmultimedia5-dev \
- qttools5-dev \
- qttools5-dev-tools \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/*
diff --git a/.ci/Fedora42/Dockerfile b/.ci/Fedora44/Dockerfile
similarity index 95%
rename from .ci/Fedora42/Dockerfile
rename to .ci/Fedora44/Dockerfile
index ee4a856f2..e6c8da7f3 100644
--- a/.ci/Fedora42/Dockerfile
+++ b/.ci/Fedora44/Dockerfile
@@ -1,4 +1,4 @@
-FROM fedora:42
+FROM fedora:44
RUN dnf install -y \
ccache \
diff --git a/.ci/Servatrice_Debian11/Dockerfile b/.ci/Servatrice_Debian12/Dockerfile
similarity index 75%
rename from .ci/Servatrice_Debian11/Dockerfile
rename to .ci/Servatrice_Debian12/Dockerfile
index fadc9e0e7..21f6a036e 100644
--- a/.ci/Servatrice_Debian11/Dockerfile
+++ b/.ci/Servatrice_Debian12/Dockerfile
@@ -1,4 +1,4 @@
-FROM debian:11
+FROM debian:12
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@@ -11,11 +11,11 @@ RUN apt-get update && \
git \
libmariadb-dev-compat \
libprotobuf-dev \
- libqt5sql5-mysql \
- libqt5websockets5-dev \
+ libqt6sql6-mysql \
ninja-build \
protobuf-compiler \
- qttools5-dev \
- qttools5-dev-tools \
+ qt6-tools-dev \
+ qt6-tools-dev-tools \
+ qt6-websockets-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
diff --git a/.ci/Ubuntu22.04/Dockerfile b/.ci/Ubuntu22.04/Dockerfile
deleted file mode 100644
index 93c8fdea9..000000000
--- a/.ci/Ubuntu22.04/Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && \
- DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
- build-essential \
- ccache \
- clang-format \
- cmake \
- file \
- g++ \
- git \
- liblzma-dev \
- libmariadb-dev-compat \
- libprotobuf-dev \
- libqt5multimedia5-plugins \
- libqt5sql5-mysql \
- libqt5svg5-dev \
- libqt5websockets5-dev \
- ninja-build \
- protobuf-compiler \
- qt5-image-formats-plugins \
- qtmultimedia5-dev \
- qttools5-dev \
- qttools5-dev-tools \
- && apt-get clean \
- && rm -rf /var/lib/apt/lists/*
diff --git a/.ci/compile.sh b/.ci/compile.sh
index c157847ed..0a109b4f4 100755
--- a/.ci/compile.sh
+++ b/.ci/compile.sh
@@ -205,7 +205,11 @@ if [[ $RUNNER_OS == macOS ]]; then
arch="x64"
fi
mkdir -p "$triplets_dir"
- cp "../vcpkg/triplets/$arch-osx.cmake" "$triplet_file"
+ triplet_source="../vcpkg/triplets/$arch-osx.cmake"
+ if [[ ! -f "$triplet_source" ]]; then
+ triplet_source="../vcpkg/triplets/community/$arch-osx.cmake"
+ fi
+ cp "$triplet_source" "$triplet_file"
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file"
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file"
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
diff --git a/.ci/release_template.md b/.ci/release_template.md
index 1ce9f4bf7..ac78a193a 100644
--- a/.ci/release_template.md
+++ b/.ci/release_template.md
@@ -19,12 +19,10 @@ Available pre-compiled binaries for installation:
Linux
• Ubuntu 26.04 LTSResolute Racoon
• Ubuntu 24.04 LTSNoble Numbat
- • Ubuntu 22.04 LTSJammy Jellyfish
• Debian 13Trixie
• Debian 12Bookworm
- • Debian 11Bullseye
+ • Fedora 44
• Fedora 43
- • Fedora 42We are also packaged in Arch Linux's official extra repository, courtesy of @FFY00.General Linux support is available via a flatpak package at Flathub!
@@ -85,7 +83,6 @@ Remove empty headers when done.
### Under the Hood
### Oracle
### Servatrice
-### Webatrice
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 88bed3663..404cac62e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -10,7 +10,7 @@ updates:
# Look for `.gitmodules` in the `root` directory
directory: "/"
ignore:
- # Ignore updates for vcpkg (Bump to latest tag not working (no SemVer used) & macOS Intel triplet broken with newer releases)
+ # Ignore updates for vcpkg (Bump to latest tag not working (no SemVer used)
- dependency-name: "vcpkg"
# Check for updates once a month
schedule:
@@ -39,13 +39,3 @@ updates:
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
diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml
index aeed5da81..62108b34a 100644
--- a/.github/workflows/desktop-build.yml
+++ b/.github/workflows/desktop-build.yml
@@ -14,10 +14,8 @@ on:
- '*/**' # matches all files not in root
- '!**.md'
- '!.github/**'
- - '!.husky/**'
- '!.tx/**'
- '!doc/**'
- - '!webclient/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
@@ -29,10 +27,8 @@ on:
- '*/**' # matches all files not in root
- '!**.md'
- '!.github/**'
- - '!.husky/**'
- '!.tx/**'
- '!doc/**'
- - '!webclient/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
@@ -46,7 +42,7 @@ concurrency:
jobs:
configure:
name: Configure
- runs-on: ubuntu-latest
+ runs-on: ubuntu-slim
outputs:
tag: ${{steps.configure.outputs.tag}}
sha: ${{steps.configure.outputs.sha}}
@@ -111,12 +107,8 @@ jobs:
package: skip # We are packaged in Arch already
allow-failure: yes
- - distro: Debian
- version: 11
- package: DEB
-
- distro: Servatrice_Debian
- version: 11
+ version: 12
package: DEB
test: skip
server_only: yes
@@ -131,22 +123,18 @@ jobs:
package: DEB
- distro: Fedora
- version: 42
+ version: 43
package: RPM
test: skip # Running tests on all distros is superfluous
- distro: Fedora
- version: 43
+ version: 44
package: RPM
- - distro: Ubuntu
- version: 22.04
- package: DEB
- test: skip # Running tests on all distros is superfluous
-
- distro: Ubuntu
version: 24.04
package: DEB
+ test: skip # Running tests on all distros is superfluous
- distro: Ubuntu
version: 26.04
@@ -265,7 +253,7 @@ jobs:
shell: bash
env:
GH_TOKEN: ${{github.token}}
- run: gh attestation verify ${{steps.build.outputs.path}} --repo Cockatrice/Cockatrice
+ run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice
build-vcpkg:
strategy:
@@ -281,7 +269,7 @@ jobs:
override_target: 13
make_package: 1
package_suffix: "-macOS13_Intel"
- qt_version: 6.11.*
+ qt_version: 6.11.0
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cmake_generator: Ninja
@@ -296,7 +284,7 @@ jobs:
type: Release
make_package: 1
package_suffix: "-macOS14"
- qt_version: 6.11.*
+ qt_version: 6.11.0
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cmake_generator: Ninja
@@ -311,7 +299,7 @@ jobs:
type: Release
make_package: 1
package_suffix: "-macOS15"
- qt_version: 6.11.*
+ qt_version: 6.11.0
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cmake_generator: Ninja
@@ -324,7 +312,7 @@ jobs:
soc: Apple
xcode: "16.4"
type: Debug
- qt_version: 6.11.*
+ qt_version: 6.11.0
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cmake_generator: Ninja
@@ -337,7 +325,7 @@ jobs:
type: Release
make_package: 1
package_suffix: "-Win10"
- qt_version: 6.11.*
+ qt_version: 6.11.0
qt_arch: win64_msvc2022_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cmake_generator: "Visual Studio 17 2022"
@@ -494,7 +482,7 @@ jobs:
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
- /usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose ${{steps.build.outputs.path}}
+ /usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "${{steps.build.outputs.path}}"
fi
- name: Notarize app bundle
@@ -514,7 +502,7 @@ jobs:
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
# notarization service
echo "Creating temp notarization archive"
- ditto -c -k --keepParent ${{steps.build.outputs.path}} "notarization.zip"
+ ditto -c -k --keepParent "${{steps.build.outputs.path}}" "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
@@ -526,7 +514,7 @@ jobs:
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available.
echo "Attach staple"
- xcrun stapler staple ${{steps.build.outputs.path}}
+ xcrun stapler staple "${{steps.build.outputs.path}}"
fi
- name: Upload artifact
@@ -573,4 +561,4 @@ jobs:
shell: bash
env:
GH_TOKEN: ${{github.token}}
- run: gh attestation verify ${{steps.build.outputs.path}} --repo Cockatrice/Cockatrice
+ run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice
diff --git a/.github/workflows/desktop-lint.yml b/.github/workflows/desktop-lint.yml
index 433f302a5..df8b9f89e 100644
--- a/.github/workflows/desktop-lint.yml
+++ b/.github/workflows/desktop-lint.yml
@@ -8,10 +8,8 @@ on:
- '!**.md'
- '!.ci/**'
- '!.github/**'
- - '!.husky/**'
- '!.tx/**'
- '!doc/**'
- - '!webclient/**'
- '.ci/lint_cpp.sh'
- '.github/workflows/desktop-lint.yml'
- '.clang-format'
@@ -20,13 +18,13 @@ on:
jobs:
format:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-slim
steps:
- name: Checkout
uses: actions/checkout@v6
with:
- fetch-depth: 20 # should be enough to find merge base
+ fetch-depth: 20 # should be enough to find merge base
- name: Install dependencies
shell: bash
diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml
index fca1e97d4..b869d1fa9 100644
--- a/.github/workflows/docker-release.yml
+++ b/.github/workflows/docker-release.yml
@@ -1,9 +1,10 @@
name: Build Docker Image
on:
+ release:
+ types:
+ - released # publishing of stable releases
push:
- tags:
- - '*Release*'
branches:
- master
pull_request:
@@ -16,16 +17,18 @@ on:
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
concurrency:
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
- cancel-in-progress: ${{ github.ref_type != 'tag' }}
+ cancel-in-progress: ${{ github.event_name != 'release' }}
jobs:
docker:
name: amd64 & arm64
+ if: ${{ github.repository_owner == 'Cockatrice' }}
runs-on: ubuntu-latest
+
permissions:
contents: read
packages: write
-
+
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -33,6 +36,8 @@ jobs:
- name: Docker metadata
id: metadata
uses: docker/metadata-action@v6
+ env:
+ DOCKER_METADATA_ANNOTATIONS_LEVELS: index # needed for GHCR
with:
images: |
ghcr.io/cockatrice/servatrice
@@ -52,7 +57,7 @@ jobs:
uses: docker/setup-buildx-action@v4
- name: Login to GitHub Container Registry
- if: github.ref_type == 'tag'
+ if: contains(github.event.release.tag_name, 'Release') && github.event.release.target_commitish == 'master'
uses: docker/login-action@v4
with:
registry: ghcr.io
diff --git a/.github/workflows/documentation-build.yml b/.github/workflows/documentation-build.yml
index ce331d113..7306c726a 100644
--- a/.github/workflows/documentation-build.yml
+++ b/.github/workflows/documentation-build.yml
@@ -33,7 +33,7 @@ jobs:
- name: Install Doxygen
uses: ssciwr/doxygen-install@v2
with:
- version: "1.14.0"
+ version: "1.16.1"
- name: Update Doxygen Configuration
run: |
diff --git a/.github/workflows/translations-pull.yml b/.github/workflows/translations-pull.yml
index ed61e3b19..8f673fce9 100644
--- a/.github/workflows/translations-pull.yml
+++ b/.github/workflows/translations-pull.yml
@@ -16,7 +16,7 @@ jobs:
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
name: Pull languages
- runs-on: ubuntu-latest
+ runs-on: ubuntu-slim
steps:
- name: Checkout repo
@@ -38,7 +38,6 @@ jobs:
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
diff --git a/.github/workflows/translations-push.yml b/.github/workflows/translations-push.yml
index d5524e782..ad5b1c170 100644
--- a/.github/workflows/translations-push.yml
+++ b/.github/workflows/translations-push.yml
@@ -16,7 +16,7 @@ jobs:
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
name: Push strings
- runs-on: ubuntu-latest
+ runs-on: ubuntu-slim
steps:
- name: Checkout repo
@@ -49,7 +49,7 @@ jobs:
- name: Render template
id: template
- uses: chuhlomin/render-template@v1
+ uses: chuhlomin/render-template/binary@v1
with:
template: .ci/update_translation_source_strings_template.md
vars: |
diff --git a/.github/workflows/web-build.yml b/.github/workflows/web-build.yml
deleted file mode 100644
index 8d756da02..000000000
--- a/.github/workflows/web-build.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-name: Build Web
-
-on:
- push:
- branches:
- - master
- paths:
- - '.husky/**'
- - 'webclient/**'
- - '!**.md'
- - '.github/workflows/web-build.yml'
- pull_request:
- paths:
- - '.husky/**'
- - 'webclient/**'
- - '!**.md'
- - '.github/workflows/web-build.yml'
-
-jobs:
- build-web:
- name: React (Node ${{matrix.node_version}})
-
- runs-on: ubuntu-latest
-
- defaults:
- run:
- working-directory: webclient
-
- strategy:
- fail-fast: false
- matrix:
- node_version:
- - 16
- - lts/*
-
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: ${{matrix.node_version}}
- cache: 'npm'
- cache-dependency-path: 'webclient/package-lock.json'
-
- - name: Install dependencies
- run: npm clean-install
-
- - name: Build app
- run: npm run build
-
- - name: Test app
- run: npm run test
diff --git a/.github/workflows/web-lint.yml b/.github/workflows/web-lint.yml
deleted file mode 100644
index 8a90325e7..000000000
--- a/.github/workflows/web-lint.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: Code Style (TypeScript)
-
-on:
- # push trigger not needed for linting, we do not allow direct pushes to master
- pull_request:
- paths:
- - 'webclient/**'
- - '!**.md'
- - '.github/workflows/web-lint.yml'
-
-jobs:
- ESLint:
- runs-on: ubuntu-latest
-
- defaults:
- run:
- working-directory: webclient
-
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- cache: 'npm'
- cache-dependency-path: 'webclient/package-lock.json'
-
- - name: Install ESLint
- run: npm clean-install --ignore-scripts
-
- - name: Run ESLint
- run: npm run lint
diff --git a/.husky/pre-commit b/.husky/pre-commit
deleted file mode 100755
index 369435d6b..000000000
--- a/.husky/pre-commit
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
-cd webclient
-npm run translate
-
-git add src/i18n-default.json
diff --git a/.tx/config b/.tx/config
index 9bc5ce950..8174a4dfd 100644
--- a/.tx/config
+++ b/.tx/config
@@ -16,11 +16,3 @@ source_file = oracle/oracle_en@source.ts
file_filter = oracle/translations/oracle_.ts
type = QT
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//translation.json
-type = KEYVALUEJSON
-minimum_perc = 10
diff --git a/CMakeLists.txt b/CMakeLists.txt
index afdd4f1b3..652c8e840 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,11 +72,11 @@ endif()
# A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake
-project("Cockatrice" VERSION 2.11.0)
+project("Cockatrice" VERSION 3.0.1)
# Set release name if not provided via env/cmake var
if(NOT DEFINED GIT_TAG_RELEASENAME)
- set(GIT_TAG_RELEASENAME "Omenpath")
+ set(GIT_TAG_RELEASENAME "Graduation Day")
endif()
# Use c++20 for all targets
@@ -172,6 +172,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-Wno-error=delete-non-virtual-dtor
-Wno-error=sign-compare
-Wno-error=missing-declarations
+ -Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward decls trigger this
)
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
diff --git a/Dockerfile b/Dockerfile
index d185b746a..7c5c773c9 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# -------- Build Stage --------
-FROM ubuntu:24.04 AS build
+FROM ubuntu:26.04 AS build
ARG DEBIAN_FRONTEND=noninteractive
@@ -26,7 +26,7 @@ RUN mkdir build && cd build && \
# -------- Runtime Stage (clean) --------
-FROM ubuntu:24.04
+FROM ubuntu:26.04
RUN apt-get update && apt-get install -y --no-install-recommends \
libprotobuf32t64 \
diff --git a/Doxyfile b/Doxyfile
index 0f2642fd8..fc96b5f22 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.14.0
+# Doxyfile 1.16.1
# This file describes the settings to be used by the documentation system
# Doxygen (www.doxygen.org) for a project.
@@ -361,6 +361,20 @@ EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
+# If the MARKDOWN_STRICT tag is enabled then Doxygen treats text in comments as
+# Markdown formatted also in cases where Doxygen's native markup format
+# conflicts with that of Markdown. This is only relevant in cases where
+# backticks are used. Doxygen's native markup style allows a single quote to end
+# a text fragment started with a backtick and then treat it as a piece of quoted
+# text, whereas in Markdown such text fragment is treated as verbatim and only
+# ends when a second matching backtick is found. Also, Doxygen's native markup
+# format requires double quotes to be escaped when they appear in a backtick
+# section, whereas this is not needed for Markdown.
+# The default value is: YES.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+MARKDOWN_STRICT = YES
+
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
@@ -392,8 +406,8 @@ AUTOLINK_SUPPORT = YES
# This tag specifies a list of words that, when matching the start of a word in
# the documentation, will suppress auto links generation, if it is enabled via
-# AUTOLINK_SUPPORT. This list does not affect links explicitly created using \#
-# or the \link or commands.
+# AUTOLINK_SUPPORT. This list does not affect links explicitly created using #
+# or the \link or \ref commands.
# This tag requires that the tag AUTOLINK_SUPPORT is set to YES.
AUTOLINK_IGNORE_WORDS =
@@ -510,9 +524,9 @@ LOOKUP_CACHE_SIZE = 0
# which effectively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
-# Minimum value: 0, maximum value: 32, default value: 1.
+# Minimum value: 0, maximum value: 512, default value: 1.
-NUM_PROC_THREADS = 1
+NUM_PROC_THREADS = 0
# If the TIMESTAMP tag is set different from NO then each generated page will
# contain the date or date and time when the page was generated. Setting this to
@@ -779,6 +793,27 @@ GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
+# The GENERATE_REQUIREMENTS tag can be used to enable (YES) or disable (NO) the
+# requirements page. When enabled, this page is automatically created when at
+# least one comment block with a \requirement command appears in the input.
+# The default value is: YES.
+
+GENERATE_REQUIREMENTS = YES
+
+# The REQ_TRACEABILITY_INFO tag controls if traceability information is shown on
+# the requirements page (only relevant when using \requirement comment blocks).
+# The setting NO will disable the traceablility information altogether. The
+# setting UNSATISFIED_ONLY will show a list of requirements that are missing a
+# satisfies relation (through the command: \satisfies). Similarly the setting
+# UNVERIFIED_ONLY will show a list of requirements that are missing a verifies
+# relation (through the command: \verifies). Setting the tag to YES (the
+# default) will show both lists if applicable.
+# Possible values are: YES, NO, UNSATISFIED_ONLY and UNVERIFIED_ONLY.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_REQUIREMENTS is set to YES.
+
+REQ_TRACEABILITY_INFO = YES
+
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if ... \endif and \cond
# ... \endcond blocks.
@@ -1070,8 +1105,7 @@ EXCLUDE = build/ \
cmake/ \
doc/doxygen/theme/docs/ \
doc/doxygen/theme/include/ \
- vcpkg/ \
- webclient/
+ vcpkg/
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -1887,7 +1921,7 @@ USE_MATHJAX = NO
# regards to the different settings, so it is possible that also other MathJax
# settings have to be changed when switching between the different MathJax
# versions.
-# Possible values are: MathJax_2 and MathJax_3.
+# Possible values are: MathJax_2, MathJax_3 and MathJax_4.
# The default value is: MathJax_2.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1896,9 +1930,10 @@ MATHJAX_VERSION = MathJax_2
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. For more details about the output format see MathJax
# version 2 (see:
-# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# https://docs.mathjax.org/en/v2.7/output.html), MathJax version 3 (see:
+# https://docs.mathjax.org/en/v3.2/output/index.html) and MathJax version 4
# (see:
-# http://docs.mathjax.org/en/latest/web/components/output.html).
+# https://docs.mathjax.org/en/v4.0/output/index.htm).
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
@@ -1911,36 +1946,50 @@ MATHJAX_VERSION = MathJax_2
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
-# output directory using the MATHJAX_RELPATH option. The destination directory
-# should contain the MathJax.js script. For instance, if the mathjax directory
-# is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
-# Content Delivery Network so you can quickly see the result without installing
-# MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from https://www.mathjax.org before deployment. The default value is:
+# output directory using the MATHJAX_RELPATH option. For Mathjax version 2 the
+# destination directory should contain the MathJax.js script. For instance, if
+# the mathjax directory is located at the same level as the HTML output
+# directory, then MATHJAX_RELPATH should be ../mathjax.s For Mathjax versions 3
+# and 4 the destination directory should contain the tex-.js script
+# (where is either chtml or svg). The default value points to the
+# MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax. However, it is strongly recommended to install a local
+# copy of MathJax from https://www.mathjax.org before deployment. The default
+# value is:
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# - in case of MathJax version 4: https://cdn.jsdelivr.net/npm/mathjax@4
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH =
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
-# for MathJax version 2 (see
-# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# for MathJax version 2 (see https://docs.mathjax.org/en/v2.7/tex.html):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# For example for MathJax version 3 (see
-# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# https://docs.mathjax.org/en/v3.2/input/tex/extensions/):
# MATHJAX_EXTENSIONS = ams
+# For example for MathJax version 4 (see
+# https://docs.mathjax.org/en/v4.0/input/tex/extensions/):
+# MATHJAX_EXTENSIONS = units
+# Note that for Mathjax version 4 quite a few extensions are already
+# automatically loaded. To disable a package in Mathjax version 4 one can use
+# the package name prepended with a minus sign (- like MATHJAX_EXTENSIONS +=
+# -textmacros)
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces
-# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see:
-# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
-# example see the documentation.
+# of code that will be used on startup of the MathJax code. See the Mathjax site
+# for more details:
+# - MathJax version 2 (see:
+# https://docs.mathjax.org/en/v2.7/)
+# - MathJax version 3 (see:
+# https://docs.mathjax.org/en/v3.2/)
+# - MathJax version 4 (see:
+# https://docs.mathjax.org/en/v4.0/) For an example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
@@ -2601,7 +2650,7 @@ HAVE_DOT = YES
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
-# Minimum value: 0, maximum value: 32, default value: 0.
+# Minimum value: 0, maximum value: 512, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
diff --git a/README.md b/README.md
index 8fda3c865..f22df461f 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
Related|Community|Contribute|
- Build|
+ Build|Run
@@ -25,7 +25,6 @@
Cockatrice is an open-source, multiplatform application for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline.
This project uses C++ and the Qt libraries.
-First work on a webclient with Typescript was started as well.
# Download [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0)
@@ -48,6 +47,7 @@ Latest beta version:
- [Magic-Spoiler](https://github.com/Cockatrice/Magic-Spoiler): Code to generate MtG spoiler data from [MTGJSON](https://github.com/mtgjson/mtgjson) for use in Cockatrice
- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official Cockatrice webpage
- [io.github.Cockatrice.cockatrice](https://github.com/flathub/io.github.Cockatrice.cockatrice): Configuration of our Linux `flatpak` package hosted at [Flathub](https://flathub.org/en/apps/io.github.Cockatrice.cockatrice)
+- [Webatrice](https://github.com/Cockatrice/Webatrice): Web client for Cockatrice servers (TypeScript / React)
# Community Resources [](https://discord.gg/3Z9yzmA)
@@ -107,12 +107,12 @@ Cockatrice tries to use the [Google Developer Documentation Style Guide](https:/
### Translation [](https://explore.transifex.com/cockatrice/cockatrice/)
-Cockatrice uses Transifex to manage translations. You can help us bring Cockatrice, Oracle and Webatrice to your language and just adjust single wordings right from within your browser by visiting our [Transifex project page](https://explore.transifex.com/cockatrice/cockatrice/).
+Cockatrice uses Transifex to manage translations. You can help us bring Cockatrice and Oracle to your language and just adjust single wordings right from within your browser by visiting our [Transifex project page](https://explore.transifex.com/cockatrice/cockatrice/). The [Webatrice](https://github.com/seavor/Webatrice) web client manages its own translations in its repo.
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about getting involved, and join a group of hundreds of others!
-# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
+# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml?query=branch%3Amaster+event%3Apush)
Dependencies: *(for minimum versions search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
- [Qt](https://www.qt.io/developers/)
diff --git a/cmake/NSIS.template.in b/cmake/NSIS.template.in
index 2fdc61fb9..7b52b7bcc 100644
--- a/cmake/NSIS.template.in
+++ b/cmake/NSIS.template.in
@@ -11,6 +11,7 @@ SetCompressor LZMA
Var NormalDestDir
Var PortableDestDir
Var PortableMode
+Var ReinstallMode
!include LogicLib.nsh
!include FileFunc.nsh
@@ -28,13 +29,23 @@ Var PortableMode
!define MUI_FINISHPAGE_RUN_TEXT "Run 'Cockatrice' now"
!define MUI_ICON "${NSIS_SOURCE_PATH}\cockatrice\resources\appicon.ico"
+!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
!insertmacro MUI_PAGE_WELCOME
+
+!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\LICENSE"
+
Page Custom PortableModePageCreate PortableModePageLeave
!define MUI_PAGE_CUSTOMFUNCTION_PRE componentsPagePre
!insertmacro MUI_PAGE_COMPONENTS
+
+!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
!insertmacro MUI_PAGE_DIRECTORY
+
+!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
!insertmacro MUI_PAGE_INSTFILES
+
+!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
@@ -73,6 +84,7 @@ ${IfNot} ${Errors}
MessageBox MB_ICONINFORMATION|MB_SETFOREGROUND "\
/PORTABLE : Install in portable mode$\n\
/S : Silent install$\n\
+ /R : Silent upgrade$\n\
/D=%directory% : Specify destination directory$\n"
Quit
${EndIf}
@@ -90,6 +102,16 @@ ${Else}
${EndIf}
${EndIf}
+ClearErrors
+${GetOptions} $9 "/R" $8
+${IfNot} ${Errors}
+ StrCpy $ReinstallMode 1
+ SetSilent silent
+ SetAutoClose true
+${Else}
+ StrCpy $ReinstallMode 0
+${EndIf}
+
${If} $InstDir == ""
; User did not use /D to specify a directory,
; we need to set a default based on the install mode
@@ -97,6 +119,22 @@ ${If} $InstDir == ""
${EndIf}
Call SetModeDestinationFromInstdir
+; --- Detect portable install when using /R ---
+${If} $ReinstallMode = 1
+ IfFileExists "$InstDir\portable.dat" 0 not_portable
+ StrCpy $PortableMode 1
+ Goto portable_done
+
+ not_portable:
+ StrCpy $PortableMode 0
+
+ portable_done:
+${EndIf}
+
+${If} $ReinstallMode = 1
+ Call AutoUninstallIfNeeded
+${EndIf}
+
FunctionEnd
Function un.onInit
@@ -126,8 +164,46 @@ ${Else}
${EndIf}
FunctionEnd
+Function SkipIfReinstall
+${If} $ReinstallMode = 1
+ Abort
+${EndIf}
+FunctionEnd
+
+Function AutoUninstallIfNeeded
+
+SetShellVarContext all
+
+; --- 32-bit uninstall ---
+SetRegView 32
+ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
+
+StrCmp $R0 "" done32
+DetailPrint "Removing previous version (32-bit)..."
+ExecWait '$R0'
+
+done32:
+
+; --- 64-bit uninstall ---
+${If} ${RunningX64}
+ SetRegView 64
+ ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
+
+ StrCmp $R0 "" done64
+ DetailPrint "Removing previous version (64-bit)..."
+ ExecWait '$R0'
+
+ done64:
+${EndIf}
+
+FunctionEnd
Function PortableModePageCreate
+
+${If} $ReinstallMode = 1
+ Abort
+${EndIf}
+
Call SetModeDestinationFromInstdir ; If the user clicks BACK on the directory page we will remember their mode specific directory
!insertmacro MUI_HEADER_TEXT "Install Mode" "Choose how you want to install Cockatrice."
nsDialogs::Create 1018
@@ -159,6 +235,11 @@ ${EndIf}
FunctionEnd
Function componentsPagePre
+
+${If} $ReinstallMode = 1
+ Return
+${EndIf}
+
${If} $PortableMode = 0
SetShellVarContext all
@@ -168,8 +249,12 @@ ${If} $PortableMode = 0
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString"
StrCmp $R0 "" done32
- MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst32
- Abort
+ ${If} $ReinstallMode = 0
+ MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst32
+ Abort
+ ${Else}
+ Goto uninst32
+ ${EndIf}
uninst32:
ClearErrors
@@ -184,8 +269,12 @@ ${If} $PortableMode = 0
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString"
StrCmp $R0 "" done64
- MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst64
- Abort
+ ${If} $ReinstallMode = 0
+ MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst64
+ Abort
+ ${Else}
+ Goto uninst64
+ ${EndIf}
uninst64:
ClearErrors
@@ -277,6 +366,12 @@ ${Else}
FileWrite $0 "PORTABLE"
FileClose $0
${EndIf}
+
+${If} $ReinstallMode = 1
+ IfFileExists "$INSTDIR\cockatrice.exe" 0 +2
+ Exec '"$INSTDIR\cockatrice.exe"'
+${EndIf}
+
SectionEnd
Section "Start menu item" SecStartMenu
diff --git a/cmake/getversion.cmake b/cmake/getversion.cmake
index cb27ebd87..b24b520d5 100644
--- a/cmake/getversion.cmake
+++ b/cmake/getversion.cmake
@@ -213,7 +213,8 @@ set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
# Format: [-ReleaseName]-MAJ.MIN.PATCH[-prerelease_label]
set(PROJECT_VERSION_FILENAME "${PROJECT_NAME}")
if(PROJECT_VERSION_RELEASENAME)
- set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME}")
+ string(REPLACE " " "-" PROJECT_VERSION_RELEASENAME_SAFE "${PROJECT_VERSION_RELEASENAME}")
+ set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME_SAFE}")
endif()
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION}")
diff --git a/cmake/gtest-CMakeLists.txt.in b/cmake/gtest-CMakeLists.txt.in
index 2d71a55e5..2062d7f8c 100644
--- a/cmake/gtest-CMakeLists.txt.in
+++ b/cmake/gtest-CMakeLists.txt.in
@@ -1,15 +1,16 @@
-cmake_minimum_required(VERSION 3.2)
+cmake_minimum_required(VERSION 3.10)
project(gtest-download LANGUAGES NONE)
include(ExternalProject)
-ExternalProject_Add(googletest
- URL https://github.com/google/googletest/archive/release-1.11.0.zip
- URL_HASH SHA1=9ffb7b5923f4a8fcdabf2f42c6540cce299f44c0
+externalproject_add(
+ googletest
+ URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip
+ URL_HASH SHA1=f638fa0e724760e2ba07ff8cfba32cd644e1ce28
SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/gtest-build"
CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- TEST_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
)
diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt
index e5e6f90b3..5212ef3c2 100644
--- a/cockatrice/CMakeLists.txt
+++ b/cockatrice/CMakeLists.txt
@@ -7,6 +7,7 @@ project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${
set(cockatrice_SOURCES
${VERSION_STRING_CPP}
# sort by alphabetical order, so that there is no debate about where to add new sources to the list
+ src/client/network/connection_controller/remote_connection_controller.cpp
src/client/network/update/client/update_downloader.cpp
src/client/network/interfaces/deck_stats_interface.cpp
src/client/network/interfaces/tapped_out_interface.cpp
@@ -216,6 +217,7 @@ set(cockatrice_SOURCES
src/interface/widgets/replay/replay_manager.cpp
src/interface/widgets/replay/replay_timeline_widget.cpp
src/interface/widgets/server/chat_view/chat_view.cpp
+ src/interface/widgets/server/game_filter_configs.cpp
src/interface/widgets/server/game_selector.cpp
src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp
src/interface/widgets/server/games_model.cpp
@@ -498,6 +500,7 @@ if(WIN32)
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
DESTINATION ./
FILES_MATCHING
+ PATTERN "CMakeFiles" EXCLUDE
PATTERN "*.ini"
)
diff --git a/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp
new file mode 100644
index 000000000..f517acdc4
--- /dev/null
+++ b/cockatrice/src/client/network/connection_controller/remote_connection_controller.cpp
@@ -0,0 +1,581 @@
+#include "remote_connection_controller.h"
+
+#include "../../settings/cache_settings.h"
+#include "../interface/widgets/dialogs/dlg_connect.h"
+#include "../interface/widgets/dialogs/dlg_forgot_password_challenge.h"
+#include "../interface/widgets/dialogs/dlg_forgot_password_request.h"
+#include "../interface/widgets/dialogs/dlg_forgot_password_reset.h"
+#include "../interface/widgets/dialogs/dlg_register.h"
+#include "../interface/widgets/utility/get_text_with_max.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+ConnectionController::ConnectionController(QWidget *dialogParent, QObject *parent)
+ : QObject(parent), dialogParent(dialogParent)
+{
+ remoteClient = new RemoteClient(nullptr, &SettingsCache::instance());
+
+ clientThread = new QThread(this);
+ remoteClient->moveToThread(clientThread);
+ clientThread->start();
+
+ wireClientSignals();
+}
+
+ConnectionController::~ConnectionController()
+{
+ remoteClient->deleteLater();
+ clientThread->wait();
+}
+
+void ConnectionController::wireClientSignals()
+{
+ connect(remoteClient, &RemoteClient::connectionClosedEventReceived, this,
+ &ConnectionController::onConnectionClosedEvent);
+
+ connect(remoteClient, &RemoteClient::serverShutdownEventReceived, this,
+ &ConnectionController::onServerShutdownEvent);
+
+ connect(remoteClient, &RemoteClient::statusChanged, this, &ConnectionController::onStatusChanged);
+
+ connect(remoteClient, &RemoteClient::userInfoChanged, this, &ConnectionController::onUserInfoReceived,
+ Qt::BlockingQueuedConnection);
+
+ connect(remoteClient, &RemoteClient::loginError, this,
+ [this](Response::ResponseCode r, QString rs, quint32 et, QList mf) {
+ onLoginError(static_cast(r), rs, et, mf);
+ });
+
+ connect(remoteClient, &RemoteClient::registerError, this,
+ [this](Response::ResponseCode r, QString rs, quint32 et) { onRegisterError(static_cast(r), rs, et); });
+
+ connect(remoteClient, &RemoteClient::activateError, this, &ConnectionController::onActivateError);
+ connect(remoteClient, &RemoteClient::socketError, this, &ConnectionController::onSocketError);
+ connect(remoteClient, &RemoteClient::serverTimeout, this, &ConnectionController::onServerTimeout);
+
+ connect(remoteClient, &RemoteClient::protocolVersionMismatch, this,
+ &ConnectionController::onProtocolVersionMismatch);
+
+ connect(remoteClient, &RemoteClient::registerAccepted, this, &ConnectionController::onRegisterAccepted);
+
+ connect(remoteClient, &RemoteClient::registerAcceptedNeedsActivate, this,
+ &ConnectionController::onRegisterAcceptedNeedsActivate);
+
+ connect(remoteClient, &RemoteClient::activateAccepted, this, &ConnectionController::onActivateAccepted);
+
+ connect(remoteClient, &RemoteClient::notifyUserAboutUpdate, this, &ConnectionController::onNotifyUserAboutUpdate);
+
+ connect(remoteClient, &RemoteClient::sigForgotPasswordSuccess, this,
+ &ConnectionController::onForgotPasswordSuccess);
+
+ connect(remoteClient, &RemoteClient::sigForgotPasswordError, this, &ConnectionController::onForgotPasswordError);
+
+ connect(remoteClient, &RemoteClient::sigPromptForForgotPasswordReset, this,
+ &ConnectionController::onPromptForgotPasswordReset);
+
+ connect(remoteClient, &RemoteClient::sigPromptForForgotPasswordChallenge, this,
+ &ConnectionController::onPromptForgotPasswordChallenge);
+}
+
+void ConnectionController::connectToServer()
+{
+ dlgConnect = new DlgConnect(dialogParent);
+ connect(dlgConnect, &DlgConnect::sigStartForgotPasswordRequest, this, &ConnectionController::forgotPasswordRequest);
+
+ if (dlgConnect->exec()) {
+ remoteClient->connectToServer(dlgConnect->getHost(), static_cast(dlgConnect->getPort()),
+ dlgConnect->getPlayerName(), dlgConnect->getPassword());
+ }
+}
+
+void ConnectionController::connectToServerDirect(const QString &host,
+ unsigned int port,
+ const QString &playerName,
+ const QString &password)
+{
+ remoteClient->connectToServer(host, port, playerName, password);
+}
+
+void ConnectionController::disconnectFromServer()
+{
+ remoteClient->disconnectFromServer();
+}
+
+void ConnectionController::registerToServer()
+{
+ DlgRegister dlg(dialogParent);
+ if (dlg.exec()) {
+ remoteClient->registerToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName(),
+ dlg.getPassword(), dlg.getEmail(), dlg.getCountry(), dlg.getRealName());
+ }
+}
+
+void ConnectionController::forgotPasswordRequest()
+{
+ DlgForgotPasswordRequest dlg(dialogParent);
+ if (dlg.exec()) {
+ remoteClient->requestForgotPasswordToServer(dlg.getHost(), static_cast(dlg.getPort()),
+ dlg.getPlayerName());
+ }
+}
+
+void ConnectionController::onConnectionClosedEvent(const Event_ConnectionClosed &event)
+{
+ remoteClient->disconnectFromServer();
+
+ QString reasonStr;
+ switch (event.reason()) {
+ case Event_ConnectionClosed::USER_LIMIT_REACHED: {
+ reasonStr = tr("The server has reached its maximum user capacity, please check back later.");
+ break;
+ }
+ case Event_ConnectionClosed::TOO_MANY_CONNECTIONS: {
+ reasonStr = tr("There are too many concurrent connections from your address.");
+ break;
+ }
+ case Event_ConnectionClosed::BANNED: {
+ reasonStr = tr("Banned by moderator");
+ if (event.has_end_time())
+ reasonStr.append(
+ "\n" + tr("Expected end time: %1").arg(QDateTime::fromSecsSinceEpoch(event.end_time()).toString()));
+ else
+ reasonStr.append("\n" + tr("This ban lasts indefinitely."));
+ if (event.has_reason_str())
+ reasonStr.append("\n\n" + QString::fromStdString(event.reason_str()));
+ break;
+ }
+ case Event_ConnectionClosed::SERVER_SHUTDOWN: {
+ reasonStr = tr("Scheduled server shutdown.");
+ break;
+ }
+ case Event_ConnectionClosed::USERNAMEINVALID: {
+ reasonStr = tr("Invalid username.");
+ break;
+ }
+ case Event_ConnectionClosed::LOGGEDINELSEWERE: {
+ reasonStr = tr("You have been logged out due to logging in at another location.");
+ break;
+ }
+ default:
+ reasonStr = QString::fromStdString(event.reason_str());
+ }
+
+ QMessageBox::critical(dialogParent, tr("Connection closed"),
+ tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
+}
+
+void ConnectionController::onServerShutdownEvent(const Event_ServerShutdown &event)
+{
+ serverShutdownMessageBox.setInformativeText(tr("The server is going to be restarted in %n minute(s).\nAll running "
+ "games will be lost.\nReason for shutdown: %1",
+ "", event.minutes())
+ .arg(QString::fromStdString(event.reason())));
+ serverShutdownMessageBox.setIconPixmap(QPixmap("theme:cockatrice").scaled(64, 64));
+ serverShutdownMessageBox.setText(tr("Scheduled server shutdown"));
+ serverShutdownMessageBox.setWindowModality(Qt::ApplicationModal);
+ serverShutdownMessageBox.setVisible(true);
+}
+
+void ConnectionController::onStatusChanged(ClientStatus status)
+{
+ // Update the window title first, then let MainWindow handle its own UI
+ // state via the forwarded signal
+ updateWindowTitle();
+ emit statusChanged(status);
+
+ // TabSupervisor::stop() needs calling on disconnect; start() is driven by
+ // onUserInfoReceived → tabSupervisorStartRequested.
+ if (status == StatusDisconnected) {
+ emit tabSupervisorStopRequested();
+ }
+}
+
+void ConnectionController::onUserInfoReceived(const ServerInfo_User &info)
+{
+ emit tabSupervisorStartRequested(info);
+}
+
+void ConnectionController::onLoginError(int r,
+ QString reasonStr,
+ quint32 endTime,
+ const QList &missingFeatures)
+{
+ switch (static_cast(r)) {
+ case Response::RespClientUpdateRequired: {
+ QString formatted = "Missing Features: ";
+ for (int i = 0; i < missingFeatures.size(); ++i) {
+ formatted.append(QString("\n %1").arg(QChar(0x2022)) + " " + missingFeatures.value(i));
+ }
+
+ QMessageBox msgBox(dialogParent);
+ msgBox.setIcon(QMessageBox::Critical);
+ msgBox.setWindowTitle(tr("Failed Login"));
+ msgBox.setText(tr("Your client seems to be missing features this server requires for connection.") +
+ "\n\n" + tr("To update your client, go to 'Help -> Check for Client Updates'."));
+ msgBox.setDetailedText(formatted);
+ msgBox.exec();
+ break;
+ }
+
+ case Response::RespWrongPassword: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("Incorrect username or password. "
+ "Please check your authentication information and try again."));
+ break;
+ }
+
+ case Response::RespWouldOverwriteOldSession: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("There is already an active session using this user name.\n"
+ "Please close that session first and re-login."));
+ break;
+ }
+
+ case Response::RespUserIsBanned: {
+ QString bannedStr =
+ endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString())
+ : tr("You are banned indefinitely.");
+ if (!reasonStr.isEmpty())
+ bannedStr.append("\n\n" + reasonStr);
+ QMessageBox::critical(dialogParent, tr("Error"), bannedStr);
+ break;
+ }
+
+ case Response::RespUsernameInvalid: {
+ QMessageBox::critical(dialogParent, tr("Error"), extractInvalidUsernameMessage(reasonStr));
+ break;
+ }
+
+ case Response::RespRegistrationRequired: {
+ if (QMessageBox::question(dialogParent, tr("Error"),
+ tr("This server requires user registration. Do you want to register now?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ registerToServer();
+ }
+ return; // don't re-prompt connect
+ }
+
+ case Response::RespClientIdRequired: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("This server requires client IDs. Your client is either failing to generate an "
+ "ID or you are running a modified client.\n"
+ "Please close and reopen your client to try again."));
+ break;
+ }
+
+ case Response::RespContextError: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("An internal error has occurred, please close and reopen Cockatrice before "
+ "trying again.\nIf the error persists, ensure you are running the latest "
+ "version of the software and if needed contact the software developers."));
+ break;
+ }
+
+ case Response::RespAccountNotActivated: {
+ bool ok = false;
+ QString token =
+ getTextWithMax(dialogParent, tr("Account activation"),
+ tr("Your account has not been activated yet.\n"
+ "You need to provide the activation token received in the activation email."),
+ QLineEdit::Normal, QString(), &ok);
+
+ if (ok && !token.isEmpty()) {
+ remoteClient->activateToServer(token);
+ return;
+ }
+ remoteClient->disconnectFromServer();
+ return;
+ }
+
+ case Response::RespServerFull: {
+ QMessageBox::critical(dialogParent, tr("Server Full"),
+ tr("The server has reached its maximum user capacity, please check back later."));
+ break;
+ }
+
+ default: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("Unknown login error: %1").arg(r) +
+ tr("\nThis usually means that your client version is out of date, and the server "
+ "sent a reply your client doesn't understand."));
+ break;
+ }
+ }
+
+ // Re-open the connect dialog after any handled error
+ connectToServer();
+}
+
+void ConnectionController::onRegisterError(int r, QString reasonStr, quint32 endTime)
+{
+ switch (static_cast(r)) {
+ case Response::RespRegistrationDisabled: {
+ QMessageBox::critical(dialogParent, tr("Registration denied"),
+ tr("Registration is currently disabled on this server"));
+ break;
+ }
+ case Response::RespUserAlreadyExists: {
+ QMessageBox::critical(dialogParent, tr("Registration denied"),
+ tr("There is already an existing account with the same user name."));
+ break;
+ }
+ case Response::RespEmailRequiredToRegister: {
+ QMessageBox::critical(dialogParent, tr("Registration denied"),
+ tr("It's mandatory to specify a valid email address when registering."));
+ break;
+ }
+ case Response::RespEmailBlackListed: {
+ if (reasonStr.isEmpty()) {
+ reasonStr =
+ "The email address provider used during registration has been blocked from use on this server.";
+ }
+ QMessageBox::critical(dialogParent, tr("Registration denied"), reasonStr);
+ break;
+ }
+ case Response::RespTooManyRequests: {
+ QMessageBox::critical(dialogParent, tr("Registration denied"),
+ tr("It appears you are attempting to register a new account on this server yet you "
+ "already have an account registered with the email provided. This server "
+ "restricts the number of accounts a user can register per address. Please "
+ "contact the server operator for further assistance or to obtain your "
+ "credential information."));
+ break;
+ }
+ case Response::RespPasswordTooShort: {
+ QMessageBox::critical(dialogParent, tr("Registration denied"), tr("Password too short."));
+ break;
+ }
+ case Response::RespUserIsBanned: {
+ QString bannedStr =
+ endTime ? tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString())
+ : tr("You are banned indefinitely.");
+ if (!reasonStr.isEmpty())
+ bannedStr.append("\n\n" + reasonStr);
+ QMessageBox::critical(dialogParent, tr("Error"), bannedStr);
+ break;
+ }
+ case Response::RespUsernameInvalid: {
+ QMessageBox::critical(dialogParent, tr("Error"), extractInvalidUsernameMessage(reasonStr));
+ break;
+ }
+ case Response::RespRegistrationFailed: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("Registration failed for a technical problem on the server."));
+ break;
+ }
+ case Response::RespNotConnected: {
+ QMessageBox::critical(dialogParent, tr("Error"), tr("The connection to the server has been lost."));
+ break;
+ }
+ default: {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("Unknown registration error: %1").arg(r) +
+ tr("\nThis usually means that your client version is out of date, and the server "
+ "sent a reply your client doesn't understand."));
+ break;
+ }
+ }
+
+ registerToServer();
+}
+
+void ConnectionController::onActivateError()
+{
+ QMessageBox::critical(dialogParent, tr("Error"), tr("Account activation failed"));
+ remoteClient->disconnectFromServer();
+ connectToServer();
+}
+
+void ConnectionController::onSocketError(const QString &errorStr)
+{
+ QMessageBox::critical(dialogParent, tr("Error"), tr("Socket error: %1").arg(errorStr));
+ connectToServer();
+}
+
+void ConnectionController::onServerTimeout()
+{
+ QMessageBox::critical(dialogParent, tr("Error"), tr("Server timeout"));
+ connectToServer();
+}
+
+void ConnectionController::onProtocolVersionMismatch(int localVersion, int remoteVersion)
+{
+ if (localVersion > remoteVersion) {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("You are trying to connect to an obsolete server. Please downgrade your Cockatrice "
+ "version or connect to a suitable server.\n"
+ "Local version is %1, remote version is %2.")
+ .arg(localVersion)
+ .arg(remoteVersion));
+ } else {
+ QMessageBox::critical(dialogParent, tr("Error"),
+ tr("Your Cockatrice client is obsolete. Please update your Cockatrice version.\n"
+ "Local version is %1, remote version is %2.")
+ .arg(localVersion)
+ .arg(remoteVersion));
+ }
+}
+
+void ConnectionController::onRegisterAccepted()
+{
+ QMessageBox::information(dialogParent, tr("Success"), tr("Registration accepted.\nWill now login."));
+}
+
+void ConnectionController::onRegisterAcceptedNeedsActivate()
+{
+ // Server will send activation email; nothing to display here.
+}
+
+void ConnectionController::onActivateAccepted()
+{
+ QMessageBox::information(dialogParent, tr("Success"), tr("Account activation accepted.\nWill now login."));
+}
+
+void ConnectionController::onNotifyUserAboutUpdate()
+{
+ QMessageBox::information(
+ dialogParent, tr("Information"),
+ tr("This server supports additional features that your client doesn't have.\n"
+ "This is most likely not a problem, but this message might mean there is a new version of "
+ "Cockatrice available or this server is running a custom or pre-release version.\n\n"
+ "To update your client, go to Help -> Check for Updates."));
+}
+
+void ConnectionController::onForgotPasswordSuccess()
+{
+ QMessageBox::information(
+ dialogParent, tr("Reset Password"),
+ tr("Your password has been reset successfully, you can now log in using the new credentials."));
+ SettingsCache::instance().servers().setFPHostName("");
+ SettingsCache::instance().servers().setFPPort("");
+ SettingsCache::instance().servers().setFPPlayerName("");
+}
+
+void ConnectionController::onForgotPasswordError()
+{
+ QMessageBox::warning(
+ dialogParent, tr("Reset Password"),
+ tr("Failed to reset user account password, please contact the server operator to reset your password."));
+ SettingsCache::instance().servers().setFPHostName("");
+ SettingsCache::instance().servers().setFPPort("");
+ SettingsCache::instance().servers().setFPPlayerName("");
+}
+
+void ConnectionController::onPromptForgotPasswordReset()
+{
+ QMessageBox::information(dialogParent, tr("Reset Password"),
+ tr("Activation request received, please check your email for an activation token."));
+ DlgForgotPasswordReset dlg(dialogParent);
+ if (dlg.exec()) {
+ remoteClient->submitForgotPasswordResetToServer(dlg.getHost(), static_cast(dlg.getPort()),
+ dlg.getPlayerName(), dlg.getToken(), dlg.getPassword());
+ }
+}
+
+void ConnectionController::onPromptForgotPasswordChallenge()
+{
+ DlgForgotPasswordChallenge dlg(dialogParent);
+ if (dlg.exec()) {
+ remoteClient->submitForgotPasswordChallengeToServer(dlg.getHost(), static_cast(dlg.getPort()),
+ dlg.getPlayerName(), dlg.getEmail());
+ }
+}
+
+void ConnectionController::updateWindowTitle()
+{
+ const QString appName = QStringLiteral("Cockatrice");
+ QString title;
+
+ switch (remoteClient->getStatus()) {
+ case StatusConnecting: {
+ title = appName + " - " + tr("Connecting to %1...").arg(remoteClient->peerName());
+ break;
+ }
+ case StatusRegistering: {
+ title = appName + " - " +
+ tr("Registering to %1 as %2...").arg(remoteClient->peerName()).arg(remoteClient->getUserName());
+ break;
+ }
+ case StatusDisconnected: {
+ title = appName + " - " + tr("Disconnected");
+ break;
+ }
+ case StatusLoggingIn: {
+ title = appName + " - " + tr("Connected, logging in at %1").arg(remoteClient->peerName());
+ break;
+ }
+ case StatusLoggedIn: {
+ title = remoteClient->getUserName() + "@" + remoteClient->peerName();
+ break;
+ }
+ case StatusRequestingForgotPassword:
+ case StatusSubmitForgotPasswordChallenge:
+ case StatusSubmitForgotPasswordReset:
+ title = appName + " - " +
+ tr("Requesting forgotten password to %1 as %2...")
+ .arg(remoteClient->peerName())
+ .arg(remoteClient->getUserName());
+ break;
+ default:
+ title = appName;
+ }
+
+ emit windowTitleChanged(title);
+}
+
+// static
+QString ConnectionController::extractInvalidUsernameMessage(QString &in)
+{
+ QString out = tr("Invalid username.") + " ";
+ QStringList rules = in.split(QChar('|'));
+
+ if (rules.size() == 7 || rules.size() == 9) {
+ out += tr("Your username must respect these rules:") + "
" + tr("can contain the following punctuation: %1").arg(rules.at(6).toHtmlEscaped()) + "
";
+
+ out += "
" +
+ tr("first character can %1 be a punctuation mark").arg((rules.at(5).toInt() > 0) ? "" : tr("NOT")) +
+ "
";
+
+ if (rules.size() == 9) {
+ if (rules.at(7).size() > 0) {
+ QString words = rules.at(7).toHtmlEscaped();
+ if (words.startsWith("\n")) {
+ out += tr("no unacceptable language as specified by these server rules:",
+ "note that the following lines will not be translated");
+ for (QString &line : words.split("\n", Qt::SkipEmptyParts)) {
+ out += "
" + line + "
";
+ }
+ } else {
+ out += "
" + tr("can not contain any of the following words: %1").arg(words) + "
";
+ }
+ }
+
+ if (rules.at(8).size() > 0)
+ out += "
" +
+ tr("can not match any of the following expressions: %1").arg(rules.at(8).toHtmlEscaped()) +
+ "
";
+ }
+
+ out += "
";
+ } else {
+ out += tr("You may only use A-Z, a-z, 0-9, _, ., and - in your username.");
+ }
+
+ return out;
+}
\ No newline at end of file
diff --git a/cockatrice/src/client/network/connection_controller/remote_connection_controller.h b/cockatrice/src/client/network/connection_controller/remote_connection_controller.h
new file mode 100644
index 000000000..7486bc81a
--- /dev/null
+++ b/cockatrice/src/client/network/connection_controller/remote_connection_controller.h
@@ -0,0 +1,98 @@
+#ifndef COCKATRICE_REMOTE_CONNECTION_CONTROLLER_H
+#define COCKATRICE_REMOTE_CONNECTION_CONTROLLER_H
+
+#include "abstract_client.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class RemoteClient;
+class ServerInfo_User;
+class DlgConnect;
+
+/**
+ * Owns the RemoteClient and its worker thread.
+ * Encapsulates all connection, authentication, and registration logic so that
+ * MainWindow only needs to react to high-level signals.
+ */
+class ConnectionController : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ConnectionController(QWidget *dialogParent, QObject *parent = nullptr);
+ ~ConnectionController() override;
+
+ RemoteClient *client() const
+ {
+ return remoteClient;
+ }
+
+ void registerToServer();
+ void forgotPasswordRequest();
+ void connectToServer();
+ void
+ connectToServerDirect(const QString &host, unsigned int port, const QString &playerName, const QString &password);
+ void disconnectFromServer();
+
+ void refreshWindowTitle()
+ {
+ updateWindowTitle();
+ }
+
+signals:
+ void windowTitleChanged(const QString &title);
+
+ void tabSupervisorStartRequested(const ServerInfo_User &info);
+ void tabSupervisorStopRequested();
+
+ // Passes the raw ClientStatus through so MainWindow can drive its own
+ // action enable/disable logic
+ void statusChanged(ClientStatus status);
+
+private slots:
+ // Slots wired directly to RemoteClient signals
+ void onStatusChanged(ClientStatus status);
+ void onUserInfoReceived(const ServerInfo_User &info);
+ void onLoginError(int r, QString reasonStr, quint32 endTime, const QList &missingFeatures);
+ void onRegisterAccepted();
+ void onRegisterAcceptedNeedsActivate();
+ void onRegisterError(int r, QString reasonStr, quint32 endTime);
+ void onActivateAccepted();
+ void onActivateError();
+ void onProtocolVersionMismatch(int localVersion, int remoteVersion);
+ void onNotifyUserAboutUpdate();
+ void onConnectionClosedEvent(const Event_ConnectionClosed &event);
+ void onServerShutdownEvent(const Event_ServerShutdown &event);
+ void onSocketError(const QString &errorStr);
+ void onServerTimeout();
+
+ // Forgot-password flow
+ void onForgotPasswordSuccess();
+ void onForgotPasswordError();
+ void onPromptForgotPasswordReset();
+ void onPromptForgotPasswordChallenge();
+
+private:
+ void wireClientSignals();
+ void updateWindowTitle();
+
+ /** Parse the server's pipe-delimited username-rule string into HTML. */
+ static QString extractInvalidUsernameMessage(QString &in);
+
+ RemoteClient *remoteClient{nullptr};
+ QThread *clientThread{nullptr};
+ QWidget *dialogParent{nullptr}; // used as parent for QMessageBox / dialog calls
+
+ // Persistent so it can be updated in-place by onServerShutdownEvent
+ QMessageBox serverShutdownMessageBox;
+
+ // Kept as a member so the forgot-password signal can be wired to it
+ DlgConnect *dlgConnect{nullptr};
+};
+
+#endif // COCKATRICE_REMOTE_CONNECTION_CONTROLLER_H
diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
index a30a7f531..af377d176 100644
--- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
+++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp
@@ -89,6 +89,8 @@ void TappedOutInterface::analyzeDeck(const DeckList &deck)
QNetworkRequest request(QUrl("https://tappedout.net/mtg-decks/paste/"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
+ // we interpret the redirect and open it in the browser instead, do not follow redirects
+ request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
manager->post(request, data);
}
diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp
index a66897b4a..9a46c6426 100644
--- a/cockatrice/src/client/settings/cache_settings.cpp
+++ b/cockatrice/src/client/settings/cache_settings.cpp
@@ -211,6 +211,7 @@ SettingsCache::SettingsCache()
startupCardUpdateCheckAlwaysUpdate = settings->value("personal/startupCardUpdateCheckAlwaysUpdate", false).toBool();
cardUpdateCheckInterval = settings->value("personal/cardUpdateCheckInterval", 7).toInt();
lastCardUpdateCheck = settings->value("personal/lastCardUpdateCheck", QDateTime::currentDateTime().date()).toDate();
+ alwaysEnableNewSets = settings->value("personal/alwaysEnableNewSets", false).toBool();
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
notifyAboutNewVersion = settings->value("personal/newversionnotification", true).toBool();
@@ -1246,6 +1247,12 @@ void SettingsCache::setLastCardUpdateCheck(QDate value)
settings->setValue("personal/lastCardUpdateCheck", lastCardUpdateCheck);
}
+void SettingsCache::setAlwaysEnableNewSets(bool value)
+{
+ alwaysEnableNewSets = value;
+ settings->setValue("personal/alwaysEnableNewSets", alwaysEnableNewSets);
+}
+
void SettingsCache::setRememberGameSettings(const bool _rememberGameSettings)
{
rememberGameSettings = _rememberGameSettings;
diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h
index ece61487f..0cd5ceb68 100644
--- a/cockatrice/src/client/settings/cache_settings.h
+++ b/cockatrice/src/client/settings/cache_settings.h
@@ -216,6 +216,7 @@ private:
bool checkCardUpdatesOnStartup;
int cardUpdateCheckInterval;
QDate lastCardUpdateCheck;
+ bool alwaysEnableNewSets;
bool notifyAboutUpdates;
bool notifyAboutNewVersion;
bool showTipsOnStartup;
@@ -502,6 +503,10 @@ public:
return getLastCardUpdateCheck().daysTo(QDateTime::currentDateTime().date()) >= getCardUpdateCheckInterval() &&
getLastCardUpdateCheck() != QDateTime::currentDateTime().date();
}
+ [[nodiscard]] bool getAlwaysEnableNewSets() const
+ {
+ return alwaysEnableNewSets;
+ }
[[nodiscard]] bool getNotifyAboutUpdates() const override
{
return notifyAboutUpdates;
@@ -1125,6 +1130,7 @@ public slots:
void setStartupCardUpdateCheckAlwaysUpdate(bool value);
void setCardUpdateCheckInterval(int value);
void setLastCardUpdateCheck(QDate value);
+ void setAlwaysEnableNewSets(bool value);
void setNotifyAboutUpdate(QT_STATE_CHANGED_T _notifyaboutupdate);
void setNotifyAboutNewVersion(QT_STATE_CHANGED_T _notifyaboutnewversion);
void setUpdateReleaseChannelIndex(int value);
diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h
index 1de73c165..d9ea494dc 100644
--- a/cockatrice/src/client/settings/shortcuts_settings.h
+++ b/cockatrice/src/client/settings/shortcuts_settings.h
@@ -664,6 +664,9 @@ private:
{"Player/aRollDie", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Roll Dice..."),
parseSequenceString("Ctrl+I"),
ShortcutGroup::Gameplay)},
+ {"Player/aFlipCoin", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Flip Coin"),
+ parseSequenceString("Ctrl+Shift+I"),
+ ShortcutGroup::Gameplay)},
{"Player/aShuffle", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Shuffle Library"),
parseSequenceString("Ctrl+S"),
ShortcutGroup::Gameplay)},
diff --git a/cockatrice/src/game/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp
index cf3c7db20..072c1a231 100644
--- a/cockatrice/src/game/board/card_item.cpp
+++ b/cockatrice/src/game/board/card_item.cpp
@@ -396,6 +396,37 @@ void CardItem::playCard(bool faceDown)
}
}
+QVariantList CardItem::parsePT(const QString &pt)
+{
+ QVariantList ptList = QVariantList();
+ if (!pt.isEmpty()) {
+ int sep = pt.indexOf('/');
+ if (sep == 0) {
+ ptList.append(QVariant(pt.mid(1))); // cut off starting '/' and take full string
+ } else {
+ int start = 0;
+ for (;;) {
+ QString item = pt.mid(start, sep - start);
+ if (item.isEmpty()) {
+ ptList.append(QVariant(QString()));
+ } else if (item[0] == '+') {
+ ptList.append(QVariant(item.mid(1).toInt())); // add as int
+ } else if (item[0] == '-') {
+ ptList.append(QVariant(item.toInt())); // add as int
+ } else {
+ ptList.append(QVariant(item)); // add as qstring
+ }
+ if (sep == -1) {
+ break;
+ }
+ start = sep + 1;
+ sep = pt.indexOf('/', start);
+ }
+ }
+ }
+ return ptList;
+}
+
/**
* @brief returns true if the zone is a unwritable reveal zone view (eg a card reveal window). Will return false if zone
* is nullptr.
@@ -460,9 +491,6 @@ void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
bool CardItem::animationEvent()
{
- if (owner == nullptr) {
- return false;
- }
int rotation = ROTATION_DEGREES_PER_FRAME;
bool animationIncomplete = true;
if (!tapped)
diff --git a/cockatrice/src/game/board/card_item.h b/cockatrice/src/game/board/card_item.h
index da2097a2c..9799b5067 100644
--- a/cockatrice/src/game/board/card_item.h
+++ b/cockatrice/src/game/board/card_item.h
@@ -146,6 +146,26 @@ public:
void drawAttachArrow();
void playCard(bool faceDown);
+ /**
+ * @brief Parses a string representing a p/t in order to extract the values from it.
+ *
+ * If the string contains '/', the string will be split at the '/' and each side will be parsed separately,
+ * which means the result list will have two elements.
+ *
+ * If '/' is not found, then the entire string is parsed together, which means the result list will
+ * have a single element.
+ *
+ * If either side of the split is empty, there will also only be a single element in the result list.
+ *
+ * This function will attempt to parse each substring as an int first, handling plus and minus prefixes.
+ * If successful, it will put the parsed value into the QVariant as an int.
+ * If failed, it will just put the substring into the QVariant as a QString.
+ *
+ * @param pt The p/t string
+ * @return A QVariantList that can contain one or two elements, where each QVariant can be either int or QString
+ */
+ static QVariantList parsePT(const QString &pt);
+
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp
index 7bfc4da75..42dd49458 100644
--- a/cockatrice/src/game/game_event_handler.cpp
+++ b/cockatrice/src/game/game_event_handler.cpp
@@ -429,13 +429,13 @@ void GameEventHandler::eventLeave(const Event_Leave &event, int eventPlayerId, c
if (!player)
return;
+ player->clear();
emit playerLeft(eventPlayerId);
emit logLeave(player, getLeaveReason(event.reason()));
game->getPlayerManager()->removePlayer(eventPlayerId);
- player->clear();
player->deleteLater();
// Rearrange all remaining zones so that attachment relationship updates take place
diff --git a/cockatrice/src/game/game_scene.cpp b/cockatrice/src/game/game_scene.cpp
index 034ff6947..323adda38 100644
--- a/cockatrice/src/game/game_scene.cpp
+++ b/cockatrice/src/game/game_scene.cpp
@@ -58,6 +58,18 @@ void GameScene::retranslateUi()
view->retranslateUi();
}
+QList GameScene::selectedCards() const
+{
+ QList selectedCards;
+ for (auto item : selectedItems()) {
+ if (auto card = qgraphicsitem_cast(item)) {
+ selectedCards.append(card);
+ }
+ }
+
+ return selectedCards;
+}
+
/**
* @brief Adds a player to the scene and stores their graphics item.
* @param player Player to add.
diff --git a/cockatrice/src/game/game_scene.h b/cockatrice/src/game/game_scene.h
index f08e83aa4..2ce92b775 100644
--- a/cockatrice/src/game/game_scene.h
+++ b/cockatrice/src/game/game_scene.h
@@ -70,6 +70,9 @@ public:
/** Updates UI text for all zone views. */
void retranslateUi();
+ /** Gets all selected CardItems */
+ QList selectedCards() const;
+
/**
* @brief Adds a player to the scene and stores their graphics item.
* @param player Player to add.
diff --git a/cockatrice/src/game/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp
index c38e433eb..09f6e656b 100644
--- a/cockatrice/src/game/log/message_log_widget.cpp
+++ b/cockatrice/src/game/log/message_log_widget.cpp
@@ -54,7 +54,7 @@ MessageLogWidget::getFromStr(CardZoneLogic *zone, QString cardName, int position
fromStr = tr(" from the top of their library");
}
}
- } else if (position >= zone->getCards().size() - 1) {
+ } else if (position == zone->getCards().size()) {
if (cardName.isEmpty()) {
if (ownerChange) {
cardName = tr("the bottom card of %1's library").arg(zone->getPlayer()->getPlayerInfo()->getName());
diff --git a/cockatrice/src/game/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp
index 66ca5e46b..34ed254fb 100644
--- a/cockatrice/src/game/player/menu/card_menu.cpp
+++ b/cockatrice/src/game/player/menu/card_menu.cpp
@@ -75,17 +75,17 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
for (int i = 0; i < 6; ++i) {
auto *tempAddCounter = new QAction(this);
- tempAddCounter->setData(9 + i * 1000);
auto *tempRemoveCounter = new QAction(this);
- tempRemoveCounter->setData(10 + i * 1000);
auto *tempSetCounter = new QAction(this);
- tempSetCounter->setData(11 + i * 1000);
aAddCounter.append(tempAddCounter);
aRemoveCounter.append(tempRemoveCounter);
aSetCounter.append(tempSetCounter);
- connect(tempAddCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger);
- connect(tempRemoveCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger);
- connect(tempSetCounter, &QAction::triggered, playerActions, &PlayerActions::actCardCounterTrigger);
+ connect(tempAddCounter, &QAction::triggered, playerActions,
+ [playerActions, i] { playerActions->actAddCardCounter(i); });
+ connect(tempRemoveCounter, &QAction::triggered, playerActions,
+ [playerActions, i] { playerActions->actRemoveCardCounter(i); });
+ connect(tempSetCounter, &QAction::triggered, playerActions,
+ [playerActions, i] { playerActions->actSetCardCounter(i); });
}
setShortcutsActive();
diff --git a/cockatrice/src/game/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp
index 37bdcbbaf..bcb4683fd 100644
--- a/cockatrice/src/game/player/menu/utility_menu.cpp
+++ b/cockatrice/src/game/player/menu/utility_menu.cpp
@@ -19,6 +19,9 @@ UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu)
aRollDie = new QAction(this);
connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRollDie);
+ aFlipCoin = new QAction(this);
+ connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin);
+
aCreateToken = new QAction(this);
connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken);
@@ -38,6 +41,7 @@ UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu)
playerMenu->addAction(aUntapAll);
playerMenu->addSeparator();
playerMenu->addAction(aRollDie);
+ playerMenu->addAction(aFlipCoin);
playerMenu->addSeparator();
playerMenu->addAction(aCreateToken);
playerMenu->addAction(aCreateAnotherToken);
@@ -50,6 +54,7 @@ UtilityMenu::UtilityMenu(Player *_player, QMenu *playerMenu) : QMenu(playerMenu)
aIncrementAllCardCounters = nullptr;
aUntapAll = nullptr;
aRollDie = nullptr;
+ aFlipCoin = nullptr;
}
retranslateUi();
@@ -89,6 +94,7 @@ void UtilityMenu::retranslateUi()
aIncrementAllCardCounters->setText(tr("Increment all card counters"));
aUntapAll->setText(tr("&Untap all permanents"));
aRollDie->setText(tr("R&oll die..."));
+ aFlipCoin->setText(tr("Flip coin"));
aCreateToken->setText(tr("&Create token..."));
aCreateAnotherToken->setText(tr("C&reate another token"));
createPredefinedTokenMenu->setTitle(tr("Cr&eate predefined token"));
@@ -103,6 +109,7 @@ void UtilityMenu::setShortcutsActive()
aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters"));
aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll"));
aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie"));
+ aFlipCoin->setShortcuts(shortcuts.getShortcut("Player/aFlipCoin"));
aCreateToken->setShortcuts(shortcuts.getShortcut("Player/aCreateToken"));
aCreateAnotherToken->setShortcuts(shortcuts.getShortcut("Player/aCreateAnotherToken"));
}
@@ -113,6 +120,7 @@ void UtilityMenu::setShortcutsInactive()
if (player->getPlayerInfo()->getLocalOrJudge()) {
aUntapAll->setShortcut(QKeySequence());
aRollDie->setShortcut(QKeySequence());
+ aFlipCoin->setShortcut(QKeySequence());
aCreateToken->setShortcut(QKeySequence());
aCreateAnotherToken->setShortcut(QKeySequence());
aIncrementAllCardCounters->setShortcut(QKeySequence());
diff --git a/cockatrice/src/game/player/menu/utility_menu.h b/cockatrice/src/game/player/menu/utility_menu.h
index f6577d7d1..117a7e13a 100644
--- a/cockatrice/src/game/player/menu/utility_menu.h
+++ b/cockatrice/src/game/player/menu/utility_menu.h
@@ -47,7 +47,7 @@ private:
QMenu *createPredefinedTokenMenu;
QAction *aIncrementAllCardCounters;
- QAction *aUntapAll, *aRollDie;
+ QAction *aUntapAll, *aRollDie, *aFlipCoin;
QAction *aCreateToken, *aCreateAnotherToken;
};
diff --git a/cockatrice/src/game/player/player.cpp b/cockatrice/src/game/player/player.cpp
index ac4149f0e..e95e2b2ef 100644
--- a/cockatrice/src/game/player/player.cpp
+++ b/cockatrice/src/game/player/player.cpp
@@ -43,20 +43,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, A
connect(this, &Player::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged);
connect(this, &Player::openDeckEditor, game->getTab(), &TabGame::openDeckEditor);
-
- forwardActionSignalsToEventHandler();
-}
-
-// Event Handler is the controller i.e. everything hooks up to this to know about player state
-// Player should forward (private) signals to the event handler
-
-void Player::forwardActionSignalsToEventHandler()
-{
- connect(playerActions, &PlayerActions::logSetTapped, playerEventHandler, &PlayerEventHandler::logSetTapped);
- connect(playerActions, &PlayerActions::logSetDoesntUntap, playerEventHandler,
- &PlayerEventHandler::logSetDoesntUntap);
- connect(playerActions, &PlayerActions::logSetAnnotation, playerEventHandler, &PlayerEventHandler::logSetAnnotation);
- connect(playerActions, &PlayerActions::logSetPT, playerEventHandler, &PlayerEventHandler::logSetPT);
}
void Player::initializeZones()
@@ -323,19 +309,10 @@ void Player::clearCounters()
void Player::incrementAllCardCounters()
{
- QList cardsToUpdate;
-
- auto selectedItems = getGameScene()->selectedItems();
- if (!selectedItems.isEmpty()) {
- // If cards are selected, only update those
- for (const auto &item : selectedItems) {
- auto *card = static_cast(item);
- cardsToUpdate.append(card);
- }
- } else {
+ auto cardsToUpdate = getGameScene()->selectedCards();
+ if (cardsToUpdate.isEmpty()) {
// If no cards selected, update all cards on table
- const CardList &tableCards = getTableZone()->getCards();
- cardsToUpdate = tableCards;
+ cardsToUpdate = static_cast>(getTableZone()->getCards());
}
QList commandList;
diff --git a/cockatrice/src/game/player/player.h b/cockatrice/src/game/player/player.h
index e9c008821..9b8456aaf 100644
--- a/cockatrice/src/game/player/player.h
+++ b/cockatrice/src/game/player/player.h
@@ -82,7 +82,6 @@ public slots:
public:
Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent);
- void forwardActionSignalsToEventHandler();
~Player() override;
void initializeZones();
diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp
index 53d9d176a..e987335d8 100644
--- a/cockatrice/src/game/player/player_actions.cpp
+++ b/cockatrice/src/game/player/player_actions.cpp
@@ -852,6 +852,14 @@ void PlayerActions::actRollDie()
sendGameCommand(cmd);
}
+void PlayerActions::actFlipCoin()
+{
+ Command_RollDie cmd;
+ cmd.set_sides(2);
+ cmd.set_count(1);
+ sendGameCommand(cmd);
+}
+
void PlayerActions::actCreateToken()
{
DlgCreateToken dlg(player->getPlayerMenu()->getUtilityMenu()->getPredefinedTokens(), player->getGame()->getTab());
@@ -1149,61 +1157,6 @@ void PlayerActions::actSayMessage()
sendGameCommand(cmd);
}
-void PlayerActions::setCardAttrHelper(const GameEventContext &context,
- CardItem *card,
- CardAttribute attribute,
- const QString &avalue,
- bool allCards,
- EventProcessingOptions options)
-{
- if (card == nullptr) {
- return;
- }
-
- bool moveCardContext = context.HasExtension(Context_MoveCard::ext);
- switch (attribute) {
- case AttrTapped: {
- bool tapped = avalue == "1";
- if (!(!tapped && card->getDoesntUntap() && allCards)) {
- if (!allCards) {
- emit logSetTapped(player, card, tapped);
- }
- bool canAnimate = !options.testFlag(SKIP_TAP_ANIMATION) && !moveCardContext;
- card->setTapped(tapped, canAnimate);
- }
- break;
- }
- case AttrAttacking: {
- card->setAttacking(avalue == "1");
- break;
- }
- case AttrFaceDown: {
- card->setFaceDown(avalue == "1");
- break;
- }
- case AttrColor: {
- card->setColor(avalue);
- break;
- }
- case AttrAnnotation: {
- emit logSetAnnotation(player, card, avalue);
- card->setAnnotation(avalue);
- break;
- }
- case AttrDoesntUntap: {
- bool value = (avalue == "1");
- emit logSetDoesntUntap(player, card, value);
- card->setDoesntUntap(value);
- break;
- }
- case AttrPT: {
- emit logSetPT(player, card, avalue);
- card->setPT(avalue);
- break;
- }
- }
-}
-
void PlayerActions::actMoveCardXCardsFromTop()
{
int deckSize = player->getDeckZone()->getCards().size() + 1; // add the card to move to the deck
@@ -1220,16 +1173,11 @@ void PlayerActions::actMoveCardXCardsFromTop()
defaultNumberTopCardsToPlaceBelow = number;
- QList sel = player->getGameScene()->selectedItems();
- if (sel.isEmpty()) {
+ QList cardList = player->getGameScene()->selectedCards();
+ if (cardList.isEmpty()) {
return;
}
- QList cardList;
- while (!sel.isEmpty()) {
- cardList.append(qgraphicsitem_cast(sel.takeFirst()));
- }
-
QList commandList;
ListOfCardsToMove idList;
for (const auto &i : cardList) {
@@ -1261,10 +1209,9 @@ void PlayerActions::actIncPT(int deltaP, int deltaT)
int playerid = player->getPlayerInfo()->getId();
QList commandList;
- for (const auto &item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
+ for (auto card : player->getGameScene()->selectedCards()) {
QString pt = card->getPT();
- const auto ptList = parsePT(pt);
+ const auto ptList = CardItem::parsePT(pt);
QString newpt;
if (ptList.isEmpty()) {
newpt = QString::number(deltaP) + (deltaT ? "/" + QString::number(deltaT) : "");
@@ -1294,8 +1241,7 @@ void PlayerActions::actResetPT()
{
int playerid = player->getPlayerInfo()->getId();
QList commandList;
- for (const auto &item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
+ for (auto card : player->getGameScene()->selectedCards()) {
QString ptString;
if (!card->getFaceDown()) { // leave the pt empty if the card is face down
ExactCard ec = card->getCard();
@@ -1324,45 +1270,13 @@ void PlayerActions::actResetPT()
}
}
-QVariantList PlayerActions::parsePT(const QString &pt)
-{
- QVariantList ptList = QVariantList();
- if (!pt.isEmpty()) {
- int sep = pt.indexOf('/');
- if (sep == 0) {
- ptList.append(QVariant(pt.mid(1))); // cut off starting '/' and take full string
- } else {
- int start = 0;
- for (;;) {
- QString item = pt.mid(start, sep - start);
- if (item.isEmpty()) {
- ptList.append(QVariant(QString()));
- } else if (item[0] == '+') {
- ptList.append(QVariant(item.mid(1).toInt())); // add as int
- } else if (item[0] == '-') {
- ptList.append(QVariant(item.toInt())); // add as int
- } else {
- ptList.append(QVariant(item)); // add as qstring
- }
- if (sep == -1) {
- break;
- }
- start = sep + 1;
- sep = pt.indexOf('/', start);
- }
- }
- }
- return ptList;
-}
-
void PlayerActions::actSetPT()
{
QString oldPT;
int playerid = player->getPlayerInfo()->getId();
- auto sel = player->getGameScene()->selectedItems();
- for (const auto &item : sel) {
- auto *card = static_cast(item);
+ auto cards = player->getGameScene()->selectedCards();
+ for (auto card : cards) {
if (!card->getPT().isEmpty()) {
oldPT = card->getPT();
}
@@ -1376,16 +1290,15 @@ void PlayerActions::actSetPT()
return;
}
- const auto ptList = parsePT(pt);
+ const auto ptList = CardItem::parsePT(pt);
bool empty = ptList.isEmpty();
QList commandList;
- for (const auto &item : sel) {
- auto *card = static_cast(item);
+ for (auto card : cards) {
auto *cmd = new Command_SetCardAttr;
QString newpt = QString();
if (!empty) {
- const auto oldpt = parsePT(card->getPT());
+ const auto oldpt = CardItem::parsePT(card->getPT());
int ptIter = 0;
for (const auto &_item : ptList) {
if (_item.typeId() == QMetaType::Type::Int) {
@@ -1474,9 +1387,8 @@ void AnnotationDialog::keyPressEvent(QKeyEvent *event)
void PlayerActions::actSetAnnotation()
{
QString oldAnnotation;
- auto sel = player->getGameScene()->selectedItems();
- for (const auto &item : sel) {
- auto *card = static_cast(item);
+ auto cards = player->getGameScene()->selectedCards();
+ for (auto card : cards) {
if (!card->getAnnotation().isEmpty()) {
oldAnnotation = card->getAnnotation();
}
@@ -1496,8 +1408,7 @@ void PlayerActions::actSetAnnotation()
QString annotation = dialog->textValue().left(MAX_NAME_LENGTH);
QList commandList;
- for (const auto &item : sel) {
- auto *card = static_cast(item);
+ for (auto card : cards) {
auto *cmd = new Command_SetCardAttr;
cmd->set_zone(card->getZone()->getName().toStdString());
cmd->set_card_id(card->getId());
@@ -1521,9 +1432,7 @@ void PlayerActions::actAttach()
void PlayerActions::actUnattach()
{
QList commandList;
- for (QGraphicsItem *item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
-
+ for (auto card : player->getGameScene()->selectedCards()) {
if (!card->getAttachedTo()) {
continue;
}
@@ -1536,80 +1445,73 @@ void PlayerActions::actUnattach()
sendGameCommand(prepareGameCommand(commandList));
}
-void PlayerActions::actCardCounterTrigger()
+void PlayerActions::actAddCardCounter(int counterId)
+{
+ offsetCardCounter(counterId, 1);
+}
+
+void PlayerActions::actRemoveCardCounter(int counterId)
+{
+ offsetCardCounter(counterId, -1);
+}
+
+void PlayerActions::offsetCardCounter(int counterId, int offset)
{
- auto *action = static_cast(sender());
- int counterId = action->data().toInt() / 1000;
QList commandList;
- switch (action->data().toInt() % 1000) {
- case 9: { // increment counter
- for (const auto &item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
- if (card->getCounters().value(counterId, 0) < MAX_COUNTERS_ON_CARD) {
- auto *cmd = new Command_SetCardCounter;
- cmd->set_zone(card->getZone()->getName().toStdString());
- cmd->set_card_id(card->getId());
- cmd->set_counter_id(counterId);
- cmd->set_counter_value(card->getCounters().value(counterId, 0) + 1);
- commandList.append(cmd);
- }
- }
- break;
+ for (auto card : player->getGameScene()->selectedCards()) {
+ int oldValue = card->getCounters().value(counterId, 0);
+ int newValue = oldValue + offset;
+
+ if (newValue >= 0 && newValue <= MAX_COUNTERS_ON_CARD) {
+ auto *cmd = new Command_SetCardCounter;
+ cmd->set_zone(card->getZone()->getName().toStdString());
+ cmd->set_card_id(card->getId());
+ cmd->set_counter_id(counterId);
+ cmd->set_counter_value(newValue);
+ commandList.append(cmd);
}
- case 10: { // decrement counter
- for (const auto &item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
- if (card->getCounters().value(counterId, 0)) {
- auto *cmd = new Command_SetCardCounter;
- cmd->set_zone(card->getZone()->getName().toStdString());
- cmd->set_card_id(card->getId());
- cmd->set_counter_id(counterId);
- cmd->set_counter_value(card->getCounters().value(counterId, 0) - 1);
- commandList.append(cmd);
- }
- }
- break;
- }
- case 11: { // set counter with dialog
- player->setDialogSemaphore(true);
-
- // If a single card is selected, we show the old value in the dialog. Otherwise, we show "x"
- QList sel = player->getGameScene()->selectedItems();
- QString oldValueForDlg = "x";
- if (sel.size() == 1) {
- auto *card = dynamic_cast(sel.first());
- oldValueForDlg = QString::number(card->getCounters().value(counterId, 0));
- }
-
- auto &cardCounterSettings = SettingsCache::instance().cardCounters();
- QString counterName = cardCounterSettings.displayName(counterId);
-
- AbstractCounterDialog dialog(counterName, oldValueForDlg, player->getGame()->getTab());
- int ok = dialog.exec();
-
- player->setDialogSemaphore(false);
- if (player->clearCardsToDelete() || !ok) {
- return;
- }
-
- for (const auto &item : sel) {
- auto *card = dynamic_cast(item);
-
- int oldValue = card->getCounters().value(counterId, 0);
- Expression exp(oldValue);
- int number = static_cast(exp.parse(dialog.textValue()));
-
- auto *cmd = new Command_SetCardCounter;
- cmd->set_zone(card->getZone()->getName().toStdString());
- cmd->set_card_id(card->getId());
- cmd->set_counter_id(counterId);
- cmd->set_counter_value(number);
- commandList.append(cmd);
- }
- break;
- }
- default:;
}
+
+ sendGameCommand(prepareGameCommand(commandList));
+}
+
+void PlayerActions::actSetCardCounter(int counterId)
+{
+ player->setDialogSemaphore(true);
+
+ // If a single card is selected, we show the old value in the dialog. Otherwise, we show "x"
+ QList sel = player->getGameScene()->selectedCards();
+ QString oldValueForDlg = "x";
+ if (sel.size() == 1) {
+ auto *card = sel.first();
+ oldValueForDlg = QString::number(card->getCounters().value(counterId, 0));
+ }
+
+ auto &cardCounterSettings = SettingsCache::instance().cardCounters();
+ QString counterName = cardCounterSettings.displayName(counterId);
+
+ AbstractCounterDialog dialog(counterName, oldValueForDlg, player->getGame()->getTab());
+ int ok = dialog.exec();
+
+ player->setDialogSemaphore(false);
+ if (player->clearCardsToDelete() || !ok) {
+ return;
+ }
+
+ QList commandList;
+ for (auto card : sel) {
+ int oldValue = card->getCounters().value(counterId, 0);
+ Expression exp(oldValue);
+ int number = static_cast(exp.parse(dialog.textValue()));
+
+ auto *cmd = new Command_SetCardCounter;
+ cmd->set_zone(card->getZone()->getName().toStdString());
+ cmd->set_card_id(card->getId());
+ cmd->set_counter_id(counterId);
+ cmd->set_counter_value(number);
+ commandList.append(cmd);
+ }
+
sendGameCommand(prepareGameCommand(commandList));
}
@@ -1627,11 +1529,7 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone)
void PlayerActions::playSelectedCards(const bool faceDown)
{
- QList selectedCards;
- for (const auto &item : player->getGameScene()->selectedItems()) {
- auto *card = static_cast(item);
- selectedCards.append(card);
- }
+ QList selectedCards = player->getGameScene()->selectedCards();
// CardIds will get shuffled downwards when cards leave the deck.
// We need to iterate through the cards in reverse order so cardIds don't get changed out from under us as we play
@@ -1658,7 +1556,7 @@ void PlayerActions::actPlayFacedown()
void PlayerActions::actHide()
{
- for (const auto &item : player->getGameScene()->selectedItems()) {
+ for (const auto &item : player->getGameScene()->selectedCards()) {
auto *card = static_cast(item);
if (card && isUnwritableRevealZone(card->getZone())) {
card->getZone()->removeCard(card);
@@ -1675,9 +1573,7 @@ void PlayerActions::actReveal(QAction *action)
cmd.set_player_id(otherPlayerId);
}
- QList sel = player->getGameScene()->selectedItems();
- while (!sel.isEmpty()) {
- const auto *card = qgraphicsitem_cast(sel.takeFirst());
+ for (auto card : player->getGameScene()->selectedCards()) {
if (!cmd.has_zone_name()) {
cmd.set_zone_name(card->getZone()->getName().toStdString());
}
@@ -1762,11 +1658,7 @@ void PlayerActions::actRevealRandomGraveyardCard(int revealToPlayerId)
void PlayerActions::cardMenuAction()
{
auto *a = dynamic_cast(sender());
- QList sel = player->getGameScene()->selectedItems();
- QList cardList;
- while (!sel.isEmpty()) {
- cardList.append(qgraphicsitem_cast(sel.takeFirst()));
- }
+ QList cardList = player->getGameScene()->selectedCards();
QList commandList;
if (a->data().toInt() <= (int)cmClone) {
diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h
index d4c6daacf..181b1b135 100644
--- a/cockatrice/src/game/player/player_actions.h
+++ b/cockatrice/src/game/player/player_actions.h
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
namespace google
{
@@ -35,12 +34,6 @@ class PlayerActions : public QObject
{
Q_OBJECT
-signals:
- void logSetTapped(Player *player, CardItem *card, bool tapped);
- void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
- void logSetDoesntUntap(Player *player, CardItem *card, bool doesntUntap);
- void logSetPT(Player *player, CardItem *card, QString newPT);
-
public:
enum CardsToReveal
{
@@ -55,13 +48,6 @@ public:
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
PendingCommand *prepareGameCommand(const QList &cmdList);
- void setCardAttrHelper(const GameEventContext &context,
- CardItem *card,
- CardAttribute attribute,
- const QString &avalue,
- bool allCards,
- EventProcessingOptions options);
-
void moveOneCardUntil(CardItem *card);
void stopMoveTopCardsUntil();
@@ -77,6 +63,7 @@ public slots:
void actUntapAll();
void actRollDie();
+ void actFlipCoin();
void actCreateToken();
void actCreateAnotherToken();
void actShuffle();
@@ -141,7 +128,9 @@ public slots:
void actCreateAllRelatedCards();
void actMoveCardXCardsFromTop();
- void actCardCounterTrigger();
+ void actRemoveCardCounter(int counterId);
+ void actAddCardCounter(int counterId);
+ void actSetCardCounter(int counterId);
void actAttach();
void actUnattach();
void actDrawArrow();
@@ -197,7 +186,7 @@ private:
void cmdSetTopCard(Command_MoveCard &cmd);
void cmdSetBottomCard(Command_MoveCard &cmd);
- QVariantList parsePT(const QString &pt);
+ void offsetCardCounter(int counterId, int offset);
};
#endif // COCKATRICE_PLAYER_ACTIONS_H
diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp
index 6fb1ff19a..dc1e2393c 100644
--- a/cockatrice/src/game/player/player_event_handler.cpp
+++ b/cockatrice/src/game/player/player_event_handler.cpp
@@ -149,8 +149,8 @@ void PlayerEventHandler::eventSetCardAttr(const Event_SetCardAttr &event,
if (!event.has_card_id()) {
const CardList &cards = zone->getCards();
for (int i = 0; i < cards.size(); ++i) {
- player->getPlayerActions()->setCardAttrHelper(context, cards.at(i), event.attribute(),
- QString::fromStdString(event.attr_value()), true, options);
+ setCardAttrHelper(context, cards.at(i), event.attribute(), QString::fromStdString(event.attr_value()), true,
+ options);
}
if (event.attribute() == AttrTapped) {
emit logSetTapped(player, nullptr, event.attr_value() == "1");
@@ -161,8 +161,62 @@ void PlayerEventHandler::eventSetCardAttr(const Event_SetCardAttr &event,
qWarning() << "PlayerEventHandler::eventSetCardAttr: card id=" << event.card_id() << "not found";
return;
}
- player->getPlayerActions()->setCardAttrHelper(context, card, event.attribute(),
- QString::fromStdString(event.attr_value()), false, options);
+ setCardAttrHelper(context, card, event.attribute(), QString::fromStdString(event.attr_value()), false, options);
+ }
+}
+
+void PlayerEventHandler::setCardAttrHelper(const GameEventContext &context,
+ CardItem *card,
+ CardAttribute attribute,
+ const QString &avalue,
+ bool allCards,
+ EventProcessingOptions options)
+{
+ if (card == nullptr) {
+ return;
+ }
+
+ bool moveCardContext = context.HasExtension(Context_MoveCard::ext);
+ switch (attribute) {
+ case AttrTapped: {
+ bool tapped = avalue == "1";
+ if (!(!tapped && card->getDoesntUntap() && allCards)) {
+ if (!allCards) {
+ emit logSetTapped(player, card, tapped);
+ }
+ bool canAnimate = !options.testFlag(SKIP_TAP_ANIMATION) && !moveCardContext;
+ card->setTapped(tapped, canAnimate);
+ }
+ break;
+ }
+ case AttrAttacking: {
+ card->setAttacking(avalue == "1");
+ break;
+ }
+ case AttrFaceDown: {
+ card->setFaceDown(avalue == "1");
+ break;
+ }
+ case AttrColor: {
+ card->setColor(avalue);
+ break;
+ }
+ case AttrAnnotation: {
+ emit logSetAnnotation(player, card, avalue);
+ card->setAnnotation(avalue);
+ break;
+ }
+ case AttrDoesntUntap: {
+ bool value = (avalue == "1");
+ emit logSetDoesntUntap(player, card, value);
+ card->setDoesntUntap(value);
+ break;
+ }
+ case AttrPT: {
+ emit logSetPT(player, card, avalue);
+ card->setPT(avalue);
+ break;
+ }
}
}
diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h
index 5d1ddd4b4..9f67d24ab 100644
--- a/cockatrice/src/game/player/player_event_handler.h
+++ b/cockatrice/src/game/player/player_event_handler.h
@@ -9,6 +9,7 @@
#include "event_processing_options.h"
#include
+#include
#include
#include
@@ -110,6 +111,13 @@ public:
private:
Player *player;
+
+ void setCardAttrHelper(const GameEventContext &context,
+ CardItem *card,
+ CardAttribute attribute,
+ const QString &avalue,
+ bool allCards,
+ EventProcessingOptions options);
};
#endif // COCKATRICE_PLAYER_EVENT_HANDLER_H
diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp
index 19353b1e9..c7f259ec0 100644
--- a/cockatrice/src/interface/theme_manager.cpp
+++ b/cockatrice/src/interface/theme_manager.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#define NONE_THEME_NAME "Default"
@@ -112,6 +113,39 @@ void ThemeManager::ensureThemeDirectoryExists()
}
}
+bool ThemeManager::isDarkMode()
+{
+ auto themeName = SettingsCache::instance().getThemeName();
+ // Explicit Dark Mode
+ if (themeName == FUSION_THEME_NAME_LIGHT || themeName.endsWith("(Light)")) {
+ return false;
+ }
+ // Explicit Light Mode
+ if (themeName == FUSION_THEME_NAME_DARK || themeName.endsWith("(Dark)")) {
+ return true;
+ }
+
+ // Auto detection on compatible Qt versions
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
+ if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark &&
+ (themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName.endsWith("(System Default)"))) {
+ return true;
+ } else {
+ return false;
+ }
+#endif
+ // Default to light mode
+ return false;
+}
+
+bool ThemeManager::isBuiltInTheme()
+{
+ const auto themeName = SettingsCache::instance().getThemeName();
+
+ return themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName == FUSION_THEME_NAME_LIGHT ||
+ themeName == FUSION_THEME_NAME_DARK;
+}
+
QStringMap &ThemeManager::getAvailableThemes()
{
QDir dir;
@@ -335,26 +369,53 @@ void ThemeManager::themeChangedSlot()
qApp->setStyleSheet("");
}
+ QStyle *newStyle = nullptr;
+ QPalette newPalette;
+
if (themeName == FUSION_THEME_NAME) {
- QStyle *fusionStyle = QStyleFactory::create("Fusion");
- qApp->setStyle(fusionStyle);
+ newStyle = QStyleFactory::create("Fusion");
+
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
// Start from Fusion's own palette so dark mode is handled correctly,
// then apply any tweaks on top of it.
- QPalette palette = fusionStyle->standardPalette();
+ newPalette = newStyle->standardPalette();
if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
- palette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
+ newPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
}
- qApp->setPalette(palette);
+#else
+ newPalette = qApp->palette();
#endif
} else if (themeName == FUSION_THEME_NAME_LIGHT) {
- qApp->setStyle(QStyleFactory::create("Fusion"));
- qApp->setPalette(createLightGreenFusionPalette());
+ newStyle = QStyleFactory::create("Fusion");
+ newPalette = createLightGreenFusionPalette();
} else if (themeName == FUSION_THEME_NAME_DARK) {
- qApp->setStyle(QStyleFactory::create("Fusion"));
- qApp->setPalette(createDarkGreenFusionPalette());
+ newStyle = QStyleFactory::create("Fusion");
+ newPalette = createDarkGreenFusionPalette();
} else {
- qApp->setStyle(QStyleFactory::create(defaultStyleName)); // setting the style also sets the palette
+ newStyle = QStyleFactory::create(defaultStyleName);
+ // Use the style's default palette.
+ newPalette = newStyle->standardPalette();
+ }
+
+ // Apply palette FIRST.
+ qApp->setPalette(newPalette);
+ // Then apply style.
+ qApp->setStyle(newStyle);
+
+ // Force every widget to re-polish and repaint immediately rather than
+ // waiting for natural expose events, which produces a patchwork of old
+ // and new colours during a live preview.
+ // Note: we do NOT call widget->setPalette(base) here — qApp->setPalette()
+ // already propagates to all widgets that haven't explicitly overridden their
+ // palette (WA_SetPalette not set). Calling it unconditionally would clobber
+ // intentional per-widget palette customisations across the whole app.
+ for (QWidget *widget : qApp->allWidgets()) {
+ if (widget->isVisible()) {
+ newStyle->unpolish(widget);
+ newStyle->polish(widget);
+
+ widget->update();
+ }
}
if (dirPath.isEmpty()) {
diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h
index d942f0fef..416923128 100644
--- a/cockatrice/src/interface/theme_manager.h
+++ b/cockatrice/src/interface/theme_manager.h
@@ -54,6 +54,8 @@ protected:
QBrush loadExtraBrush(QString fileName, QBrush &fallbackBrush);
public:
+ bool isBuiltInTheme();
+ bool isDarkMode();
QStringMap &getAvailableThemes();
QBrush &getBgBrush(Role zone);
diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp
index 456e1533a..f5f343807 100644
--- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp
+++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp
@@ -62,7 +62,7 @@ void CardInfoTextWidget::setCard(const ExactCard &exactCard)
text += QString("
" + tr("can contain the following punctuation: %1").arg(rules.at(6).toHtmlEscaped()) + "
";
-
- out += "
" +
- tr("first character can %1 be a punctuation mark").arg((rules.at(5).toInt() > 0) ? "" : tr("NOT")) +
- "
";
-
- if (rules.size() == 9) {
- if (rules.at(7).size() > 0) {
- QString words = rules.at(7).toHtmlEscaped();
- if (words.startsWith("\n")) {
- out += tr("no unacceptable language as specified by these server rules:",
- "note that the following lines will not be translated");
- for (QString &line : words.split("\n", Qt::SkipEmptyParts)) {
- out += "
" + line + "
";
- }
- } else {
- out += "
" + tr("can not contain any of the following words: %1").arg(words) + "
";
- }
- }
-
- if (rules.at(8).size() > 0)
- out += "
" +
- tr("can not match any of the following expressions: %1").arg(rules.at(8).toHtmlEscaped()) +
- "
";
- }
-
- out += "
";
- } else {
- out += tr("You may only use A-Z, a-z, 0-9, _, ., and - in your username.");
- }
-
- return out;
-}
-
-void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime)
-{
- switch (r) {
- case Response::RespRegistrationDisabled:
- QMessageBox::critical(this, tr("Registration denied"),
- tr("Registration is currently disabled on this server"));
- break;
- case Response::RespUserAlreadyExists:
- QMessageBox::critical(this, tr("Registration denied"),
- tr("There is already an existing account with the same user name."));
- break;
- case Response::RespEmailRequiredToRegister:
- QMessageBox::critical(this, tr("Registration denied"),
- tr("It's mandatory to specify a valid email address when registering."));
- break;
- case Response::RespEmailBlackListed:
- if (reasonStr.isEmpty()) {
- reasonStr =
- "The email address provider used during registration has been blocked from use on this server.";
- }
- QMessageBox::critical(this, tr("Registration denied"), reasonStr);
- break;
- case Response::RespTooManyRequests:
- QMessageBox::critical(
- this, tr("Registration denied"),
- tr("It appears you are attempting to register a new account on this server yet you already have an "
- "account registered with the email provided. This server restricts the number of accounts a user "
- "can register per address. Please contact the server operator for further assistance or to obtain "
- "your credential information."));
- break;
- case Response::RespPasswordTooShort:
- QMessageBox::critical(this, tr("Registration denied"), tr("Password too short."));
- break;
- case Response::RespUserIsBanned: {
- QString bannedStr;
- if (endTime)
- bannedStr = tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString());
- else
- bannedStr = tr("You are banned indefinitely.");
- if (!reasonStr.isEmpty())
- bannedStr.append("\n\n" + reasonStr);
-
- QMessageBox::critical(this, tr("Error"), bannedStr);
- break;
- }
- case Response::RespUsernameInvalid: {
- QMessageBox::critical(this, tr("Error"), extractInvalidUsernameMessage(reasonStr));
- break;
- }
- case Response::RespRegistrationFailed:
- QMessageBox::critical(this, tr("Error"), tr("Registration failed for a technical problem on the server."));
- break;
- case Response::RespNotConnected:
- QMessageBox::critical(this, tr("Error"), tr("The connection to the server has been lost."));
- break;
- default:
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown registration error: %1").arg(static_cast(r)) +
- tr("\nThis usually means that your client version is out of date, and the server "
- "sent a reply your client doesn't understand."));
- }
- actRegister();
-}
-
-void MainWindow::activateError()
-{
- QMessageBox::critical(this, tr("Error"), tr("Account activation failed"));
- client->disconnectFromServer();
- actConnect();
-}
-
-void MainWindow::socketError(const QString &errorStr)
-{
- QMessageBox::critical(this, tr("Error"), tr("Socket error: %1").arg(errorStr));
- actConnect();
-}
-
-void MainWindow::protocolVersionMismatch(int localVersion, int remoteVersion)
-{
- if (localVersion > remoteVersion)
- QMessageBox::critical(this, tr("Error"),
- tr("You are trying to connect to an obsolete server. Please downgrade your Cockatrice "
- "version or connect to a suitable server.\nLocal version is %1, remote version is %2.")
- .arg(localVersion)
- .arg(remoteVersion));
- else
- QMessageBox::critical(this, tr("Error"),
- tr("Your Cockatrice client is obsolete. Please update your Cockatrice version.\nLocal "
- "version is %1, remote version is %2.")
- .arg(localVersion)
- .arg(remoteVersion));
-}
-
-void MainWindow::setClientStatusTitle()
-{
- switch (client->getStatus()) {
- case StatusConnecting:
- setWindowTitle(appName + " - " + tr("Connecting to %1...").arg(client->peerName()));
- break;
- case StatusRegistering:
- setWindowTitle(appName + " - " +
- tr("Registering to %1 as %2...").arg(client->peerName()).arg(client->getUserName()));
- break;
- case StatusDisconnected:
- setWindowTitle(appName + " - " + tr("Disconnected"));
- break;
- case StatusLoggingIn:
- setWindowTitle(appName + " - " + tr("Connected, logging in at %1").arg(client->peerName()));
- break;
- case StatusLoggedIn:
- setWindowTitle(client->getUserName() + "@" + client->peerName());
- break;
- case StatusRequestingForgotPassword:
- setWindowTitle(
- appName + " - " +
- tr("Requesting forgotten password to %1 as %2...").arg(client->peerName()).arg(client->getUserName()));
- break;
- case StatusSubmitForgotPasswordChallenge:
- setWindowTitle(
- appName + " - " +
- tr("Requesting forgotten password to %1 as %2...").arg(client->peerName()).arg(client->getUserName()));
- break;
- case StatusSubmitForgotPasswordReset:
- setWindowTitle(
- appName + " - " +
- tr("Requesting forgotten password to %1 as %2...").arg(client->peerName()).arg(client->getUserName()));
- break;
- default:
- setWindowTitle(appName);
- }
-}
-
void MainWindow::retranslateUi()
{
- setClientStatusTitle();
+ connectionController->refreshWindowTitle();
aConnect->setText(tr("&Connect..."));
aDisconnect->setText(tr("&Disconnect"));
@@ -717,9 +344,9 @@ void MainWindow::createActions()
aFullScreen->setCheckable(true);
connect(aFullScreen, &QAction::toggled, this, &MainWindow::actFullScreen);
aRegister = new QAction(this);
- connect(aRegister, &QAction::triggered, this, &MainWindow::actRegister);
+ connect(aRegister, &QAction::triggered, connectionController, &ConnectionController::registerToServer);
aForgotPassword = new QAction(this);
- connect(aForgotPassword, &QAction::triggered, this, &MainWindow::actForgotPasswordRequest);
+ connect(aForgotPassword, &QAction::triggered, connectionController, &ConnectionController::forgotPasswordRequest);
aSettings = new QAction(this);
connect(aSettings, &QAction::triggered, this, &MainWindow::actSettings);
aExit = new QAction(this);
@@ -844,38 +471,22 @@ MainWindow::MainWindow(QWidget *parent)
&MainWindow::pixmapCacheSizeChanged);
pixmapCacheSizeChanged(SettingsCache::instance().getPixmapCacheSize());
- client = new RemoteClient(nullptr, &SettingsCache::instance());
- connect(client, &RemoteClient::connectionClosedEventReceived, this, &MainWindow::processConnectionClosedEvent);
- connect(client, &RemoteClient::serverShutdownEventReceived, this, &MainWindow::processServerShutdownEvent);
- connect(client, &RemoteClient::loginError, this, &MainWindow::loginError);
- connect(client, &RemoteClient::socketError, this, &MainWindow::socketError);
- connect(client, &RemoteClient::serverTimeout, this, &MainWindow::serverTimeout);
- connect(client, &RemoteClient::statusChanged, this, &MainWindow::statusChanged);
- connect(client, &RemoteClient::protocolVersionMismatch, this, &MainWindow::protocolVersionMismatch);
- connect(client, &RemoteClient::userInfoChanged, this, &MainWindow::userInfoReceived, Qt::BlockingQueuedConnection);
- connect(client, &RemoteClient::notifyUserAboutUpdate, this, &MainWindow::notifyUserAboutUpdate);
- connect(client, &RemoteClient::registerAccepted, this, &MainWindow::registerAccepted);
- connect(client, &RemoteClient::registerAcceptedNeedsActivate, this, &MainWindow::registerAcceptedNeedsActivate);
- connect(client, &RemoteClient::registerError, this, &MainWindow::registerError);
- connect(client, &RemoteClient::activateAccepted, this, &MainWindow::activateAccepted);
- connect(client, &RemoteClient::activateError, this, &MainWindow::activateError);
- connect(client, &RemoteClient::sigForgotPasswordSuccess, this, &MainWindow::forgotPasswordSuccess);
- connect(client, &RemoteClient::sigForgotPasswordError, this, &MainWindow::forgotPasswordError);
- connect(client, &RemoteClient::sigPromptForForgotPasswordReset, this, &MainWindow::promptForgotPasswordReset);
- connect(client, &RemoteClient::sigPromptForForgotPasswordChallenge, this,
- &MainWindow::promptForgotPasswordChallenge);
-
- clientThread = new QThread(this);
- client->moveToThread(clientThread);
- clientThread->start();
+ connectionController = new ConnectionController(this, this);
createActions();
createMenus();
- tabSupervisor = new TabSupervisor(client, tabsMenu, this);
+ connect(connectionController, &ConnectionController::windowTitleChanged, this, &MainWindow::setWindowTitle);
+ connect(connectionController, &ConnectionController::statusChanged, this, &MainWindow::statusChanged);
+
+ tabSupervisor = new TabSupervisor(connectionController->client(), tabsMenu, this);
connect(tabSupervisor, &TabSupervisor::setMenu, this, &MainWindow::updateTabMenu);
connect(tabSupervisor, &TabSupervisor::localGameEnded, this, &MainWindow::localGameEnded);
connect(tabSupervisor, &TabSupervisor::showWindowIfHidden, this, &MainWindow::showWindowIfHidden);
+ connect(connectionController, &ConnectionController::tabSupervisorStartRequested, tabSupervisor,
+ &TabSupervisor::start);
+ connect(connectionController, &ConnectionController::tabSupervisorStopRequested, tabSupervisor,
+ &TabSupervisor::stop);
tabSupervisor->initStartupTabs();
setCentralWidget(tabSupervisor);
@@ -1043,9 +654,6 @@ MainWindow::~MainWindow()
cardUpdateProcess->waitForFinished(1000);
cardUpdateProcess = nullptr;
}
-
- client->deleteLater();
- clientThread->wait();
}
void MainWindow::createTrayIcon()
@@ -1079,14 +687,6 @@ void MainWindow::actShow()
});
}
-void MainWindow::promptForgotPasswordChallenge()
-{
- DlgForgotPasswordChallenge dlg(this);
- if (dlg.exec())
- client->submitForgotPasswordChallengeToServer(dlg.getHost(), static_cast(dlg.getPort()),
- dlg.getPlayerName(), dlg.getEmail());
-}
-
void MainWindow::closeEvent(QCloseEvent *event)
{
// workaround Qt bug where closeEvent gets called twice
@@ -1116,13 +716,14 @@ void MainWindow::changeEvent(QEvent *event)
bHasActivated = true;
if (!connectTo.isEmpty()) {
qCInfo(WindowMainStartupAutoconnectLog) << "Command line connect to " << connectTo;
- client->connectToServer(connectTo.host(), connectTo.port(), connectTo.userName(), connectTo.password());
+ connectionController->connectToServerDirect(connectTo.host(), connectTo.port(), connectTo.userName(),
+ connectTo.password());
} else if (SettingsCache::instance().servers().getAutoConnect() &&
!SettingsCache::instance().debug().getLocalGameOnStartup()) {
qCInfo(WindowMainStartupAutoconnectLog) << "Attempting auto-connect...";
DlgConnect dlg(this);
- client->connectToServer(dlg.getHost(), static_cast(dlg.getPort()), dlg.getPlayerName(),
- dlg.getPassword());
+ connectionController->connectToServerDirect(dlg.getHost(), static_cast(dlg.getPort()),
+ dlg.getPlayerName(), dlg.getPassword());
}
}
}
@@ -1173,6 +774,13 @@ void MainWindow::cardDatabaseLoadingFailed()
void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames)
{
+ if (SettingsCache::instance().getAlwaysEnableNewSets()) {
+ CardDatabaseManager::getInstance()->enableAllUnknownSets();
+ const auto reloadOk1 =
+ QtConcurrent::run([] { CardDatabaseManager::getInstance()->reloadCardDatabasesAndNotify(); });
+ return;
+ }
+
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("New sets found"));
msgBox.setIcon(QMessageBox::Question);
@@ -1183,6 +791,7 @@ void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknow
.arg(unknownSetsNames.join(", ")));
QPushButton *yesButton = msgBox.addButton(tr("Yes"), QMessageBox::YesRole);
+ QPushButton *yesAlwaysButton = msgBox.addButton(tr("Yes, always enable"), QMessageBox::YesRole);
QPushButton *noButton = msgBox.addButton(tr("No"), QMessageBox::NoRole);
QPushButton *settingsButton = msgBox.addButton(tr("View sets"), QMessageBox::ActionRole);
msgBox.setDefaultButton(yesButton);
@@ -1191,7 +800,13 @@ void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknow
if (msgBox.clickedButton() == yesButton) {
CardDatabaseManager::getInstance()->enableAllUnknownSets();
- const auto reloadOk1 = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
+ const auto reloadOk1 =
+ QtConcurrent::run([] { CardDatabaseManager::getInstance()->reloadCardDatabasesAndNotify(); });
+ } else if (msgBox.clickedButton() == yesAlwaysButton) {
+ CardDatabaseManager::getInstance()->enableAllUnknownSets();
+ const auto reloadOk1 =
+ QtConcurrent::run([] { CardDatabaseManager::getInstance()->reloadCardDatabasesAndNotify(); });
+ SettingsCache::instance().setAlwaysEnableNewSets(true);
} else if (msgBox.clickedButton() == noButton) {
CardDatabaseManager::getInstance()->markAllSetsAsKnown();
} else if (msgBox.clickedButton() == settingsButton) {
@@ -1381,15 +996,6 @@ void MainWindow::refreshShortcuts()
aStatusBar->setShortcuts(shortcuts.getShortcut("MainWindow/aStatusBar"));
}
-void MainWindow::notifyUserAboutUpdate()
-{
- QMessageBox::information(
- this, tr("Information"),
- tr("This server supports additional features that your client doesn't have.\nThis is most likely not a "
- "problem, but this message might mean there is a new version of Cockatrice available or this server is "
- "running a custom or pre-release version.\n\nTo update your client, go to Help -> Check for Updates."));
-}
-
void MainWindow::actOpenCustomFolder()
{
QString dir = SettingsCache::instance().getCustomPicsPath();
@@ -1473,7 +1079,7 @@ int MainWindow::getNextCustomSetPrefix(QDir dataDir)
void MainWindow::actReloadCardDatabase()
{
const auto reloadOk1 = QtConcurrent::run([] {
- CardDatabaseManager::getInstance()->loadCardDatabases();
+ CardDatabaseManager::getInstance()->reloadCardDatabasesAndNotify();
SettingsCache::instance().downloads().sync();
});
}
@@ -1490,42 +1096,3 @@ void MainWindow::actEditTokens()
dlg.exec();
CardDatabaseManager::getInstance()->saveCustomTokensToFile();
}
-
-void MainWindow::actForgotPasswordRequest()
-{
- DlgForgotPasswordRequest dlg(this);
- if (dlg.exec())
- client->requestForgotPasswordToServer(dlg.getHost(), static_cast(dlg.getPort()),
- dlg.getPlayerName());
-}
-
-void MainWindow::forgotPasswordSuccess()
-{
- QMessageBox::information(
- this, tr("Reset Password"),
- tr("Your password has been reset successfully, you can now log in using the new credentials."));
- SettingsCache::instance().servers().setFPHostName("");
- SettingsCache::instance().servers().setFPPort("");
- SettingsCache::instance().servers().setFPPlayerName("");
-}
-
-void MainWindow::forgotPasswordError()
-{
- QMessageBox::warning(
- this, tr("Reset Password"),
- tr("Failed to reset user account password, please contact the server operator to reset your password."));
- SettingsCache::instance().servers().setFPHostName("");
- SettingsCache::instance().servers().setFPPort("");
- SettingsCache::instance().servers().setFPPlayerName("");
-}
-
-void MainWindow::promptForgotPasswordReset()
-{
- QMessageBox::information(this, tr("Reset Password"),
- tr("Activation request received, please check your email for an activation token."));
- DlgForgotPasswordReset dlg(this);
- if (dlg.exec()) {
- client->submitForgotPasswordResetToServer(dlg.getHost(), static_cast(dlg.getPort()),
- dlg.getPlayerName(), dlg.getToken(), dlg.getPassword());
- }
-}
diff --git a/cockatrice/src/interface/window_main.h b/cockatrice/src/interface/window_main.h
index ed6de5b0d..528e6f211 100644
--- a/cockatrice/src/interface/window_main.h
+++ b/cockatrice/src/interface/window_main.h
@@ -25,6 +25,7 @@
#ifndef WINDOW_H
#define WINDOW_H
+#include "connection_controller/remote_connection_controller.h"
#include "widgets/dialogs/dlg_local_game_options.h"
#include
@@ -68,38 +69,19 @@ public slots:
private slots:
void updateTabMenu(const QList &newMenuList);
void statusChanged(ClientStatus _status);
- void processConnectionClosedEvent(const Event_ConnectionClosed &event);
- void processServerShutdownEvent(const Event_ServerShutdown &event);
- void serverTimeout();
- void loginError(Response::ResponseCode r, QString reasonStr, quint32 endTime, QList missingFeatures);
- void registerError(Response::ResponseCode r, QString reasonStr, quint32 endTime);
- void activateError();
- void socketError(const QString &errorStr);
- void protocolVersionMismatch(int localVersion, int remoteVersion);
- void userInfoReceived(const ServerInfo_User &userInfo);
- void registerAccepted();
- void registerAcceptedNeedsActivate();
- void activateAccepted();
void localGameEnded();
void pixmapCacheSizeChanged(int newSizeInMBs);
- void notifyUserAboutUpdate();
void actDisconnect();
void actSinglePlayer();
void actWatchReplay();
void actFullScreen(bool checked);
- void actRegister();
void actSettings();
- void actForgotPasswordRequest();
void actAbout();
void actTips();
void actUpdate();
void actViewLog();
void actOpenSettingsFolder();
- void forgotPasswordSuccess();
- void forgotPasswordError();
- void promptForgotPasswordReset();
void actShow();
- void promptForgotPasswordChallenge();
void showWindowIfHidden();
void cardUpdateError(QProcess::ProcessError err);
@@ -125,7 +107,6 @@ private slots:
private:
static const QString appName;
static const QStringList fileNameFilters;
- void setClientStatusTitle();
void retranslateUi();
void createActions();
void createMenus();
@@ -152,14 +133,11 @@ private:
TabSupervisor *tabSupervisor;
WndSets *wndSets;
- RemoteClient *client;
- QThread *clientThread;
+ ConnectionController *connectionController;
LocalServer *localServer;
bool bHasActivated, askedForDbUpdater;
- QMessageBox serverShutdownMessageBox;
QProcess *cardUpdateProcess;
DlgViewLog *logviewDialog;
- DlgConnect *dlgConnect;
GameReplay *replay;
DlgTipOfTheDay *tip;
QUrl connectTo;
@@ -180,7 +158,6 @@ public:
protected:
void closeEvent(QCloseEvent *event) override;
void changeEvent(QEvent *event) override;
- QString extractInvalidUsernameMessage(QString &in);
};
#endif
diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts
index c13bfb2df..c210315c7 100644
--- a/cockatrice/translations/cockatrice_cs.ts
+++ b/cockatrice/translations/cockatrice_cs.ts
@@ -23,12 +23,12 @@
AbstractDlgDeckTextEdit
-
+ &Refresh
-
+ Parse Set Name and Number (if available)
@@ -36,60 +36,60 @@
AbstractTabDeckEditor
-
+ Open in new tab
-
+ Are you sure?
-
+ The decklist has been modified.
Do you want to save the changes?
-
-
-
-
-
-
+
+
+
+
+
+ Error
-
+ Could not open deck at %1
-
+ Could not save remote deck
-
-
+
+ The deck could not be saved.
Please check that the directory is writable and try again.
-
+ Save deck
-
+ The deck could not be saved.
-
+ There are no cards in your deck to be exported
@@ -131,190 +131,168 @@ Please check that the directory is writable and try again.
AppearanceSettingsPage
-
+ seconds
-
+ ErrorChyba
-
+ Could not create themes directory at '%1'.
-
- Enabling this feature will disable the use of the Printing Selector.
-
-You will not be able to manage printing preferences on a per-deck basis, or see printings other people have selected for their decks.
-
-You will have to use the Set Manager, available through Card Database -> Manage Sets.
-
-Are you sure you would like to enable this feature?
-
-
-
-
- Disabling this feature will enable the Printing Selector.
-
-You can now choose printings on a per-deck basis in the Deck Editor and configure which printing gets added to a deck by default by pinning it in the Printing Selector.
-
-You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available).
-
-Are you sure you would like to disable this feature?
-
-
-
-
- Confirm Change
-
-
-
-
+ Theme settingsNastavení vzhledu
-
+ Current theme:Aktuální vzhled
-
+ Open themes folder
-
+ Home tab background source:
-
+ Home tab background shuffle frequency:
-
+ Disabled
-
+
+ Display card name of background in bottom right:
+
+
+
+ Menu settings
-
+ Show keyboard shortcuts in right-click menus
-
+ Show game filter toolbar above list in room tab
-
+ Card renderingVykreslování karet
-
+ Display card names on cards having a pictureZobrazit jména karet na kartách s obrázky
-
+ Auto-Rotate cards with sideways layout
-
+ Override all card art with personal set preference (Pre-ProviderID change behavior)
-
+ Bump sets that the deck contains cards from to the top in the printing selector
-
+ Scale cards on mouse overZvětšovat karty při najetí myši
-
+ Use rounded card corners
-
+ Minimum overlap percentage of cards on the stack and in vertical hand
-
+ Maximum initial height for card view window:
-
-
+
+ rows
-
+ Maximum expanded height for card view window:
-
+ Card counters
-
+ Counter %1
-
+ Hand layoutRozvržení ruky
-
+ Display hand horizontally (wastes space)Zobrazit ruku horizontálně (plýtvá místem)
-
+ Enable left justificationZapnout
-
+ Table grid layoutRozložení herní mřížky
-
+ Invert vertical coordinatePřevrátit vertikální souřadnice
-
+ Minimum player count for multi-column layout:Minimální počet hráčů pro víceřádkové rozvržení:
-
+ Maximum font size for information displayed on cards:Maximální velikost písma pro informace na kartách
@@ -322,7 +300,12 @@ Are you sure you would like to disable this feature?
ArchidektApiResponseDeckDisplayWidget
-
+
+ Back to results
+
+
+
+ Open Deck in Deck Editor
@@ -642,22 +625,22 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
CardInfoPictureWidget
-
+ View related cards
-
+ Add card to deck
-
+ Mainboard
-
+ Sideboard
@@ -693,124 +676,124 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
CardMenu
-
+ Re&veal to...
-
+ &All players
-
+ View related cards
-
+ Token:
-
+ All tokens
-
+ &Select All
-
+ S&elect Row
-
+ S&elect Column
-
+ &Play
-
+ &Hide
-
+ Play &Face Down
-
+ &Tap / UntapTurn sideways or back again
-
- Toggle &normal untapping
+
+ Skip &untapping
-
+ T&urn OverTurn face up/face down
-
+ &Peek at card face
-
+ &Clone
-
+ Attac&h to card...
-
+ Unattac&h
-
+ &Draw arrow...
-
+ &Set annotation...
-
+ Ca&rd counters
-
+ &Add counter (%1)
-
+ &Remove counter (%1)
-
+ &Set counters (%1)...
@@ -826,133 +809,133 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
CardZoneLogic
-
+ their handnominative
-
+ %1's handnominative
-
+ their librarylook at zone
-
+ %1's librarylook at zone
-
+ of their librarytop cards of zone,
-
+ of %1's librarytop cards of zone
-
+ their libraryreveal zone
-
+ %1's libraryreveal zone
-
+ their libraryshuffle
-
+ %1's libraryshuffle
-
+ their librarynominative
-
-
- %1's library
- nominative
-
-
+ %1's library
+ nominative
+
+
+
+ their graveyardnominative
-
+ %1's graveyardnominative
-
+ their exilenominative
-
+ %1's exilenominative
-
-
- their sideboard
- look at zone
-
-
-
-
- %1's sideboard
- look at zone
-
- their sideboard
- nominative
+ look at zone%1's sideboard
+ look at zone
+
+
+
+
+ their sideboardnominative
-
+
+ %1's sideboard
+ nominative
+
+
+
+ their custom zone '%1'nominative
-
+ %1's custom zone '%2'nominative
@@ -1014,7 +997,7 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorCardDatabaseDockWidget
-
+ Card Database
@@ -1022,7 +1005,7 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorCardInfoDockWidget
-
+ Card Info
@@ -1045,32 +1028,32 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
-
+ Select Printing
-
+ Show on EDHRec (Commander)
-
+ Show on EDHRec (Card)
-
+ Show Related cards
-
+ Add card to &maindeck
-
+ Add card to &sideboard
@@ -1078,32 +1061,32 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorDeckDockWidget
-
+ Loading Database...
-
+ Banner Card
-
+ Main Type
-
+ Mana Cost
-
+ Colors
-
+ Select Printing
@@ -1176,17 +1159,17 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorFilterDockWidget
-
+ Filters
-
+ &Clear all filters
-
+ Delete selected
@@ -1309,7 +1292,7 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorPrintingSelectorDockWidget
-
+ Printing Selector
@@ -1317,166 +1300,166 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckEditorSettingsPage
-
-
+
+ Update SpoilersAktualizovat spoilery
-
-
+
+ SuccessÚspěch
-
+ Download URLs have been reset.
-
+ Downloaded card pictures have been reset.Stáhnuté obrázky karet byly resetovány.
-
+ ErrorChyba
-
+ One or more downloaded card pictures could not be cleared.Některé stáhnuté obrázky karet nemohli být vymazány.
-
+ Add URL
-
-
+
+ URL:URL:
-
-
+
+ Edit URL
-
+ Network Cache Size:
-
+ Redirect Cache TTL:
-
+ How long cached redirects for urls are valid for.
-
+ Picture Cache Size:
-
+ Add New URL
-
+ Remove URL
-
+ Day(s)
-
+ Updating...Aktualizuji...
-
+ Choose pathVyberte cestu
-
+ URL Download Priority
-
+ SpoilersSpoilery
-
+ Download Spoilers AutomaticallyStahovat spoilery automaticky
-
+ Spoiler Location:
-
+ Last ChangePoslední změna
-
+ Spoilers download automatically on launchAutomaticky stahovat spoilery při spuštění
-
+ Press the button to manually update without relaunchingManuálně aktualizovat bez restartování
-
+ Do not close settings until manual update is complete
-
+ Download card pictures on the fly
-
+ How to add a custom URL
-
+ Delete Downloaded ImagesSmazat stáhnuté obrázky
-
+ Reset Download URLs
-
+ On-disk cache for downloaded pictures
-
+ In-memory cache for pictures not currently on screen
@@ -1484,32 +1467,32 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckListHistoryManagerWidget
-
+ Undo
-
+ Redo
-
+ Undo/Redo history
-
+ Click on an entry to revert to that point in the history.
-
+ [redo]
-
+ [undo]
@@ -1517,27 +1500,27 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckListModel
-
+ Count
-
+ Set
-
+ NumberPočet
-
+ Provider ID
-
+ CardKarta
@@ -1545,12 +1528,12 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckLoader
-
+ Common deck formats (%1)
-
+ All files (*.*)
@@ -1647,94 +1630,94 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
DeckPreviewWidget
-
+ Banner Card
-
+ Open in deck editor
-
+ Edit Tags
-
+ Rename Deck
-
+ Save Deck to Clipboard
-
+ Annotated
-
+ Annotated (No set info)
-
+ Not Annotated
-
+ Not Annotated (No set info)
-
+ Rename File
-
+ Delete File
-
+ Set Banner Card
-
-
+
+ New name:
-
-
+
+ Error
-
+ Rename failed
-
+ Delete file
-
+ Are you sure you want to delete the selected file?
-
+ Delete failed
@@ -1767,32 +1750,32 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
-
+ Added (%1): %2 (%3) %4
-
+ Moved to %1 1 × "%2" (%3)
-
+ Removed "%1" (all copies)
-
+ %1 1 × "%2" (%3)
-
+ Added
-
+ Removed
@@ -1859,29 +1842,29 @@ Toto je uloženo pouze pro moderátory a banovaná osoba to neuvidí.
-
-
+
+ ErrorChyba
-
+ The selected file could not be loaded.Vybraný soubor se nepodařilo načíst.
-
+ Deck is greater than maximum file size.
-
+ Are you sure you want to force start?
This will kick all non-ready players from the game.
-
+ Cockatrice
@@ -2374,17 +2357,17 @@ Pro odstranění současného avatara potvrďte bez vybrání nového obrázku.<
DlgEditDeckInClipboard
-
+ Edit deck in clipboard
-
+ Error
-
+ Invalid deck list.
@@ -2885,17 +2868,17 @@ Pro správné zobrazení si aktivujte si edici 'Token' v "Nastavi
DlgLoadDeckFromClipboard
-
+ Load deck from clipboardNahrát balíček ze schránky
-
+ ErrorChyba
-
+ Invalid deck list.Neplatný formát balíčku.
@@ -2903,43 +2886,43 @@ Pro správné zobrazení si aktivujte si edici 'Token' v "Nastavi
DlgLoadDeckFromWebsite
-
+ Paste a link to a decklist site here to import it.
(Archidekt, Deckstats, Moxfield, and TappedOut are supported.)
-
-
-
-
-
+
+
+
+
+ Load Deck from Website
-
+ No parser available for this deck provider.
(Archidekt, Deckstats, Moxfield, and TappedOut are supported.)
-
+ Network error: %1
-
+ Received empty deck data.
-
+ Failed to parse deck data: %1
-
+ The provided URL is not recognized as a valid deck URL.
Valid deck URLs look like this:
@@ -2958,40 +2941,73 @@ https://tappedout.net/mtg-decks/your-deck-name/Nahrát balíček
+
+ DlgLocalGameOptions
+
+
+ Players:
+
+
+
+
+ General
+
+
+
+
+ Starting life total:
+
+
+
+
+ Game setup options
+
+
+
+
+ Remember settings
+
+
+
+
+ Local game options
+
+
+DlgMoveTopCardsUntil
-
+ Card name (or search expressions):
-
+ Number of hits:
-
+ Auto play hits
-
+ Put top cards on stack until...
-
+ No cards matching the search expression exists in the card database. Proceed anyways?
-
+ Cockatrice
-
+ Invalid filter
@@ -3152,12 +3168,12 @@ Your email will be used to verify your account.
DlgSettings
-
+ Unknown Error loading card databaseNeznámý error při nahrávání databáze karet.
-
+ Your card database is invalid.
Cockatrice may not function correctly with an invalid database
@@ -3174,7 +3190,7 @@ Je možné že bude nutné znovu spustit Oracle pro obnovení databáze karet.
Chtěl/a by jste změnit nastavení lokace databáze?
-
+ Your card database version is too old.
This can cause problems loading card information or images
@@ -3191,7 +3207,7 @@ Je možné to spravit spuštěním Oracle pro aktualizaci vaší databáze karet
Chcete změnit nastavení lokace databáze?
-
+ Your card database did not finish loading
Please file a ticket at https://github.com/Cockatrice/Cockatrice/issues with your cards.xml attached
@@ -3200,7 +3216,7 @@ Would you like to change your database location setting?
-
+ File Error loading your card database.
Would you like to change your database location setting?
@@ -3209,7 +3225,7 @@ Would you like to change your database location setting?
Chcete změnit nastavení lokace databáze?
-
+ Your card database was loaded but contains no cards.
Would you like to change your database location setting?
@@ -3218,7 +3234,7 @@ Would you like to change your database location setting?
Chcete změnit nastavení lokace databáze?
-
+ Unknown card database load status
Please file a ticket at https://github.com/Cockatrice/Cockatrice/issues
@@ -3227,59 +3243,59 @@ Would you like to change your database location setting?
-
-
-
+
+
+ ErrorChyba
-
+ The path to your deck directory is invalid. Would you like to go back and set the correct path?Cesta k adresáři s balíčky je neplatná. Chcete se vrátit a nastavit správnou?
-
+ The path to your card pictures directory is invalid. Would you like to go back and set the correct path?Cesta k adresáři s obrázky je neplatná. Chcete se vrátit a nastavit správnou?
-
+ SettingsNastavení
-
+ GeneralObecné
-
+ AppearanceVzhled
-
+ User InterfaceRozhraní
-
+ Card Sources
-
+ ChatChat
-
+ SoundZvuk
-
+ ShortcutsSkratky
@@ -3592,67 +3608,67 @@ You may have to manually download the new version.
DrawProbabilityWidget
-
+ Draw Probability
-
+ Probability of drawing
-
+ Card Name
-
+ Type
-
+ Subtype
-
+ Mana Value
-
+ At least
-
+ Exactly
-
+ card(s) having drawn at least
-
+ cards
-
+ Category
-
+ Qty
-
+ Odds (%)
@@ -4100,143 +4116,143 @@ You may have to manually download the new version.
GeneralSettingsPage
-
+ Reset all paths
-
+ All paths have been reset
-
-
-
-
-
-
-
+
+
+
+
+
+
+ Choose pathVyberte cestu
-
+ Personal settingsOsobní nastavení
-
+ Language:Jazyk:
-
+ Paths (editing disabled in portable mode)
-
+ PathsCesty
-
+ How to help with translations
-
+ Decks directory:Adresář s balíčky:
-
+ Filters directory:
-
+ Replays directory:Adresář se záznamy her
-
+ Pictures directory:Adresář s obrázky:
-
+ Card database:Databáze karet:
-
+ Custom database directory:
-
+ Token database:Databáze tokenů:
-
+ Update channel
-
+ Check for client updates on startup
-
+ Check for card database updates on startup
-
+ Don't check
-
+ Prompt for update
-
+ Always update in the background
-
+ Check for card database updates every
-
+ days
-
+ Notify if a feature supported by the server is missing in my client
-
+ Automatically run Oracle when running a new version of CockatriceAutomaticky spustit Oracle při spouštění nové verze Cockatrice
-
+ Show tips on startupUkázat tip při spuštění
-
+ Last update check on %1 (%2 days ago)
@@ -4244,47 +4260,47 @@ You may have to manually download the new version.
GraveyardMenu
-
+ &Graveyard
-
+ &View graveyard
-
+ &Move graveyard to...
-
+ &Top of library
-
+ &Bottom of library
-
+ &All players
-
+ &Hand
-
+ &Exile
-
+ Reveal random card to...
@@ -4292,88 +4308,88 @@ You may have to manually download the new version.
HandMenu
-
+ &Hand
-
+ &View hand
-
+ Sort hand by...
-
+ Name
-
+ Type
-
+ Mana Value
-
+ Take &mulligan (Choose hand size)
-
+ Take mulligan (Same hand size)
-
+ Take mulligan (Hand size - 1)
-
+ &Move hand to...
-
+ &Top of library
-
+ &Bottom of library
-
+ &Graveyard
-
+ &Exile
-
+ &Reveal hand to...
-
-
+
+ All players
-
+ Reveal r&andom card to...
@@ -4381,52 +4397,52 @@ You may have to manually download the new version.
HomeWidget
-
+ Create New Deck
-
+ Browse Decks
-
+ Browse Card Database
-
+ Browse EDHRec
-
+ Browse Archidekt
-
+ View Replays
-
+ Quit
-
+ Connecting...
-
+ Connect
-
+ Play
@@ -4434,193 +4450,213 @@ You may have to manually download the new version.
LibraryMenu
-
+ &Library
-
+ &View library
-
+ View &top cards of library...
-
+ View bottom cards of library...
-
+ Reveal &library to...
-
+ Lend library to...
-
+ Reveal &top cards to...
-
+ &Top of library...
-
+ &Bottom of library...
-
+ &Always reveal top card
-
+ &Always look at top card
-
+ &Open deck in deck editor
-
+ &Draw card
-
+ D&raw cards...
-
+ &Undo last draw
-
+ Shuffle
-
+ &Play top card
-
+ Play top card &face down
-
+ Put top card on &bottom
-
+ Move top card to grave&yard
-
+ Move top card to e&xile
-
+ Move top cards to &graveyard...
-
+
+ Move top cards to graveyard face down...
+
+
+
+ Move top cards to &exile...
-
+
+ Move top cards to exile face down...
+
+
+
+ Put top cards on stack &until...
-
+ Shuffle top cards...
-
+ &Draw bottom card
-
+ D&raw bottom cards...
-
+ &Play bottom card
-
+ Play bottom card &face down
-
+ Move bottom card to grave&yard
-
+ Move bottom card to e&xile
-
+ Move bottom cards to &graveyard...
-
+
+ Move bottom cards to graveyard face down...
+
+
+
+ Move bottom cards to &exile...
-
+
+ Move bottom cards to exile face down...
+
+
+
+ Put bottom card on &top
-
+ Shuffle bottom cards...
-
-
+
+ &All players
-
+ Reveal top cards of library
-
+ Number of cards: (max. %1)
@@ -4712,18 +4748,8 @@ Will now login.
-
- Number of players
- Počet hráčů
-
-
-
- Please enter the number of players.
- Vložte počet hráčů.
-
-
-
-
+
+ Player %1Hráč %1
@@ -4826,8 +4852,8 @@ Will now login.
-
-
+
+ ErrorChyba
@@ -5231,144 +5257,144 @@ Lokální verze je %1, verze serveru je %2.
-
+ New Version
-
+ Congratulations on updating to Cockatrice %1!
Oracle will now launch to update your card database.
-
+ Cockatrice installed
-
+ Congratulations on installing Cockatrice %1!
Oracle will now launch to install the initial card database.
-
+ Card database
-
+ Cockatrice is unable to load the card database.
Do you want to update your card database now?
If unsure or first time user, choose "Yes"
-
-
+
+ Yes
-
-
+
+ No
-
+ Open settings
-
+ New sets found
-
+ %n new set(s) found in the card database
Set code(s): %1
Do you want to enable it/them?
-
+ View sets
-
+ Welcome
-
+ Hi! It seems like you're running this version of Cockatrice for the first time.
All the sets in the card database have been enabled.
Read more about changing the set order or disabling specific sets and consequent effects in the "Manage Sets" dialog.
-
-
+
+ Information
-
+ A card database update is already running.
-
+ Unable to run the card database updater:
-
+ Card database update running.
-
+ Failed to start. The file might be missing, or permissions might be incorrect.
-
+ The process crashed some time after starting successfully.
-
+ Timed out. The process took too long to respond. The last waitFor...() function timed out.
-
+ An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.
-
+ An error occurred when attempting to read from the process. For example, the process may not be running.
-
+ Unknown error occurred.
-
+ The card database updater exited with an error:
%1
-
+ This server supports additional features that your client doesn't have.
This is most likely not a problem, but this message might mean there is a new version of Cockatrice available or this server is running a custom or pre-release version.
@@ -5376,54 +5402,54 @@ To update your client, go to Help -> Check for Updates.
-
-
-
-
-
+
+
+
+
+ Load sets/cards
-
+ Selected file cannot be found.
-
+ You can only import XML databases at this time.
-
+ The new sets/cards have been added successfully.
Cockatrice will now reload the card database.
-
+ Sets/cards failed to import.
-
-
-
+
+
+ Reset Password
-
+ Your password has been reset successfully, you can now log in using the new credentials.
-
+ Failed to reset user account password, please contact the server operator to reset your password.
-
+ Activation request received, please check your email for an activation token.
@@ -5474,7 +5500,7 @@ Cockatrice will now reload the card database.
ManaBaseWidget
-
+ Mana Base
@@ -5628,590 +5654,610 @@ Cockatrice will now reload the card database.
MessageLogWidget
-
+ from play
-
+ from their graveyard
-
+ from exile z exilnutých karet
-
+ from their hand
-
+ the top card of %1's library
-
+ the top card of their library
-
+ from the top of %1's library
-
+ from the top of their library
-
+ the bottom card of %1's library
-
+ the bottom card of their library
-
+ from the bottom of %1's library
-
+ from the bottom of their library
-
+ from %1's library
-
+ from their library
-
+ from sideboard ze sideboardu
-
+ from the stack ze stacku
-
+ from custom zone '%1'
-
+ %1 is now keeping the top card %2 revealed.
-
+ %1 is not revealing the top card %2 any longer.
-
+ %1 can now look at top card %2 at any time.
-
+ %1 no longer can look at top card %2 at any time.
-
+ %1 attaches %2 to %3's %4.
-
+ %1 has conceded the game.
-
+ %1 has unconceded the game.
-
+ %1 has restored connection to the game.
-
+ %1 has lost connection to the game.
-
+ %1 points from their %2 to themselves.
-
+ %1 points from their %2 to %3.
-
+ %1 points from %2's %3 to themselves.
-
+ %1 points from %2's %3 to %4.
-
+ %1 points from their %2 to their %3.
-
+ %1 points from their %2 to %3's %4.
-
+ %1 points from %2's %3 to their own %4.
-
+ %1 points from %2's %3 to %4's %5.
-
+ %1 creates a face down token.
-
+ %1 creates token: %2%3.
-
+ %1 has loaded a deck (%2).
-
+ %1 has loaded a deck with %2 sideboard cards (%3).
-
+ %1 destroys %2.
-
+ a cardkartu
-
+ %1 gives %2 control over %3.%1 předává kontrolu hráči %2 karty %3.
-
+ %1 puts %2 into play%3 face down.
-
+ %1 puts %2 into play%3.%1 dává kartu %2 %3 do hry.
-
+
+ %1 puts %2%3 into their graveyard face down.
+
+
+
+ %1 puts %2%3 into their graveyard.
+
+
+ %1 exiles %2%3 face down.
+
+ %1 exiles %2%3.%1 exiluje %2%3.
-
+ %1 moves %2%3 to their hand.
-
+ %1 puts %2%3 into their library.
-
+ %1 puts %2%3 onto the bottom of their library.
-
+ %1 puts %2%3 on top of their library.
-
+ %1 puts %2%3 into their library %4 cards from the top.
-
+ %1 moves %2%3 to sideboard.%1 přesouvá %2%3 do sideboardu.
-
+
+ %1 plays %2%3 face down.
+
+
+
+ %1 plays %2%3.%1 sesílá %2%3.
-
+
+ %1 moves %2%3 to custom zone '%4' face down.
+
+
+
+ %1 moves %2%3 to custom zone '%4'.
-
+ %1 tries to draw from an empty library
-
+ %1 draws %2 card(s).
-
+ %1 is looking at %2.
-
+ %1 is looking at the %4 %3 card(s) %2.top card for singular, top %3 cards for plural
-
+ bottom
-
+ top
-
+ %1 turns %2 face-down.
-
+ %1 turns %2 face-up.
-
+ The game has been closed.Hra byla ukončena.
-
+ The game has started.Hra začíná.
-
+ You are flooding the game. Please wait a couple of seconds.
-
+ %1 has joined the game.
-
+ %1 is now watching the game.%1 nyní sleduje hru.
-
+ You have been kicked out of the game.
-
+ %1 has left the game (%2).
-
+ %1 is not watching the game any more (%2).
-
+ %1 is not ready to start the game any more.
-
+ %1 shuffles their deck and draws a new hand of %2 card(s).
-
+ %1 shuffles their deck and draws a new hand.
-
+ You are watching a replay of game #%1.
-
+ %1 is ready to start the game.
-
+ cardsan unknown amount of cards
-
+ %1 card(s)a card for singular, %1 cards for plural
-
+ %1 lends %2 to %3.
-
+ %1 reveals %2 to %3.
-
+ %1 reveals %2.
-
+ %1 randomly reveals %2%3 to %4.
-
+ %1 randomly reveals %2%3.
-
+ %1 peeks at face down card #%2.
-
+ %1 peeks at face down card #%2: %3.
-
+ %1 reveals %2%3 to %4.
-
+ %1 reveals %2%3.
-
+ %1 reversed turn order, now it's %2.
-
+ reversed
-
+ normal
-
+ Heads
-
+ Tails
-
+ %1 flipped a coin. It landed as %2.
-
+ %1 rolls a %2 with a %3-sided die.
-
+ %1 flips %2 coins. There are %3 heads and %4 tails.
-
+ %1 rolls a %2-sided dice %3 times: %4.
-
+ %1's turn.
-
+ %1 sets annotation of %2 to %3.
-
+ %1 places %2 "%3" counter(s) on %4 (now %5).
-
+ %1 removes %2 "%3" counter(s) from %4 (now %5).
-
+ %1 sets counter %2 to %3 (%4%5).
-
+ %1 sets %2 to not untap normally.
-
+ %1 sets %2 to untap normally.
-
+ %1 removes the PT of %2.
-
+ %1 changes the PT of %2 from nothing to %4.
-
+ %1 changes the PT of %2 from %3 to %4.
-
+ %1 has locked their sideboard.
-
+ %1 has unlocked their sideboard.
-
+ %1 taps their permanents.
-
+ %1 untaps their permanents.
-
+ %1 taps %2.
-
+ %1 untaps %2.
-
+ %1 shuffles %2.
-
+ %1 shuffles the bottom %3 cards of %2.
-
+ %1 shuffles the top %3 cards of %2.
-
+ %1 shuffles cards %3 - %4 of %2.
-
+ %1 unattaches %2.
-
+ %1 undoes their last draw.
-
+ %1 undoes their last draw (%2).
@@ -6219,110 +6265,110 @@ Cockatrice will now reload the card database.
MessagesSettingsPage
-
+ Word1 Word2 Word3
-
+ Add New Message
-
+ Edit Message
-
+ Remove Message
-
+ Add messagePřidat zprávu
-
-
+
+ Message:Zpráva:
-
+ Edit message
-
+ Chat settings
-
+ Custom alert words
-
+ Enable chat mentions
-
+ Enable mention completer
-
+ In-game message macros
-
+ How to use in-game message macros
-
+ Ignore chat room messages sent by unregistered users
-
+ Ignore private messages sent by unregistered users
-
-
+
+ Invert text color
-
+ Enable desktop notifications for private messages
-
+ Enable desktop notification for mentions
-
+ Enable room message history on join
-
-
+
+ (Color is hexadecimal)
-
+ Separate words with a space, alphanumeric characters only
@@ -6335,32 +6381,37 @@ Cockatrice will now reload the card database.
-
+ &Top of library in random order
-
+ X cards from the top of library...
-
+ &Bottom of library in random order
-
+
+ T&able
+
+
+
+ &Hand
-
+ &Graveyard
-
+ &Exile
@@ -6502,57 +6553,57 @@ Cockatrice will now reload the card database.
PhasesToolbar
-
+ Untap stepOdtapovací fáze
-
+ Upkeep stepUpkeep
-
+ Draw stepLízací fáze
-
+ First main phasePrvní hlavní fáze
-
+ Beginning of combat stepZačátek bojové fáze
-
+ Declare attackers stepOznámení útočníků
-
+ Declare blockers stepOznámení blokujících
-
+ Combat damage stepUdělení bojového zranění
-
+ End of combat stepKonec bojové fáze
-
+ Second main phaseDruhá hlavní fáze
-
+ End of turn stepKonec kola
@@ -6569,134 +6620,138 @@ Cockatrice will now reload the card database.
PlayerActions
-
+ View top cards of library
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Number of cards: (max. %1)
-
+ View bottom cards of library
-
+ Shuffle top cards of library
-
+ Shuffle bottom cards of library
-
+ Draw hand
-
+ 0 and lower are in comparison to current hand size
-
+ Draw cards
+
+
+
+
+
+ grave
+
+
- Move top cards to grave
+
+
+
+ exile
-
- Move top cards to exile
+
+ Move top cards to %1
-
- Move bottom cards to grave
+
+ Move bottom cards to %1
-
- Move bottom cards to exile
-
-
-
-
+ Draw bottom cards
-
-
+
+ C&reate another %1 token
-
+ Create tokens
-
-
+
+ Number:
-
+ Place card X cards from top of library
-
+ Which position should this card be placed:
-
+ (max. %1)
-
+ Change power/toughness
-
+ Change stats to:
-
+ Set annotation
-
+ Please enter the new annotation:
-
+ Set counters
@@ -6704,48 +6759,65 @@ Cockatrice will now reload the card database.
PlayerMenu
-
+ Player "%1"
-
+ &Counters
+
+
+ PrintingDisabledInfoWidget
-
- S&ay
+
+ The Printing Selector is disabled because you have currently enabled the setting to override all selected printings with personal set preferences.
+
+This setting means you'll only see the default printing for each card, instead of being able to select a printing, and will not see the printings other people have selected.
+
+
+
+
+
+
+ Enable printings againPrintingSelector
-
+ Display Navigation Buttons
+
+
+ Printing Selector
+
+ PrintingSelectorCardOverlayWidget
-
+ Preference
-
+ Pin Printing
-
+ Unpin Printing
-
+ Show Related cards
@@ -6794,17 +6866,25 @@ Cockatrice will now reload the card database.
-
-
+
+ Descending
-
+ Ascending
+
+ PrintingSelectorPlaceholderWidget
+
+
+ Select a card to view its available printings
+
+
+PtMenu
@@ -6943,6 +7023,33 @@ Cockatrice will now reload the card database.
A .cod version of this deck already exists. Overwrite it?
+
+
+ Enabling this feature will disable the use of the Printing Selector.
+
+You will not be able to manage printing preferences on a per-deck basis, or see printings other people have selected for their decks.
+
+You will have to use the Set Manager, available through Card Database -> Manage Sets.
+
+Are you sure you would like to enable this feature?
+
+
+
+
+ Disabling this feature will enable the Printing Selector.
+
+You can now choose printings on a per-deck basis in the Deck Editor and configure which printing gets added to a deck by default by pinning it in the Printing Selector.
+
+You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available).
+
+Are you sure you would like to disable this feature?
+
+
+
+
+ Confirm Change
+
+ QPlatformTheme
@@ -7091,37 +7198,37 @@ Cockatrice will now reload the card database.
RfgMenu
-
+ &Exile
-
+ &View exile
-
+ &Move exile to...
-
+ &Top of library
-
+ &Bottom of library
-
+ &Hand
-
+ &Graveyard
@@ -7164,6 +7271,14 @@ Cockatrice will now reload the card database.
Hry
+
+ SayMenu
+
+
+ S&ay
+
+
+SequenceEdit
@@ -7228,53 +7343,53 @@ Cockatrice will now reload the card database.
ShortcutSettingsPage
-
-
+
+ Restore all default shortcuts
-
+ Do you really want to restore all default shortcuts?
-
+ Clear all default shortcuts
-
+ Do you really want to clear all shortcuts?
-
+ Section:
-
+ Action:
-
+ Shortcut:
-
+ How to set custom shortcuts
-
+ Clear all shortcuts
-
+ Search by shortcut name
@@ -7341,27 +7456,27 @@ Please check your shortcut settings!
SoundSettingsPage
-
+ Enable &sounds
-
+ Current sounds theme:
-
+ Test system sound engine
-
+ Sound settings
-
+ Master volume
@@ -7577,59 +7692,123 @@ Please check your shortcut settings!
TabArchidekt
-
-
+
+
+ Desc.
-
- Asc.
+
+
+ AND
-
-
- Any Bracket
+
+
+ Require ALL selected colors
-
- Deck name contains...
+
+
+ Deck name...
-
- Owner name contains...
+
+
+ Owner...
+
+
+
+
+
+ Packages
+
+
+
+
+
+ Advanced Filters
- Disabled
+ Bracket:
-
+
+
+ Any
+
+
+
+
+
+ Contains card...
+
+
+
+
+
+ Commander...
+
+
+
+
+
+ Tag...
+
+
+
+
+
+ Deck Size
+
+
+
+
+ Cards:
+
+
+
+
+
+ Asc.
+
+
+
+
+ Sort by:
+
+
+
+
+ Filter by:
+
+
+
+
+ Display Settings
+
+
+
+
+ Search
-
+
+ Formats
-
- Min. # of Cards:
-
-
-
-
- Page:
-
-
-
-
+ Archidekt:
@@ -7637,60 +7816,52 @@ Please check your shortcut settings!
TabDeckEditor
-
+ Card Info
-
+ Deck
-
+ Filters
-
+ &View
-
+ Card Database
-
+ Printing
-
-
-
-
-
+ Visible
-
-
-
-
-
+ Floating
-
+ Reset layout
-
+ Deck: %1
@@ -7698,61 +7869,55 @@ Please check your shortcut settings!
TabDeckEditorVisual
-
+ Visual Deck: %1
-
+ &Visual Deck Editor
-
-
+
+ Card Info
-
-
+
+ Deck
-
-
+
+ Filters
-
+ &View
-
+ Printing
-
-
-
-
+ Visible
-
-
-
-
+ Floating
-
+ Reset layout
@@ -7817,7 +7982,7 @@ Please check your shortcut settings!
-
+ New folderNová složka
@@ -7899,18 +8064,18 @@ Prosím vložte jméno:
-
+ Delete remote decks
-
+ Are you sure you want to delete the selected decks?
-
+ Name of new folder:Název nové složky:
@@ -7928,12 +8093,12 @@ Prosím vložte jméno:
-
+ Error
-
+ Could not open deck at %1
@@ -7982,197 +8147,191 @@ Prosím vložte jméno:
TabGame
-
-
-
+
+
+ Replay
-
-
+
+ Game
-
-
+
+ Player List
-
-
+
+ Card Info
-
-
+
+ Messages
-
-
+
+ Replay Timeline
-
+ &Phases&Fáze
-
+ &Game&Hra
-
+ Next &phaseDalší &fáze
-
+ Next phase with &action
-
+ Next &turnDalší &kolo
-
+ Reverse turn order
-
+ &Remove all local arrows&Odstranit všechny lokální šipky
-
+ Rotate View Cl&ockwise
-
+ Rotate View Co&unterclockwise
-
+ Game &information
-
+ Un&concede
-
-
-
+
+
+ &Concede&Ukončit hru
-
+ &Leave game&Opustit hru
-
+ C&lose replay
-
+ &Focus Chat
-
+ &Say:&Chat:
-
+ Selected cards
-
+ &View
-
-
-
-
+ Visible
-
-
-
-
+ Floating
-
+ Reset layout
-
+ ConcedeUkončit hru
-
+ Are you sure you want to concede this game?Opravdu chcete ukončit tuto hru?
-
+ Unconcede
-
+ You have already conceded. Do you want to return to this game?
-
+ Leave gameOpustit hru
-
+ Are you sure you want to leave this game?Opravdu chcete opustit tuto hru?
-
+ A player has joined game #%1
-
+ %1 has joined the game
-
+ You have been kicked out of the game.
@@ -9266,142 +9425,152 @@ Please refrain from engaging in this activity or further actions may be taken ag
UserInterfaceSettingsPage
-
+ General interface settingsObecné
-
+ &Double-click cards to play them (instead of single-click)&Pro zahraní karty je třeba dvojklik
-
+ &Clicking plays all selected cards (instead of just the clicked card)
-
+ &Play all nonlands onto the stack (not the battlefield) by default
-
+ Do not delete &arrows inside of subphases
-
+ Close card view window when last card is removed
-
+ Auto focus search bar when card view window is opened
-
+ Annotate card text on tokens
-
-
- Use tear-off menus, allowing right click menus to persist on screen
-
-
-
-
- Notifications settings
-
-
-
-
- Enable notifications in taskbar
-
-
-
-
- Notify in the taskbar for game events while you are spectating
-
-
-
-
- Notify in the taskbar when users in your buddy list connect
-
-
-
-
- Animation settings
- Animace
-
-
-
- &Tap/untap animation
- &Animace tapnutí/odtapnutí
-
-
-
- Deck editor/storage settings
-
-
-
-
- Open deck in new tab by default
-
-
- Use visual deck storage in game lobby
+ Show selection counter during drag selection
- Use selection animation for Visual Deck Storage
+ Show total selection counter
+
+
+
+
+ Use tear-off menus, allowing right click menus to persist on screen
- When adding a tag in the visual deck storage to a .txt deck:
+ Notifications settings
+
+
+
+
+ Enable notifications in taskbar
- do nothing
+ Notify in the taskbar for game events while you are spectating
+
+
+
+
+ Notify in the taskbar when users in your buddy list connect
- ask to convert to .cod
-
+ Animation settings
+ Animace
+
+
+
+ &Tap/untap animation
+ &Animace tapnutí/odtapnutí
- always convert to .cod
+ Deck editor/storage settings
- Default deck editor type
+ Open deck in new tab by default
- Classic Deck Editor
+ Use visual deck storage in game lobby
- Visual Deck Editor
-
-
-
-
- Replay settings
+ Use selection animation for Visual Deck Storage
+ When adding a tag in the visual deck storage to a .txt deck:
+
+
+
+
+ do nothing
+
+
+
+
+ ask to convert to .cod
+
+
+
+
+ always convert to .cod
+
+
+
+
+ Default deck editor type
+
+
+
+
+ Classic Deck Editor
+
+
+
+
+ Visual Deck Editor
+
+
+
+
+ Replay settings
+
+
+
+ Buffer time for backwards skip via shortcut:
@@ -9465,23 +9634,24 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDatabaseDisplayColorFilterWidget
-
- Mode: Exact Match
+
+ Exact match
+
+
+
+
+ Includes
- Mode: Includes
+ Include / Exclude
+ Mode: Includes
-
- Mode: Include/Exclude
-
-
-
-
- Filter mode (AND/OR/NOT conjunctions of filters)
+
+ How selected and unselected colors are combined in the filter
@@ -9508,25 +9678,108 @@ Please refrain from engaging in this activity or further actions may be taken ag
+
+ VisualDatabaseDisplayFilterToolbarWidget
+
+
+ Sort by
+
+
+
+
+ Filter by
+
+
+
+
+ Save and load filters
+
+
+
+
+ Filter by exact card name
+
+
+
+
+ Filter by card main-type
+
+
+
+
+ Filter by card sub-type
+
+
+
+
+ Filter by set
+
+
+
+
+ Filter by format legality
+
+
+
+
+ Save/Load
+
+
+
+
+ Name
+
+
+
+
+ Main Type
+
+
+
+
+ Sub Type
+
+
+
+
+ Sets
+
+
+
+
+ Formats
+
+
+VisualDatabaseDisplayFormatLegalityFilterWidget
-
+
+ Show formats with at least:
+
+
+
+
+ cards
+
+
+
+ Do not display formats with less than this amount of cards in the database
-
+ Filter mode (AND/OR/NOT conjunctions of filters)
-
+ Mode: Exact Match
-
+ Mode: Includes
@@ -9534,22 +9787,32 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDatabaseDisplayMainTypeFilterWidget
-
+
+ Show main types with at least:
+
+
+
+
+ cards
+
+
+
+ Do not display card main-types with less than this amount of cards in the database
-
+ Filter mode (AND/OR/NOT conjunctions of filters)
-
+ Mode: Exact Match
-
+ Mode: Includes
@@ -9585,7 +9848,7 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDatabaseDisplayRecentSetFilterSettingsWidget
-
+ Filter to most recent sets
@@ -9593,19 +9856,19 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDatabaseDisplaySetFilterWidget
-
+ Search sets...
-
-
+
+ Mode: Exact Match
-
-
+
+ Mode: Includes
@@ -9613,27 +9876,37 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDatabaseDisplaySubTypeFilterWidget
-
+ Search subtypes...
-
+
+ Show sub types with at least:
+
+
+
+
+ cards
+
+
+
+ Do not display card sub-types with less than this amount of cards in the database
-
+ Filter mode (AND/OR/NOT conjunctions of filters)
-
+ Mode: Exact Match
-
+ Mode: Includes
@@ -9647,52 +9920,22 @@ Please refrain from engaging in this activity or further actions may be taken ag
-
+ Visual
-
+ Loading database ...
-
+ Clear all filters
-
- Sort by:
-
-
-
-
- Filter by:
-
-
-
-
- Save and load filters
-
-
-
-
- Filter by exact card name
-
-
-
-
- Filter by card sub-type
-
-
-
-
- Filter by set
-
-
-
-
+ Table
@@ -9700,56 +9943,64 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDeckDisplayOptionsWidget
-
+ Group by:
-
+ Change how cards are divided into categories/groups.
-
+ Sort by:
-
+ Click and drag to change the sort order within the groups
-
+ Configure how cards are sorted within their groups
-
-
+
+ Toggle Layout: Overlap
-
+ Change how cards are displayed within zones (i.e. overlapped or fully visible.)
-
+ Toggle Layout: Flat
+
+ VisualDeckEditorPlaceholderWidget
+
+
+ Add cards using the search bar or database tab to have them appear here
+
+
+VisualDeckEditorSampleHandWidget
-
+ Draw a new sample hand
-
+ Sample hand size
@@ -9757,17 +10008,17 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDeckEditorWidget
-
+ Type a card name here for suggestions from the database...
-
+ Quick search and add card
-
+ Search for closest match in the database (with auto-suggestions) and add preferred printing to the deck on pressing enter
@@ -9783,47 +10034,52 @@ Please refrain from engaging in this activity or further actions may be taken ag
VisualDeckStorageQuickSettingsWidget
-
+ Show Folders
-
+ Show Tag Filter
-
+
+ Show Color Identity
+
+
+
+ Show Tags On Deck Previews
-
+ Show Banner Card Selection Option
-
+ Draw unused Color Identities
-
+ Unused Color Identities Opacity
-
+ Deck tooltip:
-
+ None
-
+ Filepath
@@ -9924,133 +10180,133 @@ Please refrain from engaging in this activity or further actions may be taken ag
WndSets
-
+ Move selected set to the top
-
+ Move selected set up
-
+ Move selected set down
-
+ Move selected set to the bottom
-
+ Search by set name, code, or type
-
+ Default order
-
+ Restore original art priority order
-
+ Enable all sets
-
+ Disable all sets
-
+ Enable selected set(s)
-
+ Disable selected set(s)
-
+ Deck Editor
-
+ Use CTRL+A to select all sets in the view.
-
+ Only cards in enabled sets will appear in the card list of the deck editor.
-
+ Image priority is decided in the following order:
-
+ first the CUSTOM Folder (%1), then the Enabled Sets in this dialog (Top to Bottom)%1 is a link to the wiki
-
+ Include cards rebalanced for Alchemy [requires restart]
-
+ Card Art
-
+ How to use custom card art
-
+ Hints
-
+ Note
-
+ Sorting by column allows you to find a set while not changing set priority.
-
+ To enable ordering again, click the column header until this message disappears.
-
+ Use the current sorting as the set priority instead
-
+ Sorts the set priority using the same column
-
+ Manage sets
@@ -10058,72 +10314,72 @@ Please refrain from engaging in this activity or further actions may be taken ag
ZoneViewWidget
-
+ Search by card name (or search expressions)
-
+ Ungrouped
-
+ Group by Type
-
+ Group by Mana Value
-
+ Group by Color
-
+ Unsorted
-
+ Sort by Name
-
+ Sort by Type
-
+ Sort by Mana Cost
-
+ Sort by Colors
-
+ Sort by P/T
-
+ Sort by Set
-
+ shuffle when closingzamíchat po zavření
-
+ pile view
@@ -10158,7 +10414,7 @@ Please refrain from engaging in this activity or further actions may be taken ag
-
+ Deck Editor
@@ -10239,7 +10495,7 @@ Please refrain from engaging in this activity or further actions may be taken ag
-
+ Replays
@@ -10391,7 +10647,7 @@ Please refrain from engaging in this activity or further actions may be taken ag
-
+ Reset Layout
@@ -10812,7 +11068,8 @@ Please refrain from engaging in this activity or further actions may be taken ag
- Toggle Untap
+ Toggle Skip Untapping
+ Toggle Untap
@@ -10832,98 +11089,102 @@ Please refrain from engaging in this activity or further actions may be taken ag
- Attach Card...
+ Play Card, Face Down
- Unattach Card
+ Attach Card...
- Clone Card
+ Unattach Card
- Create Token...
+ Clone Card
- Create All Related Tokens
+ Create Token...
- Create Another Token
+ Create All Related Tokens
- Set Annotation...
+ Create Another Token
- Select All Cards in Zone
+ Set Annotation...
- Select All Cards in Row
+ Select All Cards in Zone
- Select All Cards in Column
+ Select All Cards in Row
- Reveal Selected Cards to All Players
+ Select All Cards in Column
-
- Bottom of Library
+ Reveal Selected Cards to All Players
+
+ Bottom of Library
+
+
+
+
-
-
+
+ ExileExil
-
+
-
+ GraveyardHřbitov
-
+ HandRuka
-
-
+
+ Top of Library
-
-
+ Battlefield, Face Down
@@ -10959,234 +11220,246 @@ Please refrain from engaging in this activity or further actions may be taken ag
-
+ Stack
-
+ Graveyard (Multiple)
-
-
+
+
+ Graveyard (Multiple), Face Down
+
+
+
+
+ Exile (Multiple)
-
+
+
+ Exile (Multiple), Face Down
+
+
+
+ Stack Until Found
-
+ Draw Bottom Card
-
+ Draw Multiple Cards from Bottom...
-
+ Draw Arrow...
-
+ Remove Local Arrows
-
+ Leave Game
-
+ ConcedeVzdát hru
-
+ Roll Dice...
-
+ Shuffle Library
-
+ Shuffle Top Cards of Library
-
+ Shuffle Bottom Cards of Library
-
+ MulliganMulligan
-
+ Mulligan (Same hand size)
-
+ Mulligan (Hand size - 1)
-
+ Draw a Card
-
+ Draw Multiple Cards...
-
+ Undo Draw
-
+ Always Reveal Top Card
-
+ Always Look At Top Card
-
+ Sort Hand by Name
-
+ Sort Hand by Type
-
+ Sort Hand by Mana Value
-
+ Reveal Hand to All Players
-
+ Reveal Random Card to All Players
-
+ Rotate View Clockwise
-
+ Rotate View Counterclockwise
-
+ Unfocus Text Box
-
+ Focus Chat
-
+ Clear Chat
-
+ Refresh
-
+ Skip Forward
-
+ Skip Backward
-
+ Skip Forward by a lot
-
+ Skip Backward by a lot
-
+ Play/Pause
-
+ Toggle Fast Forward
-
+ Home
-
+ Visual Deck Storage
-
+ Deck Storage
-
+ Server
-
+ Account
-
+ Administration
-
+ Logs
diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts
index ed1a88be8..564f39e25 100644
--- a/cockatrice/translations/cockatrice_de.ts
+++ b/cockatrice/translations/cockatrice_de.ts
@@ -23,12 +23,12 @@
AbstractDlgDeckTextEdit
-
+ &Refresh&aktualisieren
-
+ Parse Set Name and Number (if available)Setnamen und -Nummer parsen (falls verfügbar)
@@ -36,62 +36,62 @@
AbstractTabDeckEditor
-
+ Open in new tabIn neuem Reiter öffnen
-
+ Are you sure?Sind Sie sicher?
-
+ The decklist has been modified.
Do you want to save the changes?Die Deckliste wurde bearbeitet.
Änderungen speichern?
-
-
-
-
-
-
+
+
+
+
+
+ ErrorFehler
-
+ Could not open deck at %1Deck an Stelle %1 konnte nicht geöffnet werden
-
+ Could not save remote deckRemote-Deck konnte nicht gespeichert werden
-
-
+
+ The deck could not be saved.
Please check that the directory is writable and try again.Das Deck konnte nicht abgespeichert werden.
Bitte überprüfen Sie, ob das Verzeichnis bearbeitet werden kann und versuchen Sie es erneut.
-
+ Save deckDeck speichern
-
+ The deck could not be saved.Das Deck konnte nicht abgespeichert werden.
-
+ There are no cards in your deck to be exportedEs gibt keine Karten in Ihrem Deck zum Exportieren
@@ -133,202 +133,168 @@ Bitte überprüfen Sie, ob das Verzeichnis bearbeitet werden kann und versuchen
AppearanceSettingsPage
-
+ secondsSekunden
-
+ ErrorFehler
-
+ Could not create themes directory at '%1'.Das Themeverzeichnis '%1' konnte nicht erstellt werden.
-
- Enabling this feature will disable the use of the Printing Selector.
-
-You will not be able to manage printing preferences on a per-deck basis, or see printings other people have selected for their decks.
-
-You will have to use the Set Manager, available through Card Database -> Manage Sets.
-
-Are you sure you would like to enable this feature?
- Diese Funktion aktivieren wird die Nutzung der Druckauswahl deaktivieren.
-
-Es wird ihnen nicht möglich sein ihre Druckeinstellungen auf einer Per-Deck Basis zu verwalten, oder die Drucke, die andere Personen für ihre Decks ausgewählt haben, zu sehen.
-
-Sie werden den Set-Manager verwenden müssen, der über Kartendatenbank -> Sets verwalten verfügbar ist.
-
-Sind sie sicher, dass diese Funktion aktiviert werden soll?
-
-
-
- Disabling this feature will enable the Printing Selector.
-
-You can now choose printings on a per-deck basis in the Deck Editor and configure which printing gets added to a deck by default by pinning it in the Printing Selector.
-
-You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available).
-
-Are you sure you would like to disable this feature?
- Diese Funktion deaktivieren wird die Nutzung der Druckauswahl aktivieren.
-
-Es wird ihnen nun möglich sein ihre Druckeinstellungen auf einer Per-Deck Basis im Deck-Editor zu verwalten und zu konfigurieren, welcher Druck standardmäßig in ein Deck hinzugefügt wird, indem sie es anheften in der Druckauswahl
-
-Sie können auch den Set-Manager verwenden, um selbstständig die Sortierungsreihenfolge für Drucke in der Druckauswahl festzulegen (andere Sortierungsoptionen wie alphabetisch oder Veröffentlichkeitsdatum sind verfügbar).
-
-Sind sie sicher, dass diese Funktion deaktiviert werden soll?
-
-
-
- Confirm Change
- Änderung bestätigen
-
-
-
+ Theme settingsDarstellungseinstellungen
-
+ Current theme:Aktuelles Theme:
-
+ Open themes folderÖffne Themeverzeichnis
-
+ Home tab background source:Startseitenhintergrund-Quelle:
-
+ Home tab background shuffle frequency:Startseitenhintergrund Wechselfrequenz:
-
+ DisabledDeaktiviert
-
+
+ Display card name of background in bottom right:
+ Kartenname des Hintergrunds unten rechts anzeigen:
+
+
+ Menu settingsEinstellungsmenü
-
+ Show keyboard shortcuts in right-click menusTastatur-Kürzel anzeigen bei Rechtsklickmenü
-
+ Show game filter toolbar above list in room tabSpiel-Filter Symbolleiste über der Liste im Raum-Tab anzeigen
-
+ Card renderingKartendarstellung
-
+ Display card names on cards having a pictureKartennamen auch bei Karten mit Bildern darstellen
-
+ Auto-Rotate cards with sideways layoutAutomatisches Drehen von Karten mit Seitwärts-Ausrichtung
-
+ Override all card art with personal set preference (Pre-ProviderID change behavior)Überschreiben aller Kartenbilder mit persönlichen Set-Präferenzen (Vor-AnbieterID Wechselverhalten)
-
+ Bump sets that the deck contains cards from to the top in the printing selectorPriorisieren von Sets, in welchen Karten des ausgewählten Decks vorhanden sind, nach oben in der Druckauswahl
-
+ Scale cards on mouse overKarten beim Darüberfahren mit der Maus vergrößern
-
+ Use rounded card cornersAbgerundete Kartenecken verwenden
-
+ Minimum overlap percentage of cards on the stack and in vertical handMinimaler Überschneidungsanteil der Karten auf dem Stapel und in der vertikalen Hand
-
+ Maximum initial height for card view window:Maximale Starthöhe für das Kartenansichtsfenster
-
-
+
+ rowsReihen
-
+ Maximum expanded height for card view window:Maximale ausgeklappte Höhe für das Kartenansichtsfenster:
-
+ Card countersKartenzähler
-
+ Counter %1Zähler %1
-
+ Hand layoutHanddarstellung
-
+ Display hand horizontally (wastes space)Hand horizontal anzeigen (verschwendet Platz)
-
+ Enable left justificationLinksbündige Ausrichtung aktivieren
-
+ Table grid layoutSpielfeldraster
-
+ Invert vertical coordinateVertikale Koordinate umkehren
-
+ Minimum player count for multi-column layout:Mindestspieleranzahl für mehrspaltige Anordnung:
-
+ Maximum font size for information displayed on cards:Maximale Schriftgröße für die Anzeige von Informationen auf Karten:
@@ -336,7 +302,12 @@ Sind sie sicher, dass diese Funktion deaktiviert werden soll?
ArchidektApiResponseDeckDisplayWidget
-
+
+ Back to results
+ Zurück zu den Ergebnissen
+
+
+ Open Deck in Deck EditorDeck im Deck-Editor öffnen
@@ -656,22 +627,22 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
CardInfoPictureWidget
-
+ View related cardsZugehörige Karten ansehen
-
+ Add card to deckKarte zum Deck hinzufügen
-
+ MainboardMainboard
-
+ SideboardSideboard
@@ -707,124 +678,124 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
CardMenu
-
+ Re&veal to...Zeigen an....
-
+ &All players&Alle Spieler
-
+ View related cardsVerwandte Karten ansehen
-
+ Token: Spielstein:
-
+ All tokensAlle Spielsteine
-
+ &Select All&Alles auswählen
-
+ S&elect RowReihe auswählen
-
+ S&elect ColumnSpalte auswählen
-
+ &Play&Spielen
-
+ &Hide&Verstecken
-
+ Play &Face DownVerdeckt ausspielen
-
+ &Tap / UntapTurn sideways or back again&Tappen/ Enttappen
-
- Toggle &normal untapping
- Normales Enttapen umschalten
+
+ Skip &untapping
+ Enttappen überspringen
-
+ T&urn OverTurn face up/face downUmdrehen
-
+ &Peek at card face%Kartenvorderseite ansehen
-
+ &Clone&Kopieren
-
+ Attac&h to card...An Karte anhängen
-
+ Unattac&hLösen
-
+ &Draw arrow...&Pfeil zeichnen
-
+ &Set annotation...&Anmerkung setzen
-
+ Ca&rd countersKartenzähler
-
+ &Add counter (%1)&Zähler hinzufügen (%1)
-
+ &Remove counter (%1)&Zähler entfernen (%1)
-
+ &Set counters (%1)...&Zähler setzen (%1)...
@@ -840,133 +811,133 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
CardZoneLogic
-
+ their handnominativeihrer Hand
-
+ %1's handnominative%1's Hand
-
+ their librarylook at zoneihrer Bibliothek
-
+ %1's librarylook at zone%1's Bibliothek
-
+ of their librarytop cards of zone,von ihrer Bibliothek
-
+ of %1's librarytop cards of zonevon %1's Bibliothek
-
+ their libraryreveal zoneihrer Bibliothek
-
+ %1's libraryreveal zone%1's Bibliothek
-
+ their libraryshuffleihrer Bibliothek
-
+ %1's libraryshuffle%1's Bibliothek
-
-
- their library
- nominative
- ihrer Bibliothek
-
-
-
- %1's library
- nominative
- %1's Bibliothek
-
+ their library
+ nominative
+ ihrer Bibliothek
+
+
+
+ %1's library
+ nominative
+ %1's Bibliothek
+
+
+ their graveyardnominativeihres Friedhofs
-
+ %1's graveyardnominative%1's Friedhof
-
+ their exilenominativeihres Exils
-
+ %1's exilenominative%1's Exil
-
-
- their sideboard
- look at zone
- ihres Nebendecks
-
-
-
- %1's sideboard
- look at zone
- %1's Nebendeck
- their sideboard
- nominative
+ look at zoneihres Nebendecks%1's sideboard
+ look at zone
+ %1's Nebendeck
+
+
+
+ their sideboard
+ nominative
+ ihres Nebendecks
+
+
+
+ %1's sideboardnominative%1's Nebendeck
-
+ their custom zone '%1'nominativeihrer individuellen Zone '%1'
-
+ %1's custom zone '%2'nominative%1's individuelle Zone '%2'
@@ -1028,7 +999,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorCardDatabaseDockWidget
-
+ Card DatabaseKartendatenbank
@@ -1036,7 +1007,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorCardInfoDockWidget
-
+ Card InfoKarteninformation
@@ -1059,32 +1030,32 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
Zum Sideboard hinzufügen
-
+ Select PrintingAuswahl der Auflage
-
+ Show on EDHRec (Commander)Auf EDHRec ansehen (Als Commander)
-
+ Show on EDHRec (Card)Auf EDHRec ansehen (Als Karte)
-
+ Show Related cardsZeige ähnliche Karten
-
+ Add card to &maindeckKarte zum &Hauptdeck hinzufügen
-
+ Add card to &sideboardKarte zum &Sideboard hinzufügen
@@ -1092,32 +1063,32 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorDeckDockWidget
-
+ Loading Database...Datenbank wird geladen...
-
+ Banner CardBannerkarte
-
+ Main TypeHaupttyp
-
+ Mana CostManakosten
-
+ ColorsFarben
-
+ Select PrintingAuswahl der Auflage
@@ -1190,17 +1161,17 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorFilterDockWidget
-
+ FiltersFilter
-
+ &Clear all filters&Alle Filter entfernen
-
+ Delete selectedAuswahl löschen
@@ -1323,7 +1294,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorPrintingSelectorDockWidget
-
+ Printing SelectorAuflagenauswahl
@@ -1331,166 +1302,166 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckEditorSettingsPage
-
-
+
+ Update SpoilersSpoiler aktualisieren
-
-
+
+ SuccessErfolgreich
-
+ Download URLs have been reset.Download-URLs wurden zurückgesetzt.
-
+ Downloaded card pictures have been reset.Heruntergeladene Kartenbilder wurden zurückgesetzt.
-
+ ErrorFehler
-
+ One or more downloaded card pictures could not be cleared.Eines oder mehrere Kartenbilder konnten nicht gelöscht werden.
-
+ Add URLURL hinzufügen
-
-
+
+ URL:URL
-
-
+
+ Edit URLURL bearbeiten
-
+ Network Cache Size:Größe des Netzwerkzwischenspeichers:
-
+ Redirect Cache TTL:Umleitungszwischenspeicher TTL:
-
+ How long cached redirects for urls are valid for.Wie lange gespeicherte Umleitungen für URLS gültig sind.
-
+ Picture Cache Size:Größe des Bilderzwischenspeichers:
-
+ Add New URLNeue URL hinzufügen
-
+ Remove URLURL entfernen
-
+ Day(s)Tag(e)
-
+ Updating...Aktualisiere...
-
+ Choose pathPfad auswählen
-
+ URL Download PriorityURL Downloadpriorität
-
+ SpoilersSpoiler
-
+ Download Spoilers AutomaticallyLade Spoiler automatisch herunter
-
+ Spoiler Location:Spoiler Verzeichnis:
-
+ Last ChangeLetzte Änderung
-
+ Spoilers download automatically on launchSpoiler werden beim Start automatisch heruntergeladen
-
+ Press the button to manually update without relaunchingDrücke den Knopf um manuell zu aktualisieren ohne neu zu starten
-
+ Do not close settings until manual update is completeSchließen Sie die Einstellungen nicht solange die manuelle Aktualisierung nicht abgeschlossen ist.
-
+ Download card pictures on the flyKartenbilder dynamisch herunterladen
-
+ How to add a custom URLWie eine benutzerdefinierte URL hinzugefügt wird
-
+ Delete Downloaded ImagesHeruntergeladene Bilder löschen
-
+ Reset Download URLsDownload-URLs zurücksetzen
-
+ On-disk cache for downloaded picturesFestplatten-Cache für heruntergeladene Bilder
-
+ In-memory cache for pictures not currently on screenArbeitsspeicher-Cache für Bilder die gerade nicht angezeigt werden
@@ -1498,32 +1469,32 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckListHistoryManagerWidget
-
+ UndoRückgängig machen
-
+ RedoWiederholen
-
+ Undo/Redo historyRückgängig machen/Wiederholen Verlauf
-
+ Click on an entry to revert to that point in the history.Einen Eintrag anklicken um zu diesem Zeitpunkt im Verlauf zurückzukehren
-
+ [redo] [wiederholen]
-
+ [undo] [rückgängig machen]
@@ -1531,27 +1502,27 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckListModel
-
+ CountAnzahl
-
+ SetFestlegen
-
+ NumberNummer
-
+ Provider IDID des Anbieters
-
+ CardKarte
@@ -1559,12 +1530,12 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckLoader
-
+ Common deck formats (%1)Standarddeckformate (%1)
-
+ All files (*.*)Alle Dateien (*.*)
@@ -1661,94 +1632,94 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
DeckPreviewWidget
-
+ Banner CardBannerkarte
-
+ Open in deck editorIm Deckeditor öffnen
-
+ Edit TagsTags bearbeiten
-
+ Rename DeckDeck umbenennen
-
+ Save Deck to ClipboardDeck in die Zwischenablage speichern
-
+ AnnotatedKommentiert
-
+ Annotated (No set info)Komentiert (keine Setinformationen)
-
+ Not AnnotatedNicht kommentiert
-
+ Not Annotated (No set info)Nicht kommentiert (keine Setinformationen)
-
+ Rename FileDatei umbenennen
-
+ Delete FileDatei löschen
-
+ Set Banner CardBannerkarte setzen
-
-
+
+ New name:Neuer Name:
-
-
+
+ ErrorFehler
-
+ Rename failedUmbenennen fehlgeschlagen
-
+ Delete fileDatei löschen
-
+ Are you sure you want to delete the selected file?Sind Sie sicher, dass die ausgewählte Datei gelöscht werden soll?
-
+ Delete failedLöschen fehlgeschlagen
@@ -1781,32 +1752,32 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
Format setzen zu %1
-
+ Added (%1): %2 (%3) %4(%1): %2 (%3) %4 hinzugefügt
-
+ Moved to %1 1 × "%2" (%3)Nach %1 1 × "%2" (%3) bewegt
-
+ Removed "%1" (all copies)"%1" entfernt (alle Kopien)
-
+ %1 1 × "%2" (%3)%1 1 × "%2" (%3)
-
+ AddedHinzugefügt
-
+ RemovedEntfernt
@@ -1873,30 +1844,30 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic
Sideboard gesperrt
-
-
+
+ ErrorFehler
-
+ The selected file could not be loaded.Die gewählte Datei konnte nicht geladen werden.
-
+ Deck is greater than maximum file size.Deck übersteigt die maximale Dateigröße.
-
+ Are you sure you want to force start?
This will kick all non-ready players from the game.Sind Sie sicher, dass sie den Start erzwingen wollen?
Dies wirft alle nicht bereiten Spieler aus dem Spiel.
-
+ CockatriceCockatrice
@@ -2391,17 +2362,17 @@ Um Ihren derzeitigen Avatar zu entfernen, bestätigen Sie, ohne ein neues Bild z
DlgEditDeckInClipboard
-
+ Edit deck in clipboardDeck in Zwischenablage bearbeiten
-
+ ErrorFehler
-
+ Invalid deck list.Ungültige Deckliste.
@@ -2902,17 +2873,17 @@ Aktivieren Sie die Edition „Token" im „Editionen verwalten...“ Menü
DlgLoadDeckFromClipboard
-
+ Load deck from clipboardDeck aus der Zwischenablage laden
-
+ ErrorFehler
-
+ Invalid deck list.Ungültige Deckliste.
@@ -2920,45 +2891,45 @@ Aktivieren Sie die Edition „Token" im „Editionen verwalten...“ Menü
DlgLoadDeckFromWebsite
-
+ Paste a link to a decklist site here to import it.
(Archidekt, Deckstats, Moxfield, and TappedOut are supported.)Hier einen Link einer Decklistenseite einfügen um ihn zu importieren.
(Archidekt, Deckstats, Moxfield und TappedOut sind unterstützt.)
-
-
-
-
-
+
+
+
+
+ Load Deck from WebsiteDeck von Internetseite laden
-
+ No parser available for this deck provider.
(Archidekt, Deckstats, Moxfield, and TappedOut are supported.)Kein Parset verfügbar für diesen Deckanbieter.
(Archidekt, Deckstats, Moxfield und TappedOut sind unterstützt.)
-
+ Network error: %1Netzwerkfehler: %1
-
+ Received empty deck data.Leere Deckdaten erhalten.
-
+ Failed to parse deck data: %1Fehler beim parsen der Deckdaten: %1
-
+ The provided URL is not recognized as a valid deck URL.
Valid deck URLs look like this:
@@ -2983,40 +2954,73 @@ https://tappedout.net/mtg-decks/your-deck-name/
Deck laden
+
+ DlgLocalGameOptions
+
+
+ Players:
+ Spieler:
+
+
+
+ General
+ Allgemein
+
+
+
+ Starting life total:
+ Lebenspunkte zum Spielstart:
+
+
+
+ Game setup options
+ Spieleinstellungen
+
+
+
+ Remember settings
+ Einstellungen merken
+
+
+
+ Local game options
+ Lokale Spieleinstellungen
+
+DlgMoveTopCardsUntil
-
+ Card name (or search expressions):Kartenname (oder Suchbezeichnung)
-
+ Number of hits:Anzahl der Treffer:
-
+ Auto play hitsAutomatisches Ausspielen von Treffern
-
+ Put top cards on stack until...Oberste Karten auf den Stapel legen bis...
-
+ No cards matching the search expression exists in the card database. Proceed anyways?Keine Karten, die den Suchbezeichnungen entsprechen, existieren in der Kartendatenbank. Trotzdem fortfahren?
-
+ CockatriceBasilisk
-
+ Invalid filterUngültiger Filter
@@ -3178,12 +3182,12 @@ Die E-Mail-Adresse wird zur Accountverifikation genutzt.
DlgSettings
-
+ Unknown Error loading card databaseUnbekannter Fehler beim Laden der Kartendatenbank
-
+ Your card database is invalid.
Cockatrice may not function correctly with an invalid database
@@ -3200,7 +3204,7 @@ Sie müssen Oracle unter Umständen nochmals ausführen um Ihre Kartendatenbank
Möchten Sie Ihren Speicherort der Datenbank aktualisieren??
-
+ Your card database version is too old.
This can cause problems loading card information or images
@@ -3217,7 +3221,7 @@ Normalerweise kann dies durch einen erneuten Start von Oracle, um die Kartendate
Möchten Sie Ihren Speicherort der Datenbank aktualisieren?
-
+ Your card database did not finish loading
Please file a ticket at https://github.com/Cockatrice/Cockatrice/issues with your cards.xml attached
@@ -3230,7 +3234,7 @@ Bitte erstellen Sie ein Ticket auf https://github.com/Cockatrice/Cockatrice/issu
Möchten Sie die Einstellung des Datenbankspeicherorts ändern?
-
+ File Error loading your card database.
Would you like to change your database location setting?
@@ -3239,7 +3243,7 @@ Would you like to change your database location setting?
Möchten Sie Ihren Speicherort der Datenbank aktualisieren?
-
+ Your card database was loaded but contains no cards.
Would you like to change your database location setting?
@@ -3248,7 +3252,7 @@ Would you like to change your database location setting?
Möchten Sie Ihren Speicherort der Datenbank aktualisieren?
-
+ Unknown card database load status
Please file a ticket at https://github.com/Cockatrice/Cockatrice/issues
@@ -3261,59 +3265,59 @@ Bitte erstellen Sie ein Ticket auf https://github.com/Cockatrice/Cockatrice/issu
Möchten Sie die Einstellung des Datenbankspeicherorts ändern?
-
-
-
+
+
+ ErrorFehler
-
+ The path to your deck directory is invalid. Would you like to go back and set the correct path?Der Pfad zu Ihrem Deckordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen?
-
+ The path to your card pictures directory is invalid. Would you like to go back and set the correct path?Der Pfad zu Ihrem Kartenbilderordner ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen?
-
+ SettingsEinstellungen
-
+ GeneralAllgemeines
-
+ AppearanceErscheinungsbild
-
+ User InterfaceBenutzeroberfläche
-
+ Card SourcesKartenquellen
-
+ ChatChat
-
+ SoundTöne
-
+ ShortcutsTastaturkürzel
@@ -3630,67 +3634,67 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
DrawProbabilityWidget
-
+ Draw ProbabilityZieh-Wahrscheinlichkeit
-
+ Probability of drawingWahrscheinlichkeit des Ziehens
-
+ Card NameKartenname
-
+ TypeTyp
-
+ SubtypeUntertyp
-
+ Mana ValueManawert
-
+ At leastmindestens
-
+ Exactlygenau
-
+ card(s) having drawn at leastKarte(n) gezogen haben mindestens
-
+ cardsKarten
-
+ CategoryKategorie
-
+ QtyMenge
-
+ Odds (%)Wahrscheinlichkeit (%)
@@ -4138,143 +4142,143 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
GeneralSettingsPage
-
+ Reset all pathsAlle Pfade zurücksetzen
-
+ All paths have been resetAlle Pfade wurden zurückgesetzt
-
-
-
-
-
-
-
+
+
+
+
+
+
+ Choose pathPfad auswählen
-
+ Personal settingsPersönliche Einstellungen
-
+ Language:Sprache:
-
+ Paths (editing disabled in portable mode)Pfade (Anpassungen im portablen Modus deaktiviert)
-
+ PathsPfade
-
+ How to help with translationsWie man beim Übersetzen helfen kann
-
+ Decks directory:Verzeichnis mit Decklisten:
-
+ Filters directory:Filterverzeichnis:
-
+ Replays directory:Verzeichnis mit aufgezeichneten Spielen:
-
+ Pictures directory:Verzeichnis mit Bilddateien:
-
+ Card database:Kartendatenbank:
-
+ Custom database directory:Verzeichnis für benutzerdefinierte Datenbank:
-
+ Token database:Spielsteindatenbank:
-
+ Update channelAktualisierungskanal
-
+ Check for client updates on startupNach Aktualisierungen des Klienten beim Start der Anwendung suchen
-
+ Check for card database updates on startupAuf Kartendatenbankaktualisierungen beim Anwendungsstart prüfen
-
+ Don't checkNicht überprüfen
-
+ Prompt for updateZu Aktualisierungen auffordern
-
+ Always update in the backgroundImmer im Hintergrund aktualisieren
-
+ Check for card database updates everyAuf Kartendatenbankaktualisierung prüfen alle
-
+ daysTage
-
+ Notify if a feature supported by the server is missing in my clientBenachrichtigung wenn ein vom Server unterstütze Funktion in meinem Client fehlt
-
+ Automatically run Oracle when running a new version of CockatriceStarte Oracle automatisch, wenn eine neue Version von Cockatrice gestartet wird
-
+ Show tips on startupZeige Tipps beim Start
-
+ Last update check on %1 (%2 days ago)Letzte Aktualisierungsprüfung am %1 (vor %2 Tagen)
@@ -4282,47 +4286,47 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
GraveyardMenu
-
+ &Graveyard&Friedhof
-
+ &View graveyard&Friedhof ansehen
-
+ &Move graveyard to...& Friedhof nach ... bewegen
-
+ &Top of library&Oben in der Bibliothek
-
+ &Bottom of library&Unten in der Bibliothek
-
+ &All players&Alle Spieler
-
+ &Hand&Hand
-
+ &Exile&Exil
-
+ Reveal random card to...Zufällige Karte vorzeigen für ...
@@ -4330,88 +4334,88 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
HandMenu
-
+ &Hand&Hand
-
+ &View hand&Hand ansehen
-
+ Sort hand by...Hand nach ... sortieren
-
+ NameName
-
+ TypeTyp
-
+ Mana ValueManawert
-
+ Take &mulligan (Choose hand size)&Mulligan nehmen (Handgröße wählen)
-
+ Take mulligan (Same hand size)Mulligan nehmen (Gleiche Handgröße)
-
+ Take mulligan (Hand size - 1)Mulligan nehmen (Handgröße -1)
-
+ &Move hand to...&Hand nach ... bewegen
-
+ &Top of library&Oben in der Bibliothek
-
+ &Bottom of library&Unten in der Bibliothek
-
+ &Graveyard&Friedhof
-
+ &Exile&Exil
-
+ &Reveal hand to...&Hand an ... vorzeigen
-
-
+
+ All playersAlle Spieler
-
+ Reveal r&andom card to...Zufällige Karten an ... vorzeigen
@@ -4419,52 +4423,52 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
HomeWidget
-
+ Create New DeckNeues Deck erstellen
-
+ Browse DecksDecks durchsuchen
-
+ Browse Card DatabaseKartendatenbank durchsuchen
-
+ Browse EDHRecEDHRec durchsuchen
-
+ Browse ArchidektArchidekt durchsuchen
-
+ View ReplaysWiederholung ansehen
-
+ QuitVerlassen
-
+ Connecting...Verbinden...
-
+ ConnectVerbinden
-
+ PlaySpielen
@@ -4472,193 +4476,213 @@ Eventuell müssen sie manuell eine neue Version herunterladen.
LibraryMenu
-
+ &Library&Bibliothek
-
+ &View library&Bibliothek ansehen
-
+ View &top cards of library...Die obersten Karten der Bibliothek ansehen
-
+ View bottom cards of library...Die untersten Karten der Bibliothek ansehen
-
+ Reveal &library to...Bibliothek an ... vorzeigen
-
+ Lend library to...Bibliothek ... leihen
-
+ Reveal &top cards to...Die obersten Karten ... zeigen
-
+ &Top of library...&Oben auf die Bibliothek
-
+ &Bottom of library...&Unter die Bibliothek...
-
+ &Always reveal top card&Immer die oberste Karte vorzeigen
-
+ &Always look at top card&Immer die oberste Karte ansehen
-
+ &Open deck in deck editor&Deck in Deckeditor öffnen
-
+ &Draw card&Karte ziehen
-
+ D&raw cards...Karten ziehen...
-
+ &Undo last draw&Letztes Ziehen rückgängig machen
-
+ ShuffleMischen
-
+ &Play top card&Oberste Karte spielen
-
+ Play top card &face downOberste Karte verdeckt ausspielen
-
+ Put top card on &bottomOberste Karte nach unten legen
-
+ Move top card to grave&yardOberste Karte in den Friedhof bewegen
-
+ Move top card to e&xileOberste Karte ins Exil bewegen
-
+ Move top cards to &graveyard...Die obersten Karten in den Friedhof bewegen...
-
+
+ Move top cards to graveyard face down...
+ Die obersten Karten verdeckt in den Friedhof bewegen...
+
+
+ Move top cards to &exile...Die obersten Karten ins Exil bewegen
-
+
+ Move top cards to exile face down...
+ Die obersten Karten verdeckt ins Exil bewegen...
+
+
+ Put top cards on stack &until...Die obersten Karten auf den Stapel packen bis...
-
+ Shuffle top cards...Oberste Karten mischeln...
-
+ &Draw bottom card&Unterste Karte ziehen
-
+ D&raw bottom cards...Untere Karten ziehen...
-
+ &Play bottom card&Unterste Karte ausspielen
-
+ Play bottom card &face downUnterste Karte verdeckt spielen
-
+ Move bottom card to grave&yardUnterste Karte in den Friedhof bewegen
-
+ Move bottom card to e&xileUnterste Karte ins Exil bewegen
-
+ Move bottom cards to &graveyard...Unterste Karten in den Friedhof bewegen...
-
+
+ Move bottom cards to graveyard face down...
+ Die untersten Karten verdeckt in den Friedhof bewegen...
+
+
+ Move bottom cards to &exile...Unterste Karten ins Exil bewegen...
-
+
+ Move bottom cards to exile face down...
+ Die untersten Karten verdeckt ins Exil bewegen...
+
+
+ Put bottom card on &topUnterste Karte nach oben bewegen
-
+ Shuffle bottom cards...Unterste Karten mischen...
-
-
+
+ &All players&Alle Spieler
-
+ Reveal top cards of libraryOberste Karten der Bibliothek vorzeigen
-
+ Number of cards: (max. %1)Anzahl der Karten: (max. %1)
@@ -4756,18 +4780,8 @@ Will now login.
Login läuft.
-
- Number of players
- Spieleranzahl
-
-
-
- Please enter the number of players.
- Bitte die Spieleranzahl eingeben:
-
-
-
-
+
+ Player %1Spieler %1
@@ -4870,8 +4884,8 @@ Login läuft.
-
-
+
+ ErrorFehler
@@ -5279,36 +5293,36 @@ Lokale Version ist %1, Serverversion ist %2.
Ein-/Ausblenden
-
+ New VersionNeue Version
-
+ Congratulations on updating to Cockatrice %1!
Oracle will now launch to update your card database.Herzlichen Glückwunsch zur Aktualisierung auf Cockatrice %1!
Oracle wird gestartet um ihre Kartendatenbank zu aktualisieren.
-
+ Cockatrice installedCockatrice wurde installiert
-
+ Congratulations on installing Cockatrice %1!
Oracle will now launch to install the initial card database.Herzlichen Glückwunsch, dass Sie Cockatrice %1 installiert haben!
Oracle wird jetzt gestartet und installiert die initiale Kartendatenbank.
-
+ Card databaseKartendatenbank
-
+ Cockatrice is unable to load the card database.
Do you want to update your card database now?
If unsure or first time user, choose "Yes"
@@ -5317,29 +5331,29 @@ Möchten Sie Ihre Kartendatenbank jetzt aktualisieren?
Falls Sie unsicher sind oder Cockatrice das erste Mal nutzen, wählen Sie „Ja“
-
-
+
+ YesJa
-
-
+
+ NoNein
-
+ Open settingsEinstellungen öffnen
-
+ New sets foundNeue Editionen gefunden
-
+ %n new set(s) found in the card database
Set code(s): %1
Do you want to enable it/them?
@@ -5350,17 +5364,17 @@ Setcode(s): %1
Möchten Sie es/sie aktivieren?
-
+ View setsEditionen ansehen
-
+ WelcomeWillkommen
-
+ Hi! It seems like you're running this version of Cockatrice for the first time.
All the sets in the card database have been enabled.
Read more about changing the set order or disabling specific sets and consequent effects in the "Manage Sets" dialog.
@@ -5369,65 +5383,65 @@ Alle Editionen der Kartendatenbank wurden aktiviert.
Lesen Sie mehr über das Ändern der Editionsreihenfolge oder die Deaktivierung bestimmter Editionen im „Editionen verwalten...“ Fenster.
-
-
+
+ InformationInformation
-
+ A card database update is already running.Eine Datenbankaktualisierung wird bereits durchgeführt.
-
+ Unable to run the card database updater: Kartendatenbankaktualisierung nicht ausführbar:
-
+ Card database update running.Kartendatenbankaktualisierung läuft.
-
+ Failed to start. The file might be missing, or permissions might be incorrect.Starten fehlgeschlagen. Die Datei könnte fehlen oder die Berechtigung fehlen.
-
+ The process crashed some time after starting successfully.Der Prozess ist einige Zeit nach erfolgreichem Start abgestürzt.
-
+ Timed out. The process took too long to respond. The last waitFor...() function timed out.Zeitüberschreitung. Der Prozess hat zu lange nicht geantwortet. Zeitüberschreitung bei letzter waitFor...() Funktion.
-
+ An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.Ein Fehler ist beim Schreiben an den Prozess aufgetreten. Beispielsweise könnte der Prozess derzeit nicht ausgeführt werden oder er hat seinen Eingabekanal geschlossen.
-
+ An error occurred when attempting to read from the process. For example, the process may not be running.Ein Fehler ist beim Lesen vom Prozess aufgetreten. Beispielsweise könnte der Prozess derzeit nicht ausgeführt werden.
-
+ Unknown error occurred.Unbekannter Fehler aufgetreten.
-
+ The card database updater exited with an error:
%1Die Kartendatenbankaktualisierung brach mit einem Fehler ab:
%1
-
+ This server supports additional features that your client doesn't have.
This is most likely not a problem, but this message might mean there is a new version of Cockatrice available or this server is running a custom or pre-release version.
@@ -5438,55 +5452,55 @@ Dies stellt wahrscheinlich kein Problem dar, allerdings könnte dies bedeuten, d
Um Ihren Client zu aktualisieren, navigieren Sie zu Hilfe -> Auf Aktualisierungen prüfen.
-
-
-
-
-
+
+
+
+
+ Load sets/cardsLade Sets/Karten
-
+ Selected file cannot be found.Die ausgewählte Datei wurde nicht gefunden.
-
+ You can only import XML databases at this time.Im Moment ist es nur möglich XML Datenbanken zu importieren.
-
+ The new sets/cards have been added successfully.
Cockatrice will now reload the card database.Die neuen Sets/Karten wurden erfolgreich hinzugefügt.
Cockatrice wird jetzt die Kartendatenbank neu laden.
-
+ Sets/cards failed to import.Set-/Kartenimport fehlgeschlagen.
-
-
-
+
+
+ Reset PasswordPasswort zurücksetzen
-
+ Your password has been reset successfully, you can now log in using the new credentials.Ihr Passwort wurde erfolgreich zurückgesetzt, Sie können sich jetzt mit den neuen Anmeldedaten anmelden.
-
+ Failed to reset user account password, please contact the server operator to reset your password.Passwortzurücksetzung fehlgeschlagen. Bitte kontaktieren Sie den Serverbetreiber, um Ihr Passwort zurücksetzen zu lassen.
-
+ Activation request received, please check your email for an activation token.Aktivierungsanfrage erhalten. Bitte prüfen Sie Ihre E-Mails nach einem Aktivierungstoken.
@@ -5537,7 +5551,7 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
ManaBaseWidget
-
+ Mana BaseManabasis
@@ -5691,590 +5705,610 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
MessageLogWidget
-
+ from playvom Spielfeld
-
+ from their graveyardvon ihrem Friedhof
-
+ from exile aus dem Exil
-
+ from their handvon ihrer Hand
-
+ the top card of %1's librarydie oberste Karte von %1s Bibliothek
-
+ the top card of their librarydie oberste Karte ihrer Bibliothek
-
+ from the top of %1's library oben von %1s Bibliothek
-
+ from the top of their libraryvon ihrer Bibliothek von oben
-
+ the bottom card of %1's librarydie unterste Karte von %1s Bibliothek
-
+ the bottom card of their librarydie unterste Karte ihrer Bibliothek
-
+ from the bottom of %1's library von der Unterseite von %1s Bibliothek
-
+ from the bottom of their libraryvon ihrer Bibliothek von unten
-
+ from %1's libraryaus %1s Bibliothek
-
+ from their libraryvon ihrer Bibliothek
-
+ from sideboard aus dem Sideboard
-
+ from the stack vom Stapel
-
+ from custom zone '%1'von der benutzerdefinierten Zone '%1'
-
+ %1 is now keeping the top card %2 revealed.%1 lässt nun die oberste Karte %2 aufgedeckt.
-
+ %1 is not revealing the top card %2 any longer.%1 lässt die oberste Karte %2 nicht mehr aufgedeckt.
-
+ %1 can now look at top card %2 at any time.%1 kann nun die oberste Karte %2 jederzeit betrachten.
-
+ %1 no longer can look at top card %2 at any time.%1 kann die oberste Karte %2 nicht mehr jederzeit betrachten.
-
+ %1 attaches %2 to %3's %4.%1 legt %2 an %3s %4 an.
-
+ %1 has conceded the game.%1 hat das Spiel aufgegeben.
-
+ %1 has unconceded the game.%1 hat das Spiel doch nicht aufgegeben.
-
+ %1 has restored connection to the game.%1 ist wieder mit dem Spiel verbunden.
-
+ %1 has lost connection to the game.%1 hat die Verbindung zum Spiel verloren.
-
+ %1 points from their %2 to themselves.%1 zeigt von ihrem %2 auf sich selbst.
-
+ %1 points from their %2 to %3.%1 zeigt von ihrem %2 auf %3.
-
+ %1 points from %2's %3 to themselves.%1 zeigt von %2s %3 auf sich selbst.
-
+ %1 points from %2's %3 to %4.%1 zeigt von %2s %3 auf %4.
-
+ %1 points from their %2 to their %3.%1 zeigt von ihrem %2 auf ihren %3.
-
+ %1 points from their %2 to %3's %4.%1 zeigt von ihrem %2 auf %3s %4.
-
+ %1 points from %2's %3 to their own %4.%1 zeigt von %2s %3 auf ihr %4.
-
+ %1 points from %2's %3 to %4's %5.%1 zeigt von %2s %3 auf %4s %5.
-
+ %1 creates a face down token.%1 erzeugt einen umgedrehten Spielstein.
-
+ %1 creates token: %2%3.%1 erstellt Spielstein: %2%3.
-
+ %1 has loaded a deck (%2).%1 hat ein Deck geladen (%2).
-
+ %1 has loaded a deck with %2 sideboard cards (%3).%1 hat ein Deck mit %2 Sideboardkarten geladen (%3).
-
+ %1 destroys %2.%1 zerstört %2.
-
+ a cardeine Karte
-
+ %1 gives %2 control over %3.%1 überlässt %2 die Kontrolle über %3.
-
+ %1 puts %2 into play%3 face down.%1 bringt %2%3 verdeckt ins Spiel.
-
+ %1 puts %2 into play%3.%1 bringt %2%3 ins Spiel.
-
+
+ %1 puts %2%3 into their graveyard face down.
+ %1 legt %2%3 verdeckt in ihren Friedhof
+
+
+ %1 puts %2%3 into their graveyard.%1 legt %2%3 in ihren Friedhof.
+
+
+ %1 exiles %2%3 face down.
+ %1 schickt %2%3 verdeckt ins Exil.
+ %1 exiles %2%3.%1 schickt %2%3 ins Exil.
-
+ %1 moves %2%3 to their hand.%1 bewegt %2%3 in ihre Hand.
-
+ %1 puts %2%3 into their library.%1 legt %2%3 in ihre Bibliothek.
-
+ %1 puts %2%3 onto the bottom of their library.%1 legt %2%3 unter die Bibliothek.
-
+ %1 puts %2%3 on top of their library.%1 legt %2%3 auf ihre Bibliothek.
-
+ %1 puts %2%3 into their library %4 cards from the top.%1 legt %2%3 in die Bibliothek an %4 Stelle von oben.
-
+ %1 moves %2%3 to sideboard.%1 legt %2%3 in sein Sideboard.
-
+
+ %1 plays %2%3 face down.
+ %1 bringt %2%3 verdeckt ins Spiel.
+
+
+ %1 plays %2%3.%1 spielt %2%3 aus.
-
+
+ %1 moves %2%3 to custom zone '%4' face down.
+ %1 bewegt %2%3 verdeckt zur benutzerdefinierten Zone '%4'.
+
+
+ %1 moves %2%3 to custom zone '%4'.%1 bewegt %2%3 zur benutzerdefinierten Zone '%4'.
-
+ %1 tries to draw from an empty library%1 versucht von einer leeren Bibliothek zu ziehen
-
+ %1 draws %2 card(s).%1 zieht %2 Karte(n).%1 zieht %2 Karte(n).
-
+ %1 is looking at %2.%1 sieht sich %2 an.
-
+ %1 is looking at the %4 %3 card(s) %2.top card for singular, top %3 cards for plural%1 sieht sich die %4 %3 Karte(n) %2 an.%1 sieht sich die %4 %3 Karte(n) %2 an.
-
+ bottomuntersten
-
+ topobersten
-
+ %1 turns %2 face-down.%1 wendet %2 auf die Rückseite.
-
+ %1 turns %2 face-up.%1 wendet %2 auf die Vorderseite.
-
+ The game has been closed.Das Spiel wurde geschlossen.
-
+ The game has started.Das Spiel hat begonnen.
-
+ You are flooding the game. Please wait a couple of seconds.Du überschwemmst das Spiel. Warte bitte einige Sekunden.
-
+ %1 has joined the game.%1 ist dem Spiel beigetreten.
-
+ %1 is now watching the game.%1 schaut nun dem Spiel zu.
-
+ You have been kicked out of the game.Sie wurden aus dem Spiel geworfen.
-
+ %1 has left the game (%2).%1 hat das Spiel verlassen (%2).
-
+ %1 is not watching the game any more (%2).%1 schaut dem Spiel nicht mehr zu (%2).
-
+ %1 is not ready to start the game any more.%1 ist nicht mehr bereit, das Spiel zu starten.
-
+ %1 shuffles their deck and draws a new hand of %2 card(s).%1 mischt sein Deck und zieht eine Hand mit %2 Karte(n).%1 mischt sein Deck und zieht eine neue Hand mit %2 Karte(n).
-
+ %1 shuffles their deck and draws a new hand.%1 mischt sein Deck und zieht eine neue Hand.
-
+ You are watching a replay of game #%1.Sie sehen eine Aufzeichnung des Spiels #%1.
-
+ %1 is ready to start the game.%1 ist bereit, das Spiel zu starten.
-
+ cardsan unknown amount of cardsKarten
-
+ %1 card(s)a card for singular, %1 cards for plural%1 Karte(n)%1 Karte(n)
-
+ %1 lends %2 to %3.%1 verleiht %2 an %3.
-
+ %1 reveals %2 to %3.%1 zeigt %3 %2.
-
+ %1 reveals %2.%1 zeigt %2 offen vor.
-
+ %1 randomly reveals %2%3 to %4.%1 zeigt %4 zufällig %2%3 vor.
-
+ %1 randomly reveals %2%3.%1 zeigt zufällig %2%3 offen vor.
-
+ %1 peeks at face down card #%2.%1 schaut sich die umgedrehte Karte #%2 an.
-
+ %1 peeks at face down card #%2: %3.%1 schaut sich die umgedrehte Karte #%2 an: %3.
-
+ %1 reveals %2%3 to %4.%1 zeigt %4 %2%3 vor.
-
+ %1 reveals %2%3.%1 zeigt %2%3 offen vor.
-
+ %1 reversed turn order, now it's %2.%1 kehrte die Zugreihenfolge um, nun ist es %2.
-
+ reversedumgekehrt
-
+ normalnormal
-
+ HeadsKopf
-
+ TailsZahl
-
+ %1 flipped a coin. It landed as %2.%1 warf eine Münze. Es fiel %2.
-
+ %1 rolls a %2 with a %3-sided die.%1 würfelt eine %2 mit einem %3-seitigen Würfel.
-
+ %1 flips %2 coins. There are %3 heads and %4 tails.%1 wirft %2 Münzen. Es ergab %3 mal Kopf und %4 mal Zahl.
-
+ %1 rolls a %2-sided dice %3 times: %4.%1 wirft einen %2-seitigen Würfel %3 mal: %4.
-
+ %1's turn.%1 ist am Zug.
-
+ %1 sets annotation of %2 to %3.%1 versieht %2 mit dem Hinweis %3.
-
+ %1 places %2 "%3" counter(s) on %4 (now %5).%1 platziert %2 "%3" Zähler auf %4 (jetzt %5).%1 platziert %2 "%3" Zähler auf %4 (jetzt %5).
-
+ %1 removes %2 "%3" counter(s) from %4 (now %5).%1 entfernt %2 "%3" Marke(n) von %4 (jetzt %5).%1 entfernt %2 "%3" Zähler von %4 (jetzt %5).
-
+ %1 sets counter %2 to %3 (%4%5).%1 setzt Zähler %2 auf %3 (%4%5).
-
+ %1 sets %2 to not untap normally.%1 setzt %2 auf explizites Enttappen.
-
+ %1 sets %2 to untap normally.%1 setzt %2 auf normales Enttappen.
-
+ %1 removes the PT of %2.%1 entfernt die Kampfwerte von %2.
-
+ %1 changes the PT of %2 from nothing to %4.%1 ändert die Kampfwerte von %2 von nichts auf %4.
-
+ %1 changes the PT of %2 from %3 to %4.%1 ändert die Kampfwerte von %2 von %3 auf %4.
-
+ %1 has locked their sideboard.%1 hat ihr Sideboard gesperrt.
-
+ %1 has unlocked their sideboard.%1 hat ihr Sideboard entsperrt.
-
+ %1 taps their permanents.%1 tappt ihre bleibenden Karten.
-
+ %1 untaps their permanents.%1 enttappt ihre bleibenden Karten.
-
+ %1 taps %2.%1 tappt %2.
-
+ %1 untaps %2.%1 enttappt %2.
-
+ %1 shuffles %2.%1 mischt %2.
-
+ %1 shuffles the bottom %3 cards of %2.%1 mischt die untersten %3 Karten von %2.
-
+ %1 shuffles the top %3 cards of %2.%1 mischt die obersten %3 Karten von %2.
-
+ %1 shuffles cards %3 - %4 of %2.%1 mischt die Karten %3 - %4 von %2.
-
+ %1 unattaches %2.%1 löst %2 ab.
-
+ %1 undoes their last draw.%1 legt die zuletzt gezogene Karte zurück.
-
+ %1 undoes their last draw (%2).%1 legt die zuletzt gezogene Karte zurück (%2)
@@ -6282,110 +6316,110 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
MessagesSettingsPage
-
+ Word1 Word2 Word3Wort1 Wort2 Wort3
-
+ Add New MessageNeue Nachricht hinzufügen
-
+ Edit MessageNachricht bearbeiten
-
+ Remove MessageNachricht entfernen
-
+ Add messageNachricht hinzufügen
-
-
+
+ Message:Nachricht:
-
+ Edit messageNachricht bearbeiten
-
+ Chat settingsChat Einstellungen
-
+ Custom alert wordsBenutzerdefinierte Benachrichtigungswörter
-
+ Enable chat mentionsChat Erwähnungen aktivieren
-
+ Enable mention completerAutovervollständigung aktivieren
-
+ In-game message macrosMakros für Nachrichten in Spielen
-
+ How to use in-game message macrosAnleitung zum Verwenden der Makros für Nachrichten in Spielen
-
+ Ignore chat room messages sent by unregistered usersNachrichten von unregistrierten Benutzern im Chatroom ignorieren
-
+ Ignore private messages sent by unregistered usersPrivate Nachrichten von unregistrierten Benutzern ignorieren
-
-
+
+ Invert text colorTextfarbe invertieren
-
+ Enable desktop notifications for private messagesDesktop Benachrichtigungen für private Nachrichten aktivieren
-
+ Enable desktop notification for mentionsDesktop Benachrichtigungen für Erwähnungen aktivieren
-
+ Enable room message history on joinNachrichtenverlauf beim Betreten eines Raumes aktivieren
-
-
+
+ (Color is hexadecimal)(Farbcode in hexadezimal)
-
+ Separate words with a space, alphanumeric characters onlyWörter durch Leerzeichen trennen, nur alphanumerische Zeichen
@@ -6398,32 +6432,37 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
Bewegen nach
-
+ &Top of library in random order&Oben auf der Bibliothek in zufälliger Reihenfolge
-
+ X cards from the top of library...X Karten von oben in der Bibliothek...
-
+ &Bottom of library in random order&Unter die Bibliothek in zufälliger Reihenfolge
-
+
+ T&able
+ T&isch
+
+
+ &Hand&Hand
-
+ &Graveyard&Friedhof
-
+ &Exile&Exil
@@ -6565,57 +6604,57 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
PhasesToolbar
-
+ Untap stepEnttappsegment
-
+ Upkeep stepVersorgungssegment
-
+ Draw stepZiehsegment
-
+ First main phaseerste Hauptphase
-
+ Beginning of combat stepAnfangssegment der Kampfphase
-
+ Declare attackers stepAngreifer-Deklarieren-Segment
-
+ Declare blockers stepBlocker-Deklarieren-Segment
-
+ Combat damage stepKampfschadenssegment
-
+ End of combat stepEndsegment der Kampfphase
-
+ Second main phasezweite Hauptphase
-
+ End of turn stepEnde-des-Zuges-Segment
@@ -6632,134 +6671,138 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
PlayerActions
-
+ View top cards of libraryOberste Karten der Bibliothek ansehen
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Number of cards: (max. %1)Anzahl der Karten: (max. %1)
-
+ View bottom cards of libraryUnterste Karten der Bibliothek ansehen
-
+ Shuffle top cards of libraryOberste Karten der Bibliothek mischen
-
+ Shuffle bottom cards of libraryUnterste Karten der Bibliothek mischen
-
+ Draw handHand ziehen
-
+ 0 and lower are in comparison to current hand size0 und kleiner sind im Vergleich zur jetzigen Handgröße
-
+ Draw cardsKarten ziehen
+
+
+
+
+
+ grave
+ Friedhof
+
- Move top cards to grave
- Oberste Karten in den Friedhof bewegen
+
+
+
+ exile
+ Exil
-
- Move top cards to exile
- Oberste Karten ins Exil bewegen
+
+ Move top cards to %1
+ Oberste Karten nach %1 bewegen
-
- Move bottom cards to grave
- Unterste Karten in den Friedhof bewegen
+
+ Move bottom cards to %1
+ Unterste Karten nach %1 bewegen
-
- Move bottom cards to exile
- Unterste Karten ins Exil bewegen
-
-
-
+ Draw bottom cardsUnterste Karten ziehen
-
-
+
+ C&reate another %1 tokenEinen weiteren %1 Spielstein erzeugen
-
+ Create tokensSpielsteine erzeugen
-
-
+
+ Number:Anzahl:
-
+ Place card X cards from top of libraryKarte X Karten von oben in der Bibliothek plazieren
-
+ Which position should this card be placed:In welcher Position sollte diese Karte platziert werden:
-
+ (max. %1)(max. %1)
-
+ Change power/toughnessStärke/Widerstandskraft ändern
-
+ Change stats to:Ändere Werte auf:
-
+ Set annotationAnmerkung setzen
-
+ Please enter the new annotation:Bitte die neue Anmerkung eingeben:
-
+ Set countersZähler setzen
@@ -6767,48 +6810,68 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
PlayerMenu
-
+ Player "%1"Spieler "%1"
-
+ &Counters&Zähler
+
+
+ PrintingDisabledInfoWidget
-
- S&ay
- S&agen
+
+ The Printing Selector is disabled because you have currently enabled the setting to override all selected printings with personal set preferences.
+
+This setting means you'll only see the default printing for each card, instead of being able to select a printing, and will not see the printings other people have selected.
+
+
+ Die Druckauswahl ist deaktiviert, da sie momentan die Einstellung zur Überschreibung aller ausgewählten Drucke mit ihren persönlichen Setpräferenzen aktiviert ist.
+
+Diese Einstellung bedeutet, dass sie nur den Standarddruck für jede Karte sehen, anstatt einen bestimmten Druck auszuwählen, und sie werden auch nicht die von anderen Personen ausgewählten Drucke sehen können.
+
+
+
+
+ Enable printings again
+ Drucke wieder aktivierenPrintingSelector
-
+ Display Navigation ButtonsNavigationstasten anzeigen
+
+
+ Printing Selector
+ Druckauswahl
+ PrintingSelectorCardOverlayWidget
-
+ PreferencePreferenz
-
+ Pin PrintingVersion festsetzen
-
+ Unpin PrintingVersion lösen
-
+ Show Related cardsZugehörige Karten anzeigen
@@ -6857,17 +6920,25 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
Erscheinungsdatum
-
-
+
+ DescendingAbsteigend
-
+ AscendingAufsteigend
+
+ PrintingSelectorPlaceholderWidget
+
+
+ Select a card to view its available printings
+ Wählen sie eine Karte aus, um ihre verfügbaren Drucke anzusehen
+
+PtMenu
@@ -7006,6 +7077,45 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
A .cod version of this deck already exists. Overwrite it?Eine .cod Version dieses Decks existiert bereits. Überschreiben?
+
+
+ Enabling this feature will disable the use of the Printing Selector.
+
+You will not be able to manage printing preferences on a per-deck basis, or see printings other people have selected for their decks.
+
+You will have to use the Set Manager, available through Card Database -> Manage Sets.
+
+Are you sure you would like to enable this feature?
+ Diese Funktion zu aktivieren wird die Nutzung der Druckauswahl deaktivieren.
+
+Es wird ihnen nicht möglich sein ihre Druckeinstellungen auf einer Per-Deck Basis zu verwalten, oder die Drucke, die andere Personen für ihre Decks ausgewählt haben, zu sehen.
+
+Sie werden den Set-Manager verwenden müssen, der über Kartendatenbank -> Sets verwalten verfügbar ist.
+
+Sind sie sicher, dass diese Funktion aktiviert werden soll?
+
+
+
+ Disabling this feature will enable the Printing Selector.
+
+You can now choose printings on a per-deck basis in the Deck Editor and configure which printing gets added to a deck by default by pinning it in the Printing Selector.
+
+You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available).
+
+Are you sure you would like to disable this feature?
+ Diese Funktion zu deaktivieren wird die Nutzung der Druckauswahl aktivieren.
+
+Es wird ihnen nun möglich sein ihre Druckeinstellungen auf einer Per-Deck Basis im Deck-Editor zu verwalten und zu konfigurieren, welcher Druck standardmäßig in ein Deck hinzugefügt wird, indem sie es anheften in der Druckauswahl
+
+Sie können auch den Set-Manager verwenden, um selbstständig die Sortierungsreihenfolge für Drucke in der Druckauswahl festzulegen (andere Sortierungsoptionen wie alphabetisch oder Veröffentlichkeitsdatum sind verfügbar).
+
+Sind sie sicher, dass diese Funktion deaktiviert werden soll?
+
+
+
+ Confirm Change
+ Änderung bestätigen
+ QPlatformTheme
@@ -7154,37 +7264,37 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
RfgMenu
-
+ &Exile&Exil
-
+ &View exile&Exil ansehen
-
+ &Move exile to...&Exil nach ... bewegen
-
+ &Top of library&Oben in der Bibliothek
-
+ &Bottom of library&Unten in der Bibliothek
-
+ &Hand&Hand
-
+ &Graveyard&Friedhof
@@ -7227,6 +7337,14 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
Spiele
+
+ SayMenu
+
+
+ S&ay
+ S&agen
+
+SequenceEdit
@@ -7291,53 +7409,53 @@ Cockatrice wird jetzt die Kartendatenbank neu laden.
ShortcutSettingsPage
-
-
+
+ Restore all default shortcutsAlle Standard-Tastaturkürzel wiederherstellen
-
+ Do you really want to restore all default shortcuts?Möchten Sie wirklich alle Standard-Tastaturkürzel wiederherstellen?
-
+ Clear all default shortcutsAlle Standard-Tastaturkürzel entfernen
-
+ Do you really want to clear all shortcuts?Möchten Sie wirklich alle Tastaturkürzel entfernen?
-
+ Section:Abschnitt:
-
+ Action:Aktion:
-
+ Shortcut:Tastaturkürzel:
-
+ How to set custom shortcutsWie werden benutzerdefinierte Tastaturkürzel gesetzt
-
+ Clear all shortcutsAlle Tastaturkürzel entfernen
-
+ Search by shortcut nameSuchen nach Name des Tastenkürzels
@@ -7406,27 +7524,27 @@ Bitte überprüfen Sie die Verknüpfungseinstellungen!
SoundSettingsPage
-
+ Enable &soundsTöne aktivieren
-
+ Current sounds theme:Aktuelles Ton-Theme:
-
+ Test system sound engineSystemsound testen
-
+ Sound settingsToneinstellungen
-
+ Master volumeMasterlautstärke
@@ -7642,59 +7760,123 @@ Bitte überprüfen Sie die Verknüpfungseinstellungen!
TabArchidekt
-
-
+
+
+ Desc.Beschreibung.
-
+
+
+ AND
+ UND
+
+
+
+
+ Require ALL selected colors
+ Benötigt ALLE ausgewählten Farben
+
+
+
+
+ Deck name...
+ Deckname...
+
+
+
+
+ Owner...
+ Besitzer...
+
+
+
+
+ Packages
+ Pakete
+
+
+
+
+ Advanced Filters
+ Erweiterte Filter
+
+
+
+ Bracket:
+ Kategorie:
+
+
+
+
+ Any
+ Beliebig
+
+
+
+
+ Contains card...
+ Enthält Karte...
+
+
+
+
+ Commander...
+ Kommandant...
+
+
+
+
+ Tag...
+ Etikett...
+
+
+
+
+ Deck Size
+ Deckgröße
+
+
+
+ Cards:
+ Karten:
+
+
+
+ Asc.Aufsteigend.
-
-
- Any Bracket
- Jede Klammer
+
+ Sort by:
+ Sortieren nach:
-
- Deck name contains...
- Deckname enthält...
+
+ Filter by:
+ Filtern nach:
-
- Owner name contains...
- Besitzername enthält...
+
+ Display Settings
+ Anzeigeeinstellungen
-
- Disabled
- Deaktiviert
-
-
-
+
+ SearchSuche
-
+
+ FormatsFormate
-
- Min. # of Cards:
- Min. # an Karten:
-
-
-
- Page:
- Seite:
-
-
-
+ Archidekt: Archidekt:
@@ -7702,60 +7884,52 @@ Bitte überprüfen Sie die Verknüpfungseinstellungen!
TabDeckEditor
-
+ Card InfoKarteninformationen
-
+ DeckDeck
-
+ FiltersFilter
-
+ &ViewAnsicht
-
+ Card DatabaseKartendatenbank
-
+ PrintingAuflage
-
-
-
-
-
+ VisibleSichtbar
-
-
-
-
-
+ FloatingSchwebend
-
+ Reset layoutDarstellung zurücksetzen
-
+ Deck: %1Deck: %1
@@ -7763,61 +7937,55 @@ Bitte überprüfen Sie die Verknüpfungseinstellungen!
TabDeckEditorVisual
-
+ Visual Deck: %1Visuelles Deck: %1
-
+ &Visual Deck Editor&Visueller Deckeditor
-
-
+
+ Card InfoKarteninformation
-
-
+
+ DeckDeck
-
-
+
+ FiltersFilter
-
+ &View&Ansehen
-
+ PrintingAuflage
-
-
-
-
+ VisibleSichtbar
-
-
-
-
+ FloatingSchwebend
-
+ Reset layoutAnordnung zurücksetzen
@@ -7882,7 +8050,7 @@ Bitte überprüfen Sie die Verknüpfungseinstellungen!
-
+ New folderNeuer Ordner
@@ -7964,18 +8132,18 @@ Bitte geben Sie einen Namen ein:
Sind sie sicher, dass die ausgewählten Dateien gelöscht werden sollen?
-
+ Delete remote decksLöschen der online gespeicherten Decks
-
+ Are you sure you want to delete the selected decks?Sind sie sicher, dass sie die ausgewählten Decks löschen wollen?
-
+ Name of new folder:Name für den neuen Ordner:
@@ -7993,12 +8161,12 @@ Bitte geben Sie einen Namen ein:
Visuelle Deckablage
-
+ ErrorFehler
-
+ Could not open deck at %1Deck an Stelle %1 konnte nicht geöffnet werden
@@ -8047,197 +8215,191 @@ Bitte geben Sie einen Namen ein:
TabGame
-
-
-
+
+
+ ReplayWiederholung
-
-
+
+ GameSpiel
-
-
+
+ Player ListSpielerliste
-
-
+
+ Card InfoKarteninformationen
-
-
+
+ MessagesNachrichten
-
-
+
+ Replay TimelineZeitleiste der Aufzeichnung
-
+ &Phases&Phasen
-
+ &GameSpi&el
-
+ Next &phaseNächste &Phase
-
+ Next phase with &actionNächste Phase mit &Aktion
-
+ Next &turnNächster &Zug
-
+ Reverse turn orderKehre Zugreihenfolge um
-
+ &Remove all local arrows&Lokale Pfeile entfernen
-
+ Rotate View Cl&ockwiseAnsicht im Uhrzeigesinn drehen
-
+ Rotate View Co&unterclockwiseAnsicht gegen den Uhrzeigersinn drehen
-
+ Game &information&Spielinformationen
-
+ Un&concedeAufgabe zurückziehen
-
-
-
+
+
+ &Concede&Aufgeben
-
+ &Leave gameSpiel ver&lassen
-
+ C&lose replayWiederholung sch&ließen
-
+ &Focus ChatChat &fokussieren
-
+ &Say:&Sagen:
-
+ Selected cardsAusgewählte Karten
-
+ &ViewAnsicht
-
-
-
-
+ VisibleSichtbar
-
-
-
-
+ FloatingSchwebend
-
+ Reset layoutDarstellung zurücksetzen
-
+ ConcedeAufgeben
-
+ Are you sure you want to concede this game?Sind Sie sicher, dass Sie das Spiel aufgeben möchten?
-
+ UnconcedeDoch nicht aufgeben
-
+ You have already conceded. Do you want to return to this game?Sie haben bereits aufgegeben. Möchten Sie zu diesem Spiel zurückkehren?
-
+ Leave gameSpiel verlassen
-
+ Are you sure you want to leave this game?Sind Sie sicher, dass Sie das Spiel verlassen möchten?
-
+ A player has joined game #%1Ein Spieler ist Spiel #%1 beigetreten
-
+ %1 has joined the game%1 ist dem Spiel beigetreten
-
+ You have been kicked out of the game.Sie wurden aus dem Spiel geworfen.
@@ -9340,142 +9502,152 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
UserInterfaceSettingsPage
-
+ General interface settingsAllgemeine Bedienung
-
+ &Double-click cards to play them (instead of single-click)Karten durch &Doppelklick ausspielen (statt Einzelklick)
-
+ &Clicking plays all selected cards (instead of just the clicked card)&Anklicken spielt alle ausgewählten Karten aus (anstatt nur der angeklickten Karte)
-
+ &Play all nonlands onto the stack (not the battlefield) by defaultAlle Nichtländer standardmäßig über den Stapel spielen (anstatt direkt auf das Spielfeld)
-
+ Do not delete &arrows inside of subphasesKeine &Pfeile löschen in Unterphasen
-
+ Close card view window when last card is removedSchließe Kartenanzeigefenster, wenn die letzte Karte entfernt wird
-
+ Auto focus search bar when card view window is openedSucheingabe automatisch in den Fokus nehmen, wenn das Kartenansichtsfenster geöffnet wird
-
+ Annotate card text on tokensKartentext auf Spielsteinen anzeigen
-
+
+ Show selection counter during drag selection
+ Auswahlzähler während Zugauswahl anzeigen
+
+
+
+ Show total selection counter
+ Gesamtauswahlszähler anzeigen
+
+
+ Use tear-off menus, allowing right click menus to persist on screenBenutze Abreißmenüs, erlaubt Kontextmenüs auf dem Bildschirm zu verbleiben
-
+ Notifications settingsBenachrichtigungseinstellungen
-
+ Enable notifications in taskbarBenachrichtigungen in der Taskleiste aktivieren
-
+ Notify in the taskbar for game events while you are spectatingBenachrichtigungen für Spielereignisse auch beim Zuschauen anderer Spiele in der Taskbar anzeigen
-
+ Notify in the taskbar when users in your buddy list connectBenachrichtige in der Taskleiste wenn sich Benutzer aus der Freundesliste anmelden
-
+ Animation settingsAnimationseinstellungen
-
+ &Tap/untap animationAnimiertes &Tappen/Enttappen
-
+ Deck editor/storage settingsDeckeditor/-ablage Einstellungen
-
+ Open deck in new tab by defaultDecks in neuem Tab öffnen als Standard
-
+ Use visual deck storage in game lobbyVisuelle Deckablage in der Spielelobby verwenden
-
+ Use selection animation for Visual Deck StorageAuswahlanimation für Visuellen Deckspeicher verwenden
-
+ When adding a tag in the visual deck storage to a .txt deck:Wenn ein Tag im Visuellen Deckspeicher zu einem .txt Deck hinzugefügt wird:
-
+ do nothingtue nichts
-
+ ask to convert to .codfrage, ob zu .cod konvertiert werden soll
-
+ always convert to .codimmer nach .cod konvertieren
-
+ Default deck editor typeStandarddeckeditortyp
-
+ Classic Deck EditorKlassischer Deckeditor
-
+ Visual Deck EditorVisueller Deckeditor
-
+ Replay settingsWiederholungsoptionen
-
+ Buffer time for backwards skip via shortcut:Pufferzeit für Rückwärtsüberspringen durch Tastenkürzel
@@ -9539,24 +9711,25 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDatabaseDisplayColorFilterWidget
-
- Mode: Exact Match
- Modus: Exakte Übereinstimmung
+
+ Exact match
+ Exakte Übereinstimmung
+
+
+
+ Includes
+ Enthält
- Mode: Includes
- Modus: Enthält
+ Include / Exclude
+ Mode: Includes
+ Inkludieren / Exkludieren
-
- Mode: Include/Exclude
- Modus: Inkludieren/Exkludieren
-
-
-
- Filter mode (AND/OR/NOT conjunctions of filters)
- Filtermodus (UND/ODER/NICHT Verknüpfungen der Filter)
+
+ How selected and unselected colors are combined in the filter
+ Wie ausgewählte und nicht ausgewählte Farben im Filter kombiniert werden
@@ -9582,25 +9755,108 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
Dateinamen eingeben...
+
+ VisualDatabaseDisplayFilterToolbarWidget
+
+
+ Sort by
+ Sortieren nach
+
+
+
+ Filter by
+ Filtern nach
+
+
+
+ Save and load filters
+ Filter speichern und laden
+
+
+
+ Filter by exact card name
+ Nach exaktem Kartennamen filtern
+
+
+
+ Filter by card main-type
+ Nach Kartenhaupttyp filtern
+
+
+
+ Filter by card sub-type
+ Nach Kartenuntertyp filtern
+
+
+
+ Filter by set
+ Nach Set filtern
+
+
+
+ Filter by format legality
+ Nach Formatslegalität filtern
+
+
+
+ Save/Load
+ Speichern/Laden
+
+
+
+ Name
+ Name
+
+
+
+ Main Type
+ Haupttyp
+
+
+
+ Sub Type
+ Untertyp
+
+
+
+ Sets
+ Editionen
+
+
+
+ Formats
+ Formate
+
+VisualDatabaseDisplayFormatLegalityFilterWidget
-
+
+ Show formats with at least:
+ Formate anzeigen mit mindestens:
+
+
+
+ cards
+ Karten
+
+
+ Do not display formats with less than this amount of cards in the databaseKeine Formate mit weniger als dieser Anzahl an Karten in der Datenbank anzeigen
-
+ Filter mode (AND/OR/NOT conjunctions of filters)Filtermodus (UND/ODER/NICHT Verbindungen von Filtern)
-
+ Mode: Exact MatchModus: Exakte Übereinstimmung
-
+ Mode: IncludesModus: Enthält
@@ -9608,22 +9864,32 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDatabaseDisplayMainTypeFilterWidget
-
+
+ Show main types with at least:
+ Haupttypen anzeigen mit mindestens:
+
+
+
+ cards
+ Karten
+
+
+ Do not display card main-types with less than this amount of cards in the databaseKartenhaupttypen mit weniger als dieser Anzahl Karten in der Datenbank nicht anzeigen
-
+ Filter mode (AND/OR/NOT conjunctions of filters)Filtermodus (UND/ODER/NICHT Verknüpfungen der Filter)
-
+ Mode: Exact MatchModus: Exakte Übereinstimmung
-
+ Mode: IncludesModus: Enthält
@@ -9659,7 +9925,7 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDatabaseDisplayRecentSetFilterSettingsWidget
-
+ Filter to most recent setsFiltern nach aktuellsten Sets
@@ -9667,19 +9933,19 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDatabaseDisplaySetFilterWidget
-
+ Search sets...Sets durchsuchen...
-
-
+
+ Mode: Exact MatchModus: Exakte Übereinstimmung
-
-
+
+ Mode: IncludesModus: Enthält
@@ -9687,27 +9953,37 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDatabaseDisplaySubTypeFilterWidget
-
+ Search subtypes...Untertypen durchsuchen...
-
+
+ Show sub types with at least:
+ Untertypen anzeigen mit mindestens:
+
+
+
+ cards
+ Karten
+
+
+ Do not display card sub-types with less than this amount of cards in the databaseKartenuntertypen mit weniger als dieser Anzahl Karten in der Datenbank nicht anzeigen
-
+ Filter mode (AND/OR/NOT conjunctions of filters)Filtermodus (UND/ODER/NICHT Verknüpfungen der Filter)
-
+ Mode: Exact MatchModus: Exakte Übereinstimmung
-
+ Mode: IncludesModus: Enthält
@@ -9721,52 +9997,22 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
-
+ VisualVisuell
-
+ Loading database ...Datenbank wird geladen...
-
+ Clear all filtersAlle Filter entfernen
-
- Sort by:
- Sortieren nach:
-
-
-
- Filter by:
- Filtern nach:
-
-
-
- Save and load filters
- Filter speichern und laden
-
-
-
- Filter by exact card name
- Nach exaktem Kartennamen filtern
-
-
-
- Filter by card sub-type
- Nach Kartenuntertyp filtern
-
-
-
- Filter by set
- Nach Set filtern
-
-
-
+ TableTisch
@@ -9774,56 +10020,64 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDeckDisplayOptionsWidget
-
+ Group by:Gruppieren nach:
-
+ Change how cards are divided into categories/groups.Wie Karten innerhalb ihrer Kategorien/Gruppierungen sortiert werden ändern
-
+ Sort by:Sortieren nach:
-
+ Click and drag to change the sort order within the groupsKlicken und ziehen, um die Sortierungsreihenfolge innerhalb von Gruppen zu ändern
-
+ Configure how cards are sorted within their groupsWie Karten innerhalb ihrer Gruppierung sortiert werden einstellen
-
-
+
+ Toggle Layout: OverlapUmschalten des Layouts: Überlappung
-
+ Change how cards are displayed within zones (i.e. overlapped or fully visible.)Wie Karten innerhalb von Zonen angezeigt werden ändern ( z.B. überlappend oder vollständig sichtbar)
-
+ Toggle Layout: FlatUmschalten des Layouts: Flach
+
+ VisualDeckEditorPlaceholderWidget
+
+
+ Add cards using the search bar or database tab to have them appear here
+ Karten über die Suchleiste oder den Datenbanktab hinzufügen, damit sie hier angezeigt werden
+
+VisualDeckEditorSampleHandWidget
-
+ Draw a new sample handEine neue Probehand ziehen
-
+ Sample hand sizeProbehandgröße
@@ -9831,17 +10085,17 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDeckEditorWidget
-
+ Type a card name here for suggestions from the database...Hier einen Kartennahmen eingeben für Vorschläge aus der Datenbank...
-
+ Quick search and add cardSchnellsuche und Karte hinzufügen
-
+ Search for closest match in the database (with auto-suggestions) and add preferred printing to the deck on pressing enterNach bester Entsprechung in der Datenbank suchen (mit automatischen Vorschlägen) und die bevorzugte Auflage beim Betätigen der Eingabetaste dem Deck hinzufügen
@@ -9857,47 +10111,52 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
VisualDeckStorageQuickSettingsWidget
-
+ Show FoldersOrdner anzeigen
-
+ Show Tag FilterTagfilter anzeigen
-
+
+ Show Color Identity
+ Farbidentität anzeigen
+
+
+ Show Tags On Deck PreviewsTags auf Deckvorschauen anzeigen
-
+ Show Banner Card Selection OptionBannerkartenauswahloption anzeigen
-
+ Draw unused Color IdentitiesUngenutzte Farbidentitäten ziehen
-
+ Unused Color Identities OpacityDeckkraft ungenutzter Farbidentitäten
-
+ Deck tooltip:Decktooltip:
-
+ NoneKeine
-
+ FilepathDateipfad
@@ -9998,133 +10257,133 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
WndSets
-
+ Move selected set to the topAusgewählte Edition an die Spitze verschieben
-
+ Move selected set upnach oben verschieben
-
+ Move selected set downnach unten verschieben
-
+ Move selected set to the bottomAusgewählte Edition ans Ende verschieben
-
+ Search by set name, code, or typeSuche nach Setname, Code oder Typ
-
+ Default orderStandardreihenfolge
-
+ Restore original art priority orderStelle die ursprüngliche Reihenfolge für Bilderprioritäten wieder her
-
+ Enable all setsAlle Editionen aktivieren
-
+ Disable all setsAlle Editionen deaktivieren
-
+ Enable selected set(s)Ausgewählte Edition(en) aktivieren
-
+ Disable selected set(s)Ausgewählte Edition(en) deaktivieren
-
+ Deck EditorDeckeditor
-
+ Use CTRL+A to select all sets in the view.Benutzen Sie Strg+A, um alle Sets in der Ansicht auszuwählen.
-
+ Only cards in enabled sets will appear in the card list of the deck editor.Nur Karten aus aktivierten Sets werden in der Kartenliste des Deckeditors angezeigt.
-
+ Image priority is decided in the following order:Bildpriorität wird auf folgende Reihenfolge festgelegt:
-
+ first the CUSTOM Folder (%1), then the Enabled Sets in this dialog (Top to Bottom)%1 is a link to the wikizuerst der BENUTZERDEFINIERTE Ordner (%1), dann die aktivierten Sets aus diesem Dialog (von oben nach unten)
-
+ Include cards rebalanced for Alchemy [requires restart]Karten, die für Alchemy augeglichen wurden, einschließen [erfordert Neustart]
-
+ Card ArtKartenzeichnung
-
+ How to use custom card artWie benutzerdefinierte Kartenbilder verwendet werden
-
+ HintsTipps
-
+ NoteNotiz
-
+ Sorting by column allows you to find a set while not changing set priority.Nach einer Spalte sortieren erlaubt, eine Edition zu finden, ohne die Editionspriorität zu verändern.
-
+ To enable ordering again, click the column header until this message disappears.Um die Sortierung erneut zu aktivieren, klicken Sie auf den Spaltenkopf bis diese Nachricht verschwindet.
-
+ Use the current sorting as the set priority insteadBenutze die momentane Sortierung als Editionspriorität.
-
+ Sorts the set priority using the same columnSortiert die Editionspriorität mit der selben Spalte
-
+ Manage setsEditionen verwalten
@@ -10132,72 +10391,72 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
ZoneViewWidget
-
+ Search by card name (or search expressions)Suche nach Kartennamen (oder Suchausdrücken)
-
+ UngroupedUngruppiert
-
+ Group by TypeGruppieren nach Kartentyp
-
+ Group by Mana ValueGruppieren nach Manabetrag
-
+ Group by ColorGruppieren nach Farbe
-
+ UnsortedUnsortiert
-
+ Sort by NameSortieren nach Name
-
+ Sort by TypeSortieren nach Kartentyp
-
+ Sort by Mana CostSortieren nach Manakosten
-
+ Sort by ColorsSortieren nach Farben
-
+ Sort by P/TSortieren nach P/T
-
+ Sort by SetSortieren nach Auflage
-
+ shuffle when closingbeim Schließen mischen
-
+ pile viewStapelansicht
@@ -10232,7 +10491,7 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
-
+ Deck EditorDeckeditor
@@ -10313,7 +10572,7 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
-
+ ReplaysWiederholungen
@@ -10465,7 +10724,7 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
-
+ Reset LayoutDarstellung zurücksetzen
@@ -10886,8 +11145,9 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
- Toggle Untap
- Enttappen umschalten
+ Toggle Skip Untapping
+ Toggle Untap
+ Enttapen überspringen umschalten
@@ -10906,98 +11166,102 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
+ Play Card, Face Down
+ Karte spielen, verdeckt
+
+
+ Attach Card...Karte anlegen...
-
+ Unattach CardKarte lösen
-
+ Clone CardKarte klonen
-
+ Create Token...Spielstein erstellen...
-
+ Create All Related TokensAlle zugehörigen Spielsteine erstellen
-
+ Create Another TokenEinen weiter Spielstein erstellen
-
+ Set Annotation...Notiz setzen...
-
+ Select All Cards in ZoneAlle Karten in der Zone auswählen
-
+ Select All Cards in RowAlle Karten in der Reihe auswählen
-
+ Select All Cards in ColumnAlle Karten in der Spalte auswählen
-
+ Reveal Selected Cards to All PlayersAusgewählte Karten allen Spielern vorzeigen
-
-
+
+ Bottom of LibraryUntere Karte der Bibliothek
-
+
-
-
+
+ ExileExil
-
+
-
+ GraveyardFriedhof
-
+ HandHand
-
-
+
+ Top of LibraryObere Karte der Bibliothek
-
-
+ Battlefield, Face DownSpielfeld, verdeckt
@@ -11033,234 +11297,246 @@ Bitte unterlassen Sie diese Aktivitäten oder weitere Schritte werden gegen Sie
-
+ StackStapel
-
+ Graveyard (Multiple)Friedhof (mehrere)
-
-
+
+
+ Graveyard (Multiple), Face Down
+ Friedhof (mehrere), verdeckt
+
+
+
+ Exile (Multiple)Exil (mehrere)
-
+
+
+ Exile (Multiple), Face Down
+ Exil (mehrere), verdeckt
+
+
+ Stack Until FoundStapel bis gefunden
-
+ Draw Bottom CardUnterste Karte ziehen
-
+ Draw Multiple Cards from Bottom...Mehrere Karten von unten ziehen...
-
+ Draw Arrow...Pfeil zeichnen...
-
+ Remove Local ArrowsLokale Pfeile entfernen
-
+ Leave GameSpiel verlassen
-
+ ConcedeAufgeben
-
+ Roll Dice...Würfeln...
-
+ Shuffle LibraryBibliothek mischen
-
+ Shuffle Top Cards of LibraryOberste Karten der Bibliothek mischen
-
+ Shuffle Bottom Cards of LibraryUnterste Karten der Bibliothek mischen
-
+ MulliganMulligan
-
+ Mulligan (Same hand size)Mulligan nehmen (Gleiche Handgröße)
-
+ Mulligan (Hand size - 1)Mulligan nehmen (Handgröße -1)
-
+ Draw a CardEine Karte ziehen
-
+ Draw Multiple Cards...Mehrere Karten ziehen...
-
+ Undo DrawZiehen rückgängig machen
-
+ Always Reveal Top CardOberste Karte aufgedeckt lassen
-
+ Always Look At Top CardOberste Karte immer betrachten
-
+ Sort Hand by NameHand sortieren nach Name
-
+ Sort Hand by TypeHand sortieren nach Typ
-
+ Sort Hand by Mana ValueHand sortieren nach Manawert
-
+ Reveal Hand to All PlayersHand allen Spielern vorzeigen
-
+ Reveal Random Card to All PlayersZufällige Karte allen Spielern vorzeigen
-
+ Rotate View ClockwiseAnsicht im Uhrzeigersinn drehen
-
+ Rotate View CounterclockwiseAnsicht gegen den Uhrzeigersinn drehen
-
+ Unfocus Text BoxTextboxfokus aufheben
-
+ Focus ChatChat fokussieren
-
+ Clear ChatChat leeren
-
+ RefreshAktualisieren
-
+ Skip ForwardVorspulen
-
+ Skip BackwardZurückspulen
-
+ Skip Forward by a lotSehr weit vorspulen
-
+ Skip Backward by a lotSehr weit zurückspulen
-
+ Play/PauseAbspielen/Pausieren
-
+ Toggle Fast ForwardSchnelldurchlauf umschalten
-
+ HomeZuhause
-
+ Visual Deck StorageVisuelle Deckablage
-
+ Deck StorageDeckablage
-
+ ServerServer
-
+ AccountBenutzerkonto
-
+ AdministrationAdministration
-
+ LogsLogs
diff --git a/cockatrice/translations/cockatrice_el.ts b/cockatrice/translations/cockatrice_el.ts
index dac77fe01..5bd3b2826 100644
--- a/cockatrice/translations/cockatrice_el.ts
+++ b/cockatrice/translations/cockatrice_el.ts
@@ -23,12 +23,12 @@
AbstractDlgDeckTextEdit
-
+ &Refresh
-
+ Parse Set Name and Number (if available)
@@ -36,60 +36,60 @@
AbstractTabDeckEditor
-
+ Open in new tab
-
+ Are you sure?
-
+ The decklist has been modified.
Do you want to save the changes?
-
-
-
-
-
-
+
+
+
+
+
+ Error
-
+ Could not open deck at %1
-
+ Could not save remote deck
-
-
+
+ The deck could not be saved.
Please check that the directory is writable and try again.
-
+ Save deck
-
+ The deck could not be saved.
-
+ There are no cards in your deck to be exported
@@ -131,190 +131,168 @@ Please check that the directory is writable and try again.
AppearanceSettingsPage
-
+ seconds
-
+ ErrorΣφάλμα
-
+ Could not create themes directory at '%1'.
-
- Enabling this feature will disable the use of the Printing Selector.
-
-You will not be able to manage printing preferences on a per-deck basis, or see printings other people have selected for their decks.
-
-You will have to use the Set Manager, available through Card Database -> Manage Sets.
-
-Are you sure you would like to enable this feature?
-
-
-
-
- Disabling this feature will enable the Printing Selector.
-
-You can now choose printings on a per-deck basis in the Deck Editor and configure which printing gets added to a deck by default by pinning it in the Printing Selector.
-
-You can also use the Set Manager to adjust custom sort order for printings in the Printing Selector (other sort orders like alphabetical or release date are available).
-
-Are you sure you would like to disable this feature?
-
-
-
-
- Confirm Change
-
-
-
-
+ Theme settingsΡυθμίσεις θέματος
-
+ Current theme:Τρέχον θέμα:
-
+ Open themes folderΆνοιγμα φακέλου θεμάτων
-
+ Home tab background source:
-
+ Home tab background shuffle frequency:
-
+ Disabled
-
+
+ Display card name of background in bottom right:
+
+
+
+ Menu settings
-
+ Show keyboard shortcuts in right-click menus
-
+ Show game filter toolbar above list in room tab
-
+ Card renderingΑπόδοση κάρτας
-
+ Display card names on cards having a pictureΕμφανίστε τα ονόματα καρτών σε κάρτες με εικόνα
-
+ Auto-Rotate cards with sideways layout
-
+ Override all card art with personal set preference (Pre-ProviderID change behavior)
-
+ Bump sets that the deck contains cards from to the top in the printing selector
-
+ Scale cards on mouse overΑύξηση της κλίμακας των καρτών με την επιλογή του ποντικιού
-
+ Use rounded card corners
-
+ Minimum overlap percentage of cards on the stack and in vertical hand
-
+ Maximum initial height for card view window:
-
-
+
+ rows
-
+ Maximum expanded height for card view window:
-
+ Card counters
-
+ Counter %1
-
+ Hand layoutΔιάταξη χειρός
-
+ Display hand horizontally (wastes space)Εμφάνιση χεριού οριζόντια (σπατάλη χώρου)
-
+ Enable left justificationΕνεργοποιήστε την αριστερή αιτιολόγηση
-
+ Table grid layoutΔιάταξη πλέγματος πίνακα
-
+ Invert vertical coordinateΑνατροπή κάθετης συντεταγμένης
-
+ Minimum player count for multi-column layout:Ελάχιστος αριθμός παικτών για διάταξη πολλαπλών στηλών:
-
+ Maximum font size for information displayed on cards:Μέγιστο μέγεθος γραμματοσειράς για πληροφορίες που εμφανίζονται στις κάρτες:
@@ -322,7 +300,12 @@ Are you sure you would like to disable this feature?
ArchidektApiResponseDeckDisplayWidget
-