* [Theme] Revert default light palette and only include AppColors
* [Style] Also remove dark mode palette
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [PictureLoader] Fix worker thread shutdown and cross-thread cache clearing
clearNetworkCache() ran directly on the UI thread while the worker thread
owned the disk cache and redirect cache, racing cache reads/writes. Make it
a worker-thread slot invoked via a blocking queued call when the thread is
running, so the 'Cached card pictures have been reset.' message is truthful.
The worker thread was also never quit()/wait()ed: both destructors only
deleteLater'd their objects, so Qt warned 'QThread: Destroyed while thread
is still running' and leaked a running loop at exit. Wire the worker's
finished() signal to its own deleteLater() (canonical worker-object
pattern), add shutdownThread() to stop the loop, and let CardPictureLoader
destroy the QThread only after wait() has returned.
* [PictureLoader] Guard cache teardown and stop blocking the UI thread
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [PictureLoader] Add user-configurable per-host request caps
Picture downloads were throttled to a uniform 10 requests/second per host
with no way to tune a specific server. A rate-limited API host (Scryfall
caps at 10 req/s) can trip 429s during bursts, and CDN hosts with no rate
limit were throttled needlessly.
Introduce developer-owned per-host caps that users can only ever lower,
never raise, exposed in the download settings page:
- DownloadSettings::DEVELOPER_HOST_CAPS sets the ceiling per host
(api.scryfall.com 9, cards.scryfall.io unlimited, others 10).
- A new hostRequestLimits setting stores user overrides in downloads.ini;
clampHostRequestLimit() bounds them to [1, devCap] so a user can reduce
api.scryfall.com to 5 but never raise it above 9.
- The picture worker seeds, halves on 429, and recovers its sustained
per-host allowance against the effective ceiling instead of the global
maximum, and skips per-host accounting entirely for unlocked hosts
(cards.scryfall.io) while global pacing and 429 backoff still apply.
- The deck editor settings page gains one spinbox per known host, each
clamped to its developer cap.
* [PictureLoader] Let unlocked hosts skip dispatch pacing; adjust limits per URL
Two refinements to the per-host request caps:
- Unlocked hosts (UNLIMITED_HOST_QUOTA, e.g. cards.scryfall.io) no longer
wait on the 100ms dispatch pacing or consume the global per-second quota.
dispatchQueuedRequest fires their queued requests back-to-back, bounded
only by their 429 backoff window and Qt's per-host connection pool, so
an unthrottled CDN is not artificially slowed.
- The deck editor download settings page replaces the static grid of one
spinbox per known host with an "Adjust Rate Limit" toolbar action on the
URL list. It picks the host out of the selected URL and clamps the entry
against the developer cap table (including for user-added URLs).
Also fixes a review finding: resetRequestQuota could write the
UNLIMITED_HOST_QUOTA sentinel (-1) into the sustained per-host quota when a
host became unlocked mid-run, permanently poisoning its allowance. Stale
entries for unlocked hosts are now dropped, and the per-second seed is
clamped against the effective ceiling so a lowered limit applies immediately.
* [PictureLoader] Cap unlocked host bursts and adapt them to 429s
* [PictureLoader] Store per-host limits readably and show them per URL
* [PictureLoader] Make dispatch and rate-limit bookkeeping key on the real host
Addresses ZeldaZach's round-4 review nits:
- Dispatch now resolves the cached-redirect chain before the in-flight gate,
so a redirect learned after a URL was queued can no longer bypass the
MAX_IN_FLIGHT_PER_HOST cap and drain the whole queue onto the redirect
target, which may carry its own developer cap. processSingleRequest does
the same so the allowance math keys on the host that is actually hit.
- The per-host in-flight slot is released when the reply is destroyed (with
the worker as the connection context) rather than on a 'finished'
connection bound to the work object, so an aborted reply or a work object
deleted while a reply is pending can never permanently shrink the fast
path's concurrency.
- storeSettings only prunes limits for hosts with neither a URL nor a
developer cap, so throttles on redirect targets (api.scryfall.com ->
cards.scryfall.io) survive URL removal.
- Unlocked hosts are offered 0..UNLOCKED_HOST_LIMIT_MAX (50) in the rate
limit dialog, matching clampHostRequestLimit() and the documented
hand-editable range, so values written into downloads.ini are no longer
silently rewritten on the next edit.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Card] Add a setting for the language used in card search
Localized card names and texts can now be searched too, controlled by a
'Language used in card search' toggle (English, selected card language, or
both) on the general settings page. Untranslated cards always keep matching
in English.
Removed the redundant local copy of the URL templates list in the localized
picture loader while here.
* [Card] Bind search language per FilterString instance
The peg parser rules are set up once per process, so the GenericQuery and
OracleQuery rule actions could not capture per-instance state. Instead of
storing the search language in a process-global that FilterString instance
methods mutate, hand it to the rule actions through a thread-local parse
context and copy it into the filter closures they produce. Card evaluation
in FilterString::check no longer reads any process-global state, and each
instance keeps the language it was built with; constructing one instance no
longer changes what unrelated instances (deck filter, drop-to-hand, zone
views) match against.
The card database display model stores the raw query and rebuilds the
FilterString when the search language changes, since the language is now
bound at parse time.
Add tests for the English/Selected/Both search modes, the English fallback
for untranslated cards, and per-instance language independence.
* [Card] Pass the card search language to deck and zone card searches
Wire the two remaining FilterString consumers to the configured card search
language so card-name matches respect it everywhere:
- DeckFilterString now takes the search language and mode, exposes them to its
[[card name]] rule action via a thread-local parse context (same pattern as
FilterString), and the engine's card database uses them for content search.
- ZoneViewZone reads the card language from CardsDisplaySettings when applying
its search filter, and the reveal-zone widget re-applies the active search
when the language setting changes.
- The deck-storage search re-runs its filter against the current card language
setting, including live re-application when the setting changes.
Game-action targeting (DlgMoveTopCardsUntil) intentionally keeps evaluating
against English card names.
* [Card] Rename CardSearchLanguage to SearchLanguageMode
* [Card] Restore displaced namespace doc in card_localization.h
* [Filters] Pass CardSearchLanguage as a single struct
* [CardSearchModel] Match English and localized names in Both mode
Card names are stored in both English and localized forms, so search for
matches in both during the 'Both' search mode instead of checking only
the localized name.
* [CreateTokenDialog] Fetch cardsDisplay settings inside the apply lambda
Avoid capturing the raw settings pointer in the lambda: resolve the card
language and card search language from the settings cache at call time so
the values are always current when the search language is re-applied.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Themes] Add identity default palettes for the image themes
The Fabric, Leather, Plasma and VelvetMarble themes shipped only zone art and no palette, so their chrome fell back to the bare OS palette. Each theme now ships light and dark curated defaults written in the palette editor's own conventions, with [AppColors] so the home-tab buttons keep the theme's identity over static backgrounds.
- Add palette-default-light.toml / palette-default-dark.toml for the four themes; scheme resolution follows the OS since the themes declare no color scheme.
- Tint the window/base/button chrome and bevels towards each theme's identity: navy cloth (Fabric), black-brown with brass accents (Leather), electric violet with cyan sparks (Plasma), charcoal velvet with slate marble (VelvetMarble).
- Fill [AppColors] AccentStrong / AccentSoft per theme so the home-tab button gradient matches instead of falling back to the default greens.
- Derive Disabled and Inactive groups with the same conventions as PaletteGenerator::fromAccent.
* [Themes] Add home backgrounds for the image themes
* [Themes] Ship Fusion style + scheme backgrounds for the image themes
Address PR review:
- Add theme.cfg ([Style] Name = Fusion, ColorScheme = System) to Fabric,
Leather, Plasma and VelvetMarble so their curated palettes actually apply.
Without it the native style paints button chrome from the OS (windowsvista
on Windows has no dark mode), making the dark palettes' light ButtonText
unreadable on light buttons.
- Leverage the scheme-variant asset resolution: register home-dark.png and
home-light.png in resources and add them to the qrc so the built-in home
background also flips with the palette instead of staying static.
- Fix Leather [Palette.Inactive] Accent, which copied the Active Highlight
color instead of the theme accent (dark #4a5f8f -> #c9995a, light
#34508c -> #a5712f) in both palette files.
* [Themes] Align light plasma home background with the dark variant
Recolored the Plasma light home background to mirror the dark one:
brighter violet/cyan blooms, vivid azure spark arcs, and higher accent
saturation against the same pale-lavender key. Brightness is unchanged
so it still reads as a light scheme.
* [Home] Add option to disable the home tab background dim
Adds a 'Dim the home tab background' checkbox to the Home tab settings
page (Appearance). When unchecked, HomeWidget skips the translucent
black overlay it paints over the whole background. Default is on,
preserving current behavior; the home tab repaints live on change.
* Update leather backgrounds
* Update velvet marble backgrounds
* Update light plasma background
* Update light fabric background
* WIP [UI] Theme-aware onboarding banner with frosted light mode
Banner colours now derive from palette tokens at ~60fps (tick-driven,
equality-guarded setters) so scheme switches and live accent-picker
previews apply instantly:
- dark stages: byte-for-byte the original treatment (near-black stage
from window hue, Highlight accent, white centre halo, vignette 0.62)
- light stages: pastel accent-hue wash instead of a neutral grey copy,
brightness-lifted accent for additive glow legibility, deep-Highlight
halo (uGlowColor) instead of white blowout, gentler vignette
(uVignetteMin 0.88) so corners don't go muddy
- black logo silhouette variant selected on light stages
- theme picker preseeded with brand green (brand_colors.h single source)
WIP notes for next session:
- real-pixel wizard screenshot check still pending (headless capture
exists: Xvfb :77 + isolated XDG_DATA_HOME; shader vs fallback pixel
analysis not finished)
- user plans separately: promote Fusion to default theme, Default -> system
* [Themes] Align Fusion accent tokens with the SVG brand gradient
Align AccentStrong (#139740) and AccentSoft (#c9fd62) and the linked
Link/Accent roles with cockatrice.svg's linearGradient4265-7-8 stops so the
identity gradient used by the logo emulation matches the static art the icon
shipped.
* [Onboarding] Draw the banner logo as a static gradient plate
Replace the black/white logo tint switch with a ShaderEffect plate that
repaints the SVG's brand gradient (light AccentSoft -> dark AccentStrong
along the baked-in userSpaceOnUse axis) clipped to the full-color logo's
alpha silhouette, with the white highlight path overlaid on top — matching
the home widget's QPainter composite. The plate is static: no glow or
breathing. Brand colors flow from BannerShaderConfig's new brandStrong/
brandSoft pair instead of the removed logoDark flag, and the background
motifs get a touch more accent so the mark keeps its coloured surround.
* [Home] Draw the featured logo as a theme gradient composite
Repaint cockatrice.svg in Qt instead of showing the baked-in static art:
fill the full-color logo's alpha silhouette with the same brand gradient the
banner plate uses (light AccentSoft grading to dark AccentStrong along the
SVG's userSpaceOnUse axis), then overlay the white highlight path. Renders
an explicit QPixmap so the mark stays crisp at the 200px display size, and
re-seeds it on theme/palette/appearance changes so it never goes stale.
* [Resources] Drop the unused black logo asset
No consumer remains after the banner's logoDark toggle was replaced by the
static gradient plate (unit-tested in d7529e0c6a), so remove
cockatrice-logo-black.svg and its qrc entry.
* [Onboarding] Seed the theme picker from the theme's identity accent
Replace the hardcoded brand-green preseed with the shipped theme's own
AccentStrong (Plasma seeds violet, Fusion green), resolved from the default
palette so auto/user-generated palettes can't mask it, and re-seed whenever
the theme changes so the swatch never goes stale. Also consult the shipped
palette in maybeAutoGeneratePalette so scheme flips don't regenerate a fresh
palette over curated theme colors.
* Regenerate zone assets for Fabric, Leather, VelvetMarble themes
Align zone textures with each theme's palette identity:
- Fabric: linen weave in navy/steel tones (was generic green/blue/red/gray)
- Leather: grain texture in warm brown/amber tones
- VelvetMarble: smooth charcoal marble veining (replaces .jpg with .png)
All zones now have dark + light scheme variants for OS color scheme
adaptation. Plasma zones deferred to separate iteration.
* Regenerate Plasma zone assets: horizontal-hand layout, seamless tiling
Bake each zone's phase from its true world position in the horizontal-hand
layout (player 0, stack 172, table 280, hand 172+406) so the diagonal sheen
continues continuously across zone boundaries. All zones share one
mathematically tileable (1,1) diagonal at frequency 3; playerzone gets a
distinct blue-violet identity and the light scheme gets extra contrast.
* Regenerate VelvetMarble zones: classic Perlin marble, seamless tiling
* Regenerate VelvetMarble zones: domain-warped fractal veins, stone grain
* Promote Fusion to default theme, rename Default to System
Fresh installs and new profiles now default to the Fusion (dark) theme
instead of the platform-native theme. The old "Default" theme is
renamed "System" to better describe its purpose — using the OS-native
Qt style (windowsvista, macOS, etc.).
Existing users who had "Default" selected are automatically migrated
to "System" so they keep their platform-native styling. Users with
an empty or invalid theme name now fall back to Fusion.
* Move checkbox.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Client] Add [AppColors] application palette roles
The home-tab buttons' gradient over the static theme background was hardcoded, and accent-derived fallbacks could not be themed or edited: QPalette's role set is closed, so any application-specific color has to live in Cockatrice's own palette layer.
- Add an AppColor::Role enum (AccentStrong / AccentSoft) stored on PaletteConfig and round-tripped from palette-<scheme>.toml under a new [AppColors] section.
- Cache the applied app colors in ThemeManager and expose appColor(Role) with a palette-accent-derived fallback; emit paletteChanged() from applyStyleAndPalette so previews, scheme switches and OS dark mode repaint palette-driven widgets.
- Fill both app roles in PaletteGenerator::fromAccent and surface them as a dedicated section in the palette editor.
- Drive the home-tab buttons from appColor() whenever the background source is the theme (any theme, not just built-ins).
- Ship AccentStrong / AccentSoft values in the Fusion and Default default palettes so the static home-tab buttons keep their classic greens.
# Conflicts:
# cockatrice/src/interface/widgets/general/home_widget.cpp
* [AppColors] Address review comments
- PaletteEditorDialog::onSave(): compare whole PaletteConfig (colors and
appColors) so a change to only AccentStrong/AccentSoft writes the file;
add PaletteConfig::operator==.
- appColor(): derive both roles from QPalette::Highlight unconditionally.
The Fusion palettes pin Accent to near-Window values, and QPalette::Accent
only exists on Qt 6.6+, so keying on it made identical themes render very
differently across Qt versions.
- themeChangedSlot(): merge the theme default's [AppColors] into a custom
palette that predates the section instead of all-or-nothing per file;
hasPalette() now counts an appColors-only file as a palette.
- Add Default/palette-default-light.toml so the Default theme's Light scheme
keeps the classic greens instead of falling back to the OS accent.
- home_widget: restore the isBuiltInTheme() half of the Automatic condition;
non-built-in themes extract button colors from their own background art.
- palette_grid_widget: use appEnum.value(i) for the role cast (3 sites),
append appHeader to headerLabels, fix the 'Lighted' typo.
* [Themes] Route theme writes to the user themes directory
setColorScheme()/setStyleName() and the palette editor wrote directly to
the resolved theme directory, which for built-in themes is the read-only
system (install) location. Changes therefore landed in the install dir and
were lost on upgrade.
Add ThemeManager::writableThemeDir(), which always resolves to the user
themes directory, and route all theme writes through it. The palette editor
reuses the same helper, dropping its private writability probe.
* [Home] Replace 'Automatic' button color with explicit theme colors default
The Automatic option gated on isBuiltInTheme(): built-in themes used the
theme's accent colors, while non-built-in themes extracted colors from
their own background art. That made the result depend on the theme's
origin rather than what the user actually sees.
Remove Automatic and expose two explicit choices: 'From theme colors'
(always the theme's identity accents, now the default) and 'Extract from
background' (always sample the painted background). Drop the now-unused
isBuiltInTheme() helper.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Client] Show localized card names, texts and pictures
Localization wiring now runs end to end: the oracle importer collects
foreignData for the configured language and the client renders it.
- [Oracle] Import localized names and rules texts for the selected cardLang
- single-face cards store their foreignData name and full text
- multi-face (split/adventure/aftermath/prepare) cards collect the joined
name once and join each face's translated text with the same separator
as the English merge; an incomplete translation falls back to English;
the joined text follows the same highest-priority-set policy as the
single-face path and is only collected when localization is enabled
- the wizard switching languages re-imports the card database
- [Client] Display localized card info throughout the client
- card info text/picture widgets and the game board re-render on language
change
- pictures resolve cardLang art through Scryfall's named endpoint using the
localized name, falling back to id-based art when no match exists
- deck editor keeps canonical English names as card identity (EditRole)
while showing localized names (DisplayRole), so decks and wire names
stay stable
- [Card] Add CardLocalization-backed name/text lookup and cards.xml v4
localization elements with a bounded-size translation cache
- [Tests] Cover oracle foreignData import (incl. multi-face joins, priority
and fallback paths), XML v4 localization parsing, deck model localized
display and the language-aware settings default
Existing installations need to re-run Oracle to see translations: localized
data only lands in cards.xml when the Oracle app is started with the
preferred language selected — launch the separate "Oracle" program that
ships with Cockatrice, pick the language in the wizard and let it re-import
the card database.
The client's database cache (cards.xml.cache) is invalidated by the cache
format bump and the source-hash checks, but a cache written before the
re-import can still hold English-only entries (the hash uses file size and
mtime, so a same-size/same-timestamp rewrite may be served as-is); delete
cards.xml.cache and relaunch if no localized names/texts show up after
re-importing.
* [Card] Pass localized card names and texts into CardInfo construction
Address review: instead of constructing the card and then calling
setLocalizedName/setLocalizedText (which emit a cardInfoChanged signal per
language), both constructors, both newInstance overloads and their callers
(cards.xml v4 parser and the binary cache reader) now pass the localized maps
as constructor arguments.
* [Client] Rename LocalizedCard:: helpers namespace to CardLocalization
The namespace now matches its header file name, as the review pointed out;
LocalizedCard reads more like a class or struct. Callers (card info text
widget, board card name rendering) are updated to match.
* [Client] Drop unused info member from the card info text widget
The CardInfoPtr member was only ever initialized to nullptr and never read;
remove it together with its initializer.
* [PictureLoader] Add the localized picture URL explicitly, not implicitly
Address review: silently prepending the Scryfall named-picture URL to the
download list whenever a non-English card language was active was surprising,
consumed quota per card when it failed, and could grab the wrong (canon) art on
name collisions, with no way to turn it off.
The insert is now opt-in and user-controlled: changing the card language adds
the template to the top of the download URLs once (persisted, documented in the
re-import prompt, and editable/removable in the deck editor settings), while the
picture loader no longer injects it at request time.
* [Card] Show card languages in the same native (English) format as the UI
Address review: the card text & images language dropdown listed bare native
names, some in inconsistent lowercase (e.g. "čeština", "español de España"),
which makes the languages easy to mix up for users that do not read the script
(e.g. 日本語 vs 한국어). It now mirrors the UI language dropdown and always pairs
the native name with its English name (e.g. "Deutsch (German)",
"日本語 (Japanese)"), using the same fixed casing.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Replace remaining QPixmap("theme:...") call sites with themePixmap() so icons, replay controls, card backs, and other images resolve to -dark/-light variants under theme schemes. Stem-exact 1:1 migration; behavior unchanged for non-variant themes.
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [App] Add onboarding wizard
Took 10 minutes
Took 3 minutes
Took 7 minutes
Took 9 minutes
Took 2 minutes
Took 1 minute
Took 7 minutes
* Adjust CI
Took 14 minutes
Took 56 seconds
Took 2 seconds
Took 3 seconds
* Adjust CI again
Took 14 minutes
Took 2 seconds
* Comments and fixes
Took 9 seconds
Took 1 minute
* Rebase.
Took 5 minutes
Took 50 seconds
Took 15 seconds
* Comments.
Took 7 minutes
* CI lol
Took 3 minutes
* CI again lol
Took 4 minutes
* Drop some settings, add some new ones.
Took 19 minutes
* Resize when expanding section
Took 4 minutes
Took 3 minutes
Took 7 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Game] Playmats
Took 19 seconds
Took 1 minute
* [Playmats] Add fixed override and configurable fallbacks to settings.
Took 29 minutes
Took 43 seconds
* Add main to test.
Took 1 minute
Took 29 seconds
* Move settings to own group
Took 11 minutes
* Some attempts to refresh macOS compositor
Took 2 minutes
* Try something else
Took 17 minutes
* Don't manipulate live list
Took 11 minutes
* Change things about resolution, address comments.
Took 45 minutes
Took 12 minutes
* Comments.
Took 14 minutes
Took 8 seconds
* Re-order settings menu location
Took 2 minutes
* Rename PlaymatResolution to Info and add enums
Took 8 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Tabs] Add a setting to define startup tab on application launch.
Took 29 minutes
* Naming and sizing
Took 4 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [VDE] Add a new setting to determine initial tab (Context/Deck/Database)
Took 16 minutes
Took 4 seconds
* Adjust tooltip
Took 4 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Add an arrow draw animation setting
- New arrowDrawAnimation cards-display setting, default on
- The arrow draw animation checkbox joins the animation settings group
- Visual Deck Storage selection animation checkbox moves next to the
other animation checkboxes, and the enable/disable-all buttons now
cover it and the arrow animation
Took 2 minutes
Took 21 minutes
Took 7 minutes
Took 11 minutes
Took 20 seconds
* Animate arrows drawing from start to target
- The arrow stroke reveals itself along the arc with an eased timing,
followed by a short light sheen that sweeps down the shaft
- The arrow head pops in once the reveal reaches it, then the whole
arrow fades from its initial glow
- Decay is driven by GameScene's shared animation timer through the
IAnimatedItem interface (QElapsedTimer based), respecting the
arrowDrawAnimation setting
- GameScene adds the arrow item to the scene before starting its
animation so the item is registered against a valid scene
Took 6 minutes
Took 1 minute
* Defer animation start so arrows don't start halfway materialized
Took 13 minutes
* Don't draw tip/shaft outline
Took 12 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Add animations toggles for the life counter and battlefield
Per-effect toggles plus Enable/Disable-all buttons: a life-counter
flash on loss and a crimson battlefield shimmer on damage.
Took 24 seconds
* Animate life changes with a counter flash and battlefield shimmer
- Life loss/gain pulses the player life counter with a brief flash
- The battlefield table zone shimmers crimson on damage
- Respects the per-effect animation toggles
Both effects drive their decay from GameScene's shared animation timer
through the IAnimatedItem interface (QElapsedTimer based), instead of
owning per-item QTimers.
Took 8 minutes
* Revert unintentional cherry picks
Took 2 minutes
* Lambda to re-use path calculation.
Took 8 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Introduce generic IAnimatedItem interface for scene animations
GameScene's shared 10ms animation timer previously only knew about
CardItems (cardsToAnimate). Generalize it so any scene item can tick on
the shared timer instead of owning its own QTimer:
- New IAnimatedItem interface with a single animationEvent() tick.
- GameScene tracks animated items in a QHash keyed by QObject and
auto-unregisters items when they are destroyed, so an item deleted
mid-animation (concede, removePlayer, deleteLater) can never leave a
dangling pointer in the set.
- GameScene::~GameScene disconnects incoming connections before the
animation timer is deleted; all timer stops are null-guarded so
destruction ordering no longer matters.
- AbstractCardItem implements IAnimatedItem with a no-op tick so the
existing tap-animation registration path keeps working; CardItem
overrides it with the real rotate animation.
Took 5 minutes
* Add Enable/Disable all animations buttons to settings
The animation settings group gets two push buttons that toggle every
per-effect animation checkbox at once. The base branch carries the
buttons and the shared slots; per-effect toggles (life counter,
battlefield, arrow draw) are added by the feature branches on top.
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [DeckEditor] Use CommanderSpellbook.com to estimate bracket if format is 'commander'
Took 2 minutes
Took 16 minutes
* Convert json data holder to structs, rename variables, extract widget
- Extract bracket estimation UI from DeckEditorDeckDockWidget into a
new CommanderBracketWidget
- Move CommanderSpellbook integration settings from CardsDisplaySettings
to DeckEditorSettings (matching the settings refactor on master)
- Rename CommanderSpellbook integration variables to drop the redundant
'DeckEditor' prefix
Took 4 minutes
# Commit time for manual adjustment:
# Took 6 minutes
# Commit time for manual adjustment:
# Took 8 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Settings] Shuffle some settings around
Took 21 minutes
Took 1 hour 25 minutes
* [Settings] Camel case everything
* Revert debug schema change
* Add new classes
* Fix card counters writing to global
* Fix CI tests
* Fix Windows CI
* interface() is a protected keyword for MSVC
Took 5 minutes
Took 5 seconds
* [Settings] Keep menu settings on the appearance settings page
Leave the 'Menu settings' group box on the appearance settings page for
now; relocating it to the user interface settings page will be done in a
separate PR.
Took 6 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Settings] Implement search
Took 38 minutes
Took 8 seconds
Took 9 minutes
Took 5 seconds
Took 44 seconds
Took 25 seconds
* Comments
Took 23 minutes
Took 15 seconds
* Comments
Took 1 hour 14 minutes
* Minor fixes to search
Took 13 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Settings] Split cache_settings into multiple files
Took 9 minutes
Took 4 minutes
* [Settings] Fwd declare settings classes in cache_settings
Took 15 minutes
* Fix oracle includes.
Took 8 minutes
* Address comments, fix windows CI
Took 8 minutes
* fix copy constructor visibility
Took 3 minutes
* lint
Took 2 minutes
* Fix native format tests.
Took 5 minutes
* Remove test header guard
Took 4 seconds
* Remove tests invalid in CI environ
Took 24 seconds
* Adjust to rebase.
Took 11 minutes
* Change settings file name.
Took 8 minutes
---------
Co-authored-by: Lukas Brübach <lukas.bruebach@bdosecurity.de>
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [PaletteEditor] Ensure directory is writeable, don't fall back to alternate palette.
Took 17 minutes
* [ThemeManager] Extract system theme dir path resolution to helper, use it in default palette fetching
Took 8 minutes
* [ThemeManager] Expose styling again
Took 3 minutes
* [ThemeManager] Capture app palette before theme is applied for reverting
* [ThemeManager] Simply delete custom palette instead of reverting to default
* [ThemeManager] Generate and apply immediately on change.
* [PaletteEditor] Block grid signals during initial loading.
Took 5 minutes
* Address comments
Took 8 minutes
* Seed accent from scheme on reset and revert
Took 2 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* Add subtype breakdown counter for card selection
Display a categorized count of creature subtypes (and other card type
subtypes) when multiple cards are selected. The breakdown appears above
the total selection counter in the bottom-right corner.
Subtypes are grouped by main card type and sorted by frequency, with
the most common subtypes positioned adjacent to the total count for
quick reference. The feature can be toggled via a new checkbox in
Settings > User Interface.
* Alignment fix
* Computation logic moved to helper funtction in separate file
* Rename SubtypeCounter to SubtypeTally
* Fix subtype tally alignment by using grid layout instead of character padding
* Rename count to tally in the subtype breakdown feature
* partial rename
* list position fixed
* Clean up code and documentation
* Rename subtypeCountLabelStyle to subtypeTallyLabelStyle and fix include ordering
* Fix include path for selection_subtype_tally.h after file relocation
* fixed count to tally rename inconsistencies
* [Room] Additionally show a tab for friends and ignored users instead of just all online users.
Took 21 minutes
Took 12 minutes
* [Room][UserList] Introduce style delegate for user list
- Allow users to set a card name and parameters as their background banner
- Allow mods to white/blacklist cards
- Allow toggling back to the old display style
Took 7 minutes
Took 28 seconds
Took 2 minutes
Took 2 minutes
* Right checkstate.
Took 14 minutes
Took 2 minutes
* Utility for test.
Took 9 minutes
Took 8 seconds
Took 2 seconds
* Lint.
Took 10 minutes
* Algorithm for sql schema migration
Took 13 minutes
* Use {prefix}, bound card name, return errors.
Took 27 seconds
* Convert queue to while loop.
Took 19 seconds
* Hover popup.
Took 36 minutes
Took 1 minute
* More granular signals, popup for user info.
Took 25 minutes
Took 8 seconds
Took 16 minutes
---------
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
* [Messages] Add option to ignore private messages from non-buddy users
* [Messages] Exclude Moderator/Admin from non-buddy ignore filter
Moderator and Admin messages should not be filtered out when the
'Ignore private messages from non-buddies' setting is enabled, to
ensure that important warnings from server staff reach users.