Initial commit of mtgonline project

This commit is contained in:
2026-07-18 04:57:40 +00:00
commit 86c12376f8
1870 changed files with 547994 additions and 0 deletions
+270
View File
@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="UTF-8"?>
<doxygenlayout version="2.0">
<!-- Generated by doxygen 1.14.0 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="topics" visible="yes" title="" intro=""/>
<tab type="usergroup" title="Code Reference">
<tab type="modules" visible="no" title="" intro="">
<tab type="modulelist" visible="yes" title="" intro=""/>
<tab type="modulemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="concepts" visible="no" title=""/>
<tab type="interfaces" visible="no" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="no" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<tab type="exceptions" visible="no" title="">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="no" title="" intro=""/>
</tab>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_HEADERFILE"/>
<inheritancegraph visible="yes"/>
<collaborationgraph visible="yes"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes visible="yes" title=""/>
<services visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicmethods visible="yes" title=""/>
<publicstaticmethods visible="yes" title=""/>
<publicattributes visible="yes" title=""/>
<publicstaticattributes visible="yes" title=""/>
<protectedtypes visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<protectedmethods visible="yes" title=""/>
<protectedstaticmethods visible="yes" title=""/>
<protectedattributes visible="yes" title=""/>
<protectedstaticattributes visible="yes" title=""/>
<packagetypes visible="yes" title=""/>
<packagemethods visible="yes" title=""/>
<packagestaticmethods visible="yes" title=""/>
<packageattributes visible="yes" title=""/>
<packagestaticattributes visible="yes" title=""/>
<properties visible="yes" title=""/>
<events visible="yes" title=""/>
<privatetypes visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<privatemethods visible="yes" title=""/>
<privatestaticmethods visible="yes" title=""/>
<privateattributes visible="yes" title=""/>
<privatestaticattributes visible="yes" title=""/>
<friends visible="yes" title=""/>
<related visible="yes" title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<enums visible="yes" title=""/>
<services visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<constructors visible="yes" title=""/>
<functions visible="yes" title=""/>
<related visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<events visible="yes" title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<concepts visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a concept page -->
<concept>
<briefdescription visible="yes"/>
<includes visible="$SHOW_HEADERFILE"/>
<definition visible="yes" title=""/>
<detaileddescription visible="yes" title=""/>
<authorsection visible="yes"/>
</concept>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="yes"/>
<includedbygraph visible="yes"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<concepts visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="yes"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<modules visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<concepts visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<enumvalues visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<events visible="yes" title=""/>
<properties visible="yes" title=""/>
<friends visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<pagedocs/>
<inlineclasses visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<enumvalues visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<events visible="yes" title=""/>
<properties visible="yes" title=""/>
<friends visible="yes" title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a C++20 module page -->
<module>
<briefdescription visible="yes"/>
<exportedmodules visible="yes"/>
<memberdecl>
<concepts visible="yes" title=""/>
<classes visible="yes" title=""/>
<enums visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<membergroups visible="yes" title=""/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdecl>
<files visible="yes"/>
</memberdecl>
</module>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
</directory>
</doxygenlayout>
+14
View File
@@ -0,0 +1,14 @@
## Doxygen Documentation Theme
Required changes to the `Doxyfile` config from the [theme docs](https://jothepro.github.io/doxygen-awesome-css/index.html#autotoc_md16) to make [doxygen-awesome-css](https://github.com/jothepro/doxygen-awesome-css) work:
```
HTML_EXTRA_STYLESHEET = doxygen-awesome.css # Main CSS file of the theme
GENERATE_TREEVIEW = YES # Optional, also works without
HTML_COLORSTYLE = LIGHT # Required with doxygen-awesome-css theme, Auto Dark Mode will still work
DISABLE_INDEX = NO # YES is bugged in the theme, see jothepro/doxygen-awesome-css/issues/201
FULL_SIDEBAR = NO # Required for doxygen-awesome-css theme
```
<br>
Cockatrice dedicated color adjustments are configured in the [cockatrice_docs_style.css](https://github.com/Cockatrice/Cockatrice/blob/master/doc/doxygen/css/cockatrice_docs_style.css) file that uses & overrides the theme definitions.
@@ -0,0 +1,33 @@
/*
See "Awesome Doxygen CSS" theme docs:
https://jothepro.github.io/doxygen-awesome-css/md_docs_2customization.html#autotoc_md36
Adjustments here are based on the css file of the theme and variables defined there.
*/
/* Light Mode overrides */
html {
--primary-color: #33a946;
--primary-dark-color: #33a946;
--primary-light-color: #33a946;
}
/* Dark Mode overrides */
@media (prefers-color-scheme: dark) {
html:not(.light-mode) {
--primary-color: #33a946;
--primary-dark-color: #33a946;
--primary-light-color: #33a946;
}
}
/* Dark Mode overrides, defined twice to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */
html.dark-mode {
color-scheme: dark;
--primary-color: #33a946;
--primary-dark-color: #33a946;
--primary-light-color: #33a946;
}
+88
View File
@@ -0,0 +1,88 @@
/* === Accent Tuning for Doxygen Dark Mode === */
/* Main accent color */
:root {
--main-accent: #33a946;
}
/* Links */
a, a:visited {
color: var(--main-accent) !important;
}
a:hover {
color: #4fd467 !important; /* lighter green */
}
/* Project title */
#projectname {
color: var(--main-accent) !important;
}
/* Current sidebar item */
#side-nav .selected {
border-left: 3px solid var(--main-accent) !important;
}
/* Tabs */
.tablist li.current {
background: var(--main-accent) !important;
color: #fff !important;
}
/* Search box focus */
#MSearchField:focus {
outline: 1px solid var(--main-accent) !important;
}
/* Code block border highlight */
pre, code {
border: 1px solid #333;
}
pre.fragment {
border-color: var(--main-accent) !important;
}
/* Graph toggle (caller / callee two-button) */
.graph-toggle {
display: inline-flex;
margin: 0.5em 0;
border: 1px solid #444;
border-radius: 6px;
overflow: hidden;
background: #111;
}
.graph-toggle button {
flex: 1 1 50%;
padding: 0.35em 0.8em;
background: transparent;
color: #aaa;
border: 0;
cursor: pointer;
font-size: 0.95em;
}
.graph-toggle button:hover:not(:disabled) {
background: #222;
color: #fff;
}
.graph-toggle button.active {
background: var(--main-accent);
color: #fff;
}
.graph-toggle button:disabled,
.graph-toggle button.disabled {
opacity: 0.45;
cursor: default;
}
/* small accessibility focus ring */
.graph-toggle button:focus {
outline: 2px solid rgba(51, 169, 70, 0.3);
outline-offset: 1px;
}
+10
View File
@@ -0,0 +1,10 @@
/* hide navigation sync control and icons */
#nav-sync,
#nav-sync * {
display: none !important;
}
div.nav-sync-icon,
div.nav-sync-icon * {
display: none !important;
}
@@ -0,0 +1,16 @@
@page card_database_schema_and_parsing Card Database Schema and Parsing
# Card Database Schemas
Cockatrice uses `XML files` to store information of available cards to be used in the app (`cards.xml`).
The token file follows the schema of the card database (`tokens.xml`), too.
Saved decks (`<deckname>.xml`) use a different schema.
- [XSD Schema for `Card Databases`](https://github.com/Cockatrice/Cockatrice/blob/master/doc/carddatabase_v4/cards.xsd) <kbd>v4</kbd>
- [XSD Schema for `Decks`](https://github.com/Cockatrice/Cockatrice/blob/master/doc/deck.xsd) <kbd>v1</kbd>
# Card Database Parsing
TODO
@@ -0,0 +1,83 @@
@page displaying_cards Displaying Cards
Cockatrice offers a number of widgets for displaying cards. To pick the right one for your purpose, it is first
important
to determine the context in which you will be displaying the card.
# In-client
In the client (like in your custom widgets), you can use the existing card display widgets.
## Simple Display
The most general purpose of these is @ref CardInfoPictureWidget, which simply displays a picture of a card.
The textual equivalent to this is @ref CardInfoTextWidget, which displays all the properties of a card in text form.
## Detailed Display
The convenience class @ref CardInfoDisplayWidget displays both of these widgets in a tabbed container, which allows
choosing between either visual, textual, or both representations at the same time. It is the class that is most
familiar to our users when a single card is highlighted or inspected, since it is used in the deck editor and in-game
for these purposes.
If you would like the user to be able to inspect a single card in your custom widget, you should
expose a @ref CardInfoDisplayWidget to them and incorporate it as a dock widget inside your custom widget.
@ref CardInfoDisplayWidget is great for ensuring that the user has all the relevant details of a card available.
It is crucial anywhere the user might encounter a card for the first time or needs to make an informed decision.
## Visual Display
However, there is a reason why it is possible to have a visual-only representation of the card in the
@ref CardInfoDisplayWidget.
Cards are, by design, meant to be represented as images and cards which we can reasonably
expect the user to know (for example, cards contained in a user made deck or explicitly chosen by the user) can be
represented with just their image as a sort of "visual shorthand".
The simplest way to do this is of course, the above-mentioned @ref CardInfoPictureWidget which simply displays the
picture without modifications.
However, there exist a couple of other convenience classes which subclass @ref CardInfoPictureWidget to accomplish some
things which you might find useful as well.
- @ref CardInfoPictureWithTextOverlayWidget displays text overlaid on top of the card picture and scales this text to
fit automatically.
- @ref DeckPreviewCardPictureWidget is a @ref CardInfoPictureWithTextOverlayWidget which also features a
raise-on-mouse-enter animation, controlled by the global setting (TODO: specify which).
- @ref CardInfoPictureArtCropWidget attempts to display an 'art crop' of the card by cropping the upper region of the
card and only displaying that.
## Groups of Cards
Sometimes it is useful to display images of cards in groups, for example to represent the deck in the @ref
VisualDeckEditorWidget or during confirmation in the pre-game lobby.
To this end, Cockatrice offers three convenience classes to display cards for an index in a @ref DeckListModel in a
group and one to display all cards in a particular zone of a @ref DeckListModel.
The generic way to do this is @ref CardGroupDisplayWidget, which displays cards in @ref QVBoxLayout. This class is very
generic and it is probably a better choice to either subclass it or use one of the two existing implementations.
@ref FlatCardGroupDisplayWidget displays cards using a horizontal @ref FlowWidget. This means it will fill available
screen space, left to right with no margins, with card pictures, skipping to a new line if it overflows available screen
space horizontally.
@ref OverlappedCardGroupDisplayWidget displays cards using an @ref OverlapWidget, which displays widgets on top of each
other in vertical columns until it exceeds available screen space in which case it will start a new column. The amount
of overlap as well as the overlap direction is configurable.
@ref DeckCardZoneDisplayWidget can be used to visualize all cards in a zone with either a @ref
FlatCardGroupDisplayWidget or a @ref OverlappedCardGroupDisplayWidget and headed by a @ref BannerWidget. It also allows
grouping and sorting.
# In-game
The in-game view is a @ref QGraphicsScene, which means any widget we want to display inside of it should be a @ref
QGraphicsObject.
- @ref CardItem
@@ -0,0 +1,11 @@
@page developer_reference Developer Reference
- @subpage logging
- @subpage primer_cards
- @subpage card_database_schema_and_parsing
- @subpage querying_the_card_database
- @subpage loading_card_pictures
- @subpage displaying_cards
@@ -0,0 +1,52 @@
@page loading_card_pictures Loading Card Pictures
Pictures associated with CardInfo%s are retrieved either from on-disk or the network through the CardPictureLoader.
In most cases, you don't need to concern yourself with the internals of CardPictureLoader.
Simply using one of the ways described in @ref displaying_cards is enough to automatically queue a request to the
CardPictureLoader when the chosen widget is shown, emitting signals to refresh the widget when the request is finished.
# How requests are triggered
CardPictureLoader::getPixmap() is called exactly two times in the code base, in CardInfoPictureWidget::loadPixmap(), the
base class
for all widget based card picture display, and AbstractCardItem::paintPicture(), the base class for all QGraphicsItem
based card picture
display. See @ref displaying_cards for more information on the difference between these two display methods.
Because both of these calls are made in the paintEvent() methods of their respective classes, this means that requests
are issued as soon as but not before the widget is shown on screen.
It is also possible to "warm up" the cache by issuing card picture load requests to the CardPictureLoader without using
a display widget and waiting for it to be shown by calling CardPictureLoader::cacheCardPixmaps() with a list of
ExactCard%s.
# The QPixmapCache and QNetworkDiskCache
Cockatrice uses the QPixmapCache from the Qt GUI module to store card pictures in-memory and the QNetworkDiskCache from
the Qt Network module to cache network requests for card pictures on-disk.
What this means is that the CardPictureLoader will first attempt to look up a card in the QPixmapCache according to the
ExactCard::getPixmapCacheKey() method of an ExactCard object. If it does not find it in the in-memory cache, it will
issue a load request, which will first look for local images on-disk and then consult the QNetworkDiskCache and if
found, use the stored binary data from the network cache to populate the in-memory pixmap cache under the card's cache
key. If it is not found, it will then proceed with issuing a network request.
The size of both of these caches can be configured by the user in the "Card Sources" settings page.
# PixmapCacheKeys and ProviderIDs
TODO
# The Redirect Cache
TODO
# Local Image Loading
TODO
# URL Generation and Resolution
TODO
@@ -0,0 +1,184 @@
@page logging Logging
Cockatrice uses QtLogging from the QtCore module for its logging. See
the [official documentation](https://doc.qt.io/qt-6/qtlogging.html) for further details.
# Log Message Pattern
Any message logged through the QtLogging system automatically conforms to this message pattern:
Generic:
```
[<timestamp> <log_level>] [<class:function>] - <message> [<filename>:<line_no>]
```
Example:
```
[2025-12-05 14:48:25.908 I] [MainWindow::startupConfigCheck] - Startup: found config with current version [window_main.cpp:951]
```
For more information, see [Logging Setup](#logging-setup).
# Log Level and Categories
\note The default log level for the application is info.
This means that you should only use qInfo() in production-level code if you are truly sure that this message is
beneficial to end-users and other developers. As a general rule, if your functionality logs to info more than twice in
response to a user interaction, you are advised to consider moving some of these logs down to the debug level.
\warning You are strongly advised to avoid the use of the generic logging macros (e.g. qDebug(), qInfo(), qWarn()).
\note You should instead use the corresponding category logging macros (qCDebug(), qCInfo(), qCWarn()) and define
logging
categories for your log statements.
Example:
```c++
in .h
inline Q_LOGGING_CATEGORY(ExampleCategory, "cockatrice_example_category");
inline Q_LOGGING_CATEGORY(ExampleSubCategory, "cockatrice_example_category.sub_category");
in .cpp
qCInfo(ExampleCategory) << "Info level logs are usually sent through the main category"
qCDebug(ExampleSubCategory) << "Debug level logs are permitted their own category to allow selective silencing"
```
For more information on how to enable or disable logging categories,
see [Logging Configuration](#logging-configuration).
# Logging Configuration
For configuring our logging, we use the qtlogging.ini, located under cockatrice/resources/config/qtlogging.ini, which is
baked into the application in release version and set as the QT_LOGGING_CONF environment variable in main.cpp.
```c++
#ifdef Q_OS_APPLE
// <build>/cockatrice/cockatrice.app/Contents/MacOS/cockatrice
const QByteArray configPath = "../../../qtlogging.ini";
#elif defined(Q_OS_UNIX)
// <build>/cockatrice/cockatrice
const QByteArray configPath = "./qtlogging.ini";
#elif defined(Q_OS_WIN)
// <build>/cockatrice/Debug/cockatrice.exe
const QByteArray configPath = "../qtlogging.ini";
#else
const QByteArray configPath = "";
#endif
if (!qEnvironmentVariableIsSet(("QT_LOGGING_CONF"))) {
// Set the QT_LOGGING_CONF environment variable
qputenv("QT_LOGGING_CONF", configPath);
}
```
For more information on how to use this file and on how Qt evaluates which logging rules/file to use, please
see the [official Qt documentation](https://doc.qt.io/qt-6/qloggingcategory.html#configuring-categories).
Some examples:
```
# Turn off all logging except everything from card_picture_loader and all sub categories
[Rules]
# The default log level is info
*.debug = false
*.info = false
*.warning = false
*.critical = false
*.fatal = false
card_picture_loader.* = true
```
```
# Turn off all logging except info level logs from card_picture_loader and all sub categories
[Rules]
# The default log level is info
*.debug = false
*.info = false
*.warning = false
*.critical = false
*.fatal = false
card_picture_loader.*.info = true
```
```
[Rules]
# Turn on debug level logs for card_picture_loader but keep logging for sub categories suppressed
*.debug = false
card_picture_loader.debug = true
```
```
[Rules]
# Turn on all logs for worker subcategory of card_picture_loader
*.debug = false
card_picture_loader.worker = true
```
```
[Rules]
# Turn off some noisy and irrelevant startup logging for local development
*.debug = false
qt_translator = false
window_main.* = false
release_channel = false
spoiler_background_updater = false
theme_manager = false
sound_engine = false
tapped_out_interface = false
card_database = false
card_database.loading = false
card_database.loading.success_or_failure = true
cockatrice_xml.* = false
```
# Logging Setup
This is achieved through our logging setup in @ref main.cpp, where we set the message pattern and install a custom
logger which replaces the full file path at the end with just the file name (Qt shows the full and quite lengthy path by
default).
```c++
qSetMessagePattern(
"\033[0m[%{time yyyy-MM-dd h:mm:ss.zzz} "
"%{if-debug}\033[36mD%{endif}%{if-info}\033[32mI%{endif}%{if-warning}\033[33mW%{endif}%{if-critical}\033[31mC%{"
"endif}%{if-fatal}\033[1;31mF%{endif}\033[0m] [%{function}] - %{message} [%{file}:%{line}]");
QApplication app(argc, argv);
QObject::connect(&app, &QApplication::lastWindowClosed, &app, &QApplication::quit);
qInstallMessageHandler(CockatriceLogger);
```
```c++
static void CockatriceLogger(QtMsgType type, const QMessageLogContext &ctx, const QString &message)
{
QString logMessage = qFormatLogMessage(type, ctx, message);
// Regular expression to match the full path in the square brackets and extract only the filename and line number
QRegularExpression regex(R"(\[(?:.:)?[\/\\].*[\/\\]([^\/\\]+\:\d+)\])");
QRegularExpressionMatch match = regex.match(logMessage);
if (match.hasMatch()) {
// Extract the filename and line number (e.g., "main.cpp:211")
QString filenameLine = match.captured(1);
// Replace the full path in square brackets with just the filename and line number
logMessage.replace(match.captured(0), QString("[%1]").arg(filenameLine));
}
Logger::getInstance().log(type, ctx, logMessage);
}
```
@@ -0,0 +1,71 @@
@page primer_cards A Primer on Cards
# The Cockatrice Card Library
All non-gui code related to cards used by Cockatrice is contained within libcockatrice_card.
# A Basic Card Object: CardInfo
A CardInfo object is the translational unit used by the CardDatabase to represent an on-disk XML entry as an in-memory
Qt object.
For a complete overview of the fields that define a CardInfo object, see the class documentation and more specifically
@ref PrivateCardProperties.
These fields correspond to either entries or a combination of entries in the XML card entry to which the
CardDatabaseParser applies special logic to map, populate or determine their respective values in the CardInfo object.
Any property to which special parsing is not applied is stored in CardInfo::properties and may be retrieved or set with
CardInfo::getProperty() or CardInfo::setProperty() as well as CardInfo::getProperties() to get a collection of the
property keys a CardInfo contains.
For more information on how special fields contained within @ref PrivateCardProperties are parsed, see
CockatriceXml4Parser::loadCardsFromXml().
Apart from access to the basic and extended properties of a card, CardInfo also provides two important mechanisms to us.
The first is the CardInfo::pixmapUpdated() signal, which allows the CardPictureLoader to signal when it is done
manipulating (in most cases: loading) the QPixmap of an ExactCard::getPixmapCacheKey(), where the ExactCard::card
corresponds to this CardInfo object.
Put simply: Whenever the CardPictureLoader loads a new PrintingInfo which is not already in the cache, it emits this
signal so that any widget using a CardInfo object can update the display of it to possibly use this new QPixmap.
\attention It should be noted that it is not possible to use CardPictureLoader::getPixmap() with anything but an
ExactCard, which is a CardInfo object associated with a PrintingInfo, i.e. a definitive printing of a specific card
The other signal, CardInfo::cardInfoChanged() conceptually works much the same way, except it is concerned with the
properties of the CardInfo object.
# Getting specific: PrintingInfo and ExactCard
## Printing Info
A CardInfo object describes the basic properties of a card in much the same way that we say "Two cards with the same
name are and should be equal if their properties are equal". However, there are certain (mostly visual) properties which
might differ between printings of a card but still conceptually classify two instances of a card as "the same card".
The most obvious example to this are cards which fundamentally share all properties except the artwork depicted on the
card.
We refer to such differences as Printings and track them in the PrintingInfo class. A PrintingInfo is always related to
the CardSet that introduced the variation. Multiple variations can exist in the same CardSet and the respective
PrintingInfo::getProperty() can be used to determine the differences, such as the collector numbers on the printings, if
there are any.
## Exact Card
A CardInfo object is used to hold the functional properties of a card and a PrintingInfo object can be used to hold the
visual properties of a card. To represent a 'physical' card, as in, a concrete immutable instance of a card, we can use
ExactCard, which combines a CardInfo and a PrintingInfo object into one class. The class is used as a container around
CardInfo objects whenever the user (and thus the program) expects to be presented with a defined card printing.
# Using Cards
For more information on the XML database schema which the CardDatabaseParser parses to generate CardInfo objects, see
@ref card_database_schema_and_parsing.
For more information on querying the CardDatabase for CardInfo objects, see @ref querying_the_card_database.
For more information on displaying CardInfo and ExactCard objects using Qt Widgets, see @ref displaying_cards.
For more information on how card pictures are loaded from disk or the network, see @ref loading_card_pictures as well as
the CardPictureLoader documentation.
@@ -0,0 +1,39 @@
@page querying_the_card_database Querying the Card Database
# The CardDatabaseQuerier Class
The CardDatabaseQuerier is the only class used for querying the database. The CardDatabase is an in-memory map and thus
provides no structured query language. CardDatabaseQuerier offers methods to retrieve cards by name, by providerID or in
bulk, as CardSet%s.
## Obtaining a handle to the CardDatabaseQuerier for usage
To obtain the CardDatabaseQuerier related to the global CardDatabase singleton, use CardDatabaseManager::query().
## Querying for known cards
There are, essentially, two ways to ensure card equality, with the second being optional but necessitating the first.
These two ways are CardInfo name equality and PrintingInfo provider ID equality.
Because of this, most queries require, at the very least, a card name to match against and optionally a providerID to
narrow the results.
### Generic Card Infos
To check if a card with the exact provided name exists as a CardInfo in the CardDatabase use,
CardDatabaseQuerier::getCardInfo() or CardDatabaseQuerier::getCardInfos() for multiple cards.
### Guessing Cards
If the exact name might not be present in the CardDatabase, you can use CardDatabaseQuerier::getCardBySimpleName(),
which automatically simplifies the card name and matches it against simplified card names in the CardDatabase.
Alternatively, you can use CardDatabaseQuerier::lookupCardByName(), which first attempts an exact match search and then
uses CardDatabaseQuerier::getCardBySimpleName() as a fallback.
### ExactCard%s
To obtain an ExactCard from the CardDatabaseQuerier, you must use a CardRef as a parameter to
CardDatabaseQuerier::getCard(), CardDatabaseQuerier::getCards(), or CardDatabaseQuerier::guessCard().
CardRef is a simple struct consisting of a card name and a card provider ID as QString%s.
+8
View File
@@ -0,0 +1,8 @@
@mainpage Documentation
Welcome to the Cockatrice code documentation.
- @subpage user_reference
- @subpage developer_reference
Please also check the <a href="https://cockatrice.github.io/" target="_blank" rel="noopener noreferrer">Cockatrice Webpage</a> or our <a href="https://github.com/Cockatrice/Cockatrice" target="_blank" rel="noopener noreferrer">Code Repository</a> for general information.
@@ -0,0 +1,15 @@
@page creating_decks Creating Decks
Creating a new deck is done using either the \ref editing_decks_classic or \ref editing_decks_visual.
They can be accessed either by clicking the "Create Deck" button in the TabHome screen, which will open the default deck
editor configured in the "User Interface" -> "Deck editor/storage settings" -> "Default deck editor type" setting, or
by selecting "Deck Editor" or "Visual Deck Editor" under the "Tabs" application menu located at the top.
# Further References
- See @ref editing_decks for information on how to modify the attributes and contents of a deck in the Deck Editor
widgets.
- See @ref exporting_decks for information on how to store and persist your deck either in-client or to external
services.
- See @ref importing_decks for information on how to import existing decks either in-client or from external services
@@ -0,0 +1,6 @@
@page editing_decks Editing Decks
- @subpage editing_decks_classic
- @subpage editing_decks_visual
- @subpage editing_decks_printings
@@ -0,0 +1,54 @@
@page editing_decks_classic Classic Deck Editor
\image html classic_deck_editor.png width=900px
# Editing Basic Deck Information
Editing basic deck information is done through the deck dock widget (DeckEditorDeckDockWidget).
\image html deckeditordeckdockwidget.png
This widget allows editing:
- The name
- The comments
- The banner card, which is used to represent the deck in the visual deck storage
- The tags, which are used for filtering in the visual deck storage
# Adding Cards
Adding cards is done using the list of cards in the database presented in the list view on the left.
\image html classic_database_display.png
Cards can be added by either double-clicking an entry, pressing return with an entry selected to add it to the mainboard
or pressing ctrl/cmd + return to add it to the sideboard.
There are also buttons for these two functions on the right of the search bar above the list view.
\image html classic_database_display_add_buttons.png
# Modifying the Deck List
To modify or remove cards in the deck list, the tree list view in the deck dock widget can be used.
\image html deck_dock_deck_list.png
Just above the list, at the top right, there are four buttons to manipulate the currently selected card(s):
- Increment Card
- Decrement Card
- Remove Card
- Switch Card between Mainboard and Sideboard
\image html deck_dock_deck_list_buttons.png
Additionally, there is a combo box above the list, which may be used to change how cards are grouped in the list
display. This is only for visual display and does not affect how the list is saved.
\image html deck_dock_deck_list_group_by.png
# Modifying printings
For more information on modifying the printings in a deck see @ref editing_decks_printings
@@ -0,0 +1,122 @@
@page editing_decks_printings Printing Selector
\image html printing_selector.png
# Purpose
The PrintingSelector allows editing the PrintingInfo associated with CardInfo%s contained in DeckList%s.
As described in PrintingInfo, a CardInfo can have different variations contained within the same or different CardSet%s.
PrintingSelector allows the user to choose a variation, as well as pinning a variation to be used as the preferred
printing in all cases where the 'default' or 'most preferred' image should be shown.
# Pre-requisites (User Interface)
To use the printing selector, ensure that you are using the Post-ProviderID change behavior (Checkbox as shown in the
image).
\image html printing_selector_pre_providerid.png
\attention This is the default behavior, unless you have explicitly changed it, in which case you will have seen a
warning as follows. Once again, checking this box will *disable* the new behavior and revert you to the legacy system
without the printing selector.
Disabling the printing selector:
\image html printing_selector_enable.png
Enabling the printing selector:
\image html printing_selector_disable.png
# Pre-requisites (Card Database)
The PrintingSelector requires each underlying CardInfo object to have a <set> entry with a *unique* providerID attribute
for each variation that should be displayed.
Here is an example, that first defines three sets, and then the 'Ace of Hearts' card with three variations.
```xml
<set rarity="common" uuid="00000000-0000-0000-0000-000000000033" num="51" muid="AH">PKR</set>
<set rarity="common" uuid="00000000-0000-0000-0001-000000000033" num="51" muid="AHSTD">STD</set>
<set rarity="common" uuid="00000000-0000-0000-0002-000000000033" num="51" muid="AHNBR">NBR</set>
```
```xml
<?xml version='1.0' encoding='UTF-8'?>
<cockatrice_carddatabase version="4">
<sets>
<set>
<name>PKR</name>
<longname>Cockatrice Poker</longname>
<settype>Custom</settype>
<releasedate>2025-11-15</releasedate>
</set>
<set>
<name>STD</name>
<longname>Standard Poker</longname>
<settype>core</settype>
<releasedate>2025-11-14</releasedate>
</set>
<set>
<name>NBR</name>
<longname>Numbers</longname>
<settype>core</settype>
<releasedate>2025-11-14</releasedate>
</set>
</sets>
<cards>
<card>
<name>Ace of Hearts</name>
<text>Ace of Hearts</text>
<prop>
<layout>normal</layout>
<side>front</side>
<type>Ace</type>
<maintype>Ace</maintype>
<manacost>14</manacost>
<cmc>14</cmc>
<colors>H</colors>
<coloridentity>H</coloridentity>
<format-standard>legal</format-standard>
</prop>
<reverse-related>Joker</reverse-related>
<token>0</token>
<tablerow>1</tablerow>
<cipt>0</cipt>
<upsidedown>0</upsidedown>
<set rarity="common" uuid="00000000-0000-0000-0000-000000000033" num="51" muid="AH">PKR</set>
<set rarity="common" uuid="00000000-0000-0000-0001-000000000033" num="51" muid="AHSTD">STD</set>
<set rarity="common" uuid="00000000-0000-0000-0002-000000000033" num="51" muid="AHNBR">NBR</set>
</card>
</cards>
</cockatrice_carddatabase>
```
# Using the Printing Selector
To use the PrintingSelector, first select a card in the DeckEditorDeckDockWidget:
\image html deck_dock_deck_list.png
You may add a variation to the mainboard by clicking the + and - buttons in the top row. The bottom row will add the
variation to your sideboard.
\image html printing_selector.png
You can also right-click a variation to pin it, which will move it to the top of the variation list for easy access and
additionally, use it as the default printing whenever the printing isn't explicitly specified (such as adding a card
from the database in the deck editor).
Only one printing may be pinned at a time.
Additionally, the PrintingSelector offers a navigation bar at the bottom to navigate through cards in your deck, as well
as an option to modify the variations of cards in bulk via the 'Bulk Selection' option.
\image html printing_selector_navigation.png
The search bar at the top may be used to filter the displayed variations and the cogwheel may be clicked to open up
additional settings.
\image html printing_selector_options.png
@@ -0,0 +1,93 @@
@page editing_decks_visual Visual Deck Editor
\image html vde_overlap_layout_type_grouped.png width=1200px
# Editing Basic Deck Information
Editing basic deck information is done through the deck dock widget (DeckEditorDeckDockWidget).
\image html deckeditordeckdockwidget.png
This widget allows editing:
- The name
- The comments
- The banner card, which is used to represent the deck in the visual deck storage
- The tags, which are used for filtering in the visual deck storage
# Adding Cards
Adding cards is done by either using the "Quick search and add card" search bar at the top of the "Visual Deck View" tab
or by clicking on a picture of a card in the "Visual Database Display" tab.
See @ref visual_database_display for more information on how to utilize the visual database display.
# Modifying the Deck List
To modify or remove cards in the deck list, the tree list view in the deck dock widget can be used.
\image html deck_dock_deck_list.png
Just above the list, at the top right, there are four buttons to manipulate the currently selected card(s):
- Increment Card
- Decrement Card
- Remove Card
- Switch Card between Mainboard and Sideboard
\image html deck_dock_deck_list_buttons.png
Additionally, there is a combo box above the list, which may be used to change how cards are grouped in the list
display. This is only for visual display and does not affect how the list is saved.
\image html deck_dock_deck_list_group_by.png
# Modifying the visual deck layout
The visual deck editor displays cards visually, as opposed to simply in list form in the Deck Dock Widget. Each entry in
the deck list is represented by a picture. These entries are grouped together under their respective sub-groups.
Sub-groups may be collapsed (i.e. the pictures contained within them are hidden) by clicking on the name of the group in
the banner.
Cards may be displayed in a "Flat" layout, which displays each picture next to each other and ensures full
visibility for each card.
\image html vde_flat_layout_type_grouped.png width=1200px
or in an "Overlap" layout, which overlaps cards on top of each other (leaving the top 20% of
the card uncovered so names remain readable) and arranges them in stacks to save space and allow for an easy overview.
\image html vde_overlap_layout_type_grouped.png width=1200px
Additionally, it is possible to change how the cards in the deck list are grouped by selecting a different grouping
method from the combo box, either in the top left of the "Visual Deck View" tab or above the list view in the deck dock
widget.
Example - Cards grouped by suit/color:
\image html vde_flat_layout_color_grouped.png width=1200px
Furthermore, it is possible to change how the cards are sorted within the sub-group. This is done by clicking on the
button with the cogwheel icon next to the combo box that adjusts grouping in the top left of the "Visual Deck View" tab.
This presents a list of available sort criteria, which may be rearranged to change their priorities.
# Modifying printings
For more information on modifying the printings in a deck see @ref editing_decks_printings
# Deck Analytics
The visual deck editor offers a "Deck Analytics" tab, which displays information about:
- The mana curve
- The mana devotion
- The mana base
\image html vde_deck_analytics.png width=1200px
# Sample Hand
The visual deck editor offers a "Sample Hand" tab, which allows simulating drawing a configurable amount of cards from
the deck, which reduces the need to launch a single player game for testing purposes.
\image html vde_sample_hand.png width=1200px
@@ -0,0 +1,151 @@
@page exporting_decks Exporting Decks
# Where to export?
There are two screens in the client which can be used to import decks, depending on the context.
- The deck editor tab
- The deck storage tab (not to be confused with the visual deck storage tab)
# The Deck Editor Tab
The deck editor tabs (Classic and Visual) offer three ways of export a deck:
- To a file on your local storage
- To your clipboard
- To an online service
## Local File Storage
To save a deck to a file on your local storage, select the "Save Deck" action in the "Deck Editor" or "Visual Deck
Editor" menu in the application menu bar at the top of the screen. Alternatively, you can use the shortcut Ctrl/Cmd + S
to access this action.
Selecting this action will open a file picker dialog provided by your operating system. Simply enter a file name and
select a format (.cod is recommended) and confirm.
Just below the "Save Deck" action described above is the "Save Deck as..." option, which allows saving an existing file
under a different filename, which is useful for saving a different version or copy of a deck.
## From Clipboard
To save a deck to your clipboard, select the "Save deck to clipboard..." action in the "Deck Editor" or "Visual Deck
Editor" menu in the application menu bar at the top of the screen. Alternatively, you can use the shortcut Ctrl/Cmd +
Shift + C or Ctrl/Cmd + Shift + R to access this action.
Selecting this action will save the currently open deck list to your clipboard.
Saving the decklist without annotations will export the decklist, with each card being described in the following format
```
CARD_AMOUNT CARD_NAME (SET_SHORT_NAME) CARD_COLLECTOR_NUMBER
```
There is also the (no set info) option, which will simply export each card as
```
CARD_AMOUNT CARD_NAME
```
Mainboard and sideboard are delimited by a newline like so:
```
1 MainboardCard
1 OtherMainboardCard
1 SideboardCard
```
Saving the decklist as annotated will insert comments (marked with // in front of them).
It will first insert the name and any comments associated with the deck before separating each deck section into its own
newline delimited and annotated group.
Example: TODO: Adjust this to be non mtg based.
```
// Full Deck
// An example comment.
// 63 Maindeck
// 4 Ace
1 Ace of Clubs (PKR) 49
1 Ace of Diamonds (PKR) 50
1 Ace of Hearts (PKR) 51
1 Ace of Spades (PKR) 52
// 13 Face
1 Jack of Clubs (PKR) 53
1 Jack of Diamonds (PKR) 54
1 Jack of Hearts (PKR) 55
1 Jack of Spades (PKR) 56
1 King of Clubs (PKR) 57
1 King of Diamonds (PKR) 58
1 King of Spades (PKR) 60
1 Queen of Clubs (PKR) 61
1 Queen of Diamonds (PKR) 62
1 Queen of Hearts (PKR) 63
1 Queen of Spades (PKR) 64
2 King of Hearts (PKR) 59
// 44 Number
1 0 of Clubs (PKR) 1
1 0 of Diamonds (PKR) 2
1 0 of Hearts (PKR) 3
1 1 of Clubs (PKR) 11
1 1 of Diamonds (PKR) 12
1 1 of Hearts (PKR) 13
1 1 of Spades (PKR) 14
1 10 of Clubs (PKR) 5
1 10 of Diamonds (PKR) 6
1 10 of Hearts (PKR) 7
1 2 of Clubs (PKR) 17
1 2 of Diamonds (PKR) 18
1 2 of Hearts (PKR) 19
1 2 of Spades (PKR) 20
1 3 of Clubs (PKR) 21
1 3 of Diamonds (PKR) 22
1 3 of Hearts (PKR) 23
1 3 of Spades (PKR) 24
1 4 of Clubs (PKR) 25
1 4 of Diamonds (PKR) 26
1 4 of Hearts (PKR) 27
1 4 of Spades (PKR) 28
1 5 of Clubs (PKR) 29
1 5 of Diamonds (PKR) 30
1 5 of Hearts (PKR) 31
1 5 of Spades (PKR) 32
1 6 of Clubs (PKR) 33
1 6 of Diamonds (PKR) 34
1 6 of Hearts (PKR) 35
1 6 of Spades (PKR) 36
1 7 of Clubs (PKR) 37
1 7 of Diamonds (PKR) 38
1 7 of Hearts (PKR) 39
1 7 of Spades (PKR) 40
1 8 of Clubs (PKR) 41
1 8 of Diamonds (PKR) 42
1 8 of Hearts (PKR) 43
1 8 of Spades (PKR) 44
1 9 of Clubs (PKR) 45
1 9 of Diamonds (PKR) 46
1 9 of Hearts (PKR) 47
1 9 of Spades (PKR) 48
1 10 of Spades (PKR) 8
1 0 of Spades (PKR) 4
// 2 Joker
1 1 Joker (PKR) 10
1 2 Joker (PKR) 16
```
## From an online service
To export a deck to an online service, select the "Send deck to online service..." action in the "Deck Editor" or "
Visual Deck Editor" menu in the application menu bar at the top of the screen.
Selecting this action will open your browser with the selected service open and the deck list information from the
client supplied to it.
Currently supported services are DeckList and TappedOut.
@@ -0,0 +1,62 @@
@page importing_decks Importing Decks
# Where to import?
There are three screens in the client which can be used to import decks, depending on the context.
- The deck editor tab
- The pre-game lobby tab
- The deck storage tab (not to be confused with the visual deck storage tab)
# The Deck Editor Tab
The deck editor tabs (Classic and Visual) offer three ways of importing a deck:
- From a file on your local storage
- From your clipboard
- From an online service
## Local File Storage
To load a deck from a file on your local storage, select the "Load Deck" action in the "Deck Editor" or "Visual Deck
Editor" menu in the application menu bar at the top of the screen. Alternatively, you can use the shortcut Ctrl/Cmd + O
to access this action.
Selecting this action will open a file picker dialog provided by your operating system. Simply select a supported file
here and it will be loaded.
Just below the "Load Deck" action described above is the "Load recent deck" option, which keeps a record of the last 10
loaded decks for quick access.
## From Clipboard
To load a deck from your clipboard, select the "Load deck from clipboard..." action in the "Deck Editor" or "Visual Deck
Editor" menu in the application menu bar at the top of the screen. Alternatively, you can use the shortcut Ctrl/Cmd +
Shift + V to access this action.
Selecting this action will open a new text editor dialog with the contents of your clipboard pasted inside it.
The import dialog expects each line to be a card with the following format:
TODO
Each card should be on a separate line and there should be no empty lines between cards. The first empty line between
two blocks of cards will be considered as the divider between mainboard and sideboard.
Selecting "Parse Set Name and Number (if available)" will automatically parse these options and attempt to resolve them
to valid provider IDs found in the card database. If this option is unselected, Cockatrice will import all cards as
versions without provider IDs, which means they will display to everyone according to their own user defined set
preferences, rather than being the same defined printing for everyone.
## From an online service
To load a deck from an online service, select the "Load deck from online service..." action in the "Deck Editor" or "
Visual Deck Editor" menu in the application menu bar at the top of the screen.
Selecting this action will open a dialog containing the contents of your clipboard pasted into it. If your clipboard
currently contains a supported URL, the dialog will accept it and close on its own, otherwise you may adjust the URL and
confirm.
The action will automatically import the deck from the online service without any other required user action.
Currently supported services are Archidekt, Deckstats, Moxfield, and TappedOut.
@@ -0,0 +1,17 @@
@page user_reference User Reference
## Deck Management
- @subpage creating_decks
- @subpage importing_decks
- @subpage editing_decks
- @subpage exporting_decks
## Release Channels
- @subpage beta_release
## Syntax Help
- @subpage search_syntax_help
- @subpage deck_search_syntax_help
@@ -0,0 +1,54 @@
@page beta_release Beta Release
The beta version of Cockatrice features all the newest features before they make their way into the latest stable
release.
It allows us to test these features ahead of time and you to give feedback on them.
We release new betas very frequently and usually release a follow-up beta with a fix within a day or two if we break
anything. In contrast, stable releases are released much less frequently but ensured to be stable.
# What to Expect from the Beta
Using the beta and giving feedback on it helps us improve Cockatrice a lot.
We do not perform any automatic data collection so your voluntary feedback is the only way for us to get a sense of what
you enjoy, expect, or would like to change.
We highly appreciate your active participation and feedback.
That being said, some words of warning should be issued:
The beta release may contain unfinished features, bugs, or performance issues.
It is intended for testing and feedback and may be less stable than the default release.
We recommend using the beta only if you are comfortable encountering issues and helping us improve Cockatrice.
# Switching to the Beta
To switch to the Beta, navigate to your settings, using the Tab "Cockatrice → Settings" or Ctrl + Shift + P (default
shortcut).
Within the settings, in the first tab 'General', the first section 'Personal Settings' contains the setting 'Release
Channel'.
\image html release_channel_beta.png
Switch this to 'Beta'.
Afterwards, close your settings, and use the 'Help' tab to search for a client update. You should be prompted to install
the beta version.
# Switching back to Stable
Follow the same steps as above, but set Release Channel to 'Default'.
# Giving Feedback
If you encounter a bug or unexpected behavior while using the beta, please report it on:
- GitHub: https://github.com/Cockatrice/Cockatrice/issues
- Discord: https://discord.gg/4hNswvHeFd in #beta-testing
When reporting issues, please include:
- Your operating system
- The beta version number (found in 'Help → About Cockatrice')
- Steps to reproduce the problem, if possible
+724
View File
@@ -0,0 +1,724 @@
/** @file doc_groups.dox
* @brief Doxygen group definitions for Cockatrice.
*
* This file defines the documentation groups and hierarchy used
* throughout the Cockatrice codebase. Reference these groups with @ingroup.
*/
/* ------------------------------------------------------------------ */
/* Core */
/* ------------------------------------------------------------------ */
/**
* @defgroup Core Core
* @brief Core utilities, shared types, and infrastructure.
*
* Provides the foundational building blocks used throughout Cockatrice.
* This includes logging facilities, settings management, serialization helpers,
* common enumerations, and general-purpose utility classes and functions.
*/
/* ------------------------------------------------------------------ */
/* UI */
/* ------------------------------------------------------------------ */
/**
* @defgroup UI User Interface
* @brief Graphical interface components built with Qt.
*
* Includes high-level widgets, dialogs, models, and editors that form
* the interactive frontend of Cockatrice.
*/
/**
* @defgroup Widgets Widgets
* @ingroup UI
* @brief General-purpose Qt widgets.
*
* A collection of reusable widgets used throughout the application,
* such as CardInfoPictureFoilWidget, DeckAnalyticsWidget, and others.
*/
/**
* @defgroup Dialogs Dialogs
* @ingroup Widgets
* @brief Application dialogs.
*
* Includes dialogs for card prices, DeckList import/export,
* settings, and other modal user interactions.
*/
/**
* @defgroup NetworkDialogs Networking Dialogs
* @ingroup Dialogs
* @ingroup NetworkingWidgets
* @brief Dialogs related to a RemoteClient interacting with a Server.
*/
/**
* @defgroup ClientUpdateDialogs Client Update Dialogs
* @ingroup NetworkDialogs
* @brief Dialogs relating to the client updating.
*/
/**
* @defgroup CardDatabaseUpdateDialogs Card Database Update Dialogs
* @ingroup NetworkDialogs
* @ingroup CardDatabaseWidgets
* @brief Dialogs relating to the CardDatabase updating.
*/
/**
* @defgroup ConnectionDialogs Connection Dialogs
* @ingroup NetworkDialogs
* @brief Dialogs relating to the RemoteClient%s connection to a Server.
*/
/**
* @defgroup AccountDialogs Account Dialogs
* @ingroup NetworkDialogs
* @brief Dialogs relating to account information on a Server.
*/
/**
* @defgroup RoomDialogs
* @ingroup NetworkDialogs
* @brief Dialogs relating to a RemoteClient interacting with a Room on a Server.
*/
/**
* @defgroup ServerLogDialogs Server Log Dialogs
* @ingroup NetworkDialogs
* @brief Dialogs relating to a RemoteClient interacting a Server%'s logs.
*/
/**
* @defgroup Tabs Tabs
* @ingroup Widgets
* @brief Tabbed UI components.
*
* Provides tab-based interfaces for organizing and navigating
* between multiple views in the application.
*/
/**
* @defgroup DeckEditorTabs Deck Editor Tabs
* @ingroup Tabs
* @ingroup DeckEditors
* @brief Tabs for the DeckList Editors
*/
/**
* @defgroup NetworkingTabs Networking Tabs
* @ingroup Tabs
* @ingroup NetworkingWidgets
* @brief Tabs related to a RemoteClient interacting with a Server.
*/
/**
* @defgroup ServerTabs Server Tabs
* @ingroup NetworkingTabs
* @brief Tabs related to a Server.
*/
/**
* @defgroup AccountTabs Account Tabs
* @ingroup NetworkingTabs
* @brief Tabs related to user account information.
*/
/**
* @defgroup RoomTabs Room Tabs
* @ingroup NetworkingTabs
* @ingroup RoomWidgets
* @brief Tabs related to a Room on a Server.
*/
/**
* @defgroup MessagingTabs Message Tabs
* @ingroup NetworkingTabs
* @brief Tabs related to users sending messages to each other.
*/
/**
* @defgroup PictureLoader Card Picture Loader
* @ingroup UI
* @ingroup Cards
* @brief The PictureLoader for CardInfoPictureWidget%s and CardItem%s
*/
/* ------------------------------------------------------------------ */
/* Cards */
/* ------------------------------------------------------------------ */
/**
* @defgroup Cards Cards
* @brief Representation of individual cards and their state.
*
* Defines CardInfo and related objects which hold attributes, metadata, and runtime state within
* both the CardDatabase and the Game engine.
*/
/**
* @defgroup CardSets Card Sets
* @ingroup Cards
* @brief CardSet%s.
*/
/**
* @defgroup CardPrintings Card Printings
* @ingroup Cards
* @brief Information about specific printings of CardInfo%s via PrintingInfo and ExactCard.
*/
/**
* @defgroup CardWidgets Card Widgets
* @ingroup Widgets
* @ingroup Cards
* @brief Widgets for CardInfo display and interaction.
*
* Provides UI components that render individual CardInfo%s, handle
* interactions, and display card details within the application.
*/
/**
* @defgroup CardExtraInfoWidgets Card Extra Info Widgets
* @ingroup CardWidgets
* @brief Widgets for displaying additional information about CardInfo%s.
*
* Displays additional data associated with CardInfo%s or data in a different form.
*/
/**
* @defgroup CardDatabase Card Database
* @ingroup Cards
* @brief Core CardDatabase and loaders.
*
* Provides the underlying data models for cards, including loading,
* parsing, and managing the complete CardDatabase used in the application.
*/
/**
* @defgroup CardDatabaseModels Models
* @ingroup CardDatabase
* @brief Qt models for CardDatabase access.
*
* Supplies Qt model abstractions for presenting CardInfo data in views,
* supporting filtering, sorting, and data binding to widgets.
*/
/**
* @defgroup CardDatabaseModelFilters Filters
* @ingroup CardDatabaseModels
* @brief Filters for CardDatabase models.
*
* Provides reusable filtering components for Qt models, enabling
* refined queries and customized CardDatabase views.
*/
/**
* @defgroup CardDatabaseParsers Parsers
* @ingroup CardDatabase
* @brief Parsers for CardInfo data.
*
* Implements parsers for CardDatabase structures, handling the
* transformation of raw data into structured objects and models.
*/
/**
* @defgroup CardDatabaseWidgets Card Database Widgets
* @ingroup Widgets
* @ingroup CardDatabase
* @brief Widgets for browsing and selecting CardInfo%s in the CardDatabase.
*
* Provides UI components for interacting with the CardDatabase,
* including search, filtering, and browsing in tabular or list views.
*/
/**
* @defgroup VisualCardDatabaseWidgets Visual Card Database Widgets
* @ingroup CardDatabaseWidgets
* @brief VisualDatabaseDisplayWidget and related helper classes.
*
* Enhances card browsing with graphical interfaces, offering
* image-based and grid-based views for selecting cards.
*/
/* ------------------------------------------------------------------ */
/* Decks */
/* ------------------------------------------------------------------ */
/**
* @defgroup Decks Deck Management
* @brief DeckList handling, persistence, and tooling.
*
* Covers the lifecycle of DeckList%s: loading, saving, editing, import/export,
* and long-term persistence, including both textual and visual editors.
*/
/**
* @defgroup DeckModels Deck Models
* @ingroup Decks
* @brief Qt Models relating to DeckList.
*/
/**
* @defgroup DeckEditors Deck Editors
* @ingroup Decks
* @brief Editors for creating and modifying a DeckList.
*
* Provides visual and textual editors for building, modifying,
* and analyzing DeckList%s. Includes support for card search,
* sorting, and filtering of DeckList contents.
*/
/**
* @defgroup DeckEditorWidgets Deck Editor Widgets
* @ingroup Widgets
* @ingroup DeckEditors
* @brief Supporting widgets for DeckList editors.
*
* Contains specialized UI components that extend DeckList editors with
* interactive functionality, data views, and user interaction tools.
*/
/**
* @defgroup DeckEditorTabs Deck Editor Tabs
* @ingroup DeckEditorWidgets
* @brief Tabs which implement AbstractTabDeckEditor to provide DeckList editing functionality.
*/
/**
* @defgroup DeckEditorAnalyticsWidgets Deck Editor Analytics Widgets
* @ingroup DeckEditorWidgets
* @brief Widgets for analyzing a DeckList.
*
* Provides visualization and statistical tools for analyzing DeckList%s.
*/
/**
* @defgroup DeckEditorCardGroupWidgets Card Group Display Widgets
* @ingroup DeckEditorWidgets
* @brief Widgets for displaying groups of cards.
*
* Provides interactive views that organize and display cards in groups,
* enabling filtering, sorting, and direct manipulation of DeckList sections.
*/
/**
* @defgroup PrintingWidgets Printing Widgets
* @ingroup DeckEditorWidgets
* @ingroup Widgets
* @brief Widgets for handling PrintingInfo of cards in a DeckList.
*
* Manages the display and editing of card printing information within a DeckList,
* including editions, variations, and preferences.
*/
/**
* @defgroup DeckStorage Deck Storage
* @ingroup Decks
* @brief Systems for storing a DeckList on a local file system or remote service.
*/
/**
* @defgroup LocalDeckStorage Local Deck Storage
* @ingroup DeckStorage
* @brief Systems for storing a DeckList on a local file system.
*
* Handles the persistence of a DeckList, providing file-based storage,
* metadata tracking, and tagging functionality.
*/
/**
* @defgroup LocalDeckStorageWidgets Local Deck Storage Widgets
* @ingroup Widgets
* @ingroup LocalDeckStorage
* @brief Widgets for browsing and managing stored DeckList%s.
*
* Provides list and tree-based views for exploring stored DeckList%s,
* including tagging, searching, and preview functionality.
*/
/**
* @defgroup LocalDeckStorageDialogs Local Deck Storage Dialogs
* @ingroup LocalDeckStorageWidgets
* @ingroup ImportExport
* @ingroup Lobby
* @brief Dialogs related to interacting with DeckList%s on a filesystem or in a remote location.
*/
/**
* @defgroup VisualDeckStorageWidgets Visual Deck Storage Widgets
* @ingroup LocalDeckStorageWidgets
* @brief Visual widgets for DeckList storage.
*
* Offers graphical interfaces for browsing and interacting with a stored
* DeckList and tags, focusing on a more visual browsing experience.
*/
/**
* @defgroup VisualDeckPreviewWidgets Visual Deck Preview Widgets
* @ingroup VisualDeckStorageWidgets
* @brief Widgets for visually previewing a DeckList.
*
* Provides visual previews of a DeckList, allowing users
* to inspect the DeckList name, color identity, and banner card at a glance.
*/
/**
* @defgroup RemoteDeckStorage Remote Deck Storage
* @ingroup DeckStorage
* @brief Systems for storing a DeckList on a remote service.
*/
/**
* @defgroup RemoteDeckStorageWidgets Remote Deck Storage Widgets
* @ingroup Widgets
* @ingroup RemoteDeckStorage
* @ingroup ImportExport
* @ingroup Lobby
* @brief Widgets related to interacting with DeckList%s on a filesystem or in a remote location.
*/
/**
* @defgroup RemoteDeckStorageDialogs Remote Deck Storage Dialogs
* @ingroup RemoteDeckStorageWidgets
* @brief Dialogs related to interacting with DeckList%s on a filesystem or in a remote location.
*/
/**
* @defgroup ImportExport Import/Export
* @ingroup DeckStorage
* @brief DeckList import, export, and conversion.
*
* Supports importing and exporting a DeckList across formats, including
* text, Cockatrice-native formats, and third-party platforms.
*/
/**
* @defgroup Parsing Parsing
* @ingroup DeckStorage
* @brief DeckList parsing and external API integration.
*
* Contains parsers for DeckList URLs and APIs (e.g., TappedOut, Archidekt,
* Moxfield, Deckstats), allowing seamless import and synchronization.
*/
/* ------------------------------------------------------------------ */
/* Game */
/* ------------------------------------------------------------------ */
/**
* @defgroup Game Game
* @brief Core Game framework.
*
* Responsible for the main Game loop, GameState management,
* CardZone handling, and resolution of actions during a Game.
*/
/**
* @defgroup GameUi User Interface
* @ingroup Game
* @brief Graphical components for interaction during a Game.
*
* Provides Qt-based widgets, dialogs, and menus used during a Game,
* supporting both visual presentation and interaction logic.
*/
/**
* @defgroup GameLobby Lobby
* @ingroup GameUi
* @brief User interface for the multiplayer lobby.
*
* Contains widgets, dialogs, and models used to interact with the
* lobby within the Game UI layer.
*/
/**
* @defgroup GameWidgets Game Widgets
* @ingroup Widgets
* @ingroup GameUi
* @brief Widgets specific to the interface in a Game.
*
* Provides reusable visual components that represent elements
* of the ongoing Game, such as a PlayerGraphicsItem or CardZone views.
*/
/**
* @defgroup GameDialogs Dialogs
* @ingroup GameUi
* @brief Dialogs for Game%s.
*
* Modal and non-modal dialogs for Player interaction during a Game,
* including prompts, confirmations, and detailed views.
*/
/**
* @defgroup GameMenus Menus
* @ingroup GameUi
* @brief Menus for Game%s.
*
* Provides menu bars, context menus, and hierarchical options
* available to the Player during a Game session.
*/
/**
* @defgroup GameMenusPlayers Player
* @ingroup GameMenus
* @brief Menus specific to Player actions.
*
* Defines context menus and options relating to Player state and PlayerActions.
*/
/**
* @defgroup GameMenusZones Zones
* @ingroup GameMenus
* @brief Menus for interacting with zones.
*
* Provides contextual options for a CardZone such as the hand,
* library, graveyard, and battlefield.
*/
/**
* @defgroup GameMenusCards Cards
* @ingroup GameMenus
* @brief Menus for CardItem interactions.
*
* Defines right-click menus and contextual options available
* when interacting with an individual CardItem.
*/
/**
* @defgroup GameGraphics Graphics
* @ingroup GameUi
* @brief Visual graphics for Game elements.
*
* Provides rendering and layout for core Game objects such as a
* Player, CardZone, or CardItem in the interface.
*/
/**
* @defgroup GameGraphicsPlayers Players
* @ingroup GameGraphics
* @brief Player-specific graphical elements.
*
* Defines visual representations of a Player, their states,
* and associated on-screen information.
*/
/**
* @defgroup GameGraphicsZones Zones
* @ingroup GameGraphics
* @brief Graphical representations of zones.
*
* Provides layout, visuals, and animations for a CardZone like the hand,
* library, battlefield, and graveyard.
*/
/**
* @defgroup GameGraphicsCards Cards
* @ingroup GameGraphics
* @brief Graphical representation of cards.
*
* Manages the visual look and behavior of a CardItem when displayed
* in the Game interface.
*/
/**
* @defgroup GameLogic Logic
* @ingroup Game
* @brief Game logic and rules framework.
*
* Implements resolution of actions and logical
* state management for an ongoing Game.
*/
/**
* @defgroup GameLogicPlayers Players
* @ingroup GameLogic
* @brief Logic related to Player state.
*
* Handles Player attributes, PlayerActions, resources, and their impact
* on GameState.
*/
/**
* @defgroup GameLogicZones Zones
* @ingroup GameLogic
* @brief Logical handling of CardZones during a Game.
*
* Defines the rules and behaviors of zones such as the hand,
* battlefield, library, and graveyard.
*/
/**
* @defgroup GameLogicActions Actions
* @ingroup GameLogic
* @brief Actions, events, and their resolution.
*
* Encapsulates how actions are created, queued, and resolved,
* including event handling and triggered effects.
*/
/* ------------------------------------------------------------------ */
/* Networking */
/* ------------------------------------------------------------------ */
/**
* @defgroup Network Networking
* @brief Networking components for client/server communication.
*
* Contains all systems related to communication between client and server.
* This includes lobby and room management, server interaction logic, and
* message handling infrastructure based on protobuf.
*/
/**
* @defgroup ApiInterfaces API Interfaces
* @ingroup Client
* @ingroup Parsing
* @ingroup ImportExport
* @brief Interfaces for interacting with various APIs
*/
/**
* @defgroup ApiResponses API Responses
* @ingroup ApiInterfaces
* @brief Structures representing API responses.
*
* Encapsulates the data models for networking API responses,
* providing consistent interfaces for parsing and handling results.
*/
/**
* @defgroup ApiResponseDisplayWidgets API Response Display Widgets
* @ingroup Widgets
* @ingroup ApiResponses
* @brief Widgets for displaying API responses.
*
* Provides user interface components that render and present API response
* data to the user in a structured and interactive way.
*/
/**
* @defgroup Messages Protocol Messages
* @ingroup Network
* @brief Protocol message definitions and handlers.
*
* Contains the generated protobuf messages and supporting code used
* to encode, decode, and process communication between client and server.
*/
/**
* @defgroup Client Client
* @ingroup Network
* @brief The Cockatrice client application.
*
* Handles all client-side communication with the server.
*/
/**
* @defgroup NetworkingWidgets Networking Widgets
* @ingroup Widgets
* @ingroup Client
* @brief Widgets related to a RemoteClient interacting with a Server.
*/
/**
* @defgroup ClientUpdates Client Updates
* @ingroup Client
* @brief Client updates.
*/
/**
* @defgroup Server Server
* @ingroup Network
* @brief The Cockatrice server application.
*
* Provides the authoritative game backend, handling authentication,
* lobbies, game rooms, and relaying state between connected clients.
*/
/**
* @defgroup RoomWidgets Room Widgets
* @ingroup Widgets
* @ingroup Client
* @brief Server room management.
*
* Manages creation and interaction of Game lobbies and room state synchronization with the server.
*/
/* ------------------------------------------------------------------ */
/* Replay */
/* ------------------------------------------------------------------ */
/**
* @defgroup Replay Replays
* @brief Replay recording and playback.
*
* Provides mechanisms for capturing Game sessions, storing them in
* replay files, and replaying them for review or analysis.
*/
/* ------------------------------------------------------------------ */
/* Settings */
/* ------------------------------------------------------------------ */
/**
* @defgroup Settings Settings
* @brief Application settings and configuration.
*
* Centralizes the configuration system, providing persistence and
* runtime access to user preferences and application options.
*/
/**
* @defgroup SettingsWidgets Settings Widgets
* @ingroup Widgets
* @ingroup Settings
* @brief TODO: Document this
*/
/**
* @defgroup CoreSettings Core Settings
* @ingroup Settings
* @brief TODO: Document this
*/
/**
* @defgroup NetworkSettings Network Settings
* @ingroup Settings
* @brief TODO: Document this
*/
/**
* @defgroup GameSettings Game Settings
* @ingroup Settings
* @brief TODO: Document this
*/
/**
* @defgroup CardSettings Card Settings
* @ingroup Settings
* @brief TODO: Document this
*/
/**
* @defgroup DeckSettings Deck Settings
* @ingroup Settings
* @brief TODO: Document this
*/
/* ------------------------------------------------------------------ */
/* Tests */
/* ------------------------------------------------------------------ */
/**
* @defgroup Tests Tests
* @brief Automated testing framework.
*
* Provides unit tests, integration tests, and regression checks
* to ensure stability and correctness of the Cockatrice codebase.
*/
+27
View File
@@ -0,0 +1,27 @@
<!-- HTML footer for doxygen 1.14.0-->
<!-- start footer part -->
<script src="$relpath^graph_toggle.js"></script>
<!--BEGIN GENERATE_TREEVIEW-->
<div class="navpath" id="nav-path"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby <a href="https://www.doxygen.org/index.html"><img alt="doxygen"
class="footer"
height="31" src="$relpath^doxygen.svg"
width="104"/></a>
$doxygenversion
</li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/>
<address class="footer"><small>
$generatedby&#160;<a href="https://www.doxygen.org/index.html"><img alt="doxygen" class="footer"
height="31" src="$relpath^doxygen.svg" width="104"/></a>
$doxygenversion
</small></address>
</div><!-- doc-content -->
<!--END !GENERATE_TREEVIEW-->
</body>
</html>
+81
View File
@@ -0,0 +1,81 @@
<!-- HTML header for doxygen 1.14.0-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="$langISO" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/xhtml;charset=UTF-8" http-equiv="Content-Type"/>
<meta content="IE=11" http-equiv="X-UA-Compatible"/>
<meta content="Doxygen $doxygenversion" name="generator"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<!--BEGIN PROJECT_ICON-->
<link href="$relpath^$projecticon" rel="icon" type="image/x-icon"/>
<!--END PROJECT_ICON-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<!--BEGIN FULL_SIDEBAR-->
<script type="text/javascript">var page_layout = 1;</script>
<!--END FULL_SIDEBAR-->
<script src="$relpath^jquery.js" type="text/javascript"></script>
<script src="$relpath^dynsections.js" type="text/javascript"></script>
<!--BEGIN COPY_CLIPBOARD-->
<script src="$relpath^clipboard.js" type="text/javascript"></script>
<!--END COPY_CLIPBOARD-->
$treeview
$search
$mathjax
$darkmode
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css"/>
$extrastylesheet
</head>
<body>
<!--BEGIN FULL_SIDEBAR-->
<div class="ui-resizable side-nav-resizable" id="side-nav"><!-- do not remove this div, it is closed by doxygen! -->
<!--END FULL_SIDEBAR-->
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr id="projectrow">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img $logosize alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME-->
<td id="projectalign">
<div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber">&#160;$projectnumber</span>
<!--END PROJECT_NUMBER-->
</div>
<!--BEGIN PROJECT_BRIEF-->
<div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td>
<div id="projectbrief">$projectbrief</div>
</td>
<!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME-->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<!--BEGIN !FULL_SIDEBAR-->
<td>$searchbox</td>
<!--END !FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
<!--BEGIN SEARCHENGINE-->
<!--BEGIN FULL_SIDEBAR-->
<tr>
<td colspan="2">$searchbox</td>
</tr>
<!--END FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

+147
View File
@@ -0,0 +1,147 @@
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".memdoc").forEach(memdoc => {
let callContent = null, callHeader = null;
let callerContent = null, callerHeader = null;
memdoc.querySelectorAll("div.dynheader").forEach(header => {
const text = (header.textContent || "").trim().toLowerCase();
let content = header.nextElementSibling;
let tries = 0;
while (content && !content.classList.contains("dyncontent") && tries < 8) {
content = content.nextElementSibling;
tries++;
}
if (!content) return;
if (text.includes("caller")) {
callerContent = content;
callerHeader = header;
} else if (text.includes("call graph") || text.includes("callgraph") || text.includes("call graph for")) {
callContent = content;
callHeader = header;
} else if (text.includes("call")) {
if (!callContent) {
callContent = content;
callHeader = header;
}
}
});
if (!callContent && !callerContent) return;
if (memdoc.querySelector(".graph-toggle")) return;
const toggle = document.createElement("div");
toggle.className = "graph-toggle";
const callerBtn = document.createElement("button");
callerBtn.type = "button";
callerBtn.textContent = "Caller Graph";
const callBtn = document.createElement("button");
callBtn.type = "button";
callBtn.textContent = "Call Graph";
toggle.appendChild(callerBtn);
toggle.appendChild(callBtn);
const firstHeader = memdoc.querySelector("div.dynheader");
memdoc.insertBefore(toggle, firstHeader || memdoc.firstChild);
// hide everything initially
if (callerContent) {
callerContent.style.display = "none";
callerHeader.style.display = "none";
}
if (callContent) {
callContent.style.display = "none";
callHeader.style.display = "none";
}
// disable missing buttons
if (!callerContent) {
callerBtn.disabled = true;
callerBtn.classList.add("disabled");
}
if (!callContent) {
callBtn.disabled = true;
callBtn.classList.add("disabled");
}
// track current state
let current = null; // "caller", "call", "both", null=hidden
function setActive(type) {
if (type === "caller") {
if (current === "caller") { // hide it
if (callerContent) {
callerContent.style.display = "none";
callerHeader.style.display = "none";
}
current = null;
} else if (current === "call") { // show both
if (callerContent) {
callerContent.style.display = "block";
callerHeader.style.display = "block";
}
current = "both";
} else if (current === "both") { // hide caller only → call only
if (callerContent) {
callerContent.style.display = "none";
callerHeader.style.display = "none";
}
current = "call";
} else { // nothing visible → show caller
if (callerContent) {
callerContent.style.display = "block";
callerHeader.style.display = "block";
}
if (callContent) {
callContent.style.display = "none";
callHeader.style.display = "none";
}
current = "caller";
}
} else if (type === "call") {
if (current === "call") { // hide it
if (callContent) {
callContent.style.display = "none";
callHeader.style.display = "none";
}
current = null;
} else if (current === "caller") { // show both
if (callContent) {
callContent.style.display = "block";
callHeader.style.display = "block";
}
current = "both";
} else if (current === "both") { // hide call only → caller only
if (callContent) {
callContent.style.display = "none";
callHeader.style.display = "none";
}
current = "caller";
} else { // nothing visible → show call only
if (callContent) {
callContent.style.display = "block";
callHeader.style.display = "block";
}
if (callerContent) {
callerContent.style.display = "none";
callerHeader.style.display = "none";
}
current = "call";
}
}
// update button styles
callerBtn.classList.toggle("active", current === "caller" || current === "both");
callBtn.classList.toggle("active", current === "call" || current === "both");
}
callerBtn.addEventListener("click", () => {
if (!callerBtn.disabled) setActive("caller");
});
callBtn.addEventListener("click", () => {
if (!callBtn.disabled) setActive("call");
});
});
});