Compare commits

...

354 Commits

Author SHA1 Message Date
RickyRister
08bb18cefe Fix VDS filters not applying after refresh (#5662)
* reapply sort and filters after each reset

* fix unflatten folder still not applying afterwards
2025-03-05 00:57:28 +00:00
RickyRister
ecbdd32a2d Reduce redundant recursion in VDS (#5664)
* remove recursion from flattenFolderStructure

findChildren is already recursive by default

* only trigger the top-level updateVisibility on filter update

Every folder widget was connecting the filter update signals to their updateVisibility, but updateVisibility is already recursive.
That means a bunch of redundant updateVisibility calls happen every time a filter update signal is emitted

* reduce redundant recursion in updateVisibility

findChildren is recursive by default, so only the top-level updateVisibility needs to loop through the found children

* delete now-unused signals
2025-03-05 00:56:31 +00:00
RickyRister
2f415dcc6e Add action to Edit Deck via Clipboard (#5681)
* implement functionality in dlg

* add action to deck editor

* refactor and comments

* is this refactor even a good idea?

* remove the friend class stuff

* reorder

* add option for not annotated
2025-03-05 00:55:05 +00:00
BruebachL
8fc1b22889 Use the new mana symbols. (#5687)
* Use the new mana symbols.

* Fixup some thangs.

* Lint.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-05 00:53:42 +00:00
BruebachL
85a50ce9d5 Generic mana symbols. (#5685)
* Generic mana symbols.

* Update black mana symbol skull and symbol color.

* Update white mana symbol contrast.

* Update black mana symbol contrast.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-03 13:12:09 -05:00
BruebachL
b706e26a32 Fix image quality when fractional scaling is applied. (#5684)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-03 08:40:12 -05:00
BruebachL
15725c67c7 Fix banner widget buddy being uninitialized. (#5686)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-03 08:38:27 -05:00
RickyRister
d8da4473e2 add rename and delete actions to VDS right-click menu (#5683) 2025-03-03 08:35:50 -05:00
RickyRister
e1964f21de Fix memory leaks from DeckLoader usage (#5665)
* add comment

* stack allocate DeckLoader for loading tags

* deckModel now takes ownership of DeckLoader

* fix remaining

* add comment
2025-03-02 18:57:30 -05:00
RickyRister
87c5d07807 Switch current tab when opening a single-instance tab (#5651) 2025-03-02 09:30:55 -05:00
lilyhuang-github
3d0f4868df Focus tab for quit game dialog (#5670) 2025-03-02 09:29:17 -05:00
BruebachL
56bd11794e Set modification state correctly. (#5678)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-02 09:28:16 -05:00
BruebachL
e541b9d572 Silence picture loader warnings for null pixmaps by introducing checks. (#5677)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-02 09:27:52 -05:00
RickyRister
a7e8c1f59b Make BannerWidget's dropdown icon more robust (#5676)
* Make BannerWidget's dropdown icon more robust

* use isHidden

Otherwise, it doesn't work correctly if the BannerWidget is offscreen

* don't show icon if there's no buddy
2025-03-02 09:26:03 -05:00
BruebachL
ec452aabe2 Fallback to regular card name search in case the providerId one fails for the database display widget. (#5673)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-03-01 09:22:00 -05:00
RickyRister
2a9599eed8 refactor saveDeckToClipboard in AbstractTabDeckEditor (#5671)
* refactor saveDeckToClipboard in AbstractTabDeckEditor

* make deckloader functions const

* use const

* move method into DeckLoader
2025-03-01 09:21:31 -05:00
RickyRister
58a2b7ff39 Fix move to top of library shuffling an extra card (#5672)
* Fix move to top of library shuffling an extra card

* Update cockatrice/src/game/player/player.cpp

---------

Co-authored-by: ebbit1q <ebbit1q@gmail.com>
2025-03-01 13:32:07 +01:00
RickyRister
448903efe3 Add tip of the day for Expand Card View Window (#5666) 2025-02-28 11:29:09 -05:00
BruebachL
d76e8f9146 Clamp all DeckPreviewWidget children to the card size on resize. (#5669)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-28 11:10:40 -05:00
BruebachL
3620664a9f Cache correct providerId cards on deck load (#5668)
* Implement new method for DeckList to return cardlist with providerId, a new carddatabase method to fetch a cardlist with name and providerId and changed PictureLoader to use providerId versions of cards for caching.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-28 11:10:06 -05:00
lilyhuang-github
7ff43f15fc Add hint on version downloading (#5663) 2025-02-27 23:34:32 -05:00
lilyhuang-github
e271e6ecf8 Implement advertisement to FAQ page align right (#5657) 2025-02-27 23:34:06 -05:00
BruebachL
93d28717e0 Abstract deck editor (#5646)
* Generify TabDeckEditor.

* Connect dockTopLevelChanged signals.

* Connect eventFilters.

* Remove comments.

* Fix ze build (accidentally deleted a line)

* Fix some pointer chaining.

* Be a lot saner about some signals/slots, as in, individual Deck Editor widgets now internally determine their CardInfo and then simply communicate this to the DeckEditor

* Lint.

* DeckDock can handle its own menu.

* DeckDock can handle its own decrement.

* DeckDock now notifies the deck editor on deck change, instead of individually modifying menu items and modification status.

* Rename.

* Include pixelmap generator for icon.

* Directly use an AbstractTabDeckEditor as parent.

* Move clearing database filter into signal/slot relation.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-27 10:57:58 -05:00
RickyRister
6df97a156f Change "include folder name in VDS search" into a setting (#5659)
* add new setting

* implement thing
2025-02-26 12:01:30 -05:00
BruebachL
05d06f9016 Sort Tags in TagFilterWidget (#5660)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-26 11:59:59 -05:00
RickyRister
e8574641b0 use new rename icon in replays tab (#5658) 2025-02-26 00:14:27 -05:00
RickyRister
9ac13018c6 include folder name in VDS search when folders are enabled (#5637) 2025-02-25 18:39:34 -05:00
RickyRister
06b25f1cfc add "edit tags" to VDS right-click menu (#5631)
* refactor: move openTagEditDlg up a level

* add edit tags to menu

* set DeleteOnClose attribute on menu

* fix build failure
2025-02-25 18:38:55 -05:00
RickyRister
6f5d369416 Add folder dropdown icons to VDS (#5632)
* add svg

* update pixmap cache

* get icon to work

* hide icon when not clickable

* use consistent naming

* use expandOnly because apparently that leads to higher image quality
2025-02-25 18:36:48 -05:00
RickyRister
4543038fd8 add "open in deck editor" to VDS right-click menu (#5634) 2025-02-25 18:35:56 -05:00
RickyRister
345f8b772c show error message when open deck fails in VDS (#5642) 2025-02-25 18:33:16 -05:00
RickyRister
47311b1dfd Expand/shrink card view window on double click (#5652) 2025-02-25 18:32:45 -05:00
RickyRister
21e22ed5fb Destroy VDS in game lobby once game starts (#5643)
* push back setting change

* rename method and make it public

* destroy vds on game start
2025-02-25 18:31:44 -05:00
RickyRister
0d6497fcdc Fix banner card changing when opening deck in new tab (#5649) 2025-02-25 18:30:53 -05:00
RickyRister
bfaeeb5aea fix transform from non-table zones not moving card (#5648) 2025-02-25 18:30:38 -05:00
RickyRister
b46667f6db Fix memory leak when refreshing VDS (#5647)
* parent deckLoader

* leave comment
2025-02-25 18:30:20 -05:00
RickyRister
49932ee6f8 Fix segfault when oracle reads card without "num" field (#5654) 2025-02-25 18:29:43 -05:00
RickyRister
57e37e8f4d Allow loading local xml file in oracle (#5655) 2025-02-25 18:29:27 -05:00
RickyRister
af68a95964 Add rename action to deck storage tab (#5656)
* add icon

* add rename action
2025-02-25 18:29:07 -05:00
RickyRister
959a268f91 Mark deck as modified when banner card is changed (#5641)
* Mark deck as modified when banner card is changed

* set modified inside setBannerCard
2025-02-22 13:56:48 +00:00
RickyRister
77a3515470 Always download macOS 13 version on intel macs (#5630)
* Always download macOS 13 version for intel macs

* use contains instead of regex
2025-02-18 22:27:17 +00:00
BruebachL
6a008acb2b Enhance card update error description. (#5638)
* Enhance card update error description.

* Enhance card update error description.

* Lint.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-18 22:20:06 +00:00
RickyRister
247e1aff83 Also parse "colors" field in xml (#5635) 2025-02-18 20:04:59 +00:00
RickyRister
3df4efebaa Revert file watcher in VDS (#5636) 2025-02-18 20:04:37 +00:00
RickyRister
5c8d1f3cff Make AttachTo tokens work from non-table zones (#5629)
* move card to play before creating attached token

* leave comment

* hardcode createCard target zone to table

To get attached token from graveyard/exile to work
2025-02-16 17:02:45 -05:00
Zach H
01d5e58a5f Change Sorting Order of User List (#5626)
* 1) Online Users > Offline Users
* 2) Admins, judge/vip/donator status ignored
* 3) Moderators, judge/vip/donator status ignored
* 4) Judges
* 5) VIPs
* 6) Donators
* 7) Everyone else
2025-02-16 04:35:28 +00:00
RickyRister
a28300ac42 add "save deck to clipboard" to VDS right click menu (#5625) 2025-02-16 04:18:47 +00:00
RickyRister
0666483756 refactor saveDeckToClipboard in TabDeckEditor (#5623) 2025-02-16 02:43:44 +00:00
RickyRister
abca5514af support right-click menu in VDS (#5622)
* support right-click menu in VDS

* move methods around
2025-02-16 02:43:20 +00:00
RickyRister
2247c66ea6 refactor how double click signal gets passed up in VDS (#5621) 2025-02-15 19:06:11 -05:00
RickyRister
3b638598ad fix load remote deck window being empty (#5613) 2025-02-15 21:05:33 +00:00
RickyRister
63e3e3ceb1 refactor and add missing log categories to ReleaseChannel (#5615)
* adding missing log categories

* refactor version lookup

* refactor OS checking code
2025-02-15 21:05:12 +00:00
BruebachL
23f4c9c4e4 Tags in deck editor (#5608) 2025-02-12 03:18:00 +00:00
Zach H
356b00e8c7 Fix Ricky Crash (#5609) 2025-02-12 01:39:41 +00:00
RickyRister
8916e049bd fix printing selector dropdown not working on mac (#5606) 2025-02-11 04:42:31 +00:00
ZeldaZach
287b4a5597 Bump to 2.10.1 2025-02-10 23:26:35 -05:00
RickyRister
d77ee00e70 Fix crash when VDS show tags is unchecked (#5605)
* Fix crash when VDS show tags is unchecked

* revert the refactor since I don't know if there's a reason they did it that way
2025-02-11 04:24:08 +00:00
ZeldaZach
18ac4c2bd4 Set Release Name: Omenpath 2025-02-10 16:41:18 -05:00
Zach H
2dc614c6b7 Add new Tips of the Day (#5603)
- Thanks WargiCorgi!
2025-02-10 21:22:26 +00:00
BruebachL
7c9bf75393 Overhaul quick settings for VDS and PrintingSelector (#5602)
* Move show folders option next to the search bar.

* Add a new settings button and settings popup, move the folder visibility checkbox there and the ability to hide tags.

* Make popup not close when interacting with child widgets.

* Fix mocks.

* Include cog icon.

* Move PrintingSelector Display options to new quick settings widget.

* Adjust size before first show so as to not overflow.

* Add option to hide card size slider in VDS.

* Qt5 support.

* Fix some warnings by containerizing layouts because addChildLayout is silly.

* Fix an incorrect slot/signal assignment.

* Correct sub-categories for settings to persist them.

* Shuffle some slots and signals around to distinguish between the tag filter and the tags on the deck preview widgets.

* Add a quick setting to draw unused color identities and center them.

* Respect the setting on startup.

* Move card size slider to the quick settings menu.

* Move PrintingSelector card size slider to quick menu, adjust other layout from other options.

* Improve layout, add a gray border.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-10 16:50:08 +00:00
transifex-integration[bot]
d1102939a2 Translate cockatrice_en@source.ts in pt_BR (#5601)
100% translated source file: 'cockatrice_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-09 22:12:38 +00:00
Zach H
cb060f43b5 Prevent server crash if DB is down and game is attempted to be created (#5600) 2025-02-09 22:11:00 +00:00
transifex-integration[bot]
80bd783d54 Updates for project Cockatrice and language de (#5595)
* Translate cockatrice/cockatrice_en@source.ts in de

100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'de'.

* Translate cockatrice/cockatrice_en@source.ts in de

100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'de'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-02-09 19:16:27 +01:00
tooomm
82b147d235 uniform artifact naming (#5592) 2025-02-09 12:40:07 +00:00
Zach H
6944f5f81c Put Logging config on MacOS (#5591) 2025-02-09 12:39:09 +00:00
danbopes
8cbfe85ed4 Fix db reconnecting issues (#5590)
See:

c1b0d50237 (diff-02a32f437187bd4cbfab74877100fee0cfc669dab2c05418681a3557c2cf73f2R109)

We should be checking to see if the query is notActive. In this case, we're literally closing and reopening the connection to the database every time `checkSql()` is called, which is called in numerous places.
2025-02-09 12:12:16 +00:00
Zach H
eb2c71d381 Fix MacOS Finding releases (#5589) 2025-02-09 02:26:04 -05:00
RickyRister
86161185d9 Use local-aware compare in VDS file name sort (#5588) 2025-02-09 04:38:48 +00:00
RickyRister
79bf3adb2a Re-sort decks in VDS after toggling show folders (#5587) 2025-02-09 04:38:22 +00:00
Zach H
07ca243d48 Update QT_LOGGING_CONF if not set (#5578) 2025-02-08 16:10:45 +00:00
Zach H
edaca772c5 Support logging config on install (#5577)
* Support logging config on install

* Support logging config on install
2025-02-08 16:10:37 +00:00
ZeldaZach
b30b72b7c3 Fix building & logging out 2025-02-07 14:19:53 -05:00
RickyRister
57eab3d48a turn off flow_widget logger (#5576) 2025-02-07 15:36:41 +00:00
RickyRister
2c6e7d4d3a Add option to hide folder structure in Visual Deck Storage (#5575) 2025-02-07 15:36:24 +00:00
RickyRister
9ec621a1ae fix wrong size flag bounding rect on linux (#5573)
* fix flag bounding box on linux

* use the non-deprecated macro
2025-02-07 06:21:56 +00:00
RickyRister
23223e10b5 actually delete VDS when hiding it in game lobby (#5572) 2025-02-07 05:20:42 +00:00
github-actions[bot]
94129607e5 Update translation source strings (#5571)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-07 04:59:23 +00:00
RickyRister
d951b082c4 Add setting to hide visual deck storage in game lobby (#5570) 2025-02-06 13:44:33 +00:00
RickyRister
1ee0e87ba7 remove debug log that was accidentally left in (#5569) 2025-02-06 13:43:37 +00:00
Zach H
67091fff9c Fixup custom theme image loading (#5568) 2025-02-06 13:40:10 +00:00
Zach H
9b4f51d1e4 Increase Icon Size in User Lists (#5567) 2025-02-06 05:51:19 +00:00
Zach H
a6649d5401 Add Judge Pawns (+ Resize Donator Pawns) (#5566) 2025-02-06 05:51:01 +00:00
RickyRister
b509eed3e0 support shortcuts for tab menu actions (#5564)
* support shortcuts for tab menu actions

* refactor

* add migration
2025-02-06 04:00:43 +00:00
RickyRister
12ae7a9eeb Ignore unknown shortcut names in settings (#5565) 2025-02-06 04:00:31 +00:00
fluidvanadium
e6e3333673 Deck limit (#5559)
* increased MAX_FILE_LENGTH

* set MAX_FILE_LENGTH to about 2 megabytes
2025-02-04 22:22:15 +00:00
RickyRister
218ed726b6 Fix wrong position and scaling of svg pixmaps when zoomed out (#5563)
* fix scaling for player icon profile pic

* fix scaling for other svgs
2025-02-04 22:22:05 +00:00
RickyRister
0503fe589c fix playericon missing in local games (#5562) 2025-02-04 05:53:52 +00:00
Zach H
e599c6bdac Mods/Admins/PrivLevels not subject to server idle timeout policy (#5561) 2025-02-04 05:20:20 +00:00
Zach H
c2292c11a6 Support Purple Heart for Donators (#5560) 2025-02-04 05:06:05 +00:00
RickyRister
ec9feb9f50 fix wrong size flag bounding rect on windows (#5556)
* fix wrong size flag bounding rect on windows

* fix the values
2025-02-03 05:43:58 +00:00
RickyRister
9680e47bbc Deprecate userlevels icons (#5555)
* map old info to colors

* move caching up a level

* delete userlevels folder

* remove default vip color
2025-02-03 05:43:48 +00:00
RickyRister
f782bd709a preserve image quality when scaling svg (#5554)
* preserve image quality when scaling svg

* fix missing colorless counter

* do it in a way that doesn't cause warnings to be logged
2025-02-03 02:50:21 +00:00
RickyRister
c00b41f3bd add logging category for remote_client (#5553)
* add logging category for remote_client

* remove ifdef QT_DEBUG
2025-02-03 01:57:34 +00:00
BruebachL
94e2d64e55 Update sort order on VDS load. (#5552)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-02 20:16:38 +00:00
Zach H
4535a70b57 Define qtlogging.ini location (#5551) 2025-02-02 19:27:14 +00:00
BruebachL
6c1b7c83ec Debounce writing the setting to cache when adjusting card sizes. (#5550)
* Debounce writing the setting to cache when adjusting card sizes.

* Lint.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-02 18:45:26 +00:00
Zach H
f0adafb275 Reconnect Servatrice if DB Connection Dies (#5548) 2025-02-02 18:25:01 +00:00
BruebachL
9dd60d74d1 Hotfix VDS sizing scrollArea widget incorrectly when created while not visible by setting size in showEvent (#5547)
* Only resize on folder widget to make sure it doesn't squish the loading indicator.

* Clamp scrollArea widget to viewport width on showEvent to prevent widget being instantiated with wrong width when not visible.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-02-02 17:36:56 +00:00
RickyRister
1de09deb59 Fix size and image quality issues with new user icons (#5546) 2025-02-02 15:08:23 +00:00
BruebachL
a0b52ce450 Implement folder support for VDS. (#5545) 2025-02-02 15:08:04 +00:00
RickyRister
95cea0f191 Add custom server-side pawn colors (#5543) 2025-02-02 03:25:25 +00:00
RickyRister
0fc05e15cd pass ServerInfo_User down the chain (#5542) 2025-02-02 01:04:49 +00:00
RickyRister
26c0cdc072 Make settings window scrollable (#5539) 2025-02-01 05:03:30 +00:00
RickyRister
b1b48d50f3 move deck conversion settings into deck settings group (#5538) 2025-02-01 04:32:12 +00:00
Zach H
349c18aa6a Fix Crash with "c:" in deck editor (#5537) 2025-02-01 04:32:01 +00:00
Zach H
b956fd4bac Fix windows deck searching (#5536) 2025-02-01 04:13:46 +00:00
RickyRister
34e0130b90 fix view transform button disappearing on click (#5535) 2025-02-01 03:31:09 +00:00
BruebachL
33d8edeb9a Get file format from name. (#5532)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-27 19:41:29 -05:00
RickyRister
5d1e905255 remove refreshTree call in remote model's constructors (#5533) 2025-01-27 19:40:59 -05:00
RickyRister
51c542aa04 Disable add to deck submenu if no deck editor tabs are open (#5530)
* refactor

* just have the deck name

* clean up submenu parenting

* disable add to deck menu if no deck editor tabs are open
2025-01-26 10:24:09 -05:00
BruebachL
4d791f4d7a Edhrec tab (#5512)
---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: Zach H <zahalpern+github@gmail.com>
2025-01-25 22:29:27 +00:00
RickyRister
aee68f8b00 add missing override and explicit specifiers in common (#5527) 2025-01-25 14:06:03 +00:00
RickyRister
b911ea6e28 add missing override and explicit specifiers in src/server (#5526) 2025-01-25 14:05:25 +00:00
RickyRister
a41e7c75c1 add missing override and explicit specifiers in src/deck and src/utility (#5525)
* add missing override and explicit specifiers in src/deck

* add missing override and explicit specifiers in src/utility
2025-01-25 14:05:00 +00:00
RickyRister
9f729bf636 add missing override and explicit specifiers in src/dialogs (#5524) 2025-01-25 14:04:26 +00:00
RickyRister
42e4c14a82 add missing override and explicit specifiers in src/client (#5523) 2025-01-25 14:03:54 +00:00
Zach H
37a0c00b3f Support right-click on game list menu (#5522) 2025-01-25 14:03:29 +00:00
Zach H
f6c31bf901 Invert "Show" games, so all games are visible by default (#5521) 2025-01-25 07:03:36 +00:00
Zach H
b48fe8b99c Better capitalization & Deck open first (#5520) 2025-01-25 05:45:44 +00:00
RickyRister
19b758591b Allow offline Replays tab (#5519) 2025-01-25 05:44:48 +00:00
Zach H
ec6a23de56 Support more indices (#5505)
* Support more indices

* Support more indices
2025-01-25 04:16:41 +00:00
BruebachL
ce416df3fb Add a dialog to prompt user to convert to .cod format if trying to apply tags to a .txt deck. (#5514)
* Add a dialog to prompt user to convert to .cod format if trying to apply tags to a .txt deck.

* Lint mocks.

* Address comments, move dialog to appropriate folder.

* Unlint.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-25 03:20:30 +00:00
BruebachL
4e96157091 Flow Layout fixes (#5515)
* Flow Layout fixes.

* Remove some comments.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-25 03:17:39 +00:00
RickyRister
f428148f64 Allow offline Deck Storage tab (#5518)
* make deck storage tab no longer close on disconnect

* add method for clearing remote decklist model

* handle connect/disconnect in deck storage tab
2025-01-25 03:16:40 +00:00
RickyRister
e8b1e3ef0c don't autoclose card view if single card gets dragged into same zone (#5517)
* rename canResize param to toNewZone

* pass toNewZone down

* don't autoclose card view if card gets dragged into same zone
2025-01-25 02:08:28 +00:00
RickyRister
085f0dd26c reduce unnecessary CardItem creation in ViewZone addCard process (#5513) 2025-01-24 05:13:08 +00:00
BruebachL
1d2ab8d3d3 Convert lastLoaded timestamp into proper QDateTime for correct comparison. (#5506)
* Convert lastLoaded timestamp into proper QDateTime for correct comparison.

* Reintroduce null check.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-22 12:58:19 +00:00
RickyRister
66e2e7a473 add missing override and explicit specifiers to all classes in src/game (#5511) 2025-01-22 12:57:56 +00:00
RickyRister
af161f00b7 Remove spacing in CardInfoWidget caused by invisible view transformation button (#5510) 2025-01-22 12:55:21 +00:00
RickyRister
420cca2402 fix after merge to use ZoneView::close (#5509) 2025-01-20 22:43:05 -05:00
RickyRister
97fdf11c8f Add setting to auto close card view when empty (#5502) 2025-01-21 03:08:01 +00:00
RickyRister
aeb1b9fb4f Fix segfault when game is closed while card view window is open (#5507) 2025-01-21 03:06:55 +00:00
RickyRister
b004e91aa4 fix segfault when bottoming card in deck view (#5508) 2025-01-21 03:06:00 +00:00
Zach H
090cc8c144 Support more indices (#5503) 2025-01-20 01:42:24 -05:00
tooomm
0467fae51b Add label to swap button (#5501) 2025-01-19 17:26:25 +00:00
BruebachL
aa24502129 Move logging from QDebug to QCDebug and introduce LoggingCategories. (#5491)
* Move logging from QDebug to QCDebug and introduce LoggingCategories.

* Lint.

* Unlint like one change.

* Remove .debug category since this is autofilled by Qt and used to differentiate between QCDebug and QCWarning and QCError.

* Uncomment defaults, include main category.

* Make PictureLoader logging a bit more useful.

* Lint...?

* Address comments.

* Clean up some unnecessary classes in logging statements.

* Add a new message format to the logging handler.

* Lint.

* Lint.

* Support Windows in Regex

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: ZeldaZach <zahalpern+github@gmail.com>
2025-01-19 13:14:23 +00:00
BruebachL
e752578d15 Add a button to easily view the transformed version of a card. (#5498)
* Add a button to easily view the transformed version of a card.

* Minor reword

* Minor fix

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: ZeldaZach <zahalpern+github@gmail.com>
2025-01-19 12:59:53 +00:00
BruebachL
724db755af Hide load from remote button in local games (#5499)
* Hide load from remote button in local games.

* Minor fix

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: ZeldaZach <zahalpern+github@gmail.com>
2025-01-19 12:59:33 +00:00
BruebachL
ec0caaf421 Give deckList a signal to emit when the tags change and hook up the display widget to that. (#5497)
* Give deckList a signal to emit when the tags change and hook up the display widget to that.

* Reload from file when loading a visual deck to ensure latest changes propagate to the decklist.

* Eliminate loadVisualDeck and use loadDeckFromFile instead.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-19 12:32:39 +00:00
Zach H
55b490ade0 Generate PDBs for Windows Builds (#5494) 2025-01-18 07:54:01 +00:00
ZeldaZach
1392bdd258 Fix Windows 7 Crash Dump 2025-01-18 00:33:30 -05:00
Zach H
648c96ac3d Allow Moderators to Grant Replay & Activate in TabAdmin (#5492) 2025-01-18 02:23:24 +00:00
Zach H
d3a1538af3 Fix Windows Crash Reporter (#5493)
* Fix Windows Crash Reporter

* Fix NSIS template
2025-01-18 02:23:05 +00:00
RickyRister
2bc71095dd get UserListProxy from TabSupervisor instead of passing it in the constructor (#5490) 2025-01-17 15:27:52 +00:00
RickyRister
92a903b035 fix chat messages not showing in the client (#5489) 2025-01-17 03:11:13 -05:00
transifex-integration[bot]
cd373edf3d Translate cockatrice_en@source.ts in pt_BR (#5487)
100% translated source file: 'cockatrice_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-17 07:41:59 +00:00
RickyRister
ca2d438cda fix sideboard not being re-locked on load deck (#5486) 2025-01-17 05:25:01 +00:00
RickyRister
c148c8df7f replace foreach macro with standard for each loop (#5485) 2025-01-17 05:18:15 +00:00
Zach H
0cbad25385 General Cleanup of Unused Assets (#5484) 2025-01-17 05:08:53 +00:00
ZeldaZach
7b94d5d501 Better sanitization of pointers 2025-01-17 00:05:08 -05:00
RickyRister
ee938342f3 Change visible buttons in game lobby depending on if deck is loaded (#5480)
* rename method

* delete unused method

* refactor

* increase margins

* change visible buttons depending on if deck is loaded

* correctly send the ReadyStart command on unload

* fix force start button still being visible
2025-01-17 04:52:33 +00:00
Zach H
cb64a5eea0 Populate TabAccount if reopened (#5483) 2025-01-17 04:28:18 +00:00
BruebachL
80165c28a9 Add options to include/exclude set name and collector number during clipboard import/export. (#5482)
* Add options to include/exclude set name and collector number during clipboard import/export.

* Missing parentheses in action label.

* Revert the silliest lint in the world.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-17 02:38:01 +00:00
ZeldaZach
315c224f24 Fix crash on add/edit tags 2025-01-16 00:54:34 -05:00
ZeldaZach
55f624b634 Hide Loading Msg in VDE when not relevant 2025-01-16 00:06:25 -05:00
ZeldaZach
82b257b589 Fix index 0 tab not functioning 2025-01-15 23:55:51 -05:00
RickyRister
a51ca9f9cb fix incorrect values in deck editor tab's views menu on init (#5479) 2025-01-16 04:06:56 +00:00
RickyRister
7e19b52926 fix tab-specific menus not present when tab is opened on startup (#5478) 2025-01-16 04:04:15 +00:00
RickyRister
2d02955f8b delete overloaded signal in PendingCommand (#5477)
* remove overloaded signal since no one was using it

* remove usages of qOverload

* turns out new slot/signal syntax can ignore extra params
2025-01-15 13:16:06 +00:00
RickyRister
3a740f0bde group printings together when sorting in card reveal window (#5476) 2025-01-15 13:14:47 +00:00
RickyRister
455d68f9ea Move UserlistProxy to src/server/user and fix capitalization (#5475)
* move file

* fix capitalization
2025-01-15 13:14:16 +00:00
RickyRister
2def02e140 Remember which tabs are open between sessions (#5467) 2025-01-15 06:10:24 +00:00
RickyRister
23bd18a04c fix segfault that happens when account tab is closed (#5474) 2025-01-15 06:10:03 +00:00
RickyRister
d09b9eb533 Rename UserList class to UserListWidget (#5473) 2025-01-15 03:07:36 +00:00
github-actions[bot]
25caae6d0f Update translation files (#5472)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-14 20:28:36 -05:00
BruebachL
a717e715b6 Introduce null checks, add setShortName and collectorNumber to deckList export. (#5471)
* Introduce null checks, add setShortName and collectorNumber to deckList export.

* Lint.

* Lint again.

* Lint AGAIN.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 10:54:15 -05:00
BruebachL
c079715c46 Properly check if a duplicate already exists in the list, no longer break loop. (#5470)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 10:12:53 -05:00
BruebachL
f6c1253e84 Add a placeholder label to indicate database is still loading. (#5469)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 14:19:32 +00:00
BruebachL
8462b6e906 Minor fix to sorted list reconstruction to fix duplication of cards in printing selector. (#5468)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 13:59:53 +00:00
RickyRister
cca82f59eb Don't re-sort VisualDeckStorage every time it gets tabbed to (#5466)
* remove showEvent

* refresh cards on init

* fix sort order not immediately being set
2025-01-14 13:58:44 +00:00
RickyRister
81662b7fec Reduce spacing in visual deck storage (#5465)
* move thing

* reduce spacing
2025-01-14 13:52:46 +00:00
RickyRister
d2c2128e9b Rename TabUserLists to TabAccount (#5464)
* rename class

* rename variables
2025-01-14 13:50:08 +00:00
RickyRister
686645c1e4 refactor DeckViewContainer into own file (#5455)
* cut-and-paste

* remove some includes

* move refreshShortcuts

* move deck_view into src/game/deckview

* move deck_view_container to src/game/deckview

* fix build failure
2025-01-14 07:00:09 +00:00
ZeldaZach
9df71fe1e8 Update VCPkg 2025-01-14 01:47:05 -05:00
Zach H
6309e7e318 Fix Windows FlowWidget duplication (#5460)
- Delete the item widget right away, as the delay is too great with deleteLater
2025-01-14 04:33:21 +00:00
Zach H
767e83c879 Disable Force Start for host on load (#5462)
- Fix #5444
2025-01-14 04:33:04 +00:00
RickyRister
78d54b0ef2 Remove unnecessary deck_view.h includes (#5461)
* remove unnecessary deck_view imports

* remove some more imports
2025-01-14 04:32:53 +00:00
BruebachL
497e4f1be0 Add loadFromFileAsync to deckLoader and connect VisualDeckStorageWidget to it. (#5456)
* Add loadFromFileAsync to deckLoader and connect VisualDeckStorageWidget to it.

* Address comments.

* Lint.

* Unlint something.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 03:02:33 +00:00
BruebachL
6072df3522 .txt decks reportedly don't get saved when they're loaded. (#5459)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-14 01:51:41 +00:00
BruebachL
ba89495dc0 Refactor Picture Loader (#5457) 2025-01-13 18:52:54 +00:00
RickyRister
a417b049da Make Visual Deck Storage tab be managed by TabSupervisor (#5453)
* remove closeRequest override

* remove visualDeckStorage from WindowMain

* manage visual deck storage in TabSupervisor

* open on startup

* refresh vds on db load finish

* open deck editor tab first on startup
2025-01-13 18:42:58 +00:00
github-actions[bot]
883f1a5c11 Update translation source strings (#5454)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-13 11:08:32 -05:00
BruebachL
dd8ac14f99 Visual deck storage v2 (#5427)
* Restore some button states (ready/sideboard locked) to sensible defaults when unloading a deck.

* Update last loaded timestamp in decklist file and then restore original last modified timestamp if a user requests a deck load.

* Add some todos.

* Loading a deck from local file dialog should swap out scenes, enable unload button.

* Lint.

* Shuffle some classes and signals around.

* More sort options, sort widgets directly.

* Banner cards should respect providerIds.

* Properly updateSortOrder on load.

* Add the color identity to the Deck Preview Widget.

* Properly set sort indices.

* Change replace visualDeckStorageWidget with deckView to be in deckSelectFinished so that it also works on remote deck load.

* Include settings for unused color identities display.

* Change opacity scaling.

* Overload for Qt.

* Lint.

* Lint.

* Include QMouseEvent

* Template because MacOs.

* Include a quick filter for color identities.

* Include a quick filter for color identities.

* Save some space.

* Refactor DeckPreviewWidgets to reside in their own folder.

* Add Deck Loader logging category.

* Introduce a tagging system.

* Add some more default tags.

* Even more default tags.

* Lint.

* Lint a comma.

* Remove extra set of braces.

* Lint some stuff.

* Refresh banner cards when tags are added.

* Lint.

* Wrestle with Qt Checkboxes.

* Lint.

* Adjust some sizes, relayout.

* Address comments.

* Lint.

* Reorder kindred types.

* Add a search bar for tags.

* Remove close button (for now) and change "Add tags ..." to "Edit tags ..."

* Retranslate window title for Deck Tag Manager Dialog.

* Style tag addition widget to be consistent.

* Lint.

* Override paintEvent.

* Override sizeHint

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-12 17:46:22 -05:00
RickyRister
9bd024d39f Make all tabs closable; add tabs menu (#5451)
* make closeRequest call close by default

* make all tabs closable by default

* closeRequest instead of deleteLater on stop

* null out pointer on destroy

* no need to manually null out the tabs anymore

* comment

* pass tabsMenu into ctor

* comment

* implement tabs menu

* fix segfault on close (again)

* remove deck editor action from WindowMain
2025-01-12 16:15:19 -05:00
transifex-integration[bot]
e4611a8616 Translate cockatrice_en@source.ts in en_US (#5452)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-12 12:41:05 -05:00
RickyRister
3f41e5dd77 don't close replay tabs and do close message tabs on disconnect (#5450) 2025-01-12 02:47:36 -05:00
RickyRister
a6fc88c79a Always set TabSupervisor as parent in Tab subclasses (#5449)
* refactor closeTab

* always set tab parent to tabSupervisor

* set tabSupervisor parent

* use close instead of deleteLater

* be more clear about overloads
2025-01-12 02:34:11 -05:00
transifex-integration[bot]
3a4ec1062b Translate cockatrice_en@source.ts in pt_BR (#5448)
100% translated source file: 'cockatrice_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-11 23:41:57 -05:00
RickyRister
7347ba88ac fix segfault on disconnect (#5447)
* add new param to closeRequest

* don't emit signals in dtors

* send closeRequest

* fix build failure

* fix build failure

* see if we can get away with the overloaded triggered

* fix build failure
2025-01-11 22:19:45 -05:00
tooomm
3b544a36a8 Fix button label (#5441) 2025-01-11 21:28:23 -05:00
RickyRister
2851d0c7e6 add override specifier to tab subclasses (#5445) 2025-01-11 21:28:02 -05:00
transifex-integration[bot]
2b296badea Translate cockatrice_en@source.ts in zh-Hans (#5446)
100% translated source file: 'cockatrice_en@source.ts'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-11 21:27:00 -05:00
ZeldaZach
a12c4ee909 Fix MacOS Builds for Non-Main Repo PRs 2025-01-11 21:21:11 -05:00
ZeldaZach
7db9c9115e Fix SoundEngine on Windows (again) 2025-01-11 00:19:00 -05:00
ZeldaZach
503985a080 Initialize audioOutput for SoundEngine 2025-01-11 00:12:32 -05:00
RickyRister
9f466162b0 disable starting life total edit in game information window (#5440) 2025-01-10 23:14:46 -05:00
Zach H
8bea3f8997 Fix sounds on Qt6 (#5439) 2025-01-10 23:10:47 -05:00
RickyRister
1a3df84f0a fix segfault on exit if any closable tabs were open (#5435) 2025-01-10 17:27:26 -05:00
Zach H
2b3c47148e GHA MacOS Only Sign/Notarize if self repo (#5437) 2025-01-10 16:46:05 -05:00
transifex-integration[bot]
59ca4397e2 Translate oracle/oracle_en@source.ts in zh-Hans (#5436)
100% translated source file: 'oracle/oracle_en@source.ts'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-10 08:22:58 -05:00
transifex-integration[bot]
98266b0739 Translate oracle/oracle_en@source.ts in yue (#5434)
100% translated source file: 'oracle/oracle_en@source.ts'
on 'yue'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-10 08:22:48 -05:00
Zach H
5a82ff106d Update VCPkg (#5433) 2025-01-09 23:23:00 -05:00
Zach H
2194430019 Sign macOS Releases (#5396) 2025-01-09 22:32:53 -05:00
RickyRister
1f11015a2f Refactor files in src/utility and src/deck to new Qt Slot/Signal syntax (#5432)
* refactor in src/utility

* refactor in src/deck

* fix build failure
2025-01-09 06:33:20 -05:00
RickyRister
c3421669d5 Refactor files in src/game to new Qt Slot/Signal syntax (#5431)
* fix signals in CardDatabaseParser

* update remaining signals

* cleanup

* wait this was always just broken

* fix build failure

* fix build failure

* fix build failure
2025-01-09 06:32:25 -05:00
RickyRister
6e8adddc6d Refactor tab_supervisor to new Qt Slot/Signal syntax (#5430)
* Refactor tab_supervisor to new Qt Slot/Signal syntax

* fix build failure
2025-01-09 06:26:42 -05:00
RickyRister
22a6ded4f0 reduce vertical spacing in visual deck storage (#5422) 2025-01-09 06:25:40 -05:00
transifex-integration[bot]
0d7669db2c Translate cockatrice_en@source.ts in yue (#5428)
100% translated source file: 'cockatrice_en@source.ts'
on 'yue'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-08 19:23:49 -05:00
transifex-integration[bot]
9526bca168 Translate cockatrice/cockatrice_en@source.ts in de (#5429)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-08 19:23:38 -05:00
transifex-integration[bot]
0683431f35 Translate cockatrice_en@source.ts in en_US (#5426)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-06 17:31:14 -05:00
github-actions[bot]
70790264b8 Update translation source strings (#5425)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-06 12:42:46 -05:00
transifex-integration[bot]
c8a68c83e3 Translate cockatrice_en@source.ts in yue (#5424)
100% translated source file: 'cockatrice_en@source.ts'
on 'yue'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-06 12:38:58 -05:00
RickyRister
23171f79d0 Refactor window_main to new Qt Slot/Signal syntax (#5423) 2025-01-06 12:38:44 -05:00
RickyRister
b7f05a12a3 get swap cards button to work with multi-selections (#5421) 2025-01-05 22:44:40 -05:00
Zach H
6078dd092a Support viewing the bottom X cards of library (#5410)
* Get cardIds to update properly in bottom view (#5414)

* Get bottom view to update properly when card is inserted into known portion (#5415)

---------

Co-authored-by: RickyRister <42636155+RickyRister@users.noreply.github.com>
2025-01-05 21:17:18 -05:00
BruebachL
81b85e97df Extend decklist parsing (#5316)
* Extend the decklist parsing from clipboard to also support SetName, CollectorNumber and Foil Status.

* Q_UNUSED foil for now but keep parsing logic for future PR's/compatibility.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-05 21:07:17 -05:00
RickyRister
cc16b8779c improve shortcut search to split by word (#5416) 2025-01-05 19:19:00 -05:00
BruebachL
62f7c7f9ce New visual deck storage (#5290)
* Add TabDeckStorageVisual

* Visual Deck Storage

* Add BannerCard to .cod format, use it in the visual deck storage widget.

* Show filename instead of deckname if deck name is empty.

* Lint.

* Don't delint cmake list through hooks.

* Add deck loading functionality.

* Open Decks on double click, not single click.

* Void event for now.

* Fix build issue with overload?

* Fix build issue with overload?

* Include QDebug.

* Turn the tab into a widget.

* Move the signals down to the widget, move the connections and slots up to the parent widgets.

* No banner card equals an empty CardInfoPtr.

* Add an option to sort by filename or last modified.

* Flip last modified comparison.

* Lint.

* Don't open decks twice in the storage tab.

* Fix unload deck not working by showing/hiding widgets instead of adding/removing to layout.

* Add a search bar.

* Add a card size slider.

* Lint.

* Lint.

* Lint.

* Fix settings mocks.

* No need to QDebug.

* No need to QDebug.

* Member variable.

* Member variable.

* Non-lambda.

* Change set to list conversion.

* Specify overload.

* Include MouseEvent

* Adjust font size dynamically.

* Add an option to show the visual deck storage on database load.

* Fix the close button not working on the tab, add an option to launch the visual deck storage tab to Cockatrice menu.

* Override virtual functions.

* Correct tab text.

* Add a setting to remember last used sorting order for visual deck storage widget.

* Update banner card combo box correctly.

* Fix mocks.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: Zach H <zahalpern+github@gmail.com>
2025-01-05 18:12:20 -05:00
BruebachL
7496e79e8c Add a button to swap the card between mainboard and sideboard to the DeckEditor (#5175)
* Add a button to swap the card between mainboard and sideboard to the deck editor.

* Add new icon to cockatrice.qrc and force update.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-05 17:57:37 -05:00
RickyRister
b8cf3e2cab add ctrl enter as shortcut for ok in load deck from clipboard (#5417) 2025-01-05 17:41:03 -05:00
RickyRister
93fab3d78f Remember last opened directory when loading decks (#5418)
* remember last directory when loading deck

* move shared code into new dlg class
2025-01-05 17:40:20 -05:00
BruebachL
9c38c9ed1b Differentiate logging in order to silence certain modules. (#5419)
* Differentiate logging in order to silence certain modules.

* Lint cmake.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2025-01-05 17:38:51 -05:00
RickyRister
38e99f2e87 implement /card command (#5413) 2025-01-04 02:07:43 +00:00
RickyRister
68226786a2 don't redraw PrintingSelector's FlowWidget unless cards actually changed (#5392) 2025-01-04 01:49:54 +00:00
RickyRister
455cd9717a add menu action to open settings folder (#5412) 2025-01-04 01:49:41 +00:00
RickyRister
fa79c5c36a populate default debug.ini with more values (#5411)
* populate default debug.ini with more values

* move the default debug.ini to a resource
2025-01-03 20:50:30 +00:00
RickyRister
0402d4b853 add debug setting to load deck and ready on join (#5409)
* new property

* refactor deck loading to new method

* another new method

* works now
2025-01-02 17:08:51 -05:00
RickyRister
8a427955e7 Add debug setting to start local game on startup (#5408)
* new properties

* refactor

* start local game on startup

* disable autoconnect
2025-01-02 09:51:59 -05:00
RickyRister
bb4214e28a Make SettingsManager params const ref (#5405)
* pass settingsPath by const ref

* pass params by const ref

* cleanup
2025-01-02 00:33:37 -05:00
RickyRister
f924b04efd add debug settings; option to show cardIds (#5404)
* add debug settings; option to show cardIds

* pass param by const ref

* change group structure again

* create debug.ini if not exists
2025-01-02 00:32:58 -05:00
transifex-integration[bot]
62f60867a9 Translate cockatrice_en@source.ts in pt_BR (#5407)
100% translated source file: 'cockatrice_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-02 00:32:29 -05:00
transifex-integration[bot]
b5844f1244 Translate cockatrice/cockatrice_en@source.ts in it (#5406)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'it'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-01-01 22:28:42 -05:00
ryder052
8c0093d453 Crashfix for opening Deck editor (#5403)
* CardDatabase::getCards() no longer copies the whole database

---------

Co-authored-by: Jakub Mrowinski <ryder052@outlook.com>
2025-01-01 19:25:04 -05:00
RickyRister
34df4cd060 support multi-select in deck editor (#5397)
* support multiselect in deck editor

* fix crash

* don't reset selection after each action

* maintain old reselecting behavior when changing cards from left side

* fix crash for real (probably)

* maintain reselection behavior when deleting single selection
2025-01-01 00:43:47 -05:00
Zach H
99eea3a662 Improve Database Backup Speed (#5400)
* Support better indexes for Servatrice

- Prevent searching only on msg for logs
2025-01-01 00:28:57 -05:00
Zach H
6e1047032d Keep card annotations on stack (#5399) 2024-12-31 14:08:25 -05:00
transifex-integration[bot]
b2a8748bc6 Translate cockatrice/cockatrice_en@source.ts in it (#5398)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'it'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-31 13:57:14 -05:00
transifex-integration[bot]
ded6d5b8eb Translate cockatrice/cockatrice_en@source.ts in de (#5395)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-30 19:18:00 +00:00
transifex-integration[bot]
832842c20c Translate cockatrice_en@source.ts in en_US (#5394)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-30 17:42:32 +00:00
github-actions[bot]
b43e4ae469 Update translation source strings (#5393)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-30 12:38:30 +00:00
Zach H
026afeb885 Support auto-reconnect for Servatrice (#5391)
- Fix #5022
2024-12-30 04:35:32 +00:00
RickyRister
b6793a5e01 fix cards having the wrong printing if rejoin game before card db finishes loading (#5390)
* rename cardInfoUpdated to refreshCardInfo and make it public

* refresh card infos when db finishes loading
2024-12-30 03:25:11 +00:00
moryall
d231264a16 Update Dockerfile Ubuntu version to newest LTS (#5108)
* Update Dockerfile to non-outdated Ubuntu version

1. Updated image to jammy as it is still in it's LTS window. Didn't go with 24.04/Noble as it released after latest version of cockatrice released.
2. Had to add new ARG
3. No qt5-default library, so replaced with qt5-qmake

* Update Dockerfile

Upped from Jammy -> Noble
Upped from Qt5 -> Tt6

* Update Dockerfile - new port

Added Port 4748 for new features

* Update Dockerfile

Changed Noble - > 24.04

* indentation

* remove unused dependencies

---------

Co-authored-by: tooomm <tooomm@users.noreply.github.com>
2024-12-30 01:54:18 +00:00
ryder052
6e02bdec2e Fix crash on replay list sorting, fix error popups on win debug (#5388)
* Fix annoying popups on start

* Fix replay list item parent index calculation #5311

---------

Co-authored-by: Jakub Mrowinski <ryder052@outlook.com>
2024-12-30 01:10:12 +00:00
transifex-integration[bot]
cfaadc40b1 Translate cockatrice_en@source.ts in pt_BR (#5386)
100% translated source file: 'cockatrice_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-30 00:57:51 +00:00
transifex-integration[bot]
93475b43a5 Updates for project Cockatrice and language it (#5387)
* Translate cockatrice/cockatrice_en@source.ts in it

100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'it'.

* Translate webclient/src/i18n-default.json in it

100% translated source file: 'webclient/src/i18n-default.json'
on 'it'.

* Translate oracle/oracle_en@source.ts in it

100% translated source file: 'oracle/oracle_en@source.ts'
on 'it'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-30 00:57:43 +00:00
RickyRister
3348e051a1 update recently opened decks when saving a new deck (#5389) 2024-12-30 00:57:31 +00:00
Zach H
dad1aea128 Show correct art on middle mouse popup (#5385) 2024-12-29 23:24:32 +00:00
Zach H
dec001114a Clone now clones the exact printing, when possible (#5384) 2024-12-29 23:24:20 +00:00
ZeldaZach
1ce7b9f7de Update number when 'Reveal top cards of library' used 2024-12-29 16:31:13 -05:00
Zach H
2ff99f12d8 Require Admin Permissions to install Cockatrice Windows (#5383)
Fix #5382
2024-12-29 16:22:39 +00:00
tooomm
6679705254 Simpler naming (#5381) 2024-12-29 15:41:30 +00:00
transifex-integration[bot]
7eafac5b1a Translate cockatrice_en@source.ts in en_US (#5377)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-29 07:11:02 +00:00
RickyRister
ac3aa949ad add "view related cards" right click menu to card info widget (#5375) 2024-12-29 06:11:12 +00:00
Zach H
b4036c8671 Disable CardMenu iff no items selected (#5376)
- Fix #4372
2024-12-29 06:10:27 +00:00
github-actions[bot]
4e0de1c066 Update translation source strings (#5373)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-29 03:37:53 +00:00
RickyRister
f32890916d don't disable autoconnect on disconnect (#5372)
* don't disable autoconnect on disconnect

* update autoConnect on clicking the checkbox
2024-12-29 03:07:00 +00:00
Zach H
24a0dac420 Fix Windows Portable Crash (#5371) 2024-12-29 03:02:52 +00:00
RickyRister
716bc00533 fix "forgot password" closing connection dialogue on cancel (#5369) 2024-12-29 02:23:58 +00:00
Zach H
32dd18998d Combine card legalities in Oracle (#5370)
- Some printings have different legalities, which cause Oracle to bug out
- Fix #4783
2024-12-29 02:23:39 +00:00
ZeldaZach
5e62069444 Fix Windows Crash due to nullptr 2024-12-28 21:02:10 -05:00
Zach H
bf63dc4ab7 Add option to remove saved sever (#5368)
* Add option to remove saved sever

- Fix #4099
- Removes old method that didn't work
2024-12-29 00:37:49 +00:00
Danny Piper
7679546e30 Add Nix shell (#5362) 2024-12-28 23:52:57 +00:00
Zach H
45b11dc984 Add password reset button label (#5367) 2024-12-28 23:52:14 +00:00
RickyRister
25d21a3da6 refactor: remove ReleaseChannel keeping track of its own indexes (#5366) 2024-12-28 23:51:37 +00:00
Zach H
c8d49b5bf9 Support macOS-15 Builds (#5364) 2024-12-28 23:09:01 +00:00
RickyRister
f737d9a794 fix bug with release channel setting not being remembered (#5365) 2024-12-28 23:08:07 +00:00
RickyRister
df9c5ae53c Check for client updates on startup (#5359) 2024-12-28 21:29:59 +00:00
transifex-integration[bot]
e0829a75d2 Translate cockatrice/cockatrice_en@source.ts in it (#5363)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'it'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-28 21:01:34 +00:00
Zach H
1f58f7e93d Support Mod/Admin Notes Section (#5361) 2024-12-28 18:05:49 +00:00
transifex-integration[bot]
14807ba036 Translate oracle/oracle_en@source.ts in pl (#5360)
100% translated source file: 'oracle/oracle_en@source.ts'
on 'pl'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-28 15:31:16 +00:00
transifex-integration[bot]
75fb3894a6 Translate oracle/oracle_en@source.ts in pt_BR (#5358)
100% translated source file: 'oracle/oracle_en@source.ts'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-28 12:08:58 +00:00
github-actions[bot]
18119bd11b Update translation source strings (#5357)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-28 06:33:57 +00:00
RickyRister
4c7796537f Support folder download in deck storage tab (#5356)
* refactor

* support folder download
2024-12-28 06:31:18 +00:00
RickyRister
3452cb01d0 fix replay download not working if replay folder is empty (#5355)
* fix downloading single replays

* fix downloading replay folder
2024-12-28 06:15:25 +00:00
RickyRister
6a151ef97a Add button to open decks folder (#5354) 2024-12-28 05:09:46 +00:00
RickyRister
e3d651668c Add button to open replays folder (#5352) 2024-12-28 05:06:26 +00:00
Zach H
7a5704beaa Support Moderator/Admin force activating users (#5353) 2024-12-28 05:01:31 +00:00
RickyRister
37b78a9a4c change action's text to "unconcede" when player is conceded (#5351) 2024-12-28 00:01:36 +00:00
Zach H
8bc5a9d581 Merge pull request #5350 from Cockatrice/fix_1953
Allow Moderators/Admins to Grant Replay Access
2024-12-27 18:51:11 -05:00
ZeldaZach
57ed162b79 Fix Linter 2024-12-27 18:35:52 -05:00
ZeldaZach
3524231500 Allow Moderators/Admins to Grant Replay Access
- Only to themselves, at this time
- Automatically refreshes feed, no need to re-login
2024-12-27 18:32:39 -05:00
Zach H
5cfe2b4762 Merge pull request #5348 from Cockatrice/set_owner
Establish Card Ownership & Return on Player Leave
2024-12-27 18:26:45 -05:00
ZeldaZach
a8bac1e468 Return Tagged Cards to Owner, if possible, on concede/leave 2024-12-27 18:23:39 -05:00
ZeldaZach
4f798286af Establish Card Ownership Tag 2024-12-27 18:23:09 -05:00
transifex-integration[bot]
8a04b2d69d Translate cockatrice/cockatrice_en@source.ts in de (#5349)
100% translated source file: 'cockatrice/cockatrice_en@source.ts'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-27 22:26:03 +00:00
transifex-integration[bot]
17893d9747 Translate oracle/oracle_en@source.ts in it (#5347)
100% translated source file: 'oracle/oracle_en@source.ts'
on 'it'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-27 20:13:57 +00:00
ZeldaZach
8af49406cd Un-translate 'ms' 2024-12-27 14:18:44 -05:00
transifex-integration[bot]
3b068b79fe Translate webclient/src/i18n-default.json in fr (#5346)
100% translated source file: 'webclient/src/i18n-default.json'
on 'fr'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-27 08:36:06 +00:00
transifex-integration[bot]
ce14e83e78 Translate webclient/src/i18n-default.json in es (#5345)
100% translated source file: 'webclient/src/i18n-default.json'
on 'es'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-27 08:35:58 +00:00
transifex-integration[bot]
f213d6fda7 Translate cockatrice_en@source.ts in en_US (#5344)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-27 08:35:48 +00:00
RickyRister
83db00d7a3 reduce vertical spacing in PrintingSelector (#5342) 2024-12-27 08:35:38 +00:00
ZeldaZach
7e9bd88eb4 Fix Shutdown Server 2024-12-27 01:38:21 -05:00
github-actions[bot]
ea716ca440 Update translation source strings (#5343)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-27 06:19:12 +00:00
ZeldaZach
3cd7a04002 Change Settings from Min to Base Size 2024-12-26 23:54:24 -05:00
RickyRister
914002f846 use grid instead of FlowWidget for PrintingSelector display options (#5341)
* use grid instead of FlowWidget for PrintingSelector display options

* remove one level of nesting
2024-12-27 02:08:07 +00:00
Zach H
17b82a186f Add QSet for faster lookups in CardDatabase (#5332) 2024-12-26 19:52:18 -05:00
RickyRister
7a8e957476 allow playing cards directly transformed from hand (#5339) 2024-12-26 19:51:58 -05:00
Zach H
6dfd354973 Support starting games with fewer than max players (#5338) 2024-12-26 18:32:20 -05:00
RickyRister
956c12eb32 remove shortcut workaround; always add card menu to player (#5337)
* remove workaround

* make aCardMenu less innocuous

* make card menus active for all players
2024-12-26 16:49:17 -05:00
RickyRister
d5ae4eed26 Ctrl drag now adds/removes to selection (#5336)
* refactor: clean up to use for-each loop

* track cards in rect so far and toggle isSelected on change

* only clear selection if ctrl isn't held

* fix build errors
2024-12-26 15:08:20 -05:00
RickyRister
ca486e5ed9 Don't display unusable actions in opponent's card menus (#5335) 2024-12-26 10:23:54 -05:00
RickyRister
de63066b0b fix deck storage open deck not working at all when folder is in selection (#5333) 2024-12-26 00:25:30 -05:00
Zach H
c7ca55ceb5 Support Picking Select Art per Card Basis (#5329) 2024-12-25 23:12:06 -05:00
RickyRister
024bef7ded add local rename button to replays tab (#5331) 2024-12-25 22:34:24 -05:00
RickyRister
34d3d60f95 fix text missing from chat macro list's buttons when hidden (#5330)
* fix text missing from chat macro list's buttons when hidden

* turns out you don't need to set tooltip if you already set text
2024-12-25 22:32:53 -05:00
RickyRister
ed907d7c6f Support downloading replay folders (#5325)
* rename old get replay match method to get enclosing

* creat raw getReplayMatch method

* implement thing
2024-12-25 07:33:36 -05:00
RickyRister
9d7fd66546 fix text missing from download url list's buttons when hidden (#5326) 2024-12-25 07:29:55 -05:00
RickyRister
9934841950 make better use of space in download url settings window (#5327) 2024-12-25 07:29:27 -05:00
RickyRister
432fe1100b gitignore all cmake-build folders (#5328) 2024-12-25 07:28:41 -05:00
Zach H
d987628935 Reorder String options for Filtering (#5324) 2024-12-25 00:58:59 -05:00
RickyRister
4c3ceae0e4 open replays on double-click in replays tab (#5323) 2024-12-25 00:34:43 -05:00
RickyRister
2b9d7538bf open decks on double-click in deck storage tab (#5322) 2024-12-25 00:33:48 -05:00
RickyRister
4ca1fc083d add "open recent" menu option to deck editor tab (#5319)
* add "open recent" menu option to deck editor tab

* change texts

* also get it to work with loading from deck storage tab

* add error message when fail to open

* only update recents on successful open

* only update recents on successful open

* reword to "Clear"
2024-12-24 19:55:04 -05:00
BruebachL
e7585271fb The printingSelector should set the deckEditor modified flag on adding/removing cards. (#5321)
Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2024-12-24 10:28:58 -05:00
RickyRister
6e6824117d add new folder button to local deck storage tab (#5318)
* add new folder button to local deck storage tab

* allow delete button to delete folders
2024-12-24 00:26:11 -05:00
RickyRister
3e5f2fd8b2 add new folder button to game replays tab (#5317) 2024-12-24 00:23:13 -05:00
RickyRister
6e470d788e Support multi-select for remote decks in deck storage tab (#5315)
* enable multiselection

* support multi open deck

* support multi download

* support multi delete
2024-12-24 00:05:49 -05:00
RickyRister
a40d8092ce support multi-select for local decks in deck storage tab (#5314)
* allow multi-select

* support multi upload

* support multi open deck

* support multi delete deck
2024-12-23 20:41:15 -05:00
RickyRister
0234a70bfd fix bug with uploading unnamed decks ignoring the prompt (#5313) 2024-12-23 20:39:57 -05:00
RickyRister
705b1e0c2b support multi-select for remote replays in game replays tab (#5310) 2024-12-23 20:38:47 -05:00
RickyRister
69379334f9 support multi-select for local replay tab (#5309) 2024-12-23 20:31:58 -05:00
transifex-integration[bot]
12e50a1f2f Translate cockatrice_en@source.ts in en_US (#5308)
100% translated source file: 'cockatrice_en@source.ts'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-23 20:30:17 -05:00
RickyRister
ec17a477be shortcut search now displays all rows in section (#5307) 2024-12-23 20:29:52 -05:00
github-actions[bot]
205e1c7a59 Update translation source strings (#5305)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-22 18:35:34 -05:00
transifex-integration[bot]
ffb60c06cb Translate oracle_en@source.ts in en@pirate [Manual Sync] (#5295)
4% of minimum 3% translated source file: 'oracle_en@source.ts'
on 'en@pirate'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:01:02 -05:00
transifex-integration[bot]
2280f59ee6 Translate i18n-default.json in nl [Manual Sync] (#5297)
19% of minimum 3% translated source file: 'i18n-default.json'
on 'nl'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:44 -05:00
transifex-integration[bot]
0d4dd63edc Translate i18n-default.json in es [Manual Sync] (#5299)
99% of minimum 3% translated source file: 'i18n-default.json'
on 'es'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:39 -05:00
transifex-integration[bot]
69f1f4c1a5 Translate i18n-default.json in fi [Manual Sync] (#5301)
13% of minimum 3% translated source file: 'i18n-default.json'
on 'fi'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:35 -05:00
transifex-integration[bot]
d930d9c237 Updates for project Cockatrice and language tr (#5296)
* Translate oracle_en@source.ts in tr [Manual Sync]

36% of minimum 3% translated source file: 'oracle_en@source.ts'
on 'tr'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

* Translate cockatrice_en@source.ts in tr [Manual Sync]

6% of minimum 3% translated source file: 'cockatrice_en@source.ts'
on 'tr'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:31 -05:00
transifex-integration[bot]
9c782d130f Translate i18n-default.json in pt_BR [Manual Sync] (#5298)
100% translated source file: 'i18n-default.json'
on 'pt_BR'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:13 -05:00
transifex-integration[bot]
f12053f39d Translate i18n-default.json in de [Manual Sync] (#5300)
100% translated source file: 'i18n-default.json'
on 'de'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 18:00:05 -05:00
transifex-integration[bot]
bcf6ca4f87 Translate i18n-default.json in fr [Manual Sync] (#5302)
99% of minimum 3% translated source file: 'i18n-default.json'
on 'fr'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 17:59:55 -05:00
transifex-integration[bot]
46619bb425 Translate i18n-default.json in ru [Manual Sync] (#5303)
14% of minimum 3% translated source file: 'i18n-default.json'
on 'ru'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 17:59:46 -05:00
transifex-integration[bot]
cdd870a129 Translate i18n-default.json in en_US [Manual Sync] (#5304)
100% translated source file: 'i18n-default.json'
on 'en_US'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 17:59:35 -05:00
transifex-integration[bot]
7a1b7b9438 Updates for project Cockatrice and language it (#5294)
* Translate cockatrice_en@source.ts in it [Manual Sync]

99% of minimum 3% translated source file: 'cockatrice_en@source.ts'
on 'it'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

* Translate i18n-default.json in it [Manual Sync]

100% translated source file: 'i18n-default.json'
on 'it'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 17:59:24 -05:00
transifex-integration[bot]
2183ada1f2 Translate oracle_en@source.ts in cs [Manual Sync] (#5293)
3% of minimum 3% translated source file: 'oracle_en@source.ts'
on 'cs'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-12-22 17:58:35 -05:00
Zach H
1d9e64ec73 Fix settings dialog tr (#5292) 2024-12-22 17:39:43 -05:00
Zach H
5339be318e Fix "ghosting" of cards sticking on invalid moves (#5289) 2024-12-22 17:35:44 -05:00
Zach H
e1ba39c437 Fix multiple "Selected Cards" in Menu on MacOS (#5288) 2024-12-22 04:33:09 +00:00
BruebachL
07ee271478 Refactor codebase to new Qt Slot/Signal syntax - Pt1 (#5202)
---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
Co-authored-by: ZeldaZach <zahalpern+github@gmail.com>
2024-12-22 02:01:17 +00:00
RickyRister
4823cce622 Show conflicting shortcut in error message (#5287) 2024-12-22 01:58:55 +00:00
Zach H
23099f7e8b Fix token name highlight on open (#5286) 2024-12-22 01:43:00 +00:00
RickyRister
5bdbd51fa8 implement search bar in shortcuts menu (#5285)
* implement search bar in shortcuts menu

* remove unneeded imports

* use expandAll
2024-12-22 00:21:53 +00:00
BruebachL
a0e5871c6e Fix the image shrinking due to repeated scaling and FP precision loss. (#5284)
* Fix the image shrinking due to repeated scaling and FP precision loss.

* Add a setting for auto-rotating sideways layout cards.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2024-12-21 22:47:43 +00:00
RickyRister
3cf0904651 add action to select all cards in table row (#5280) 2024-12-21 18:52:19 +00:00
Zach H
2bd06ff0fd Add CrashDump support for Windows OS (#5282) 2024-12-21 18:52:07 +00:00
RickyRister
6ea333d0f1 move SearchLineEdit into custom_line_edit file (#5281) 2024-12-21 05:12:14 +00:00
Zach H
91d2485940 Update PegLib, Fix Database Searching CFG (#5244)
* Support C++20 Standard

* Update peglib.h

* Fix lambdas

* Move from for loops to std::any/all_of

* Support fixed CFG

* Fix Rarity Search to be more accurate
2024-12-21 03:37:08 +00:00
RickyRister
0d99b2bcf4 make unattach shortcut always active (#5278) 2024-12-20 05:56:48 +00:00
RickyRister
a54a424f84 add action to select all cards in column (#5277)
* add action to select all cards in column

* change default shortcut to Ctrl+Shift+C
2024-12-20 03:39:17 +00:00
RickyRister
3514699f5b check that target card is in play before attaching (#5275) 2024-12-19 23:55:04 +00:00
RickyRister
d196988cab allow attached cards to be moved to other zones (#5276) 2024-12-19 23:53:48 +00:00
BruebachL
03aff83135 Add the ability to define starting life total during game creation. (#5174)
* Have the server respect gameType info when setting up zones.

* ServerPlayer::setupZones is now passed the room->getGameTypes();
* ServerPlayer::setupZones now checks if the GameType String includes "Commander" and then sets the life total to 40 instead.

* Formatting.

* Remove debug logging imports.

* Move game option value declarations to dlg_create_game.

* Lint.

* Fix mocks.

* Add a default for backwards compatibility.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2024-12-19 23:52:47 +00:00
497 changed files with 84114 additions and 43343 deletions

17
.ci/macos.entitlements Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>

View File

@@ -217,10 +217,18 @@ jobs:
core_count: 3
make_package: 1
- target: 14
- target: 15
soc: Apple
os: macos-14
xcode: "15.4"
os: macos-15
xcode: "16.2"
type: Release
core_count: 3
make_package: 1
- target: 15
soc: Apple
os: macos-15
xcode: "16.2"
type: Debug
core_count: 3
@@ -246,7 +254,7 @@ jobs:
brew update
brew install protobuf qt --force-bottle
- name: Build on Xcode ${{matrix.xcode}}
- name: Build & Sign on Xcode ${{matrix.xcode}}
shell: bash
id: build
env:
@@ -254,16 +262,75 @@ jobs:
MAKE_TEST: 1
MAKE_PACKAGE: '${{matrix.make_package}}'
PACKAGE_SUFFIX: '-macOS${{matrix.target}}_${{matrix.soc}}'
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
# macOS runner have 3 cores usually - only the macos-13 image has 4:
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
run: .ci/compile.sh --server --parallel ${{matrix.core_count}}
run: |
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain
security set-keychain-settings -t 3600 -l build.keychain
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
fi
.ci/compile.sh --server --parallel ${{matrix.core_count}}
- name: Sign app bundle
if: matrix.make_package
env:
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
run: |
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
/usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose ${{steps.build.outputs.path}}
fi
- name: Notarize app bundle
if: matrix.make_package
env:
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
run: |
if [[ -n "$MACOS_NOTARIZATION_APPLE_ID" ]]
then
# Store the notarization credentials so that we can prevent a UI password dialog from blocking the CI
echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD"
# We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
# notarization service
echo "Creating temp notarization archive"
ditto -c -k --keepParent ${{steps.build.outputs.path}} "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
# you're curious
echo "Notarize app"
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available.
echo "Attach staple"
xcrun stapler staple ${{steps.build.outputs.path}}
fi
- name: Upload artifact
if: matrix.make_package
uses: actions/upload-artifact@v4
with:
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-dmg
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-package
path: ${{steps.build.outputs.path}}
if-no-files-found: error
@@ -347,6 +414,15 @@ jobs:
path: ${{steps.build.outputs.path}}
if-no-files-found: error
- name: Upload pdb database
uses: actions/upload-artifact@v4
with:
name: Windows${{matrix.target}}-debug-pdbs
path: |
build/cockatrice/Release/*.pdb
build/servatrice/Release/*.pdb
if-no-files-found: error
- name: Upload to release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash

3
.gitignore vendored
View File

@@ -6,10 +6,11 @@ mysql.cnf
.DS_Store
.idea/
*.aps
cmake-build-debug*
cmake-build*
preferences
compile_commands.json
.vs/
.vscode/
.cache
.gdb_history
cockatrice/resources/config/qtlogging.ini

View File

@@ -74,16 +74,16 @@ endif()
# A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake
project("Cockatrice" VERSION 2.10.0)
project("Cockatrice" VERSION 2.10.1)
# Set release name if not provided via env/cmake var
if(NOT DEFINED GIT_TAG_RELEASENAME)
set(GIT_TAG_RELEASENAME "Rings of the Wild")
set(GIT_TAG_RELEASENAME "Omenpath")
endif()
# Use c++17 for all targets
# Use c++20 for all targets
set(CMAKE_CXX_STANDARD
17
20
CACHE STRING "C++ ISO Standard"
)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -140,12 +140,17 @@ endif()
# Define proper compilation flags
if(MSVC)
# Visual Studio: Disable Warning C4251, C++17 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++17 /permissive- /W4 /MP /EHsc")
# Disable Warning C4251, C++20 compatibility, Multi-threaded Builds, Warn Detection, Unwind Semantics, Debug Symbols
set(CMAKE_CXX_FLAGS "/wd4251 /Zc:__cplusplus /std:c++20 /permissive- /W4 /MP /EHsc /Zi")
# Visual Studio: Maximum Optimization, Multi-threaded DLL
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
# Visual Studio: No Optimization, Multi-threaded Debug DLL, Debug Symbols
set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd /Zi")
# Visual Studio: No Optimization, Multi-threaded Debug DLL
set(CMAKE_CXX_FLAGS_DEBUG "/Od /MDd")
# Generate PDB, even when in release (So developers can better analyze crash logs)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
add_compile_definitions(_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING)
elseif(CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
@@ -158,7 +163,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
endif()
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++20")
endif()
set(ADDITIONAL_DEBUG_FLAGS
@@ -266,6 +271,7 @@ if(UNIX)
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script")
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/SignMacApplications.cmake")
else()
# linux
if(CPACK_GENERATOR STREQUAL "RPM")

View File

@@ -1,19 +1,20 @@
FROM ubuntu:bionic
MAINTAINER Zach Halpern <zahalpern+github@gmail.com>
FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y\
build-essential\
cmake\
git\
libprotobuf-dev\
libqt5sql5-mysql\
libmysqlclient-dev\
libqt5websockets5-dev\
protobuf-compiler\
qt5-default\
qtbase5-dev\
qttools5-dev-tools\
qttools5-dev
build-essential \
cmake \
file \
g++ \
git \
libmariadb-dev-compat \
libprotobuf-dev \
libqt6sql6-mysql \
qt6-websockets-dev \
protobuf-compiler \
qt6-tools-dev \
qt6-tools-dev-tools
COPY . /home/servatrice/code/
WORKDIR /home/servatrice/code
@@ -25,7 +26,6 @@ RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=
WORKDIR /home/servatrice
EXPOSE 4747
EXPOSE 4747 4748
ENTRYPOINT [ "servatrice", "--log-to-console" ]

View File

@@ -23,6 +23,7 @@ if(WITH_CLIENT)
Svg
WebSockets
Widgets
Xml
)
endif()
if(WITH_ORACLE)

View File

@@ -5,7 +5,7 @@ OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
RequestExecutionlevel highest
RequestExecutionlevel admin
SetCompressor LZMA
Var NormalDestDir
@@ -235,6 +235,13 @@ ${If} $PortableMode = 0
WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
; Enable Windows User-Mode Dumps
; https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps
WriteRegExpandStr HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpFolder" "%LOCALAPPDATA%\CrashDumps\Cockatrice"
WriteRegDWORD HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpCount" "5"
WriteRegDWORD HKLM "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\cockatrice.exe" "DumpType" "2"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayIcon" "$INSTDIR\cockatrice.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayName" "Cockatrice"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayVersion" "@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@.@CPACK_PACKAGE_VERSION_PATCH@"

View File

@@ -0,0 +1,27 @@
# This script re-signs all apps after CPack packages them. This is necessary because CPack modifies
# the library references used by Cockatrice to App relative paths, invalidating the code signature.
string(LENGTH "$ENV{MACOS_CERTIFICATE_NAME}" MACOS_CERTIFICATE_NAME_LEN)
if(APPLE AND MACOS_CERTIFICATE_NAME_LEN GREATER 0)
set(APPLICATIONS "cockatrice" "servatrice" "oracle" "dbconverter")
foreach(app_name IN LISTS APPLICATIONS)
set(FULL_APP_PATH "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/${app_name}.app")
message(STATUS "Signing Interior Dynamically Loaded Libraries for ${app_name}.app")
execute_process(COMMAND "find" "${FULL_APP_PATH}" "-name" "*.dylib" OUTPUT_VARIABLE INTERIOR_DLLS)
string(REPLACE "\n" ";" INTERIOR_DLLS_LIST ${INTERIOR_DLLS})
foreach(INTERIOR_DLL IN LISTS INTERIOR_DLLS_LIST)
execute_process(
COMMAND "codesign" "--sign" "$ENV{MACOS_CERTIFICATE_NAME}" "--entitlements" "../.ci/macos.entitlements"
"--options" "runtime" "--force" "--deep" "--timestamp" "--verbose" "${INTERIOR_DLL}"
)
endforeach()
message(STATUS "Signing Exterior Applications ${app_name}.app")
execute_process(
COMMAND "codesign" "--sign" "$ENV{MACOS_CERTIFICATE_NAME}" "--entitlements" "../.ci/macos.entitlements"
"--options" "runtime" "--force" "--deep" "--timestamp" "--verbose" "${FULL_APP_PATH}"
)
endforeach()
endif()

View File

@@ -12,6 +12,7 @@ set(cockatrice_SOURCES
src/game/board/abstract_graphics_item.cpp
src/game/board/arrow_item.cpp
src/game/board/arrow_target.cpp
src/client/ui/widgets/general/display/banner_widget.cpp
src/game/cards/card_database.cpp
src/game/cards/card_database_manager.cpp
src/game/cards/card_database_model.cpp
@@ -34,8 +35,8 @@ set(cockatrice_SOURCES
src/deck/deck_loader.cpp
src/deck/deck_list_model.cpp
src/deck/deck_stats_interface.cpp
src/deck/deck_view.cpp
src/dialogs/dlg_connect.cpp
src/dialogs/dlg_convert_deck_to_cod_format.cpp
src/dialogs/dlg_create_token.cpp
src/dialogs/dlg_create_game.cpp
src/dialogs/dlg_edit_avatar.cpp
@@ -56,13 +57,14 @@ set(cockatrice_SOURCES
src/dialogs/dlg_tip_of_the_day.cpp
src/dialogs/dlg_update.cpp
src/dialogs/dlg_view_log.cpp
src/dialogs/dlg_load_deck.cpp
src/game/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp
src/game/filters/filter_string.cpp
src/game/filters/filter_builder.cpp
src/game/filters/filter_tree.cpp
src/game/filters/filter_tree_model.cpp
src/client/ui/layouts/flow_layout.cpp
src/client/ui/layouts/horizontal_flow_layout.cpp
src/client/ui/layouts/vertical_flow_layout.cpp
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
src/game/game_scene.cpp
src/game/game_selector.cpp
@@ -80,6 +82,10 @@ set(cockatrice_SOURCES
src/utility/logger.cpp
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
src/client/ui/widgets/cards/additional_info/color_identity_widget.cpp
src/client/ui/widgets/cards/additional_info/mana_cost_widget.cpp
src/client/ui/widgets/cards/additional_info/mana_symbol_widget.cpp
src/client/ui/widgets/general/display/banner_widget.cpp
src/client/ui/widgets/general/display/labeled_input.cpp
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
@@ -92,7 +98,9 @@ set(cockatrice_SOURCES
src/server/pending_command.cpp
src/game/phase.cpp
src/client/ui/phases_toolbar.cpp
src/client/ui/picture_loader.cpp
src/client/ui/picture_loader/picture_loader.cpp
src/client/ui/picture_loader/picture_loader_worker.cpp
src/client/ui/picture_loader/picture_to_load.cpp
src/game/zones/pile_zone.cpp
src/client/ui/pixel_map_generator.cpp
src/game/player/player.cpp
@@ -106,10 +114,11 @@ set(cockatrice_SOURCES
src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_view_options_toolbar_widget.cpp
src/client/ui/widgets/printing_selector/printing_selector_view_options_widget.cpp
src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
src/client/ui/widgets/quick_settings/settings_button_widget.cpp
src/client/ui/widgets/quick_settings/settings_popup_widget.cpp
src/client/network/release_channel.cpp
src/client/network/client_update_checker.cpp
src/server/remote/remote_client.cpp
src/server/remote/remote_decklist_tree_widget.cpp
src/server/remote/remote_replay_list_tree_widget.cpp
@@ -122,16 +131,21 @@ set(cockatrice_SOURCES
src/settings/game_filters_settings.cpp
src/settings/layouts_settings.cpp
src/settings/message_settings.cpp
src/settings/recents_settings.cpp
src/settings/servers_settings.cpp
src/settings/settings_manager.cpp
src/settings/cache_settings.cpp
src/settings/shortcuts_settings.cpp
src/settings/shortcut_treeview.cpp
src/settings/card_override_settings.cpp
src/settings/debug_settings.cpp
src/client/sound_engine.cpp
src/client/network/spoiler_background_updater.cpp
src/game/zones/stack_zone.cpp
src/client/tabs/tab.cpp
src/client/tabs/tab_account.cpp
src/client/tabs/tab_admin.cpp
src/client/tabs/abstract_tab_deck_editor.cpp
src/client/tabs/tab_deck_editor.cpp
src/client/tabs/tab_deck_storage.cpp
src/client/tabs/tab_game.cpp
@@ -141,6 +155,19 @@ set(cockatrice_SOURCES
src/client/tabs/tab_room.cpp
src/client/tabs/tab_server.cpp
src/client/tabs/tab_supervisor.cpp
src/client/tabs/api/edhrec/tab_edhrec.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_commander_details_display_widget.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp
src/game/zones/table_zone.cpp
src/client/tapped_out_interface.cpp
src/client/ui/theme_manager.cpp
@@ -150,15 +177,39 @@ set(cockatrice_SOURCES
src/server/user/user_context_menu.cpp
src/server/user/user_info_connection.cpp
src/server/user/user_info_box.cpp
src/server/user/user_list.cpp
src/server/user/user_list_manager.cpp
src/server/user/user_list_widget.cpp
src/client/ui/window_main.cpp
src/game/zones/view_zone_widget.cpp
src/game/zones/view_zone.cpp
src/client/menus/deck_editor/deck_editor_menu.cpp
src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
src/client/ui/widgets/cards/deck_preview_card_picture_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_database_display_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_deck_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_filter_dock_widget.cpp
src/client/ui/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp
${VERSION_STRING_CPP}
)
add_subdirectory(sounds)
add_subdirectory(themes)
configure_file(
${CMAKE_SOURCE_DIR}/cockatrice/resources/config/qtlogging.ini ${CMAKE_BINARY_DIR}/cockatrice/qtlogging.ini COPYONLY
)
set(cockatrice_RESOURCES cockatrice.qrc)
@@ -279,7 +330,7 @@ if(APPLE)
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
# Qt plugins: audio (Qt5), iconengines, imageformats, multimedia (Qt6), platforms, printsupport (Qt5), styles, tls (Qt6)
install(
DIRECTORY "${QT_PLUGINS_DIR}/"
DESTINATION ${plugin_dest_dir}
@@ -290,12 +341,20 @@ if(APPLE)
PATTERN "audio/*.dylib"
PATTERN "iconengines/*.dylib"
PATTERN "imageformats/*.dylib"
PATTERN "multimedia/*.dylib"
PATTERN "platforms/*.dylib"
PATTERN "printsupport/*.dylib"
PATTERN "styles/*.dylib"
PATTERN "tls/*.dylib"
)
install(
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
DESTINATION ${qtconf_dest_dir}/
FILES_MATCHING
PATTERN "*.ini"
)
install(
CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
@@ -330,7 +389,14 @@ if(WIN32)
PATTERN "*.dll"
)
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
install(
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
DESTINATION ./
FILES_MATCHING
PATTERN "*.ini"
)
# Qt plugins: audio (Qt5), iconengines, imageformats, multimedia (Qt6) platforms, printsupport (Qt5), styles, tls (Qt6)
install(
DIRECTORY "${QT_PLUGINS_DIR}/"
DESTINATION ${plugin_dest_dir}
@@ -342,6 +408,7 @@ if(WIN32)
PATTERN "imageformats/*.dll"
PATTERN "mediaservice/dsengine.dll"
PATTERN "mediaservice/wmfengine.dll"
PATTERN "multimedia/*.dll"
PATTERN "platforms/qdirect2d.dll"
PATTERN "platforms/qminimal.dll"
PATTERN "platforms/qoffscreen.dll"

View File

@@ -1,5 +1,5 @@
<RCC>
<qresource prefix="/" >
<qresource prefix="/">
<file>resources/cardback.svg</file>
<file>resources/cockatrice.svg</file>
<file>resources/hand.svg</file>
@@ -13,9 +13,12 @@
<file>resources/icons/arrow_top_green.svg</file>
<file>resources/icons/arrow_up_green.svg</file>
<file>resources/icons/clearsearch.svg</file>
<file>resources/icons/cogwheel.svg</file>
<file>resources/icons/conceded.svg</file>
<file>resources/icons/decrement.svg</file>
<file>resources/icons/delete.svg</file>
<file>resources/icons/dropdown_collapsed.svg</file>
<file>resources/icons/dropdown_expanded.svg</file>
<file>resources/icons/forgot_password.svg</file>
<file>resources/icons/increment.svg</file>
<file>resources/icons/info.svg</file>
@@ -24,16 +27,25 @@
<file>resources/icons/pencil.svg</file>
<file>resources/icons/player.svg</file>
<file>resources/icons/ready_start.svg</file>
<file>resources/icons/reload.svg</file>
<file>resources/icons/remove_row.svg</file>
<file>resources/icons/rename.svg</file>
<file>resources/icons/scales.svg</file>
<file>resources/icons/search.svg</file>
<file>resources/icons/settings.svg</file>
<file>resources/icons/spectator.svg</file>
<file>resources/icons/swap.svg</file>
<file>resources/icons/sync.svg</file>
<file>resources/icons/tab_changed.svg</file>
<file>resources/icons/update.png</file>
<file>resources/icons/view.svg</file>
<file>resources/icons/mana/B.svg</file>
<file>resources/icons/mana/G.svg</file>
<file>resources/icons/mana/R.svg</file>
<file>resources/icons/mana/U.svg</file>
<file>resources/icons/mana/W.svg</file>
<file>resources/config/general.svg</file>
<file>resources/config/appearance.svg</file>
<file>resources/config/interface.svg</file>
@@ -41,6 +53,8 @@
<file>resources/config/deckeditor.svg</file>
<file>resources/config/shorcuts.svg</file>
<file>resources/config/sound.svg</file>
<file>resources/config/debug.ini</file>
<file>resources/config/qtlogging.ini</file>
<file>resources/counters/w.svg</file>
<file>resources/counters/w_highlight.svg</file>
@@ -326,39 +340,42 @@
<file>resources/replay/fastforward.svg</file>
<file>resources/replay/pause.svg</file>
<file>resources/userlevels/normal.svg</file>
<file>resources/userlevels/registered.svg</file>
<file>resources/userlevels/registered_buddy.svg</file>
<file>resources/userlevels/registered_vip.svg</file>
<file>resources/userlevels/registered_vip_buddy.svg</file>
<file>resources/userlevels/registered_donator.svg</file>
<file>resources/userlevels/registered_donator_buddy.svg</file>
<file>resources/userlevels/moderator.svg</file>
<file>resources/userlevels/moderator_buddy.svg</file>
<file>resources/userlevels/moderator_vip.svg</file>
<file>resources/userlevels/moderator_vip_buddy.svg</file>
<file>resources/userlevels/admin.svg</file>
<file>resources/userlevels/admin_buddy.svg</file>
<file>resources/userlevels/admin_vip.svg</file>
<file>resources/userlevels/admin_vip_buddy.svg</file>
<file>resources/usericons/pawn_single.svg</file>
<file>resources/usericons/pawn_double.svg</file>
<file>resources/usericons/pawn_donator_single.svg</file>
<file>resources/usericons/pawn_donator_double.svg</file>
<file>resources/usericons/pawn_judge_single.svg</file>
<file>resources/usericons/pawn_judge_double.svg</file>
<file>resources/usericons/pawn_vip_single.svg</file>
<file>resources/usericons/pawn_vip_double.svg</file>
<file>resources/usericons/star_single.svg</file>
<file>resources/usericons/star_double.svg</file>
<!-- ADD TIP OF THE DAY IMAGES HERE -->
<file>resources/tips/images/accounts_tab.png</file>
<file>resources/tips/images/add_card.png</file>
<file>resources/tips/images/arrows.png</file>
<file>resources/tips/images/card_select.png</file>
<file>resources/tips/images/cockatrice_register.png</file>
<file>resources/tips/images/cockatrice_wiki.png</file>
<file>resources/tips/images/coin_flip.png</file>
<file>resources/tips/images/counter_expression.png</file>
<file>resources/tips/images/discord.png</file>
<file>resources/tips/images/edhrec.png</file>
<file>resources/tips/images/expand_card_view.png</file>
<file>resources/tips/images/face_down.png</file>
<file>resources/tips/images/filter_games.png</file>
<file>resources/tips/images/github_logo.png</file>
<file>resources/tips/images/highlight_cards.png</file>
<file>resources/tips/images/pawns.png</file>
<file>resources/tips/images/setpt.png</file>
<file>resources/tips/images/shortcuts.png</file>
<file>resources/tips/images/syntax_help.png</file>
<file>resources/tips/images/themes.png</file>
<file>resources/tips/images/tip_of_the_day.png</file>
<file>resources/tips/images/token.png</file>
<file>resources/tips/images/updates.png</file>
<file>resources/tips/images/visual_deck_tags.png</file>
<file>resources/tips/tips_of_the_day.xml</file>
<file>resources/help/search.md</file>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
[debug]
showCardId=false
[localgame]
onStartup=false
playerCount=1
;deck\Player 1=path/to/deck
;deck\Player 2=path/to/deck
; Fun Fact: You can assign a deck to your username and it will auto load and ready when you join a server game
;deck\Your Username Here=path/to/deck

View File

@@ -0,0 +1,57 @@
[Rules]
# Uncomment a rule to disable logging for that category
# main = false
# qt_translator = false
# window_main.* = false
# release_channel = false
# spoiler_background_updater = false
# theme_manager = false
# sound_engine = false
# tapped_out_interface = false
# tab_game = false
# tab_message = false
# tab_supervisor = false
# dlg_edit_avatar = false
# dlg_settings = false
# dlg_tip_of_the_day = false
# dlg_update = false
# settings_cache = false
# servers_settings = false
# shortcuts_settings = false
# remote_client = false
# player = false
# game_scene = false
# game_scene.player_addition_removal = false
# card_zone = false
# view_zone = false
# user_info_connection = false
# picture_loader = false
# picture_loader.worker = false
# picture_loader.card_back_cache_fail = false
# picture_loader.picture_to_load = false
# deck_loader = false
# card_database = false
# card_database.loading = false
# card_database.loading.success_or_failure = false
# cockatrice_xml.* = false
# cockatrice_xml.xml_3_parser = false
# cockatrice_xml.xml_4_parser = false
# card_list = false
# stack_zone = false
flow_layout.debug = false
flow_widget.debug = false
flow_widget.size.debug = false
# pixel_map_generator = false
# filter_string = false

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="102.5024mm" height="102.24421mm"
viewBox="0 0 102.5024 102.24421" version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="cog_wheel.svg"
xmlns="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25"
inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" inkscape:zoom="0.66101291"
inkscape:cx="146.74449" inkscape:cy="193.64221" inkscape:window-width="1829"
inkscape:window-height="951" inkscape:window-x="0" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:current-layer="layer1"/>
<defs id="defs1"/>
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-66.148059,-97.377896)">
<g id="g1" transform="translate(-165.09777,-82.009607)">
<g id="g2" transform="matrix(0.26458333,0,0,0.26458333,64.983323,161.37858)">
<path style="fill:#333333;stroke-width:94.4882"
d="m 721.34301,94.413051 40.00966,29.763289 29.51933,-9.27053 14.63768,-46.840589 36.83817,0.48792 13.41787,46.108699 28.29952,9.5145 40.74155,-28.299519 29.0314,21.468599 -15.85748,47.08454 16.58937,23.66426 48.30432,-2.68358 12.93,34.88648 -41.71741,27.07971 -0.48792,29.27536 40.49763,26.10387 -10.2464,34.15459 -48.54834,-0.97584 -18.78502,23.42029 15.85749,45.37681 -28.29952,21.71256 -41.22947,-29.27536 -28.54348,9.75846 -13.66184,47.57246 -38.30194,-0.73188 -14.63768,-48.30435 -27.07971,-9.27054 -40.00966,29.27537 -30.25121,-20.49276 17.32125,-46.35266 -17.80918,-24.64009 -49.76812,3.17149 -11.22222,-34.64251 40.74155,-27.07971 0.48792,-30.00725 -41.71739,-27.32367 12.19807,-32.93479 48.30435,2.68358 20.24879,-24.6401 -17.32126,-47.08455 z"
id="path1"/>
<circle style="fill:#f9f9f9;stroke-width:72.1317" id="path2" cx="822.09906" cy="261.28262"
r="83.434792"/>
<circle style="fill:#4d4d4d;stroke-width:40.5147" id="circle2" cx="822.09906" cy="261.28262"
r="46.863361"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="460.5" height="531.74"
viewBox="0 0 460.5 531.74" overflow="visible" enable-background="new 0 0 460.5 531.74" xml:space="preserve">
<polygon fill="#918d8d" points="0.5,0.866 459.5,265.87 0.5,530.874 "/>
</svg>

After

Width:  |  Height:  |  Size: 657 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="531.74" height="460.5"
viewBox="0 0 531.74 460.5" overflow="visible" enable-background="new 0 0 531.74 460.5" xml:space="preserve">
<polygon fill="#918d8d" points="530.874,0.5 265.87,459.5 0.866,0.5 "/>
</svg>

After

Width:  |  Height:  |  Size: 657 B

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="B.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#ababab;fill-opacity:1"/>
<path
d="m 299.67889,84.945431 c -118.26949,0 -214.122988,83.892719 -214.122988,187.357619 0,58.63289 30.863828,110.90901 79.041488,145.28579 8.02961,5.77129 12.71356,15.13917 11.29165,25.0089 l -7.86234,55.37086 c -1.17098,8.02962 5.01851,15.22281 13.13176,15.22281 h 64.98968 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69135,-6.69135 h 13.38268 c 3.68024,0 6.69135,3.0111 6.69135,6.69135 v 46.83939 h 53.53075 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69134,-6.69135 h 13.38269 c 3.68023,0 6.69134,3.0111 6.69134,6.69135 v 46.83939 h 64.98967 c 8.11327,0 14.30275,-7.19319 13.13177,-15.22281 l -7.86234,-55.37086 c -1.4219,-9.78609 3.1784,-19.23761 11.29165,-25.0089 48.17767,-34.37678 79.0415,-86.6529 79.0415,-145.28579 0,-103.4649 -95.8535,-187.357619 -214.123,-187.357619 z M 219.38277,352.59917 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z m 160.59225,0 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z"
id="path1"
style="fill:#4d4d4d;fill-opacity:1;stroke:#000000;stroke-width:0.836419;stroke-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="U.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#5f9f56;fill-opacity:1"/>
<path
d="m 488.52401,428.04591 -80.36527,-83.50228 h 30.81218 c 9.06362,0 17.08104,-4.61393 20.90363,-12.05153 3.82262,-7.41912 2.56521,-15.92714 -3.29949,-22.19282 l -78.59482,-83.87142 h 29.06188 c 9.15413,0 17.40291,-4.93688 20.98411,-12.55902 3.54092,-7.50219 1.87106,-16.23169 -4.26525,-22.22053 L 312.83499,83.240199 c -6.06588,-5.951919 -17.38282,-5.951919 -23.45873,0 L 178.44019,191.64831 c -6.13629,5.98884 -7.79612,14.71834 -4.26523,22.22053 3.58119,7.62214 11.84001,12.55902 20.99414,12.55902 h 29.06189 l -78.60489,83.88987 c -5.84454,6.25645 -7.10199,14.75525 -3.28944,22.18361 3.82262,7.42836 11.82996,12.04229 20.90363,12.04229 h 30.81222 l -80.36527,83.50228 c -6.03569,6.26567 -7.40379,14.84754 -3.58117,22.38663 3.7723,7.42839 12.07138,12.22682 21.13497,12.22682 h 129.63669 c 0,0 -36.12127,66.38546 0,62.75824 h 80.45578 c 33.50708,5.78651 0,-62.75824 0,-62.75824 h 129.63668 c 9.06361,0 17.36266,-4.79843 21.13499,-12.22682 3.82262,-7.53909 2.45452,-16.12096 -3.58117,-22.38663 z"
id="ENVIR"
style="fill:#3f6e3a;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="B.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#c95e46;fill-opacity:1"/>
<path
style="display:inline;fill:#7e3525;fill-opacity:1;stroke:#000000;stroke-width:0.999129;stroke-dasharray:none;stroke-opacity:1"
d="m 278.25473,537.27772 c -22.36635,-1.29637 -48.78648,-8.31223 -69.74195,-18.51997 -47.30139,-23.04123 -75.19872,-59.72004 -85.45343,-112.35234 -2.77041,-14.21911 -2.51753,-48.32296 0.4755,-64.1246 4.84373,-25.57244 17.23939,-55.03329 30.65191,-72.85059 3.74877,-4.97991 16.33133,-18.11906 30.23479,-31.57223 13.09764,-12.67346 26.64745,-26.67202 30.11069,-31.10792 16.66894,-21.35045 26.46602,-44.71272 29.68313,-70.78286 1.93489,-15.67951 0.37962,-45.867231 -3.5802,-69.491071 -0.58906,-3.51428 0.36584,-3.52724 11.47726,-0.15583 36.51454,11.0792 67.37028,34.791071 89.32423,68.643431 9.96686,15.36862 20.07787,39.31263 24.78919,58.70364 2.23257,9.18886 2.53252,44.73878 0.46396,54.98571 -0.75708,3.75024 -1.10086,7.09425 -0.76396,7.43114 1.5021,1.5021 14.63666,-6.65479 21.98002,-13.65016 10.59844,-10.09621 14.32693,-17.61354 15.94714,-32.15254 l 1.16788,-10.47988 3.4626,3.95724 c 26.80954,30.6392 41.75268,56.11528 54.11775,92.26358 11.02075,32.21825 14.93902,62.79297 12.47422,97.33768 -1.88493,26.41774 -10.16486,50.6958 -24.95555,73.17369 -6.31625,9.59901 -30.86306,34.05172 -40.40914,40.25423 -23.44452,15.23295 -50.15355,25.25695 -77.26806,28.99903 -12.48732,1.72336 -38.04339,2.42637 -54.18798,1.49062 z m 48.34948,-30.34196 c 30.78066,-8.0491 53.53846,-30.12825 59.69792,-57.9177 2.48916,-11.23027 2.26087,-34.25269 -0.43747,-44.11787 -5.3998,-19.74181 -9.72931,-26.61651 -30.6237,-48.62658 -16.92925,-17.8332 -21.73398,-24.64464 -25.45673,-36.0889 -2.38622,-7.33554 -2.63126,-9.53814 -2.57644,-23.15876 0.0334,-8.27872 0.486,-17.4607 1.00593,-20.40441 0.75887,-4.29636 0.66928,-5.45812 -0.45409,-5.88919 -2.12997,-0.81736 -16.25071,4.45522 -21.90917,8.1807 -25.69349,16.91641 -42.62753,52.30879 -40.22917,84.07948 0.39046,5.17228 0.2831,8.79277 -0.26071,8.79277 -1.78935,0 -13.49435,-13.46378 -15.34792,-17.65406 -1.03171,-2.33236 -2.15967,-6.42651 -2.50657,-9.09812 -1.00143,-7.71233 -1.60778,-8.14619 -5.46339,-3.90915 -13.31687,14.63425 -24.58113,35.69359 -29.53283,55.21379 -11.75615,46.34414 2.14731,84.38956 37.55813,102.77397 16.56338,8.59931 29.2427,11.25369 51.26679,10.73261 12.58064,-0.29766 17.41119,-0.85366 25.26942,-2.90858 z"
id="path8"/>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="U.svg"
inkscape:export-filename="U.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#4a8fd8;fill-opacity:1"/>
<path
style="display:inline;fill:#3266af;fill-opacity:1;stroke:#000000;stroke-width:1.06525;stroke-opacity:1"
d="m 275.20608,536.5693 c -58.69596,-9.5447 -107.01545,-50.69962 -125.66779,-107.0344 -9.25532,-27.95342 -10.39669,-58.82111 -3.22092,-87.1088 5.31307,-20.94475 9.06296,-28.00552 81.87785,-154.17 38.54798,-66.79109 70.40461,-121.77997 70.79251,-122.19751 1.00535,-1.08215 140.3595,240.63696 145.26785,251.97682 8.6735,20.03855 12.6923,39.82747 12.6923,62.49805 0,44.25387 -16.70161,83.24077 -48.85852,114.0514 -21.46938,20.57055 -45.69209,33.39124 -76.46586,40.47213 -12.83139,2.95245 -42.64639,3.75165 -56.41742,1.51231 z"
id="path2"
sodipodi:nodetypes="ssssssssss"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
sodipodi:docname="W.svg"
inkscape:export-filename="W.png"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#ffefb3;fill-opacity:1"/>
<path
id="circle8"
d="M 387.28106,302.711 A 85.962512,85.962512 0 0 1 301.31852,388.67353 85.962512,85.962512 0 0 1 215.35597,302.711 85.962512,85.962512 0 0 1 301.31852,216.74844 85.962512,85.962512 0 0 1 387.28106,302.711 Z M 191.75349,358.6114 143.05798,460.97151 245.4181,412.27601 A 121.73882,121.73882 0 0 1 191.75349,358.6114 Z M 178.33753,302.711 c 0,-13.16763 2.23687,-25.83857 5.96271,-38.01232 L 77.71657,302.711 184.30024,340.7233 a 119.25435,119.25435 0 0 1 -5.96271,-38.0123 z m 178.8814,109.56501 102.36011,48.6955 -48.6955,-102.36011 a 121.73882,121.73882 0 0 1 -53.66461,53.66461 z m -55.90041,13.41595 c -13.16762,0 -26.0869,-2.23687 -38.01232,-5.9627 l 38.01232,106.58368 38.01231,-106.58368 a 119.25435,119.25435 0 0 1 -38.01231,5.9627 z m 109.56502,-178.88139 48.6955,-102.36012 -102.36011,48.69551 a 122.98106,122.98106 0 0 1 53.66461,53.66461 z M 245.66643,193.14596 143.30658,144.45045 192.00209,246.81057 a 121.73882,121.73882 0 0 1 53.66434,-53.66461 z M 524.92046,302.711 418.33679,264.69868 a 119.25435,119.25435 0 0 1 0,76.02462 z M 301.31852,179.73 c 13.16761,0 26.0869,2.23688 38.01231,5.96271 L 301.31852,79.109036 263.3062,185.69271 A 119.25435,119.25435 0 0 1 301.31852,179.73 Z"
style="fill:#b4a35e;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-dasharray:none;stroke-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M586.9,373.6l95.6-84.4c-49.6-39.2-129.4-79.1-198.2-79.1c-134.9,0-248.2,90.5-280.2,212.8L10.6,374.5C64.4,168.3,255.2,15.8,482.5,15.8c126.7,0,258.8,63.7,345.4,141.4l90.8-80.1L990,479.6L586.9,373.6z M317.5,710.8c49.6,39.2,129.4,79.1,198.2,79.1c134.9,0,248.2-90.5,280.2-212.8l193.5,48.5c-53.7,206.2-244.6,358.7-471.9,358.7c-126.7,0-258.8-63.7-345.4-141.4l-90.8,80.1L10,520.4l403.1,106L317.5,710.8z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 797 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200pt" height="1200pt" version="1.1" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg">
<path transform="scale(50)" d="m17 16h4v-8h-4" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m12 8h-9v8h9" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m6 12h5" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m20 4h-2c-1.1 0-2 0.9-2 2v12c0 1.1 0.9 2 2 2h2" fill="none" stroke="#000"
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m12 20h2c1.1 0 2-0.9 2-2v-12c0-1.1-0.9-2-2-2h-2" fill="none" stroke="#000"
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 875 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000" version="1.1" id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
width="800px" height="800px" viewBox="0 0 71.753 71.753"
xml:space="preserve">
<g>
<path d="M39.798,20.736H28.172v20.738L11.625,41.47V20.736H0L19.899,0.839L39.798,20.736z M51.855,70.914l19.897-19.896H60.129
V30.282l-16.547-0.004v20.74H31.957L51.855,70.914z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -1,99 +1,222 @@
<tips>
<tip>
<title>Tip of the Day</title>
<text>Tip of the Day is a new feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions!</text>
<image>tip_of_the_day.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Suggesting New Tips</title>
<text>You can suggest new Tips of the Day by reaching out to the development team on &lt;a href="https://discord.gg/3Z9yzmA"&gt;Discord&lt;/a&gt;!</text>
<image>discord.png</image>
<date>2023-10-18</date>
</tip>
<tip>
<title>Reporting Bugs</title>
<text>If you encounter a bug while using Cockatrice, you can report the bug to the development team via &lt;a href="https://github.com/cockatrice/cockatrice/issues"&gt;GitHub&lt;a&gt;</text>
<image>github_logo.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>FAQ/Troubleshooting Wiki</title>
<text>You can find answers to the most common questions and some helpful Cockatrice toubleshooting over on the &lt;a href="https://github.com/cockatrice/cockatrice/wiki"&gt;GitHub wiki&lt;a&gt;</text>
<image>cockatrice_wiki.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Register for a Server</title>
<text>Click on either Cockatrice (Windows) or Actions (Mac) and then Register to server... When the dialogue appears, fill out the desired server information.</text>
<image>cockatrice_register.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Drawing Arrows</title>
<text>You can draw arrows of different color by holding a combination of keys!
Right Click: Red Arrow
Shift + Right Click: Green Arrow
Alt + Right Click: Blue Arrow
Cmd + Right Click: Yellow Arrow
</text>
<image>arrows.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Filtering Games</title>
<text>Don't see all the active games? Want to see a smaller selection? Use the Game Filters to change your horizon</text>
<image>filter_games.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Upload Custom Avatar</title>
<text>Want to show off your hippo avatar? Need to update your password? Check out the Accounts Tab for more info!</text>
<image>accounts_tab.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Common Shortcuts</title>
<text>You can find a full list of shortcuts &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts"&gt;on the wiki&lt;/a&gt;, but a short list:
&lt;br&gt;Roll a die: CTRL + I
&lt;br&gt;Mulligan: CTRL + M
&lt;br&gt;Draw a card: CTRL + D
&lt;br&gt;Undo a draw: CTRL + SHIFT + D
&lt;br&gt;View Sideboard: CTRL + F3
&lt;br&gt;Change Life: CTRL + L
&lt;br&gt;All shortcuts can be customized via Settings->Shortcuts!
</text>
<image>shortcuts.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Changing Themes</title>
<text>Did you know Cockatrice has custom themes? You can either &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes"&gt;create one yourself&lt;/a&gt; or use one of the several pre-loaded ones! Go to Settings->Appearance and try them out!</text>
<image>themes.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Flip of the Coin</title>
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
<image>coin_flip.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Face Down Cards</title>
<text>You can hold Shift while dragging or clicking on a card to have it enter play face down</text>
<image>face_down.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Counter expressions</title>
<text>When setting a counter value, you can type a math expression in the box and the counter will be set to the result.&lt;br&gt;The "x" variable contains the current counter value.</text>
<image>counter_expression.png</image>
<date>2019-02-02</date>
</tip>
<tip>
<title>Power and Toughness</title>
<text>You can add and subtract to a creature's stats.&lt;br&gt;With a card selected, set the power and toughness ( default: ctrl + p ) and enter +3/-1 to increase power by three while decreasing toughness by one.&lt;br&gt;You can also reset it to the original value ( default: ctrl + alt + 0 ).</text>
<image>setpt.png</image>
<date>2019-03-02</date>
</tip>
<tip>
<title>Tip of the Day</title>
<text>Tip of the Day is a feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions!
Check back in with major updates for new tips to be added or old tips to be updated as features are added or expanded upon!
</text>
<image>tip_of_the_day.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Join the Community</title>
<text>You can join the community to find games, interact with other players, suggest new 'Tips of the Day' and provide user feedback to the development or support teams on &lt;a href="https://discord.gg/3Z9yzmA"&gt;Discord&lt;/a&gt;!</text>
<image>discord.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Reporting Bugs and Requesting Features</title>
<text>If you encounter a bug while using Cockatrice, you can report the bug to and request the feature from the development team via &lt;a href="https://github.com/cockatrice/cockatrice/issues"&gt;GitHub&lt;a&gt;</text>
<image>github_logo.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>FAQ/Troubleshooting Wiki</title>
<text>You can find answers to the most common questions and some helpful Cockatrice troubleshooting over on the &lt;a href="https://github.com/cockatrice/cockatrice/wiki"&gt;GitHub wiki&lt;a&gt;</text>
<image>cockatrice_wiki.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Register for a Server</title>
<text>Click on either Cockatrice (Windows) or Actions (Mac) and then Register to server... When the dialogue appears, fill out the desired server information.</text>
<image>cockatrice_register.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Filtering Games</title>
<text>Don't see an open game or want to see a smaller selection? Use the Game Filters to change your horizon!</text>
<image>filter_games.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Common Shortcuts</title>
<text>You can find a full list of default shortcuts &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts"&gt;on the wiki&lt;/a&gt; or in Settings -> Shortcuts, but a short list:
&lt;ul&gt;
&lt;li&gt;Roll a die: CMD/CTRL + I&lt;/li&gt;
&lt;li&gt;Mulligan: CMD/CTRL + M&lt;/li&gt;
&lt;li&gt;Draw 1 / X card(s): CMD/CTRL + D / E&lt;/li&gt;
&lt;li&gt;Undo a draw: CMD/CTRL + SHIFT + D&lt;/li&gt;
&lt;li&gt;View Library / Sideboard: F3 / CMD/CTRL + F3&lt;/li&gt;
&lt;li&gt;Change Life: CMD/CTRL + L&lt;/li&gt;
&lt;li&gt;Show Card Info: Middle Mouse Click&lt;/li&gt;
&lt;/ul&gt;
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
</text>
<image>shortcuts.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Power and Toughness</title>
<text>You can add and subtract to a creature's stats.
With a card selected, with the following keybindings:
&lt;ul&gt;
&lt;li&gt;Set P/T to any value: CTRL + P&lt;/li&gt;
&lt;li&gt;+1 or -1 to both to P/T: CMD/CTRL + ALT + '+' or '-'&lt;/li&gt;
&lt;li&gt;+1 or -1 to Power Only: CMD/CTRL + '+' or '-'&lt;/li&gt;
&lt;li&gt;+1 or -1 to Toughness Only: ALT + '+' or '-'&lt;/li&gt;
&lt;li&gt;Set P/T to Default: CMD/CTRL + ALT + 0&lt;/li&gt;
&lt;/ul&gt;
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
</text>
<image>setpt.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Drawing Arrows</title>
<text>You can draw arrows of different color by holding a combination of keys!
&lt;ul&gt;
&lt;li&gt;Right Click: Red Arrow&lt;/li&gt;
&lt;li&gt;SHIFT + Right Click: Green Arrow&lt;/li&gt;
&lt;li&gt;ALT + Right Click: Blue Arrow&lt;/li&gt;
&lt;li&gt;CMD/CTRL + Right Click: Yellow Arrow&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>arrows.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>General Etiquette</title>
<text>When playing on Cockatrice there are general "rules of engagement" for a better play experience for all players.
The following are some of the expectations a player should reasonably expect for how to operate smooth and enjoyable games:
&lt;ul&gt;
&lt;li&gt;Have a "Rule 0" conversation pre-game with your fellow players on the expectations of the game including deck strength, house rules (e.g. no take backs and "may is not must"), etc.&lt;/li&gt;
&lt;li&gt;When rolling your die for turn order, it is often best to create a token with the text of your roll (using CTRL + T and typing the number into "Name") and then tap this token when created to show that you have resolved your mulligans and are ready to start the game.&lt;/li&gt;
&lt;li&gt;Use the phases and steps trackers on the left of the client to show others where in the turn you are and announce when moving between them. (Double Click for the action of this button)&lt;/li&gt;
&lt;li&gt;When your turn is over leave it on your end step and DO NOT HIT PASS. Allow other players to respond if they can, and then if not, let the next player pass to themselves.&lt;/li&gt;
&lt;li&gt;Please treat others kindly and respect as per &lt;a href="https://cockatrice.us/terms.php"&gt;our Terms of Service&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>token.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Flip of the Coin</title>
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
<image>coin_flip.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Upload Custom Avatar</title>
<text>Want to show off your hippo avatar? Need to update your password? Check out the Accounts Tab for more info!</text>
<image>accounts_tab.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Player Icon Key</title>
<text>Besides your name is a player icon, this is a key for what they mean:
&lt;ul&gt;
&lt;li&gt;Flag: Country of Origin Player Selected&lt;/li&gt;
&lt;li&gt;Purple Heart: Donator (&lt;a href="https://cockatrice.us/donate"&gt;Help support us and donate here!&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Gold Star: VIP (Special Admin Given Role)&lt;/li&gt;
&lt;li&gt;Brown Gavel (Hammer): Judge / Rule's Lawyer&lt;/li&gt;
&lt;li&gt;Black/White Pawn: Moderator (Support for Client Issues)&lt;/li&gt;
&lt;li&gt;Red: Administrator (Sever Operators)&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>pawns.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Changing Themes</title>
<text>Did you know Cockatrice has custom themes? You can either &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes"&gt;create one yourself&lt;/a&gt; or use one of the several preloaded ones! Go to Settings->Appearance and try them out!</text>
<image>themes.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Face Down Cards</title>
<text>You can hold Shift while dragging or clicking on a card to have it enter play face down.
You can also hold CTRL + SHIFT and click and drag from your library to move bottom card face down as well!
</text>
<image>face_down.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Counter expressions</title>
<text>When setting a counter value, you can type a math expression in the box and the counter will be set to the result.&lt;br&gt;The "x" variable contains the current counter value.</text>
<image>counter_expression.png</image>
<date>2019-02-02</date>
</tip>
<tip>
<title>Select Multiple Cards</title>
<text>You can click and drag in any zone in order to highlight all cards within the created box.
You can also hold CMD/CTRL and clik or click and drag to maintain other previously selected cards while adding others!
You can move, alter and attach multiple highlighted cards at the same time!
Other useful multi-select keybindings:
&lt;ul&gt;
&lt;li&gt;Select All Cards in Zone: CMD/CTRL + A&lt;/li&gt;
&lt;li&gt;Select All Cards in Column: CMD/CTRL + SHIFT + C&lt;/li&gt;
&lt;li&gt;Select All Cards in Row: CMD/CTRL + SHIFT + X&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>highlight_cards.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Auto Cascade and Search Parameters</title>
<text>You can use the default keybind of CMD/CTRL + SHIFT + Y in order to perform auto cascade or similar effects from your library using Scryfall search syntax.
If you are unfamiliar with the syntax you may find it by opening a deck in deck editor and clicking the "i" next to the search bar in order to pull up a list of syntax commands.
This same syntax can be used in the deck editor search bar as well to help you find the best cards for your decks!
</text>
<image>syntax_help.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Visual Deck Storage and Tags</title>
<text>You can now view your saved decks visually with integrated folder,tags and filter support!
Pro Tip: If you want to use emoji's press WinKey + '.' or CTRL + CMD + SPACE on Windows or Mac respectively!
</text>
<image>visual_deck_tags.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Card Selector And Card Preferences</title>
<text>Cockatrice's deck editor now has the ability for players to bling out their decks by selecting the arts for cards on a per-card basis!
You can also have multiple printings of the same card in your deck if you so choose!
Not only that, other players will see the arts you have chosen by default!
If you want to disable this feature for other players: Settings -> Appearance -> Select "Override all card art with personal set preference"
</text>
<image>card_select.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>EDHREC Integration</title>
<text>We now have in-client integration for EDHREC, which allows you to right-click on any card name in the deck editor in order to bring up the contextual menu for the card.</text>
<image>edhrec.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Add Cards to Deck</title>
<text>You can now right-click anywhere on a card in any card info view in order to add it to any decks you have open in your tabs.</text>
<image>add_card.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Update Client and Card Database</title>
<text>You can update your client by going to Help and selecting whichever you wish to update.
Client Update: Updates the client (if available) for new features, fixes and changes.
Card Update: Updates card sources for spoilers and new card printings.
Updating your card sources can often fix issues of cards not working or displaying properly, if not, go to Cockatrice -> Settings -> Card Sources -> Update Spoilers
</text>
<image>updates.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Expand Card View Window</title>
<text>Double click on the title bar of the card view window to expand it! Double click again to shrink it back down.
You can configure the initial and expanded heights of the window in the settings, under "Appearance".
</text>
<image>expand_card_view.png</image>
<date>2025-02-27</date>
</tip>
</tips>

View File

@@ -2,20 +2,20 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="registered.svg">
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_donator_double.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs3">
<inkscape:perspective
@@ -226,16 +226,6 @@
offset="1"
id="stop5193-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5181-9"
id="linearGradient5436"
x1="12.105612"
y1="1021.5341"
x2="87.549789"
y2="1021.5341"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,-952.36218)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173-1"
@@ -288,6 +278,28 @@
id="linearGradient5799"
xlink:href="#linearGradient5181-9"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2"
id="linearGradient3"
x1="49.889599"
y1="87.971054"
x2="50.103622"
y2="27.668242"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2878408,0,0,1.2878408,-14.204862,937.12313)" />
<linearGradient
id="linearGradient2"
inkscape:collect="always">
<stop
style="stop-color:#8c5fd3;stop-opacity:1;"
offset="0"
id="stop2" />
<stop
style="stop-color:#b284e9;stop-opacity:1;"
offset="0.5"
id="stop1" />
</linearGradient>
</defs>
<sodipodi:namedview
inkscape:document-units="mm"
@@ -297,16 +309,26 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="-150.71429"
inkscape:cy="59.570011"
inkscape:zoom="6.0735294"
inkscape:cx="53.675545"
inkscape:cy="53.922518"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
inkscape:window-width="1147"
inkscape:window-height="1211"
inkscape:window-x="2678"
inkscape:window-y="120"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true">
<sodipodi:guide
position="49.829627,61.114263"
orientation="1,0"
id="guide1"
inkscape:locked="false" />
</sodipodi:namedview>
<metadata
id="metadata4">
<rdf:RDF>
@@ -325,9 +347,20 @@
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:url(#linearGradient5436);fill-opacity:1;stroke:black;stroke-width:2.78220295999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
id="right" />
<path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="left"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.77952756;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 32.758369,1023.3386 c -11.433625,-11.4486 -17.473759,-17.611 -17.925056,-18.2881 -5.1991493,-7.80033 -4.072462,-18.0055 2.698653,-24.44352 0.714467,-0.67932 1.7595,-1.54783 2.322296,-1.93001 1.523368,-1.0345 4.16292,-2.23825 5.970504,-2.72281 1.443337,-0.38692 1.89368,-0.43006 4.608041,-0.44142 3.235152,-0.0136 4.137158,0.12212 6.533598,0.9827 3.134814,1.12573 4.852536,2.32851 8.590659,6.01531 1.655211,1.63249 3.214977,3.04629 3.466142,3.14178 0.581823,0.22121 1.425484,0.22197 2.004581,0.002 0.248578,-0.0945 1.808341,-1.50526 3.466143,-3.135 3.106188,-3.05362 4.561863,-4.18308 6.729637,-5.22153 5.163233,-2.47341 10.985326,-2.50551 16.312741,-0.0899 2.006474,0.90978 3.995303,2.39379 5.679043,4.16678 1.393273,1.46713 2.577641,3.13214 3.390238,4.83339 1.300107,2.7219 1.79207,4.98307 1.79207,8.23671 0,4.67613 -1.161204,8.04312 -4.066015,11.78952 -0.567611,0.7321 -8.293484,8.5311 -17.668765,17.8362 l -16.660107,16.5352 z"
id="path2"
sodipodi:nodetypes="sssssssssssssssssscs"
inkscape:label="heart" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,229 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_donator_single.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
id="defs3"><linearGradient
id="linearGradient2"
inkscape:collect="always"><stop
style="stop-color:#8c5fd3;stop-opacity:1;"
offset="0"
id="stop2" /><stop
style="stop-color:#b284e9;stop-opacity:1;"
offset="0.5"
id="stop1" /></linearGradient><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5328" /><inkscape:perspective
id="perspective5305"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
id="linearGradient5181"><stop
style="stop-color:#0fbb00;stop-opacity:1;"
offset="0"
id="stop5183" /><stop
style="stop-color:#064400;stop-opacity:1;"
offset="1"
id="stop5185" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-2"
id="radialGradient3606-7"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-2"><stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-4" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-9" /></linearGradient><inkscape:perspective
id="perspective5478"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
id="linearGradient5189"><stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191" /><stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-4"
id="radialGradient3606-1"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-4"><stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-3" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-5" /></linearGradient><inkscape:perspective
id="perspective5559"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173"
id="linearGradient5179"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientUnits="userSpaceOnUse" /><linearGradient
id="linearGradient5173"><stop
style="stop-color:#f50000;stop-opacity:1;"
offset="0"
id="stop5175" /><stop
style="stop-color:#950000;stop-opacity:1;"
offset="1"
id="stop5177" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600"
id="radialGradient5169"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276" /><linearGradient
id="linearGradient3600"><stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604" /></linearGradient><radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5574"
xlink:href="#linearGradient3600"
inkscape:collect="always" /><inkscape:perspective
id="perspective5663"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-7"
id="radialGradient3606-8"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-7"><stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602-7" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-6" /></linearGradient><radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5676"
xlink:href="#linearGradient3600-7"
inkscape:collect="always" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2"
id="linearGradient3"
x1="49.889599"
y1="87.971054"
x2="50.103622"
y2="27.668242"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2878408,0,0,1.2878408,-14.204016,-15.239682)" /></defs><sodipodi:namedview
inkscape:document-units="mm"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.9195959"
inkscape:cx="55.179583"
inkscape:cy="45.519999"
inkscape:current-layer="layer2"
showgrid="false"
inkscape:window-width="1147"
inkscape:window-height="1211"
inkscape:window-x="3260"
inkscape:window-y="138"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true"><sodipodi:guide
position="50.002551,111.99556"
orientation="1,0"
id="guide3"
inkscape:locked="false" /></sodipodi:namedview><metadata
id="metadata4"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)"
style="display:inline"><path
style="display:inline;opacity:1;fill-opacity:1;stroke:#000000;stroke-width:2.7822;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 49.84375,1.71875 C 36.719738,1.71875 26.0625,12.375988 26.0625,25.5 c 0,7.477454 3.475825,14.112734 8.875,18.46875 -10.497549,5.974948 -17.018351,18.227376 -20.625,31.6875 -5.2744126,19.6844 15.911513,22.5625 35.53125,22.5625 19.619736,0 40.705577,-3.2516 35.53125,-22.5625 C 81.693381,61.916246 75.224585,49.827177 64.8125,43.9375 70.181573,39.580662 73.59375,32.953205 73.59375,25.5 c 0,-13.124012 -10.625988,-23.78125 -23.75,-23.78125 z"
id="left"
transform="translate(0,952.36218)" /></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"><path
style="display:inline;fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.77952756;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 32.759215,70.975878 C 21.325591,59.527249 15.285457,53.364742 14.83416,52.687661 9.63501,44.887358 10.761698,34.682189 17.532813,28.244167 c 0.714467,-0.67932 1.7595,-1.547825 2.322296,-1.930012 1.523368,-1.034499 4.16292,-2.238249 5.970504,-2.722807 1.443337,-0.386915 1.89368,-0.430056 4.60804,-0.441421 3.235152,-0.01355 4.137158,0.122126 6.533598,0.982701 3.134814,1.125736 4.852536,2.328512 8.590659,6.015311 1.655211,1.632489 3.214977,3.046293 3.466142,3.141784 0.581823,0.221209 1.425484,0.221963 2.004581,0.0018 0.248578,-0.09451 1.808341,-1.50526 3.466143,-3.135003 3.106188,-3.053615 4.561863,-4.183076 6.729637,-5.221531 5.163233,-2.473409 10.985326,-2.505514 16.312741,-0.08995 2.006474,0.909779 3.995303,2.393791 5.679043,4.166785 1.393273,1.467129 2.577641,3.132133 3.390238,4.833386 1.300107,2.721904 1.79207,4.98307 1.79207,8.23671 0,4.676126 -1.161204,8.043076 -4.066015,11.789548 -0.567611,0.732076 -8.293484,8.531153 -17.668765,17.836181 l -16.660107,16.53525 z"
id="path2"
sodipodi:nodetypes="sssssssssssssssssscs"
inkscape:label="heart" /></g></svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -2,20 +2,20 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="normal.svg">
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_double.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs3">
<inkscape:perspective
@@ -195,66 +195,16 @@
id="stop3604-6" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-7"
id="radialGradient5254"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
cx="324.32715"
cy="131.40274"
fx="324.32715"
r="25.501276"
fy="131.40274"
r="25.501276" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5189-1"
id="linearGradient5394"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
x1="385.03503"
y1="180.09546"
x2="462.48297"
y2="180.09546"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-360.365,847.52359)" />
<linearGradient
id="linearGradient5189-1">
<stop
style="stop-color:#32c8ed;stop-opacity:1;"
offset="0"
id="stop5191-0" />
<stop
style="stop-color:#32c8ed;stop-opacity:1;"
offset="1"
id="stop5193-4" />
</linearGradient>
<linearGradient
y2="180.09546"
x2="462.48297"
y1="180.09546"
x1="385.03503"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-318.22214,876.88769)"
gradientUnits="userSpaceOnUse"
id="linearGradient5411"
xlink:href="#linearGradient5189-1"
id="radialGradient5676"
xlink:href="#linearGradient3600-7"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5189-1"
id="linearGradient5436"
x1="12.105612"
y1="1021.5341"
x2="87.549789"
y2="1021.5341"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5189-1"
id="linearGradient3795"
gradientUnits="userSpaceOnUse"
x1="12.105612"
y1="1021.5341"
x2="87.549789"
y2="1021.5341"
gradientTransform="translate(0,-952.36218)" />
</defs>
<sodipodi:namedview
inkscape:document-units="mm"
@@ -264,16 +214,19 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="-150.71429"
inkscape:cy="59.570011"
inkscape:current-layer="layer1"
inkscape:zoom="5.6"
inkscape:cx="63.214286"
inkscape:cy="46.160714"
inkscape:current-layer="g5249"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
inkscape:window-width="1147"
inkscape:window-height="1211"
inkscape:window-x="2842"
inkscape:window-y="58"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata4">
<rdf:RDF>
@@ -291,10 +244,25 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:url(#linearGradient3795);fill-opacity:1;stroke:black;stroke-width:2.78220295999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;opacity:1"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
<g
id="g5249"
transform="translate(0.53874115,0.90502985)">
<path
style="stroke:#000000;stroke-width:4.45809746000000030;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1"
d="m 49.582319,954.34642 c -12.850034,0 -23.284789,10.43476 -23.284789,23.28479 0,7.32135 3.403263,13.81811 8.689724,18.08319 -10.278401,5.8502 -16.663073,17.8469 -20.19443,31.0259 -5.1178053,19.1 15.207096,22.0401 34.269334,22.0915 l 0,0.031 c 0.290839,0 0.566498,0.031 0.856734,0.031 19.210152,0 39.855802,-3.1837 34.789494,-22.0914 -3.636192,-13.5705 -10.027831,-25.4711 -20.378015,-31.17899 5.208701,-4.26694 8.506139,-10.73278 8.506139,-17.9914 0,-12.85003 -10.404159,-23.28479 -23.254191,-23.28479 z"
id="left"
inkscape:connector-curvature="0" />
<path
fill="none"
style="stroke:#000000;stroke-width:1.97203517px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 50.522358,952.70715 0,95.71425"
id="center"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.71966;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.054254,1001.4773 v -45.77683 l 1.097241,0.005 c 3.642211,0.0172 9.170661,2.46935 12.395732,5.49816 4.897489,4.59945 7.421654,10.97001 6.981907,17.62114 -0.389167,5.88609 -2.631878,10.66609 -6.951818,14.81672 l -2.05562,1.97506 2.959813,2.0746 c 3.467097,2.43015 7.403677,6.55065 9.666109,10.11765 3.325898,5.2437 6.79289,13.8355 8.153827,20.2065 2.584451,12.0989 -5.997953,18.2384 -26.592174,19.0232 l -5.655017,0.2154 v -45.7768 z"
id="right"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -2,33 +2,22 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="registered_vip.svg">
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_judge_double.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs3">
<linearGradient
id="linearGradient5181-9-1">
<stop
id="stop4188"
offset="0"
style="stop-color:#ece400;stop-opacity:1" />
<stop
id="stop4190"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
@@ -237,16 +226,6 @@
offset="1"
id="stop5193-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5181-9-1"
id="linearGradient5436"
x1="47.268291"
y1="933.14362"
x2="48.665382"
y2="1050.2666"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,-952.36218)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173-1"
@@ -309,15 +288,18 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.2946338"
inkscape:cx="35.27742"
inkscape:cy="65.175571"
inkscape:current-layer="layer1"
inkscape:cx="34.112338"
inkscape:cy="64.964794"
inkscape:current-layer="svg5322"
showgrid="false"
inkscape:window-width="1152"
inkscape:window-height="811"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
inkscape:window-width="1440"
inkscape:window-height="792"
inkscape:window-x="2921"
inkscape:window-y="661"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata4">
<rdf:RDF>
@@ -326,7 +308,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -336,9 +318,20 @@
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:url(#linearGradient5436);fill-opacity:1;stroke:black;stroke-width:2.78149606;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
id="right" />
<path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="left"
inkscape:connector-curvature="0" />
<path
d="m 46.656521,12.167234 18.055171,18.054184 a 6.6081919,6.6078288 0 0 1 -0.126303,9.352065 6.6804126,6.6800456 0 0 1 -8.233169,1.011048 l -7.944268,7.943843 6.463762,6.445343 a 6.9331851,6.9328042 0 0 1 5.741536,2.022073 l 28.057729,28.092294 a 6.9962797,6.9958953 0 0 1 -9.894222,9.893685 L 50.719018,66.907526 A 7.0595711,7.0591833 0 0 1 49.18433,59.270613 l -5.741527,-5.741238 -7.944298,7.943843 A 6.716523,6.7161541 0 0 1 25.134866,69.832263 L 7.079684,51.778091 a 6.716523,6.7161541 0 0 1 8.39566,-10.345064 L 36.31101,20.59853 a 6.716523,6.7161541 0 0 1 10.345612,-8.431329 z"
id="path1-2"
style="display:inline;fill:#e1964c;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.7852;stroke-dasharray:none;stroke-opacity:1"
inkscape:label="gavel"
transform="translate(0,952.36218)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_judge_single.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><defs
id="defs3"><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5328" /><inkscape:perspective
id="perspective5305"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
id="linearGradient5181"><stop
style="stop-color:#0fbb00;stop-opacity:1;"
offset="0"
id="stop5183" /><stop
style="stop-color:#064400;stop-opacity:1;"
offset="1"
id="stop5185" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-2"
id="radialGradient3606-7"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-2"><stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-4" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-9" /></linearGradient><inkscape:perspective
id="perspective5478"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
id="linearGradient5189"><stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191" /><stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-4"
id="radialGradient3606-1"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-4"><stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-3" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-5" /></linearGradient><inkscape:perspective
id="perspective5559"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173"
id="linearGradient5179"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientUnits="userSpaceOnUse" /><linearGradient
id="linearGradient5173"><stop
style="stop-color:#f50000;stop-opacity:1;"
offset="0"
id="stop5175" /><stop
style="stop-color:#950000;stop-opacity:1;"
offset="1"
id="stop5177" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600"
id="radialGradient5169"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276" /><linearGradient
id="linearGradient3600"><stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604" /></linearGradient><radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5574"
xlink:href="#linearGradient3600"
inkscape:collect="always" /><inkscape:perspective
id="perspective5663"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-7"
id="radialGradient3606-8"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" /><linearGradient
id="linearGradient3600-7"><stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602-7" /><stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-6" /></linearGradient><radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5676"
xlink:href="#linearGradient3600-7"
inkscape:collect="always" /></defs><sodipodi:namedview
inkscape:document-units="mm"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="58.035715"
inkscape:cy="30.982143"
inkscape:current-layer="svg5322"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1369"
inkscape:window-x="2552"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showguides="true"><sodipodi:guide
position="50.002551,111.99556"
orientation="1,0"
id="guide3"
inkscape:locked="false" /></sodipodi:namedview><metadata
id="metadata4"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)"
style="display:inline">
<path
style="display:inline;opacity:1;fill-opacity:1;stroke:#000000;stroke-width:2.7822;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 49.84375,1.71875 C 36.719738,1.71875 26.0625,12.375988 26.0625,25.5 c 0,7.477454 3.475825,14.112734 8.875,18.46875 -10.497549,5.974948 -17.018351,18.227376 -20.625,31.6875 -5.2744126,19.6844 15.911513,22.5625 35.53125,22.5625 19.619736,0 40.705577,-3.2516 35.53125,-22.5625 C 81.693381,61.916246 75.224585,49.827177 64.8125,43.9375 70.181573,39.580662 73.59375,32.953205 73.59375,25.5 c 0,-13.124012 -10.625988,-23.78125 -23.75,-23.78125 z"
id="left"
sodipodi:insensitive="true"
transform="translate(0,952.36218)" />
<path
d="m 46.233565,28.34179 -1.622479,1.622479 a 0.59382712,0.59382712 0 0 1 -0.840444,-0.01135 0.60031703,0.60031703 0 0 1 -0.09086,-0.739851 l -0.713891,-0.71389 -0.579225,0.580848 a 0.62303175,0.62303175 0 0 1 -0.181718,0.515948 l -2.524576,2.521331 a 0.62870157,0.62870157 0 0 1 -0.889118,-0.889117 l 2.522954,-2.521332 a 0.63438908,0.63438908 0 0 1 0.686308,-0.137911 l 0.515949,-0.515947 -0.713891,-0.713892 a 0.603562,0.603562 0 0 1 -0.751204,-0.9313 l 1.622478,-1.62248 a 0.603562,0.603562 0 0 1 0.929682,0.754453 l 1.872338,1.87234 a 0.603562,0.603562 0 0 1 0.7577,0.92968 z"
id="path1-2"
style="display:inline;fill:#e1964c;fill-rule:nonzero;stroke:#000000;stroke-width:0.34015748;stroke-opacity:1;fill-opacity:1;stroke-dasharray:none"
transform="matrix(0,-11.111111,11.111111,0,-268.32014,1478.2316)"
inkscape:label="gavel" /></g></svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -2,20 +2,20 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="vip.svg">
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pawn_single.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs3">
<inkscape:perspective
@@ -194,57 +194,16 @@
offset="1"
id="stop3604-6" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5189-1"
id="linearGradient5394"
<radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
x1="385.03503"
y1="180.09546"
x2="462.48297"
y2="180.09546"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-360.365,847.52359)" />
<linearGradient
id="linearGradient5189-1">
<stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191-0" />
<stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173-1"
id="linearGradient5581"
gradientUnits="userSpaceOnUse"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-149.54484,848.74636)" />
<linearGradient
id="linearGradient5173-1">
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="0"
id="stop5175-5" />
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="1"
id="stop5177-3" />
</linearGradient>
<linearGradient
y2="178.83276"
x2="244.78181"
y1="178.83276"
x1="167.33386"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-52.401983,877.75333)"
gradientUnits="userSpaceOnUse"
id="linearGradient5598"
xlink:href="#linearGradient5173-1"
id="radialGradient5676"
xlink:href="#linearGradient3600-7"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
@@ -255,16 +214,19 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="-59.166471"
inkscape:cy="4.9508223"
inkscape:zoom="5.6"
inkscape:cx="63.214286"
inkscape:cy="46.160714"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1440"
inkscape:window-height="792"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
inkscape:window-width="1147"
inkscape:window-height="1211"
inkscape:window-x="3185"
inkscape:window-y="44"
inkscape:window-maximized="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata4">
<rdf:RDF>
@@ -283,9 +245,9 @@
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:#8d5fd3;fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;opacity:1"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
id="path3597-8"
id="left"
transform="translate(0,952.36218)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -337,19 +337,19 @@
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:#ffffff;fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
id="right" />
<path
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="path5355"
id="left"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:url(#linearGradient3425-5);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path3415-0"
id="star"
sodipodi:sides="5"
sodipodi:cx="27.80283"
sodipodi:cy="970.9433"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -337,14 +337,14 @@
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:#ff0000;fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
id="left" />
<path
sodipodi:type="star"
style="fill:url(#linearGradient3425);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path3415"
id="star"
sodipodi:sides="5"
sodipodi:cx="27.80283"
sodipodi:cy="970.9433"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -114,18 +114,18 @@
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
id="outline"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 55.041981,25.814432 36.921945,25.730432 31.404334,7.3935963 25.885923,25.730432 7.7650846,25.814434 22.476316,37.520057 15.0387,57.488097 31.404334,44.800071 47.777965,57.488097 40.331551,37.520057 z"
id="path4"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero"
id="left"
style="fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0" />
<path
d="M 56.276895,25.211993 37.3433,24.856806 31.486705,5.7742084 c 0.04705,37.4359336 -0.01851,2.6744908 -0.0678,40.1841446 L 48.19932,58.580578 40.956295,37.527792 z"
id="path4-1"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero"
id="right"
style="fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -109,7 +109,7 @@
inkscape:connector-curvature="0" />
<path
d="M 57.150089,25.064396 37.504323,24.973324 31.522122,5.092503 25.539054,24.973324 5.8924192,25.064399 21.842354,37.75565 13.778482,59.405024 31.522122,45.64865 49.274434,59.405024 41.201022,37.75565 z"
id="path4"
style="fill:url(#linearGradient3756);fill-opacity:1"
id="left"
style="fill-opacity:1"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,301 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="admin.svg">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5328" />
<inkscape:perspective
id="perspective5305"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient5181">
<stop
style="stop-color:#0fbb00;stop-opacity:1;"
offset="0"
id="stop5183" />
<stop
style="stop-color:#064400;stop-opacity:1;"
offset="1"
id="stop5185" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-2"
id="radialGradient3606-7"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-2">
<stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-4" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-9" />
</linearGradient>
<inkscape:perspective
id="perspective5478"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient5189">
<stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191" />
<stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-4"
id="radialGradient3606-1"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-4">
<stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-3" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-5" />
</linearGradient>
<inkscape:perspective
id="perspective5559"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173"
id="linearGradient5179"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5173">
<stop
style="stop-color:#f50000;stop-opacity:1;"
offset="0"
id="stop5175" />
<stop
style="stop-color:#950000;stop-opacity:1;"
offset="1"
id="stop5177" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600"
id="radialGradient5169"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276" />
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5574"
xlink:href="#linearGradient3600"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5663"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-7"
id="radialGradient3606-8"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-7">
<stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602-7" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-6" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5189-1"
id="linearGradient5394"
gradientUnits="userSpaceOnUse"
x1="385.03503"
y1="180.09546"
x2="462.48297"
y2="180.09546"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-360.365,847.52359)" />
<linearGradient
id="linearGradient5189-1">
<stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191-0" />
<stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193-4" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173-1"
id="linearGradient5436"
x1="12.105612"
y1="1021.5341"
x2="87.549789"
y2="1021.5341"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,-952.36218)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173-1"
id="linearGradient5581"
gradientUnits="userSpaceOnUse"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-149.54484,848.74636)" />
<linearGradient
id="linearGradient5173-1">
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="0"
id="stop5175-5" />
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="1"
id="stop5177-3" />
</linearGradient>
<linearGradient
y2="178.83276"
x2="244.78181"
y1="178.83276"
x1="167.33386"
gradientTransform="matrix(0.96839241,0,0,0.96839241,-52.401983,877.75333)"
gradientUnits="userSpaceOnUse"
id="linearGradient5598"
xlink:href="#linearGradient5173-1"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
inkscape:document-units="mm"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="-32.045264"
inkscape:cy="65.284297"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)">
<path
style="fill:url(#linearGradient5436);fill-opacity:1;stroke:black;stroke-width:2.78220295999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)"
id="path3597-8" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 64 64"
enable-background="new 0 0 64 64"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
width="100%"
height="100%"
sodipodi:docname="admin_buddy.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient3766">
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="0"
id="stop3768" />
<stop
style="stop-color:#820000;stop-opacity:1;"
offset="1"
id="stop3770" />
</linearGradient>
<linearGradient
id="linearGradient5225">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5227" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop5229" />
</linearGradient>
<linearGradient
id="linearGradient5219"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5221" />
</linearGradient>
<linearGradient
id="linearGradient3758">
<stop
id="stop3760"
offset="0"
style="stop-color:#0fbb00;stop-opacity:1;" />
<stop
id="stop3762"
offset="1"
style="stop-color:#064400;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3750">
<stop
style="stop-color:#ece400;stop-opacity:1;"
offset="0"
id="stop3752" />
<stop
style="stop-color:#ece400;stop-opacity:0;"
offset="1"
id="stop3754" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756-1"
x1="1.960216"
y1="31.261461"
x2="60.456024"
y2="31.261461"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3758-7">
<stop
id="stop3760-4"
offset="0"
style="stop-color:#ece400;stop-opacity:1;" />
<stop
id="stop3762-0"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview8"
showgrid="false"
inkscape:zoom="5.2149125"
inkscape:cx="-37.840247"
inkscape:cy="51.245759"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 57.150089,25.064396 37.504323,24.973324 31.522122,5.092503 25.539054,24.973324 5.8924192,25.064399 21.842354,37.75565 13.778482,59.405024 31.522122,45.64865 49.274434,59.405024 41.201022,37.75565 z"
id="path4"
style="fill:#ff2700;fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 64 64"
enable-background="new 0 0 64 64"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
width="100%"
height="100%"
sodipodi:docname="admin_buddy.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient3766">
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="0"
id="stop3768" />
<stop
style="stop-color:#820000;stop-opacity:1;"
offset="1"
id="stop3770" />
</linearGradient>
<linearGradient
id="linearGradient5225">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5227" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop5229" />
</linearGradient>
<linearGradient
id="linearGradient5219"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5221" />
</linearGradient>
<linearGradient
id="linearGradient3758">
<stop
id="stop3760"
offset="0"
style="stop-color:#0fbb00;stop-opacity:1;" />
<stop
id="stop3762"
offset="1"
style="stop-color:#064400;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3750">
<stop
style="stop-color:#ece400;stop-opacity:1;"
offset="0"
id="stop3752" />
<stop
style="stop-color:#ece400;stop-opacity:0;"
offset="1"
id="stop3754" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756-1"
x1="1.960216"
y1="31.261461"
x2="60.456024"
y2="31.261461"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3758-7">
<stop
id="stop3760-4"
offset="0"
style="stop-color:#ece400;stop-opacity:1;" />
<stop
id="stop3762-0"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview8"
showgrid="false"
inkscape:zoom="5.2149125"
inkscape:cx="-37.840247"
inkscape:cy="51.245759"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 57.150089,25.064396 37.504323,24.973324 31.522122,5.092503 25.539054,24.973324 5.8924192,25.064399 21.842354,37.75565 13.778482,59.405024 31.522122,45.64865 49.274434,59.405024 41.201022,37.75565 z"
id="path4"
style="fill:#ff2700;fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,294 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="100"
height="100"
id="svg5322"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="moderator.svg">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5328" />
<inkscape:perspective
id="perspective5305"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient5181">
<stop
style="stop-color:#0fbb00;stop-opacity:1;"
offset="0"
id="stop5183" />
<stop
style="stop-color:#064400;stop-opacity:1;"
offset="1"
id="stop5185" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-2"
id="radialGradient3606-7"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-2">
<stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-4" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-9" />
</linearGradient>
<inkscape:perspective
id="perspective5478"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient5189">
<stop
style="stop-color:#000ec9;stop-opacity:1;"
offset="0"
id="stop5191" />
<stop
style="stop-color:#000657;stop-opacity:1;"
offset="1"
id="stop5193" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-4"
id="radialGradient3606-1"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-4">
<stop
style="stop-color:#ffc33d;stop-opacity:1;"
offset="0"
id="stop3602-3" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-5" />
</linearGradient>
<inkscape:perspective
id="perspective5559"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5173"
id="linearGradient5179"
x1="167.33386"
y1="178.83276"
x2="244.78181"
y2="178.83276"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient5173">
<stop
style="stop-color:#f50000;stop-opacity:1;"
offset="0"
id="stop5175" />
<stop
style="stop-color:#950000;stop-opacity:1;"
offset="1"
id="stop5177" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600"
id="radialGradient5169"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276" />
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5574"
xlink:href="#linearGradient3600"
inkscape:collect="always" />
<inkscape:perspective
id="perspective5663"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3600-7"
id="radialGradient3606-8"
cx="324.32715"
cy="131.40274"
fx="324.32715"
fy="131.40274"
r="25.501276"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)" />
<linearGradient
id="linearGradient3600-7">
<stop
style="stop-color:#ffc13d;stop-opacity:1;"
offset="0"
id="stop3602-7" />
<stop
style="stop-color:#e09900;stop-opacity:1;"
offset="1"
id="stop3604-6" />
</linearGradient>
<radialGradient
r="25.501276"
fy="131.40274"
fx="324.32715"
cy="131.40274"
cx="324.32715"
gradientTransform="matrix(0.92332021,0.38403097,-0.41592401,1.0000002,78.192026,-120.05314)"
gradientUnits="userSpaceOnUse"
id="radialGradient5676"
xlink:href="#linearGradient3600-7"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
inkscape:document-units="mm"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="63.241533"
inkscape:cy="46.246766"
inkscape:current-layer="g5249"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-952.36218)">
<g
id="g5249"
transform="translate(0.53874115,0.90502985)">
<path
style="fill:#ffffff;stroke:#000000;stroke-width:4.45809746000000030;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1"
d="m 49.582319,954.34642 c -12.850034,0 -23.284789,10.43476 -23.284789,23.28479 0,7.32135 3.403263,13.81811 8.689724,18.08319 -10.278401,5.8502 -16.663073,17.8469 -20.19443,31.0259 -5.1178053,19.1 15.207096,22.0401 34.269334,22.0915 l 0,0.031 c 0.290839,0 0.566498,0.031 0.856734,0.031 19.210152,0 39.855802,-3.1837 34.789494,-22.0914 -3.636192,-13.5705 -10.027831,-25.4711 -20.378015,-31.17899 5.208701,-4.26694 8.506139,-10.73278 8.506139,-17.9914 0,-12.85003 -10.404159,-23.28479 -23.254191,-23.28479 z"
id="path3597-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:0.97203517px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 50.522358,952.70715 0,95.71425"
id="path5303"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.5844 0,-46.66155 1.096703,0.005 c 3.640423,0.0175 9.166159,2.51708 12.389647,5.60443 4.895085,4.68835 7.418012,11.18204 6.97848,17.96172 -0.388976,5.99986 -2.630586,10.87224 -6.948405,15.1031 l -2.054611,2.01323 2.95836,2.1147 c 3.465395,2.47714 7.400043,6.67727 9.661364,10.31317 3.324266,5.3451 6.789556,14.1029 8.149825,20.5971 2.583182,12.3327 -5.995009,18.5909 -26.579121,19.3908 l -5.652242,0.2196 0,-46.6616 z"
id="path5343"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.5844 0,-46.66155 1.096703,0.005 c 3.711439,0.0179 9.230395,2.54932 12.52612,5.74551 2.710429,2.62858 4.363146,5.23853 5.699734,9.00096 0.930917,2.62048 1.042531,3.35671 1.066373,7.03397 0.02902,4.47725 -0.343832,6.4262 -1.860873,9.72679 -1.358173,2.95494 -2.652341,4.81714 -4.971275,7.15326 l -2.043484,2.05863 2.932618,2.09329 c 6.98445,4.98544 12.210204,12.81934 15.750058,23.61084 3.543721,10.8033 3.39602,15.1985 -0.654452,19.4747 -4.329667,4.571 -11.449354,6.7169 -23.88928,7.2003 l -5.652242,0.2196 0,-46.6616 z"
id="path5345"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.5844 0,-46.66155 1.127086,0 c 1.963684,0 6.316627,1.3793 8.624731,2.73288 1.305624,0.76568 3.277555,2.429 4.764529,4.01888 4.347263,4.6481 6.318993,10.15893 5.954049,16.6411 -0.326518,5.79966 -2.122114,9.97998 -6.25177,14.55473 -1.44716,1.60313 -2.388203,2.91735 -2.210758,3.08744 0.169927,0.16289 1.447842,1.10199 2.839812,2.08691 6.268453,4.43531 11.362918,11.94641 14.960201,22.05661 2.740177,7.7013 3.480992,12.7857 2.399253,16.4664 -0.490882,1.6703 -1.040601,2.5538 -2.66191,4.2781 -4.29247,4.5651 -11.326737,6.6778 -23.892981,7.176 l -5.652242,0.2241 0,-46.6616 z"
id="path5347"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.5855 0,-46.66265 1.127086,0 c 1.830826,0 6.182017,1.32383 8.427379,2.56398 3.074383,1.69804 7.222246,6.22736 8.789514,9.59784 4.043357,8.69543 2.602054,18.25614 -3.837601,25.45626 -1.482649,1.65774 -2.695724,3.09743 -2.695724,3.19932 0,0.10189 1.186029,0.99046 2.635621,1.97461 3.078254,2.08987 6.81705,5.92344 9.062839,9.29254 3.274171,4.9119 7.232757,14.564 8.731682,21.29 0.646579,2.9014 0.614978,6.1318 -0.08275,8.4594 -0.86467,2.8846 -4.147214,6.2392 -7.573604,7.74 -5.13932,2.251 -10.156844,3.194 -18.763476,3.5265 l -5.820965,0.2249 0,-46.6627 z"
id="path5349"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.5853 0,-46.66245 1.164456,0 c 4.764705,0 11.112502,3.49049 14.697127,8.08157 5.260553,6.73756 6.190324,16.72129 2.284493,24.53056 -0.608066,1.21576 -2.304134,3.5367 -3.77148,5.16099 -1.466571,1.62342 -2.603753,3.01808 -2.527074,3.09924 0.07667,0.0811 1.300896,0.95003 2.720481,1.93083 6.904062,4.77006 12.487313,13.40446 16.085176,24.87536 1.733472,5.5268 2.208105,8.1847 2.003089,11.2173 -0.604468,8.9414 -9.318247,13.5855 -26.66658,14.2125 l -5.989688,0.2165 0,-46.6624 z"
id="path5351"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.7111 0,-46.78825 1.265427,0.005 c 4.153532,0.0173 9.758512,2.75815 13.295303,6.50137 1.792452,1.89707 2.63621,3.17089 3.798098,5.73397 1.746736,3.85324 2.225454,6.0014 2.225454,9.98629 0,6.50755 -2.416561,12.11247 -7.223569,16.75421 -0.945331,0.91283 -1.642858,1.7317 -1.550059,1.81971 0.0928,0.088 1.155757,0.85585 2.362131,1.70631 3.35942,2.36829 4.992087,3.86859 7.229212,6.64329 3.924869,4.8681 7.249491,11.7229 9.87191,20.3544 1.173448,3.8623 1.289753,4.5994 1.289753,8.1737 0,3.6878 -0.0614,4.0459 -1.001592,5.8425 -1.309266,2.5017 -3.108338,4.122 -6.422247,5.7839 -4.375689,2.1945 -9.62921,3.3669 -16.70364,3.7278 -2.134354,0.1088 -4.905639,0.2757 -6.158413,0.3708 l -2.277768,0.1729 0,-46.7882 z"
id="path5353"
inkscape:connector-curvature="0" />
<path
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 51.062274,1000.6174 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938259,6.36366 4.743924,4.9715 6.879132,11.35611 6.164642,18.43328 -0.537028,5.31935 -3.090083,10.59498 -6.838339,14.13074 l -1.940717,1.83069 3.040832,2.20427 c 3.580837,2.59571 7.189745,6.4912 9.552957,10.3116 4.895721,7.9144 9.235933,21.4918 8.504868,26.6055 -0.813112,5.6877 -5.438715,9.6977 -13.622159,11.8093 -3.808212,0.9826 -7.680557,1.4713 -14.763317,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="path5355"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 64 64"
enable-background="new 0 0 64 64"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
width="100%"
height="100%"
sodipodi:docname="moderator_buddy.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient5225">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5227" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop5229" />
</linearGradient>
<linearGradient
id="linearGradient5219"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5221" />
</linearGradient>
<linearGradient
id="linearGradient3758">
<stop
id="stop3760"
offset="0"
style="stop-color:#0fbb00;stop-opacity:1;" />
<stop
id="stop3762"
offset="1"
style="stop-color:#064400;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3750">
<stop
style="stop-color:#ece400;stop-opacity:1;"
offset="0"
id="stop3752" />
<stop
style="stop-color:#ece400;stop-opacity:0;"
offset="1"
id="stop3754" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756-1"
x1="1.960216"
y1="31.261461"
x2="60.456024"
y2="31.261461"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3758-7">
<stop
id="stop3760-4"
offset="0"
style="stop-color:#ece400;stop-opacity:1;" />
<stop
id="stop3762-0"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview8"
showgrid="false"
inkscape:zoom="5.2149125"
inkscape:cx="-26.445493"
inkscape:cy="31.598459"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 55.041981,25.814432 36.921945,25.730432 31.404334,7.3935963 25.885923,25.730432 7.7650846,25.814434 22.476316,37.520057 15.0387,57.488097 31.404334,44.800071 47.777965,57.488097 40.331551,37.520057 z"
id="path4"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0" />
<path
d="M 56.276895,25.211993 37.3433,24.856806 31.486705,5.7742084 c 0.04705,37.4359336 -0.01851,2.6744908 -0.0678,40.1841446 L 48.19932,58.580578 40.956295,37.527792 z"
id="path4-1"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 64 64"
enable-background="new 0 0 64 64"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
width="100%"
height="100%"
sodipodi:docname="vip_buddy.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient3766">
<stop
style="stop-color:#ff2700;stop-opacity:1;"
offset="0"
id="stop3768" />
<stop
style="stop-color:#820000;stop-opacity:1;"
offset="1"
id="stop3770" />
</linearGradient>
<linearGradient
id="linearGradient5225">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5227" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop5229" />
</linearGradient>
<linearGradient
id="linearGradient5219"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5221" />
</linearGradient>
<linearGradient
id="linearGradient3758">
<stop
id="stop3760"
offset="0"
style="stop-color:#0fbb00;stop-opacity:1;" />
<stop
id="stop3762"
offset="1"
style="stop-color:#064400;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3750">
<stop
style="stop-color:#ece400;stop-opacity:1;"
offset="0"
id="stop3752" />
<stop
style="stop-color:#ece400;stop-opacity:0;"
offset="1"
id="stop3754" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756-1"
x1="1.960216"
y1="31.261461"
x2="60.456024"
y2="31.261461"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3758-7">
<stop
id="stop3760-4"
offset="0"
style="stop-color:#ece400;stop-opacity:1;" />
<stop
id="stop3762-0"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1440"
inkscape:window-height="792"
id="namedview8"
showgrid="false"
inkscape:zoom="5.2149125"
inkscape:cx="14.509163"
inkscape:cy="51.245759"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 57.150089,25.064396 37.504323,24.973324 31.522122,5.092503 25.539054,24.973324 5.8924192,25.064399 21.842354,37.75565 13.778482,59.405024 31.522122,45.64865 49.274434,59.405024 41.201022,37.75565 z"
id="path4"
style="fill:#8d5fd3;fill-opacity:1;fill-rule:nonzero"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,127 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 64 64"
enable-background="new 0 0 64 64"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
width="100%"
height="100%"
sodipodi:docname="registered_vip_buddy.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10">
<linearGradient
id="linearGradient4153">
<stop
style="stop-color:#ffec79;stop-opacity:1"
offset="0"
id="stop4155" />
<stop
style="stop-color:#f2c15b;stop-opacity:1"
offset="1"
id="stop4157" />
</linearGradient>
<linearGradient
id="linearGradient3758">
<stop
id="stop3760"
offset="0"
style="stop-color:#80d600;stop-opacity:1;" />
<stop
id="stop3762"
offset="1"
style="stop-color:#80d600;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3750">
<stop
style="stop-color:#ece400;stop-opacity:1;"
offset="0"
id="stop3752" />
<stop
style="stop-color:#ece400;stop-opacity:0;"
offset="1"
id="stop3754" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756"
x1="31.290251"
y1="-19.003599"
x2="31.135509"
y2="67.496323"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.87626222,0,0,0.87626222,4.174756,4.8555263)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3758-7"
id="linearGradient3756-1"
x1="1.960216"
y1="31.261461"
x2="60.456024"
y2="31.261461"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3758-7">
<stop
id="stop3760-4"
offset="0"
style="stop-color:#ece400;stop-opacity:1;" />
<stop
id="stop3762-0"
offset="1"
style="stop-color:#ec8b00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1152"
inkscape:window-height="811"
id="namedview8"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="29.258475"
inkscape:cy="35.341768"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="M 61.442826,23.621762 38.532402,23.515555 31.556101,0.331013 24.578789,23.515555 1.6673502,23.621765 20.267785,38.422001 10.863888,63.668987 31.556101,47.626631 52.258426,63.668987 42.843404,38.422001 z"
id="path4-9"
style="fill:#000000;fill-opacity:1"
inkscape:connector-curvature="0" />
<path
d="M 57.150089,25.064396 37.504323,24.973324 31.522122,5.092503 25.539054,24.973324 5.8924192,25.064399 21.842354,37.75565 13.778482,59.405024 31.522122,45.64865 49.274434,59.405024 41.201022,37.75565 z"
id="path4"
style="fill:url(#linearGradient3756);fill-opacity:1"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -52,7 +52,7 @@ AbstractClient::AbstractClient(QObject *parent)
FeatureSet features;
features.initalizeFeatureList(clientFeatures);
connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
connect(this, &AbstractClient::sigQueuePendingCommand, this, &AbstractClient::queuePendingCommand);
}
AbstractClient::~AbstractClient()

View File

@@ -48,6 +48,7 @@ class AbstractClient : public QObject
Q_OBJECT
signals:
void statusChanged(ClientStatus _status);
void maxPingTime(int seconds, int maxSeconds);
// Room events
void roomEventReceived(const RoomEvent &event);
@@ -97,8 +98,8 @@ protected:
virtual void sendCommandContainer(const CommandContainer &cont) = 0;
public:
AbstractClient(QObject *parent = nullptr);
~AbstractClient();
explicit AbstractClient(QObject *parent = nullptr);
~AbstractClient() override;
ClientStatus getStatus() const
{

View File

@@ -23,7 +23,7 @@ signals:
void onCtrlC();
protected:
virtual bool eventFilter(QObject *, QEvent *event);
bool eventFilter(QObject *, QEvent *event) override;
};
#endif

View File

@@ -0,0 +1,189 @@
#include "deck_editor_menu.h"
#include "../../../settings/cache_settings.h"
#include "../../../settings/shortcuts_settings.h"
DeckEditorMenu::DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *_deckEditor)
: QMenu(parent), deckEditor(_deckEditor)
{
aNewDeck = new QAction(QString(), this);
connect(aNewDeck, SIGNAL(triggered()), deckEditor, SLOT(actNewDeck()));
aLoadDeck = new QAction(QString(), this);
connect(aLoadDeck, SIGNAL(triggered()), deckEditor, SLOT(actLoadDeck()));
loadRecentDeckMenu = new QMenu(this);
connect(&SettingsCache::instance().recents(), &RecentsSettings::recentlyOpenedDeckPathsChanged, this,
&DeckEditorMenu::updateRecentlyOpened);
aClearRecents = new QAction(QString(), this);
connect(aClearRecents, &QAction::triggered, this, &DeckEditorMenu::actClearRecents);
updateRecentlyOpened();
aSaveDeck = new QAction(QString(), this);
connect(aSaveDeck, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeck()));
aSaveDeckAs = new QAction(QString(), this);
connect(aSaveDeckAs, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckAs()));
aLoadDeckFromClipboard = new QAction(QString(), this);
connect(aLoadDeckFromClipboard, SIGNAL(triggered()), deckEditor, SLOT(actLoadDeckFromClipboard()));
aEditDeckInClipboard = new QAction(QString(), this);
connect(aEditDeckInClipboard, SIGNAL(triggered()), deckEditor, SLOT(actEditDeckInClipboard()));
aEditDeckInClipboardRaw = new QAction(QString(), this);
connect(aEditDeckInClipboardRaw, SIGNAL(triggered()), deckEditor, SLOT(actEditDeckInClipboardRaw()));
aSaveDeckToClipboard = new QAction(QString(), this);
connect(aSaveDeckToClipboard, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckToClipboard()));
aSaveDeckToClipboardNoSetNameAndNumber = new QAction(QString(), this);
connect(aSaveDeckToClipboardNoSetNameAndNumber, SIGNAL(triggered()), deckEditor,
SLOT(actSaveDeckToClipboardNoSetNameAndNumber()));
aSaveDeckToClipboardRaw = new QAction(QString(), this);
connect(aSaveDeckToClipboardRaw, SIGNAL(triggered()), deckEditor, SLOT(actSaveDeckToClipboardRaw()));
aSaveDeckToClipboardRawNoSetNameAndNumber = new QAction(QString(), this);
connect(aSaveDeckToClipboardRawNoSetNameAndNumber, SIGNAL(triggered()), deckEditor,
SLOT(actSaveDeckToClipboardRawNoSetNameAndNumber()));
aPrintDeck = new QAction(QString(), this);
connect(aPrintDeck, SIGNAL(triggered()), deckEditor, SLOT(actPrintDeck()));
aExportDeckDecklist = new QAction(QString(), this);
connect(aExportDeckDecklist, SIGNAL(triggered()), deckEditor, SLOT(actExportDeckDecklist()));
aAnalyzeDeckDeckstats = new QAction(QString(), this);
connect(aAnalyzeDeckDeckstats, SIGNAL(triggered()), deckEditor, SLOT(actAnalyzeDeckDeckstats()));
aAnalyzeDeckTappedout = new QAction(QString(), this);
connect(aAnalyzeDeckTappedout, SIGNAL(triggered()), deckEditor, SLOT(actAnalyzeDeckTappedout()));
analyzeDeckMenu = new QMenu(this);
analyzeDeckMenu->addAction(aExportDeckDecklist);
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
aClose = new QAction(QString(), this);
connect(aClose, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::closeRequest);
editDeckInClipboardMenu = new QMenu(this);
editDeckInClipboardMenu->addAction(aEditDeckInClipboard);
editDeckInClipboardMenu->addAction(aEditDeckInClipboardRaw);
saveDeckToClipboardMenu = new QMenu(this);
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboard);
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardNoSetNameAndNumber);
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardRaw);
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardRawNoSetNameAndNumber);
addAction(aNewDeck);
addAction(aLoadDeck);
addMenu(loadRecentDeckMenu);
addAction(aSaveDeck);
addAction(aSaveDeckAs);
addSeparator();
addAction(aLoadDeckFromClipboard);
addMenu(editDeckInClipboardMenu);
addMenu(saveDeckToClipboardMenu);
addSeparator();
addAction(aPrintDeck);
addMenu(analyzeDeckMenu);
addSeparator();
addAction(deckEditor->filterDockWidget->aClearFilterOne);
addAction(deckEditor->filterDockWidget->aClearFilterAll);
addSeparator();
addAction(aClose);
retranslateUi();
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
refreshShortcuts();
}
void DeckEditorMenu::setSaveStatus(bool newStatus)
{
aSaveDeck->setEnabled(newStatus);
aSaveDeckAs->setEnabled(newStatus);
aSaveDeckToClipboard->setEnabled(newStatus);
aSaveDeckToClipboardNoSetNameAndNumber->setEnabled(newStatus);
aSaveDeckToClipboardRaw->setEnabled(newStatus);
aSaveDeckToClipboardRawNoSetNameAndNumber->setEnabled(newStatus);
saveDeckToClipboardMenu->setEnabled(newStatus);
aPrintDeck->setEnabled(newStatus);
analyzeDeckMenu->setEnabled(newStatus);
}
void DeckEditorMenu::updateRecentlyOpened()
{
loadRecentDeckMenu->clear();
for (const auto &deckPath : SettingsCache::instance().recents().getRecentlyOpenedDeckPaths()) {
QAction *aRecentlyOpenedDeck = new QAction(deckPath, this);
loadRecentDeckMenu->addAction(aRecentlyOpenedDeck);
connect(aRecentlyOpenedDeck, &QAction::triggered, deckEditor,
[=, this] { deckEditor->actOpenRecent(aRecentlyOpenedDeck->text()); });
}
loadRecentDeckMenu->addSeparator();
loadRecentDeckMenu->addAction(aClearRecents);
aClearRecents->setEnabled(SettingsCache::instance().recents().getRecentlyOpenedDeckPaths().length() > 0);
}
void DeckEditorMenu::actClearRecents()
{
SettingsCache::instance().recents().clearRecentlyOpenedDeckPaths();
}
void DeckEditorMenu::retranslateUi()
{
setTitle(tr("&Deck Editor"));
aNewDeck->setText(tr("&New deck"));
aLoadDeck->setText(tr("&Load deck..."));
loadRecentDeckMenu->setTitle(tr("Load recent deck..."));
aClearRecents->setText(tr("Clear"));
aSaveDeck->setText(tr("&Save deck"));
aSaveDeckAs->setText(tr("Save deck &as..."));
aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard..."));
editDeckInClipboardMenu->setTitle(tr("Edit deck in clipboard"));
aEditDeckInClipboard->setText(tr("Annotated"));
aEditDeckInClipboardRaw->setText(tr("Not Annotated"));
saveDeckToClipboardMenu->setTitle(tr("Save deck to clipboard"));
aSaveDeckToClipboard->setText(tr("Annotated"));
aSaveDeckToClipboardNoSetNameAndNumber->setText(tr("Annotated (No set name or number)"));
aSaveDeckToClipboardRaw->setText(tr("Not Annotated"));
aSaveDeckToClipboardRawNoSetNameAndNumber->setText(tr("Not Annotated (No set name or number)"));
aPrintDeck->setText(tr("&Print deck..."));
analyzeDeckMenu->setTitle(tr("&Send deck to online service"));
aExportDeckDecklist->setText(tr("Create decklist (decklist.org)"));
aAnalyzeDeckDeckstats->setText(tr("Analyze deck (deckstats.net)"));
aAnalyzeDeckTappedout->setText(tr("Analyze deck (tappedout.net)"));
aClose->setText(tr("&Close"));
}
void DeckEditorMenu::refreshShortcuts()
{
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
aNewDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aNewDeck"));
aLoadDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aLoadDeck"));
aSaveDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeck"));
aExportDeckDecklist->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aExportDeckDecklist"));
aSaveDeckAs->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckAs"));
aLoadDeckFromClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
aEditDeckInClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aEditDeckInClipboard"));
aEditDeckInClipboardRaw->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aEditDeckInClipboardRaw"));
aPrintDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aPrintDeck"));
aAnalyzeDeckDeckstats->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aAnalyzeDeck"));
aClose->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aClose"));
aSaveDeckToClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboard"));
aSaveDeckToClipboardRaw->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboardRaw"));
aClose->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aClose"));
}

View File

@@ -0,0 +1,32 @@
#ifndef DECK_EDITOR_MENU_H
#define DECK_EDITOR_MENU_H
#include "../../tabs/abstract_tab_deck_editor.h"
#include <QMenu>
class AbstractTabDeckEditor;
class DeckEditorMenu : public QMenu
{
Q_OBJECT
public:
explicit DeckEditorMenu(QWidget *parent, AbstractTabDeckEditor *deckEditor);
AbstractTabDeckEditor *deckEditor;
QAction *aNewDeck, *aLoadDeck, *aClearRecents, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard,
*aEditDeckInClipboard, *aEditDeckInClipboardRaw, *aSaveDeckToClipboard, *aSaveDeckToClipboardNoSetNameAndNumber,
*aSaveDeckToClipboardRaw, *aSaveDeckToClipboardRawNoSetNameAndNumber, *aPrintDeck, *aExportDeckDecklist,
*aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose;
QMenu *loadRecentDeckMenu, *analyzeDeckMenu, *editDeckInClipboardMenu, *saveDeckToClipboardMenu;
void setSaveStatus(bool newStatus);
public slots:
void updateRecentlyOpened();
void actClearRecents();
void retranslateUi();
void refreshShortcuts();
};
#endif

View File

@@ -0,0 +1,35 @@
#include "client_update_checker.h"
#include "../../settings/cache_settings.h"
#include "release_channel.h"
ClientUpdateChecker::ClientUpdateChecker(QObject *parent) : QObject(parent)
{
}
void ClientUpdateChecker::check()
{
auto releaseChannel = SettingsCache::instance().getUpdateReleaseChannel();
finishedCheckConnection =
connect(releaseChannel, &ReleaseChannel::finishedCheck, this, &ClientUpdateChecker::actFinishedCheck);
errorConnection = connect(releaseChannel, &ReleaseChannel::error, this, &ClientUpdateChecker::actError);
releaseChannel->checkForUpdates();
}
void ClientUpdateChecker::actFinishedCheck(bool needToUpdate, bool isCompatible, Release *release)
{
disconnect(finishedCheckConnection);
disconnect(errorConnection);
emit finishedCheck(needToUpdate, isCompatible, release);
}
void ClientUpdateChecker::actError(const QString &errorString)
{
disconnect(finishedCheckConnection);
disconnect(errorConnection);
emit error(errorString);
}

View File

@@ -0,0 +1,45 @@
#ifndef CLIENT_UPDATE_CHECKER_H
#define CLIENT_UPDATE_CHECKER_H
#include <QObject>
class Release;
/**
* We use a singleton instance of UpdateChannel, which can cause interference and feedback loops when multiple objects
* connect to it.
*
* This class encapsulates the usage of that UpdateChannel to ensure that the check only happens once per connection and
* the connection is destroyed after it's been used.
*/
class ClientUpdateChecker : public QObject
{
Q_OBJECT
QMetaObject::Connection finishedCheckConnection;
QMetaObject::Connection errorConnection;
void actFinishedCheck(bool needToUpdate, bool isCompatible, Release *release);
void actError(const QString &errorString);
public:
explicit ClientUpdateChecker(QObject *parent = nullptr);
/**
* Actually performs the check, using the currently selected update channel in the settings.
* Any resulting signals will only be sent once.
* This method should only be called ONCE per instance.
*/
void check();
signals:
/**
* Forwarded from UpdateChannel::finishedCheck
*/
void finishedCheck(bool needToUpdate, bool isCompatible, Release *release);
/**
* Forwarded from UpdateChannel::error
*/
void error(const QString &errorString);
};
#endif // CLIENT_UPDATE_CHECKER_H

View File

@@ -11,6 +11,11 @@
#include <QSysInfo>
#include <QtGlobal>
#if defined(Q_OS_MACOS)
#include <sys/sysctl.h>
#include <sys/types.h>
#endif
#define STABLERELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/latest"
#define STABLEMANUALDOWNLOAD_URL "https://github.com/Cockatrice/Cockatrice/releases/latest"
#define STABLETAG_URL "https://api.github.com/repos/Cockatrice/Cockatrice/git/refs/tags/"
@@ -21,11 +26,8 @@
#define GIT_SHORT_HASH_LEN 7
int ReleaseChannel::sharedIndex = 0;
ReleaseChannel::ReleaseChannel() : netMan(new QNetworkAccessManager(this)), response(nullptr), lastRelease(nullptr)
{
index = sharedIndex++;
}
ReleaseChannel::~ReleaseChannel()
@@ -36,31 +38,42 @@ ReleaseChannel::~ReleaseChannel()
void ReleaseChannel::checkForUpdates()
{
QString releaseChannelUrl = getReleaseChannelUrl();
qDebug() << "Searching for updates on the channel: " << releaseChannelUrl;
qCDebug(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl;
response = netMan->get(QNetworkRequest(releaseChannelUrl));
connect(response, SIGNAL(finished()), this, SLOT(releaseListFinished()));
connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished);
}
// Different release channel checking functions for different operating systems
#if defined(Q_OS_MACOS)
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
{
static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
#if defined(Q_OS_MACOS)
static QRegularExpression version_regex("macOS(\\d+)");
auto match = version_regex.match(fileName);
if (!match.hasMatch()) {
return false;
}
auto getSystemVersion = [] {
// QSysInfo does not go through translation layers
// We need to use sysctl to reliably detect the underlying architecture
char arch[255];
size_t len = sizeof(arch);
if (sysctlbyname("machdep.cpu.brand_string", arch, &len, nullptr, 0) == 0) {
// Intel mac is only supported on macOS 13 versions
if (QString::fromUtf8(arch).contains("Intel")) {
return 13;
}
}
return QSysInfo::productVersion().split(".")[0].toInt();
};
// older(smaller) releases are compatible with a newer or the same system version
int sys_maj = QSysInfo::productVersion().split(".")[0].toInt();
int sys_min = QSysInfo::productVersion().split(".")[1].toInt();
int sys_maj = getSystemVersion();
int rel_maj = match.captured(1).toInt();
int rel_min = match.captured(2).toInt();
return rel_maj < sys_maj || (rel_maj == sys_maj && rel_min <= sys_min);
}
return rel_maj == sys_maj;
#elif defined(Q_OS_WIN)
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
{
#if Q_PROCESSOR_WORDSIZE == 4
return fileName.contains("32bit");
#elif Q_PROCESSOR_WORDSIZE == 8
@@ -71,16 +84,15 @@ bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
return fileName.contains("Win10");
}
#else
Q_UNUSED(fileName);
return false;
#endif
#else // If the OS doesn't fit one of the above #defines, then it will never match
Q_UNUSED(fileName);
return false;
#endif
}
#else
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &)
{
// If the OS doesn't fit one of the above #defines, then it will never match
return false;
}
#endif
QString StableReleaseChannel::getManualDownloadUrl() const
{
@@ -89,7 +101,7 @@ QString StableReleaseChannel::getManualDownloadUrl() const
QString StableReleaseChannel::getName() const
{
return tr("Stable Releases");
return tr("Default");
}
QString StableReleaseChannel::getReleaseChannelUrl() const
@@ -104,7 +116,7 @@ void StableReleaseChannel::releaseListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "No reply received from the release update server.";
qCWarning(ReleaseChannelLog) << "No reply received from the release update server.";
emit error(tr("No reply received from the release update server."));
return;
}
@@ -112,7 +124,7 @@ void StableReleaseChannel::releaseListFinished()
QVariantMap resultMap = jsonResponse.toVariant().toMap();
if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") &&
resultMap.contains("published_at"))) {
qWarning() << "Invalid received from the release update server.";
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap;
emit error(tr("Invalid reply received from the release update server."));
return;
}
@@ -126,39 +138,31 @@ void StableReleaseChannel::releaseListFinished()
if (resultMap.contains("assets")) {
auto rawAssets = resultMap["assets"].toList();
// [(name, url)]
QVector<std::pair<QString, QString>> assets;
std::transform(rawAssets.begin(), rawAssets.end(), std::back_inserter(assets), [](QVariant _asset) {
QVariantMap asset = _asset.toMap();
for (const auto &rawAsset : rawAssets) {
QVariantMap asset = rawAsset.toMap();
QString name = asset["name"].toString();
QString url = asset["browser_download_url"].toString();
return std::make_pair(name, url);
});
auto _releaseAsset = std::find_if(assets.begin(), assets.end(), [](std::pair<QString, QString> nameAndUrl) {
return downloadMatchesCurrentOS(nameAndUrl.first);
});
if (_releaseAsset != assets.end()) {
std::pair<QString, QString> releaseAsset = *_releaseAsset;
auto releaseUrl = releaseAsset.second;
lastRelease->setDownloadUrl(releaseUrl);
if (downloadMatchesCurrentOS(name)) {
lastRelease->setDownloadUrl(url);
break;
}
}
}
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT);
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
qDebug() << "Got reply from release server, name=" << lastRelease->getName()
<< "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate()
<< "url=" << lastRelease->getDownloadUrl();
qCDebug(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName()
<< "desc=" << lastRelease->getDescriptionUrl()
<< "date=" << lastRelease->getPublishDate() << "url=" << lastRelease->getDownloadUrl();
const QString &tagName = resultMap["tag_name"].toString();
QString url = QString(STABLETAG_URL) + tagName;
qDebug() << "Searching for commit hash corresponding to stable channel tag: " << tagName;
qCDebug(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName;
response = netMan->get(QNetworkRequest(url));
connect(response, SIGNAL(finished()), this, SLOT(tagListFinished()));
connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished);
}
void StableReleaseChannel::tagListFinished()
@@ -168,24 +172,24 @@ void StableReleaseChannel::tagListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "No reply received from the tag update server.";
qCWarning(ReleaseChannelLog) << "No reply received from the tag update server.";
emit error(tr("No reply received from the tag update server."));
return;
}
QVariantMap resultMap = jsonResponse.toVariant().toMap();
if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) {
qWarning() << "Invalid received from the tag update server.";
qCWarning(ReleaseChannelLog) << "Invalid received from the tag update server.";
emit error(tr("Invalid reply received from the tag update server."));
return;
}
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
qDebug() << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
qCDebug(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT);
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease);
@@ -203,7 +207,7 @@ QString BetaReleaseChannel::getManualDownloadUrl() const
QString BetaReleaseChannel::getName() const
{
return tr("Beta Releases");
return tr("Beta");
}
QString BetaReleaseChannel::getReleaseChannelUrl() const
@@ -228,7 +232,7 @@ void BetaReleaseChannel::releaseListFinished()
QVariantMap resultMap = array.at(0).toObject().toVariantMap();
if (array.empty() || resultMap.empty()) {
qWarning() << "No reply received from the release update server:" << QString(jsonData);
qCWarning(ReleaseChannelLog) << "No reply received from the release update server:" << QString(jsonData);
emit error(tr("No reply received from the release update server."));
return;
}
@@ -237,7 +241,7 @@ void BetaReleaseChannel::releaseListFinished()
if (!resultMap.contains("assets") || !resultMap.contains("author") || !resultMap.contains("tag_name") ||
!resultMap.contains("target_commitish") || !resultMap.contains("assets_url") ||
!resultMap.contains("published_at")) {
qWarning() << "Invalid received from the release update server:" << resultMap;
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap;
emit error(tr("Invalid reply received from the release update server."));
return;
}
@@ -252,15 +256,15 @@ void BetaReleaseChannel::releaseListFinished()
lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash));
lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash));
qDebug() << "Got reply from release server, size=" << resultMap.size() << "name=" << lastRelease->getName()
<< "desc=" << lastRelease->getDescriptionUrl() << "commit=" << lastRelease->getCommitHash()
<< "date=" << lastRelease->getPublishDate();
qCDebug(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size()
<< "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl()
<< "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate();
QString betaBuildDownloadUrl = resultMap["assets_url"].toString();
qDebug() << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
qCDebug(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
connect(response, SIGNAL(finished()), this, SLOT(fileListFinished()));
connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished);
}
void BetaReleaseChannel::fileListFinished()
@@ -270,7 +274,7 @@ void BetaReleaseChannel::fileListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "No reply received from the file update server.";
qCWarning(ReleaseChannelLog) << "No reply received from the file update server.";
emit error(tr("No reply received from the file update server."));
return;
}
@@ -278,7 +282,7 @@ void BetaReleaseChannel::fileListFinished()
QVariantList resultList = jsonResponse.toVariant().toList();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT);
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
bool compatibleVersion = false;
@@ -295,7 +299,7 @@ void BetaReleaseChannel::fileListFinished()
if (downloadMatchesCurrentOS(*url)) {
compatibleVersion = true;
lastRelease->setDownloadUrl(*url);
qDebug() << "Found compatible version url=" << *url;
qCDebug(ReleaseChannelLog) << "Found compatible version url=" << *url;
break;
}
}

View File

@@ -2,11 +2,14 @@
#define RELEASECHANNEL_H
#include <QDate>
#include <QLoggingCategory>
#include <QObject>
#include <QString>
#include <QVariantMap>
#include <utility>
inline Q_LOGGING_CATEGORY(ReleaseChannelLog, "release_channel");
class QNetworkReply;
class QNetworkAccessManager;
@@ -82,9 +85,6 @@ public:
~ReleaseChannel() override;
protected:
// shared by all instances
static int sharedIndex;
int index;
QNetworkAccessManager *netMan;
QNetworkReply *response;
Release *lastRelease;
@@ -94,10 +94,6 @@ protected:
virtual QString getReleaseChannelUrl() const = 0;
public:
int getIndex() const
{
return index;
}
Release *getLastRelease()
{
return lastRelease;

View File

@@ -10,7 +10,7 @@ ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
currentEvent(0)
{
replayTimer = new QTimer(this);
connect(replayTimer, SIGNAL(timeout()), this, SLOT(replayTimerTimeout()));
connect(replayTimer, &QTimer::timeout, this, &ReplayTimelineWidget::replayTimerTimeout);
rewindBufferingTimer = new QTimer(this);
rewindBufferingTimer->setSingleShot(true);

View File

@@ -57,28 +57,29 @@ public:
SortRole = Qt::UserRole
};
SetsModel(CardDatabase *_db, QObject *parent = nullptr);
~SetsModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const
explicit SetsModel(CardDatabase *_db, QObject *parent = nullptr);
~SetsModel() override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override
{
Q_UNUSED(parent);
return NUM_COLS;
}
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
Qt::DropActions supportedDropActions() const;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
Qt::DropActions supportedDropActions() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool
dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
QStringList mimeTypes() const override;
void swapRows(int oldRow, int newRow);
void toggleRow(int row, bool enable);
void toggleRow(int row);
void toggleAll(bool);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
void save(CardDatabase *db);
void restore(CardDatabase *db);
void restoreOriginalOrder();
@@ -88,7 +89,7 @@ class SetsDisplayModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
SetsDisplayModel(QObject *parent = NULL);
explicit SetsDisplayModel(QObject *parent = nullptr);
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;

View File

@@ -28,7 +28,7 @@ SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(
// File exists means we're in spoiler season
startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false);
} else {
qDebug() << "Spoilers Disabled";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled";
}
}
@@ -45,10 +45,10 @@ void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults)
if (saveResults) {
// This will write out to the file (used for spoiler.xml)
connect(reply, SIGNAL(finished()), this, SLOT(actDownloadFinishedSpoilersFile()));
connect(reply, &QNetworkReply::finished, this, &SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile);
} else {
// This will check the status (used to see if we're in spoiler season or not)
connect(reply, SIGNAL(finished()), this, SLOT(actCheckIfSpoilerSeasonEnabled()));
connect(reply, &QNetworkReply::finished, this, &SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled);
}
}
@@ -67,7 +67,7 @@ void SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile()
reply->deleteLater();
emit spoilerCheckerDone();
} else {
qDebug() << "Error downloading spoilers file" << errorCode;
qCDebug(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode;
emit spoilerCheckerDone();
}
}
@@ -81,11 +81,11 @@ bool SpoilerBackgroundUpdater::deleteSpoilerFile()
// Delete the spoiler.xml file
if (file.exists() && file.remove()) {
qDebug() << "Deleting spoiler.xml";
qCDebug(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml";
return true;
}
qDebug() << "Error: Spoiler.xml not found or not deleted";
qCDebug(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted";
return false;
}
@@ -101,24 +101,24 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle"));
}
qDebug() << "Spoiler Season Offline";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline";
emit spoilerCheckerDone();
} else if (errorCode == QNetworkReply::NoError) {
qDebug() << "Spoiler Service Online";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online";
startSpoilerDownloadProcess(SPOILERS_URL, true);
} else if (errorCode == QNetworkReply::HostNotFoundError) {
if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection"));
}
qDebug() << "Spoiler download failed due to no internet connection";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection";
emit spoilerCheckerDone();
} else {
if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
}
qDebug() << "Spoiler download failed with reason" << errorCode;
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode;
emit spoilerCheckerDone();
}
}
@@ -139,19 +139,19 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added"));
}
qDebug() << "Spoilers Up to Date";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date";
return false;
}
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Spoiler Service Error: File open (w) failed for" << fileName;
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName;
file.close();
return false;
}
if (file.write(data) == -1) {
qDebug() << "Spoiler Service Error: File write (w) failed for" << fileName;
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName;
file.close();
return false;
}
@@ -159,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
file.close();
// Data written, so reload the card database
qDebug() << "Spoiler Service Data Written";
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
// If the user has notifications enabled, let them know
@@ -167,7 +167,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
if (trayIcon) {
QList<QByteArray> lines = data.split('\n');
foreach (QByteArray line, lines) {
for (const QByteArray &line : lines) {
if (line.contains("Created At:")) {
QString timeStamp = QString(line).replace("Created At:", "").trimmed();
timeStamp.chop(6); // Remove " (UTC)"
@@ -202,12 +202,12 @@ QByteArray SpoilerBackgroundUpdater::getHash(const QString fileName)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes);
qDebug() << "File Hash =" << hash.result();
qCDebug(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result();
file.close();
return hash.result();
} else {
qDebug() << "getHash ReadOnly failed!";
qCDebug(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!";
file.close();
return QByteArray();
}
@@ -221,7 +221,7 @@ QByteArray SpoilerBackgroundUpdater::getHash(QByteArray data)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes);
qDebug() << "Data Hash =" << hash.result();
qCDebug(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result();
return hash.result();
}

View File

@@ -2,9 +2,12 @@
#define COCKATRICE_SPOILER_DOWNLOADER_H
#include <QByteArray>
#include <QLoggingCategory>
#include <QObject>
#include <QProcess>
inline Q_LOGGING_CATEGORY(SpoilerBackgroundUpdaterLog, "spoiler_background_updater");
class SpoilerBackgroundUpdater : public QObject
{
Q_OBJECT

View File

@@ -12,11 +12,11 @@
#define DEFAULT_THEME_NAME "Default"
#define TEST_SOUND_FILENAME "player_join"
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), player(nullptr)
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), audioOutput(nullptr), player(nullptr)
{
ensureThemeDirectoryExists();
connect(&SettingsCache::instance(), SIGNAL(soundThemeChanged()), this, SLOT(themeChangedSlot()));
connect(&SettingsCache::instance(), SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged()));
connect(&SettingsCache::instance(), &SettingsCache::soundThemeChanged, this, &SoundEngine::themeChangedSlot);
connect(&SettingsCache::instance(), &SettingsCache::soundEnabledChanged, this, &SoundEngine::soundEnabledChanged);
soundEnabledChanged();
themeChangedSlot();
@@ -28,26 +28,34 @@ SoundEngine::~SoundEngine()
player->deleteLater();
player = nullptr;
}
if (audioOutput) {
audioOutput->deleteLater();
audioOutput = nullptr;
}
}
void SoundEngine::soundEnabledChanged()
{
if (SettingsCache::instance().getSoundEnabled()) {
qDebug() << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
qCDebug(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
if (!player) {
player = new QMediaPlayer;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
auto qAudioOutput = new QAudioOutput;
player->setAudioOutput(qAudioOutput);
audioOutput = new QAudioOutput(player);
player->setAudioOutput(audioOutput);
#endif
}
} else {
qDebug() << "SoundEngine: disabling sound";
qCDebug(SoundEngineLog) << "SoundEngine: disabling sound";
if (player) {
player->stop();
player->deleteLater();
player = nullptr;
}
if (audioOutput) {
audioOutput->deleteLater();
audioOutput = nullptr;
}
}
}
@@ -82,7 +90,7 @@ void SoundEngine::ensureThemeDirectoryExists()
{
if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
qDebug() << "Sounds theme name not set, setting default value";
qCDebug(SoundEngineLog) << "Sounds theme name not set, setting default value";
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
}
}
@@ -123,7 +131,7 @@ QStringMap &SoundEngine::getAvailableThemes()
void SoundEngine::themeChangedSlot()
{
QString themeName = SettingsCache::instance().getSoundThemeName();
qDebug() << "Sound theme changed:" << themeName;
qCDebug(SoundEngineLog) << "Sound theme changed:" << themeName;
QDir dir = getAvailableThemes().value(themeName);

View File

@@ -1,12 +1,15 @@
#ifndef SOUNDENGINE_H
#define SOUNDENGINE_H
#include <QAudioOutput>
#include <QLoggingCategory>
#include <QMap>
#include <QMediaPlayer>
#include <QObject>
#include <QString>
class QAudioOutput;
inline Q_LOGGING_CATEGORY(SoundEngineLog, "sound_engine");
class QBuffer;
typedef QMap<QString, QString> QStringMap;
@@ -23,6 +26,7 @@ public:
private:
QStringMap availableThemes;
QMap<QString, QString> audioData;
QAudioOutput *audioOutput;
QMediaPlayer *player;
protected:

View File

@@ -0,0 +1,546 @@
#include "abstract_tab_deck_editor.h"
#include "../../client/game_logic/abstract_client.h"
#include "../../client/tapped_out_interface.h"
#include "../../client/ui/widgets/cards/card_info_frame_widget.h"
#include "../../deck/deck_stats_interface.h"
#include "../../dialogs/dlg_load_deck.h"
#include "../../dialogs/dlg_load_deck_from_clipboard.h"
#include "../../game/cards/card_database_manager.h"
#include "../../game/cards/card_database_model.h"
#include "../../server/pending_command.h"
#include "../../settings/cache_settings.h"
#include "../ui/picture_loader/picture_loader.h"
#include "../ui/pixel_map_generator.h"
#include "pb/command_deck_upload.pb.h"
#include "pb/response.pb.h"
#include "tab_supervisor.h"
#include "trice_limits.h"
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QCloseEvent>
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QFileDialog>
#include <QHeaderView>
#include <QLineEdit>
#include <QMenuBar>
#include <QMessageBox>
#include <QPrintPreviewDialog>
#include <QProcessEnvironment>
#include <QPushButton>
#include <QRegularExpression>
#include <QSplitter>
#include <QTextStream>
#include <QTreeView>
#include <QUrl>
AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
databaseDisplayDockWidget = new DeckEditorDatabaseDisplayWidget(this);
deckDockWidget = new DeckEditorDeckDockWidget(this);
cardInfoDockWidget = new DeckEditorCardInfoDockWidget(this);
filterDockWidget = new DeckEditorFilterDockWidget(this);
printingSelectorDockWidget = new DeckEditorPrintingSelectorDockWidget(this);
connect(deckDockWidget, &DeckEditorDeckDockWidget::deckChanged, this, &AbstractTabDeckEditor::onDeckChanged);
connect(deckDockWidget, &DeckEditorDeckDockWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard);
connect(this, &AbstractTabDeckEditor::decrementCard, deckDockWidget, &DeckEditorDeckDockWidget::actDecrementCard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, this,
&AbstractTabDeckEditor::updateCard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, this,
&AbstractTabDeckEditor::actAddCard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::addCardToSideboard, this,
&AbstractTabDeckEditor::actAddCardToSideboard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromMainDeck, this,
&AbstractTabDeckEditor::actDecrementCard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromSideboard, this,
&AbstractTabDeckEditor::actDecrementCardFromSideboard);
connect(filterDockWidget, &DeckEditorFilterDockWidget::clearAllDatabaseFilters, databaseDisplayDockWidget,
&DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters);
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
}
void AbstractTabDeckEditor::updateCard(CardInfoPtr _card)
{
cardInfoDockWidget->updateCard(_card);
printingSelectorDockWidget->printingSelector->setCard(_card, DECK_ZONE_MAIN);
}
void AbstractTabDeckEditor::onDeckChanged()
{
setModified(isBlankNewDeck());
deckMenu->setSaveStatus(!isBlankNewDeck());
}
void AbstractTabDeckEditor::addCardHelper(const CardInfoPtr info, QString zoneName)
{
if (!info)
return;
if (info->getIsToken())
zoneName = DECK_ZONE_TOKENS;
QModelIndex newCardIndex = deckDockWidget->deckModel->addPreferredPrintingCard(info->getName(), zoneName, false);
// recursiveExpand(newCardIndex);
deckDockWidget->deckView->clearSelection();
deckDockWidget->deckView->setCurrentIndex(newCardIndex);
setModified(true);
databaseDisplayDockWidget->searchEdit->setSelection(0, databaseDisplayDockWidget->searchEdit->text().length());
}
void AbstractTabDeckEditor::actAddCard(CardInfoPtr info)
{
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
actAddCardToSideboard(info);
else
addCardHelper(info, DECK_ZONE_MAIN);
deckMenu->setSaveStatus(true);
}
void AbstractTabDeckEditor::actAddCardToSideboard(CardInfoPtr info)
{
addCardHelper(info, DECK_ZONE_SIDE);
deckMenu->setSaveStatus(true);
}
void AbstractTabDeckEditor::actDecrementCard(CardInfoPtr info)
{
emit decrementCard(info, DECK_ZONE_MAIN);
}
void AbstractTabDeckEditor::actDecrementCardFromSideboard(CardInfoPtr info)
{
emit decrementCard(info, DECK_ZONE_SIDE);
}
void AbstractTabDeckEditor::actSwapCard(CardInfoPtr info, QString zoneName)
{
QString providerId = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("uuid");
QString collectorNumber = CardDatabaseManager::getInstance()->getSetInfoForCard(info).getProperty("num");
deckDockWidget->swapCard(
deckDockWidget->deckModel->findCard(info->getName(), zoneName, providerId, collectorNumber));
}
/**
* Sets the currently active deck for this tab
* @param _deck The deck. Takes ownership of the object
*/
void AbstractTabDeckEditor::setDeck(DeckLoader *_deck)
{
deckDockWidget->setDeck(_deck);
PictureLoader::cacheCardPixmaps(
CardDatabaseManager::getInstance()->getCardsByNameAndProviderId(getDeckList()->getCardListWithProviderId()));
setModified(false);
// If they load a deck, make the deck list appear
aDeckDockVisible->setChecked(true);
deckDockWidget->setVisible(aDeckDockVisible->isChecked());
}
DeckLoader *AbstractTabDeckEditor::getDeckList() const
{
return deckDockWidget->getDeckList();
}
void AbstractTabDeckEditor::setModified(bool _modified)
{
modified = _modified;
emit tabTextChanged(this, getTabText());
}
/**
* @brief Returns true if this tab is a blank newly opened tab, as if it was just created with the `New Deck` action.
*/
bool AbstractTabDeckEditor::isBlankNewDeck() const
{
DeckLoader *deck = getDeckList();
return !modified && deck->hasNotBeenLoaded();
}
void AbstractTabDeckEditor::actNewDeck()
{
auto deckOpenLocation = confirmOpen(false);
if (deckOpenLocation == CANCELLED) {
return;
}
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(nullptr);
return;
}
cleanDeckAndResetModified();
}
void AbstractTabDeckEditor::cleanDeckAndResetModified()
{
deckMenu->setSaveStatus(false);
deckDockWidget->cleanDeck();
setModified(false);
}
/**
* @brief Displays the save confirmation dialogue that is shown before loading a deck, if required. Takes into
* account the `openDeckInNewTab` settting.
*
* @param openInSameTabIfBlank Open the deck in the same tab instead of a new tab if the current tab is completely
* blank. Only relevant when the `openDeckInNewTab` setting is enabled.
*
* @returns An enum that indicates if and where to load the deck
*/
AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const bool openInSameTabIfBlank)
{
// handle `openDeckInNewTab` setting
if (SettingsCache::instance().getOpenDeckInNewTab()) {
if (openInSameTabIfBlank && isBlankNewDeck()) {
return SAME_TAB;
} else {
return NEW_TAB;
}
}
// early return if deck is unmodified
if (!modified) {
return SAME_TAB;
}
// do the save confirmation dialogue
tabSupervisor->setCurrentWidget(this);
QMessageBox *msgBox = createSaveConfirmationWindow();
QPushButton *newTabButton = msgBox->addButton(tr("Open in new tab"), QMessageBox::ApplyRole);
int ret = msgBox->exec();
// `exec()` returns an opaque value if a non-standard button was clicked.
// Directly check if newTabButton was clicked before switching over the standard buttons.
if (msgBox->clickedButton() == newTabButton) {
return NEW_TAB;
}
switch (ret) {
case QMessageBox::Save:
return actSaveDeck() ? SAME_TAB : CANCELLED;
case QMessageBox::Discard:
return SAME_TAB;
default:
return CANCELLED;
}
}
/**
* @brief Creates the base save confirmation dialogue box.
*
* @returns A QMessageBox that can be further modified
*/
QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow()
{
QMessageBox *msgBox = new QMessageBox(this);
msgBox->setIcon(QMessageBox::Warning);
msgBox->setWindowTitle(tr("Are you sure?"));
msgBox->setText(tr("The decklist has been modified.\nDo you want to save the changes?"));
msgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
return msgBox;
}
void AbstractTabDeckEditor::actLoadDeck()
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
return;
}
DlgLoadDeck dialog(this);
if (!dialog.exec())
return;
QString fileName = dialog.selectedFiles().at(0);
openDeckFromFile(fileName, deckOpenLocation);
deckDockWidget->updateBannerCardComboBox();
}
void AbstractTabDeckEditor::actOpenRecent(const QString &fileName)
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
return;
}
openDeckFromFile(fileName, deckOpenLocation);
}
/**
* Actually opens the deck from file
* @param fileName The path of the deck to open
* @param deckOpenLocation Which tab to open the deck
*/
void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation)
{
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
auto *l = new DeckLoader;
if (l->loadFromFile(fileName, fmt, true)) {
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(l);
l->deleteLater();
} else {
deckMenu->setSaveStatus(false);
setDeck(l);
}
} else {
l->deleteLater();
QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(fileName));
}
deckMenu->setSaveStatus(true);
}
bool AbstractTabDeckEditor::actSaveDeck()
{
DeckLoader *const deck = getDeckList();
if (deck->getLastRemoteDeckId() != -1) {
QString deckString = deck->writeToString_Native();
if (deckString.length() > MAX_FILE_LENGTH) {
QMessageBox::critical(this, tr("Error"), tr("Could not save remote deck"));
return false;
}
Command_DeckUpload cmd;
cmd.set_deck_id(static_cast<google::protobuf::uint32>(deck->getLastRemoteDeckId()));
cmd.set_deck_list(deckString.toStdString());
PendingCommand *pend = AbstractClient::prepareSessionCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this,
SLOT(saveDeckRemoteFinished(Response)));
tabSupervisor->getClient()->sendCommand(pend);
return true;
} else if (deck->getLastFileName().isEmpty())
return actSaveDeckAs();
else if (deck->saveToFile(deck->getLastFileName(), deck->getLastFileFormat())) {
setModified(false);
return true;
}
QMessageBox::critical(
this, tr("Error"),
tr("The deck could not be saved.\nPlease check that the directory is writable and try again."));
return false;
}
bool AbstractTabDeckEditor::actSaveDeckAs()
{
QFileDialog dialog(this, tr("Save deck"));
dialog.setDirectory(SettingsCache::instance().getDeckPath());
dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDefaultSuffix("cod");
dialog.setNameFilters(DeckLoader::fileNameFilters);
dialog.selectFile(getDeckList()->getName().trimmed() + ".cod");
if (!dialog.exec())
return false;
QString fileName = dialog.selectedFiles().at(0);
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);
if (!getDeckList()->saveToFile(fileName, fmt)) {
QMessageBox::critical(
this, tr("Error"),
tr("The deck could not be saved.\nPlease check that the directory is writable and try again."));
return false;
}
setModified(false);
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
return true;
}
void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response)
{
if (response.response_code() != Response::RespOk)
QMessageBox::critical(this, tr("Error"), tr("The deck could not be saved."));
else
setModified(false);
}
void AbstractTabDeckEditor::actLoadDeckFromClipboard()
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
return;
}
DlgLoadDeckFromClipboard dlg(this);
if (!dlg.exec())
return;
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(dlg.getDeckList());
} else {
setDeck(dlg.getDeckList());
setModified(true);
}
deckMenu->setSaveStatus(true);
}
void AbstractTabDeckEditor::editDeckInClipboard(bool annotated)
{
DlgEditDeckInClipboard dlg(*getDeckList(), annotated, this);
if (!dlg.exec())
return;
setDeck(dlg.getDeckList());
setModified(true);
deckMenu->setSaveStatus(true);
}
void AbstractTabDeckEditor::actEditDeckInClipboard()
{
editDeckInClipboard(true);
}
void AbstractTabDeckEditor::actEditDeckInClipboardRaw()
{
editDeckInClipboard(false);
}
void AbstractTabDeckEditor::actSaveDeckToClipboard()
{
getDeckList()->saveToClipboard(true, true);
}
void AbstractTabDeckEditor::actSaveDeckToClipboardNoSetNameAndNumber()
{
getDeckList()->saveToClipboard(true, false);
}
void AbstractTabDeckEditor::actSaveDeckToClipboardRaw()
{
getDeckList()->saveToClipboard(false, true);
}
void AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetNameAndNumber()
{
getDeckList()->saveToClipboard(false, false);
}
void AbstractTabDeckEditor::actPrintDeck()
{
auto *dlg = new QPrintPreviewDialog(this);
connect(dlg, SIGNAL(paintRequested(QPrinter *)), deckDockWidget->deckModel, SLOT(printDeckList(QPrinter *)));
dlg->exec();
}
// Action called when export deck to decklist menu item is pressed.
void AbstractTabDeckEditor::actExportDeckDecklist()
{
// Get the decklist class for the deck.
DeckLoader *const deck = getDeckList();
// create a string to load the decklist url into.
QString decklistUrlString;
// check if deck is not null
if (deck) {
// Get the decklist url string from the deck loader class.
decklistUrlString = deck->exportDeckToDecklist();
// Check to make sure the string isn't empty.
if (QString::compare(decklistUrlString, "", Qt::CaseInsensitive) == 0) {
// Show an error if the deck is empty, and return.
QMessageBox::critical(this, tr("Error"), tr("There are no cards in your deck to be exported"));
return;
}
// Encode the string recieved from the model to make sure all characters are encoded.
// first we put it into a qurl object
QUrl decklistUrl = QUrl(decklistUrlString);
// we get the correctly encoded url.
decklistUrlString = decklistUrl.toEncoded();
// We open the url in the user's default browser
QDesktopServices::openUrl(decklistUrlString);
} else {
// if there's no deck loader object, return an error
QMessageBox::critical(this, tr("Error"), tr("No deck was selected to be saved."));
}
}
void AbstractTabDeckEditor::actAnalyzeDeckDeckstats()
{
auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(),
this); // it deletes itself when done
interface->analyzeDeck(getDeckList());
}
void AbstractTabDeckEditor::actAnalyzeDeckTappedout()
{
auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(),
this); // it deletes itself when done
interface->analyzeDeck(getDeckList());
}
void AbstractTabDeckEditor::filterTreeChanged(FilterTree *filterTree)
{
databaseDisplayDockWidget->setFilterTree(filterTree);
}
// Method uses to sync docks state with menu items state
bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QEvent::Close) {
if (o == cardInfoDockWidget) {
aCardInfoDockVisible->setChecked(false);
aCardInfoDockFloating->setEnabled(false);
} else if (o == deckDockWidget) {
aDeckDockVisible->setChecked(false);
aDeckDockFloating->setEnabled(false);
} else if (o == filterDockWidget) {
aFilterDockVisible->setChecked(false);
aFilterDockFloating->setEnabled(false);
} else if (o == printingSelectorDockWidget) {
aPrintingSelectorDockVisible->setChecked(false);
aPrintingSelectorDockFloating->setEnabled(false);
}
}
if (o == this && e->type() == QEvent::Hide) {
LayoutsSettings &layouts = SettingsCache::instance().layouts();
layouts.setDeckEditorLayoutState(saveState());
layouts.setDeckEditorGeometry(saveGeometry());
layouts.setDeckEditorCardSize(cardInfoDockWidget->size());
layouts.setDeckEditorFilterSize(filterDockWidget->size());
layouts.setDeckEditorDeckSize(deckDockWidget->size());
layouts.setDeckEditorPrintingSelectorSize(printingSelectorDockWidget->size());
}
return false;
}
bool AbstractTabDeckEditor::confirmClose()
{
if (modified) {
tabSupervisor->setCurrentWidget(this);
int ret = createSaveConfirmationWindow()->exec();
if (ret == QMessageBox::Save)
return actSaveDeck();
else if (ret == QMessageBox::Cancel)
return false;
}
return true;
}
void AbstractTabDeckEditor::closeRequest(bool forced)
{
if (!forced && !confirmClose()) {
return;
}
emit deckEditorClosing(this);
close();
}

View File

@@ -0,0 +1,152 @@
#ifndef TAB_GENERIC_DECK_EDITOR_H
#define TAB_GENERIC_DECK_EDITOR_H
#include "../../game/cards/card_database.h"
#include "../menus/deck_editor/deck_editor_menu.h"
#include "../ui/widgets/deck_editor/deck_editor_card_info_dock_widget.h"
#include "../ui/widgets/deck_editor/deck_editor_database_display_widget.h"
#include "../ui/widgets/deck_editor/deck_editor_deck_dock_widget.h"
#include "../ui/widgets/deck_editor/deck_editor_filter_dock_widget.h"
#include "../ui/widgets/deck_editor/deck_editor_printing_selector_dock_widget.h"
#include "../ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
#include "tab.h"
class CardDatabaseModel;
class CardDatabaseDisplayModel;
class CardInfoFrameWidget;
class DeckLoader;
class DeckEditorMenu;
class DeckEditorCardInfoDockWidget;
class DeckEditorDatabaseDisplayWidget;
class DeckEditorDeckDockWidget;
class DeckEditorFilterDockWidget;
class DeckEditorPrintingSelectorDockWidget;
class DeckPreviewDeckTagsDisplayWidget;
class Response;
class FilterTreeModel;
class FilterBuilder;
class QTreeView;
class QTextEdit;
class QLabel;
class QComboBox;
class QGroupBox;
class QMessageBox;
class QHBoxLayout;
class QVBoxLayout;
class QPushButton;
class QDockWidget;
class QMenu;
class QAction;
class AbstractTabDeckEditor : public Tab
{
Q_OBJECT
public:
explicit AbstractTabDeckEditor(TabSupervisor *_tabSupervisor);
// UI and Navigation
virtual void createMenus() = 0;
[[nodiscard]] virtual QString getTabText() const override = 0;
bool confirmClose();
virtual void retranslateUi() override = 0;
// Deck Management
virtual void setDeck(DeckLoader *_deckLoader);
DeckLoader *getDeckList() const;
void setModified(bool _windowModified);
// UI Elements
DeckEditorMenu *deckMenu;
DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget;
DeckEditorCardInfoDockWidget *cardInfoDockWidget;
DeckEditorDeckDockWidget *deckDockWidget;
DeckEditorFilterDockWidget *filterDockWidget;
DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget;
public slots:
void onDeckChanged();
void updateCard(CardInfoPtr _card);
void actAddCard(CardInfoPtr info);
void actAddCardToSideboard(CardInfoPtr info);
void actDecrementCard(CardInfoPtr info);
void actDecrementCardFromSideboard(CardInfoPtr info);
void actOpenRecent(const QString &fileName);
void filterTreeChanged(FilterTree *filterTree);
void closeRequest(bool forced = false) override;
virtual void showPrintingSelector() = 0;
virtual void dockTopLevelChanged(bool topLevel) = 0;
signals:
void openDeckEditor(const DeckLoader *deckLoader);
void deckEditorClosing(AbstractTabDeckEditor *tab);
void decrementCard(CardInfoPtr card, QString zoneName);
protected slots:
// Deck Operations
virtual void actNewDeck();
void cleanDeckAndResetModified();
virtual void actLoadDeck();
bool actSaveDeck();
bool actSaveDeckAs();
virtual void actLoadDeckFromClipboard();
void actEditDeckInClipboard();
void actEditDeckInClipboardRaw();
void actSaveDeckToClipboard();
void actSaveDeckToClipboardNoSetNameAndNumber();
void actSaveDeckToClipboardRaw();
void actSaveDeckToClipboardRawNoSetNameAndNumber();
void actPrintDeck();
void actExportDeckDecklist();
void actAnalyzeDeckDeckstats();
void actAnalyzeDeckTappedout();
// Remote Save
void saveDeckRemoteFinished(const Response &r);
// UI Layout Management
virtual void loadLayout() = 0;
virtual void restartLayout() = 0;
virtual void freeDocksSize() = 0;
virtual void refreshShortcuts() = 0;
bool eventFilter(QObject *o, QEvent *e) override;
virtual void dockVisibleTriggered() = 0;
virtual void dockFloatingTriggered() = 0;
private:
void editDeckInClipboard(bool annotated);
protected:
/**
* @brief Enum for selecting deck open location
*/
enum DeckOpenLocation
{
CANCELLED,
SAME_TAB,
NEW_TAB
};
DeckOpenLocation confirmOpen(bool openInSameTabIfBlank = true);
QMessageBox *createSaveConfirmationWindow();
bool isBlankNewDeck() const;
// Helper functions for card actions
void addCardHelper(CardInfoPtr info, QString zoneName);
void actSwapCard(CardInfoPtr info, QString zoneName);
virtual void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation);
// UI Menu Elements
QMenu *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *printingSelectorDockMenu;
QAction *aResetLayout;
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating;
QAction *aFilterDockVisible, *aFilterDockFloating, *aPrintingSelectorDockVisible, *aPrintingSelectorDockFloating;
bool modified;
};
#endif // TAB_GENERIC_DECK_EDITOR_H

View File

@@ -0,0 +1,45 @@
#include "edhrec_commander_api_response.h"
#include <QDebug>
#include <QJsonArray>
void EdhrecCommanderApiResponse::fromJson(const QJsonObject &json)
{
// Parse the collapsed DeckStatistics
deckStats.fromJson(json);
// Parse Archidekt section
QJsonArray archidektJson = json.value("archidekt").toArray();
archidekt.fromJson(archidektJson);
// Parse other fields
similar = json.value("similar").toObject();
header = json.value("header").toString();
panels = json.value("panels").toObject();
description = json.value("description").toString();
QJsonObject containerJson = json.value("container").toObject();
container.fromJson(containerJson);
}
void EdhrecCommanderApiResponse::debugPrint() const
{
qDebug() << "Deck Statistics:";
qDebug() << " Creature:" << deckStats.creature;
qDebug() << " Instant:" << deckStats.instant;
qDebug() << " Sorcery:" << deckStats.sorcery;
qDebug() << " Artifact:" << deckStats.artifact;
qDebug() << " Enchantment:" << deckStats.enchantment;
qDebug() << " Battle:" << deckStats.battle;
qDebug() << " Planeswalker:" << deckStats.planeswalker;
qDebug() << " Land:" << deckStats.land;
qDebug() << " Basic:" << deckStats.basic;
qDebug() << " Nonbasic:" << deckStats.nonbasic;
archidekt.debugPrint();
qDebug() << "Similar:" << similar;
qDebug() << "Header:" << header;
qDebug() << "Panels:" << panels;
qDebug() << "Description:" << description;
container.debugPrint();
}

View File

@@ -0,0 +1,28 @@
#ifndef DECKDATA_H
#define DECKDATA_H
#include "edhrec_commander_api_response_archidekt_links.h"
#include "edhrec_commander_api_response_average_deck_statistics.h"
#include "edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject>
#include <QString>
// Represents the main structure of the JSON
class EdhrecCommanderApiResponse
{
public:
EdhrecCommanderApiResponseAverageDeckStatistics deckStats;
EdhrecCommanderApiResponseArchidektLinks archidekt;
QJsonObject similar;
QString header;
QJsonObject panels;
QString description;
EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
#endif // DECKDATA_H

View File

@@ -0,0 +1,43 @@
#include "edhrec_commander_api_response_archidekt_links.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
void EdhrecCommanderApiResponseArchidektLink::fromJson(const QJsonObject &json)
{
c = json.value("c").toString();
f = json.value("f").toInt(0);
q = json.value("q").toInt(0);
u = json.value("u").toString();
}
void EdhrecCommanderApiResponseArchidektLink::debugPrint() const
{
qDebug() << " C:" << c;
qDebug() << " F:" << f;
qDebug() << " Q:" << q;
qDebug() << " U:" << u;
}
void EdhrecCommanderApiResponseArchidektLinks::fromJson(const QJsonArray &json)
{
entries.clear();
for (const QJsonValue &value : json) {
if (value.isObject()) {
QJsonObject entryJson = value.toObject();
EdhrecCommanderApiResponseArchidektLink entry;
entry.fromJson(entryJson);
entries.append(entry);
}
}
}
void EdhrecCommanderApiResponseArchidektLinks::debugPrint() const
{
qDebug() << "Archidekt Entries:";
for (const auto &entry : entries) {
entry.debugPrint();
}
}

View File

@@ -0,0 +1,32 @@
#ifndef ARCHIDEKTENTRY_H
#define ARCHIDEKTENTRY_H
#include <QDebug>
#include <QJsonObject>
#include <QString>
#include <QVector>
// Represents a single Archidekt entry
class EdhrecCommanderApiResponseArchidektLink
{
public:
QString c;
int f = 0;
int q = 0;
QString u;
void fromJson(const QJsonObject &json);
void debugPrint() const;
};
// Represents the Archidekt section as a list of entries
class EdhrecCommanderApiResponseArchidektLinks
{
public:
QVector<EdhrecCommanderApiResponseArchidektLink> entries;
void fromJson(const QJsonArray &json);
void debugPrint() const;
};
#endif // ARCHIDEKTENTRY_H

View File

@@ -0,0 +1,15 @@
#include "edhrec_commander_api_response_average_deck_statistics.h"
void EdhrecCommanderApiResponseAverageDeckStatistics::fromJson(const QJsonObject &json)
{
creature = json.value("creature").toInt(0);
instant = json.value("instant").toInt(0);
sorcery = json.value("sorcery").toInt(0);
artifact = json.value("artifact").toInt(0);
enchantment = json.value("enchantment").toInt(0);
battle = json.value("battle").toInt(0);
planeswalker = json.value("planeswalker").toInt(0);
land = json.value("land").toInt(0);
basic = json.value("basic").toInt(0);
nonbasic = json.value("nonbasic").toInt(0);
}

View File

@@ -0,0 +1,22 @@
#ifndef AVERAGE_DECK_STATISTICS_H
#define AVERAGE_DECK_STATISTICS_H
#include <QJsonObject>
// Represents the typical deck statistics (collapsed section)
struct EdhrecCommanderApiResponseAverageDeckStatistics
{
int creature = 0;
int instant = 0;
int sorcery = 0;
int artifact = 0;
int enchantment = 0;
int battle = 0;
int planeswalker = 0;
int land = 0;
int basic = 0;
int nonbasic = 0;
void fromJson(const QJsonObject &json);
};
#endif // AVERAGE_DECK_STATISTICS_H

View File

@@ -0,0 +1,49 @@
#include "edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
void EdhrecCommanderApiResponseCardContainer::fromJson(const QJsonObject &json)
{
// Parse breadcrumb
QJsonArray breadcrumbArray = json.value("breadcrumb").toArray();
for (const QJsonValue &breadcrumbValue : breadcrumbArray) {
breadcrumb.push_back(breadcrumbValue.toObject());
}
description = json.value("description").toString();
QJsonObject jsonDict = json.value("json_dict").toObject();
card.fromJson(jsonDict.value("card").toObject());
QJsonArray cardlistsArray = jsonDict.value("cardlists").toArray();
for (const QJsonValue &cardlistValue : cardlistsArray) {
QJsonObject cardlistObj = cardlistValue.toObject();
QJsonArray cardviewsArray = cardlistObj.value("cardviews").toArray();
EdhrecCommanderApiResponseCardList cardView;
cardView.fromJson(cardlistValue.toObject());
cardlists.push_back(cardView);
}
keywords = json.value("keywords").toString();
title = json.value("title").toString();
}
void EdhrecCommanderApiResponseCardContainer::debugPrint() const
{
qDebug() << "Breadcrumb:";
for (const auto &breadcrumbEntry : breadcrumb) {
qDebug() << breadcrumbEntry;
}
qDebug() << "Description:" << description;
card.debugPrint();
qDebug() << "Cardlists:";
for (const auto &cardlist : cardlists) {
cardlist.debugPrint();
}
qDebug() << "Keywords:" << keywords;
qDebug() << "Title:" << title;
}

View File

@@ -0,0 +1,60 @@
#ifndef CONTAINER_ENTRY_H
#define CONTAINER_ENTRY_H
#include "edhrec_commander_api_response_card_list.h"
#include "edhrec_commander_api_response_commander_details.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVector>
class EdhrecCommanderApiResponseCardContainer
{
public:
// Constructor
EdhrecCommanderApiResponseCardContainer() = default;
// Parse deck-related data from JSON
void fromJson(const QJsonObject &json);
// Debug method for logging
void debugPrint() const;
// Getter methods for deck container
const QString &getDescription() const
{
return description;
}
const QVector<QJsonObject> &getBreadcrumb() const
{
return breadcrumb;
}
const EdhrecCommanderApiResponseCommanderDetails &getCommanderDetails() const
{
return card;
}
const QVector<EdhrecCommanderApiResponseCardList> &getCardlists() const
{
return cardlists;
}
const QString &getKeywords() const
{
return keywords;
}
const QString &getTitle() const
{
return title;
}
private:
QString description;
QVector<QJsonObject> breadcrumb;
EdhrecCommanderApiResponseCommanderDetails card;
QVector<EdhrecCommanderApiResponseCardList> cardlists;
QString keywords;
QString title;
};
#endif // CONTAINER_ENTRY_H

View File

@@ -0,0 +1,36 @@
#include "edhrec_commander_api_response_card_details.h"
#include <QDebug>
EdhrecCommanderApiResponseCardDetails::EdhrecCommanderApiResponseCardDetails()
: synergy(0.0), inclusion(0), numDecks(0), potentialDecks(0)
{
}
void EdhrecCommanderApiResponseCardDetails::fromJson(const QJsonObject &json)
{
// Parse the fields from the JSON object
name = json.value("name").toString();
sanitized = json.value("sanitized").toString();
sanitizedWo = json.value("sanitized_wo").toString();
url = json.value("url").toString();
synergy = json.value("synergy").toDouble(0.0);
inclusion = json.value("inclusion").toInt(0);
label = json.value("label").toString();
numDecks = json.value("num_decks").toInt(0);
potentialDecks = json.value("potential_decks").toInt(0);
}
void EdhrecCommanderApiResponseCardDetails::debugPrint() const
{
// Print out all the fields for debugging
qDebug() << "Name:" << name;
qDebug() << "Sanitized:" << sanitized;
qDebug() << "Sanitized Wo:" << sanitizedWo;
qDebug() << "URL:" << url;
qDebug() << "Synergy:" << synergy;
qDebug() << "Inclusion:" << inclusion;
qDebug() << "Label:" << label;
qDebug() << "Num Decks:" << numDecks;
qDebug() << "Potential Decks:" << potentialDecks;
}

View File

@@ -0,0 +1,29 @@
#ifndef CARD_VIEW_H
#define CARD_VIEW_H
#include <QJsonObject>
#include <QString>
class EdhrecCommanderApiResponseCardDetails
{
public:
QString name;
QString sanitized;
QString sanitizedWo;
QString url;
double synergy;
int inclusion;
QString label;
int numDecks;
int potentialDecks;
EdhrecCommanderApiResponseCardDetails();
// Method to populate the object from a JSON object
void fromJson(const QJsonObject &json);
// Debug method to print out the data
void debugPrint() const;
};
#endif // CARD_VIEW_H

View File

@@ -0,0 +1,33 @@
#include "edhrec_commander_api_response_card_list.h"
#include <QDebug>
EdhrecCommanderApiResponseCardList::EdhrecCommanderApiResponseCardList()
{
}
void EdhrecCommanderApiResponseCardList::fromJson(const QJsonObject &json)
{
// Parse the header from the JSON object
header = json.value("header").toString();
// Parse the cardviews array and populate cardViews
QJsonArray cardviewsArray = json.value("cardviews").toArray();
for (const QJsonValue &value : cardviewsArray) {
QJsonObject cardviewObj = value.toObject();
EdhrecCommanderApiResponseCardDetails cardView;
cardView.fromJson(cardviewObj);
cardViews.append(cardView);
}
}
void EdhrecCommanderApiResponseCardList::debugPrint() const
{
// Print out the header
qDebug() << "Header:" << header;
// Print out all the CardView objects
for (const EdhrecCommanderApiResponseCardDetails &cardView : cardViews) {
cardView.debugPrint();
}
}

View File

@@ -0,0 +1,27 @@
#ifndef CARD_LIST_H
#define CARD_LIST_H
#include "edhrec_commander_api_response_card_details.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QList>
#include <QString>
class EdhrecCommanderApiResponseCardList
{
public:
QString header;
QList<EdhrecCommanderApiResponseCardDetails> cardViews;
// Default constructor
EdhrecCommanderApiResponseCardList();
// Method to populate the object from a JSON object
void fromJson(const QJsonObject &json);
// Debug method to print out the data
void debugPrint() const;
};
#endif // CARD_LIST_H

View File

@@ -0,0 +1,31 @@
#include "edhrec_commander_api_response_card_prices.h"
#include <QDebug>
void CardPrices::fromJson(const QJsonObject &json)
{
// Parse prices from various sources
cardhoarder = json.value("cardhoarder").toObject();
cardkingdom = json.value("cardkingdom").toObject();
cardmarket = json.value("cardmarket").toObject();
face2face = json.value("face2face").toObject();
manapool = json.value("manapool").toObject();
mtgstocks = json.value("mtgstocks").toObject();
scg = json.value("scg").toObject();
tcgl = json.value("tcgl").toObject();
tcgplayer = json.value("tcgplayer").toObject();
}
void CardPrices::debugPrint() const
{
qDebug() << "Card Prices:";
qDebug() << "Cardhoarder:" << cardhoarder;
qDebug() << "Cardkingdom:" << cardkingdom;
qDebug() << "Cardmarket:" << cardmarket;
qDebug() << "Face2Face:" << face2face;
qDebug() << "Manapool:" << manapool;
qDebug() << "Mtgstocks:" << mtgstocks;
qDebug() << "SCG:" << scg;
qDebug() << "TCGL:" << tcgl;
qDebug() << "Tcgplayer:" << tcgplayer;
}

View File

@@ -0,0 +1,66 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H
#include <QJsonObject>
class CardPrices
{
public:
// Constructor
CardPrices() = default;
// Parse prices from JSON
void fromJson(const QJsonObject &json);
void debugPrint() const;
// Getter methods for card prices
const QJsonObject &getCardhoarder() const
{
return cardhoarder;
}
const QJsonObject &getCardkingdom() const
{
return cardkingdom;
}
const QJsonObject &getCardmarket() const
{
return cardmarket;
}
const QJsonObject &getFace2face() const
{
return face2face;
}
const QJsonObject &getManapool() const
{
return manapool;
}
const QJsonObject &getMtgstocks() const
{
return mtgstocks;
}
const QJsonObject &getScg() const
{
return scg;
}
const QJsonObject &getTcgl() const
{
return tcgl;
}
const QJsonObject &getTcgplayer() const
{
return tcgplayer;
}
private:
QJsonObject cardhoarder;
QJsonObject cardkingdom;
QJsonObject cardmarket;
QJsonObject face2face;
QJsonObject manapool;
QJsonObject mtgstocks;
QJsonObject scg;
QJsonObject tcgl;
QJsonObject tcgplayer;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_PRICES_H

View File

@@ -0,0 +1,90 @@
#include "edhrec_commander_api_response_commander_details.h"
#include <QDebug>
void EdhrecCommanderApiResponseCommanderDetails::fromJson(const QJsonObject &json)
{
// Parse card-related data
aetherhubUri = json.value("aetherhub_uri").toString();
archidektUri = json.value("archidekt_uri").toString();
cmc = json.value("cmc").toInt(0);
colorIdentity = json.value("color_identity").toArray();
combos = json.value("combos").toBool(false);
deckstatsUri = json.value("deckstats_uri").toString();
// Parse image URIs
QJsonArray imageUrisArray = json.value("image_uris").toArray();
for (const QJsonValue &imageValue : imageUrisArray) {
QJsonObject imageObject = imageValue.toObject();
imageUris.push_back(imageObject.value("normal").toString());
imageUris.push_back(imageObject.value("art_crop").toString());
}
inclusion = json.value("inclusion").toInt(0);
isCommander = json.value("is_commander").toBool(false);
label = json.value("label").toString();
layout = json.value("layout").toString();
legalCommander = json.value("legal_commander").toBool(false);
moxfieldUri = json.value("moxfield_uri").toString();
mtggoldfishUri = json.value("mtggoldfish_uri").toString();
name = json.value("name").toString();
names = json.value("names").toArray();
numDecks = json.value("num_decks").toInt(0);
potentialDecks = json.value("potential_decks").toInt(0);
precon = json.value("precon").toString();
// Parse prices
prices.fromJson(json.value("prices").toObject());
primaryType = json.value("primary_type").toString();
rarity = json.value("rarity").toString();
salt = json.value("salt").toDouble(0.0);
sanitized = json.value("sanitized").toString();
sanitizedWo = json.value("sanitized_wo").toString();
scryfallUri = json.value("scryfall_uri").toString();
spellbookUri = json.value("spellbook_uri").toString();
type = json.value("type").toString();
url = json.value("url").toString();
}
void EdhrecCommanderApiResponseCommanderDetails::debugPrint() const
{
qDebug() << "Card Data:";
qDebug() << "Aetherhub URI:" << aetherhubUri;
qDebug() << "Archidekt URI:" << archidektUri;
qDebug() << "CMC:" << cmc;
qDebug() << "Color Identity:" << colorIdentity;
qDebug() << "Combos:" << combos;
qDebug() << "Deckstats URI:" << deckstatsUri;
qDebug() << "Image URIs:";
for (const auto &uri : imageUris) {
qDebug() << uri;
}
qDebug() << "Inclusion:" << inclusion;
qDebug() << "Is Commander:" << isCommander;
qDebug() << "Label:" << label;
qDebug() << "Layout:" << layout;
qDebug() << "Legal Commander:" << legalCommander;
qDebug() << "Moxfield URI:" << moxfieldUri;
qDebug() << "MTGGoldfish URI:" << mtggoldfishUri;
qDebug() << "Name:" << name;
qDebug() << "Names:" << names;
qDebug() << "Number of Decks:" << numDecks;
qDebug() << "Potential Decks:" << potentialDecks;
qDebug() << "Precon:" << precon;
// Print the prices using the debugPrint method from CardPrices
prices.debugPrint();
qDebug() << "Primary Type:" << primaryType;
qDebug() << "Rarity:" << rarity;
qDebug() << "Salt:" << salt;
qDebug() << "Sanitized:" << sanitized;
qDebug() << "Sanitized WO:" << sanitizedWo;
qDebug() << "Scryfall URI:" << scryfallUri;
qDebug() << "Spellbook URI:" << spellbookUri;
qDebug() << "Type:" << type;
qDebug() << "URL:" << url;
}

View File

@@ -0,0 +1,173 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H
#include "edhrec_commander_api_response_card_prices.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QString>
#include <QVector>
class EdhrecCommanderApiResponseCommanderDetails
{
public:
// Constructor
EdhrecCommanderApiResponseCommanderDetails() = default;
// Parse card-related data from JSON
void fromJson(const QJsonObject &json);
// Debug method for logging
void debugPrint() const;
// Getters for the card data
const QString &getAetherhubUri() const
{
return aetherhubUri;
}
const QString &getArchidektUri() const
{
return archidektUri;
}
int getCmc() const
{
return cmc;
}
const QJsonArray &getColorIdentity() const
{
return colorIdentity;
}
bool isCombos() const
{
return combos;
}
const QString &getDeckstatsUri() const
{
return deckstatsUri;
}
const QVector<QString> &getImageUris() const
{
return imageUris;
}
int getInclusion() const
{
return inclusion;
}
bool getIsCommander() const
{
return isCommander;
}
const QString &getLabel() const
{
return label;
}
const QString &getLayout() const
{
return layout;
}
bool getLegalCommander() const
{
return legalCommander;
}
const QString &getMoxfieldUri() const
{
return moxfieldUri;
}
const QString &getMtggoldfishUri() const
{
return mtggoldfishUri;
}
const QString &getName() const
{
return name;
}
const QJsonArray &getNames() const
{
return names;
}
int getNumDecks() const
{
return numDecks;
}
int getPotentialDecks() const
{
return potentialDecks;
}
const QString &getPrecon() const
{
return precon;
}
const CardPrices &getPrices() const
{
return prices;
}
const QString &getPrimaryType() const
{
return primaryType;
}
const QString &getRarity() const
{
return rarity;
}
double getSalt() const
{
return salt;
}
const QString &getSanitized() const
{
return sanitized;
}
const QString &getSanitizedWo() const
{
return sanitizedWo;
}
const QString &getScryfallUri() const
{
return scryfallUri;
}
const QString &getSpellbookUri() const
{
return spellbookUri;
}
const QString &getType() const
{
return type;
}
const QString &getUrl() const
{
return url;
}
private:
QString aetherhubUri;
QString archidektUri;
int cmc = 0;
QJsonArray colorIdentity;
bool combos = false;
QString deckstatsUri;
QVector<QString> imageUris;
int inclusion = 0;
bool isCommander = false;
QString label;
QString layout;
bool legalCommander = false;
QString moxfieldUri;
QString mtggoldfishUri;
QString name;
QJsonArray names;
int numDecks = 0;
int potentialDecks = 0;
QString precon;
CardPrices prices;
QString primaryType;
QString rarity;
double salt = 0.0;
QString sanitized;
QString sanitizedWo;
QString scryfallUri;
QString spellbookUri;
QString type;
QString url;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_H

View File

@@ -0,0 +1,41 @@
#include "edhrec_commander_api_response_card_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h"
EdhrecCommanderApiResponseCardDetailsDisplayWidget::EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCardDetails &_toDisplay)
: QWidget(parent), toDisplay(_toDisplay)
{
layout = new QVBoxLayout(this);
setLayout(layout);
cardPictureWidget = new CardInfoPictureWidget(this);
cardPictureWidget->setCard(CardDatabaseManager::getInstance()->getCard(toDisplay.name));
label = new QLabel(this);
label->setText(toDisplay.name + "\n" + toDisplay.label);
label->setAlignment(Qt::AlignHCenter);
// Set label color based on inclusion rate
int inclusionRate = (toDisplay.numDecks * 100) / toDisplay.potentialDecks;
QColor labelColor;
if (inclusionRate <= 30) {
labelColor = QColor(255, 0, 0); // Red
} else if (inclusionRate <= 60) {
int red = 255 - ((inclusionRate - 30) * 2);
int green = (inclusionRate - 30) * 4; // Adjust green to make the transition smoother
labelColor = QColor(red, green, 0); // purple-ish
} else if (inclusionRate <= 90) {
int green = (inclusionRate - 60) * 5; // Increase green
labelColor = QColor(100, green, 100); // Green shades
} else {
labelColor = QColor(100, 200, 100); // Dark Green
}
label->setStyleSheet(QString("color: %1").arg(labelColor.name()));
layout->addWidget(cardPictureWidget);
layout->addWidget(label);
}

View File

@@ -0,0 +1,26 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_card_details.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QWidget>
class EdhrecCommanderApiResponseCardDetailsDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseCardDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCardDetails &_toDisplay);
private:
EdhrecCommanderApiResponseCardDetails toDisplay;
QVBoxLayout *layout;
CardInfoPictureWidget *cardPictureWidget;
QLabel *label;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_DETAILS_DISPLAY_WIDGET_H

View File

@@ -0,0 +1,34 @@
#include "edhrec_commander_api_response_card_list_display_widget.h"
#include "../../../ui/widgets/general/display/banner_widget.h"
#include "edhrec_commander_api_response_card_details_display_widget.h"
#include <QLabel>
EdhrecCommanderApiResponseCardListDisplayWidget::EdhrecCommanderApiResponseCardListDisplayWidget(
QWidget *parent,
EdhrecCommanderApiResponseCardList toDisplay)
: QWidget(parent)
{
layout = new QVBoxLayout(this);
setLayout(layout);
header = new BannerWidget(this, toDisplay.header);
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
header->setBuddy(flowWidget);
foreach (EdhrecCommanderApiResponseCardDetails card_detail, toDisplay.cardViews) {
auto widget = new EdhrecCommanderApiResponseCardDetailsDisplayWidget(flowWidget, card_detail);
flowWidget->addWidget(widget);
}
layout->addWidget(header);
layout->addWidget(flowWidget);
}
void EdhrecCommanderApiResponseCardListDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << event->size();
}

View File

@@ -0,0 +1,30 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H
#include "../../../ui/widgets/general/display/banner_widget.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "api_response/edhrec_commander_api_response_card_list.h"
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderApiResponseCardListDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseCardListDisplayWidget(QWidget *parent,
EdhrecCommanderApiResponseCardList toDisplay);
void resizeEvent(QResizeEvent *event) override;
[[nodiscard]] QString getBannerText() const
{
return header->getText();
};
private:
QVBoxLayout *layout;
BannerWidget *header;
FlowWidget *flowWidget;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_CARD_LIST_DISPLAY_WIDGET_H

View File

@@ -0,0 +1,36 @@
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include <QLabel>
EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails)
: QWidget(parent), commanderDetails(_commanderDetails)
{
layout = new QVBoxLayout(this);
setLayout(layout);
commanderPicture = new CardInfoPictureWidget(this);
commanderPicture->setCard(CardDatabaseManager::getInstance()->getCard(commanderDetails.getName()));
commanderDetails.debugPrint();
label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
salt = new QLabel(this);
salt->setAlignment(Qt::AlignCenter);
layout->addWidget(commanderPicture);
layout->addWidget(label);
layout->addWidget(salt);
retranslateUi();
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
{
label->setText(commanderDetails.getLabel());
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
}

View File

@@ -0,0 +1,28 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response_commander_details.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderResponseCommanderDetailsDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderResponseCommanderDetailsDisplayWidget(
QWidget *parent,
const EdhrecCommanderApiResponseCommanderDetails &_commanderDetails);
void retranslateUi();
private:
QLabel *label;
QLabel *salt;
QVBoxLayout *layout;
CardInfoPictureWidget *commanderPicture;
EdhrecCommanderApiResponseCommanderDetails commanderDetails;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_COMMANDER_DETAILS_DISPLAY_WIDGET_H

View File

@@ -0,0 +1,102 @@
#include "edhrec_commander_api_response_display_widget.h"
#include "../../../ui/widgets/cards/card_info_picture_widget.h"
#include "api_response/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_card_list_display_widget.h"
#include "edhrec_commander_api_response_commander_details_display_widget.h"
#include <QListView>
#include <QResizeEvent>
#include <QScrollArea>
#include <QSplitter>
#include <QStringListModel>
EdhrecCommanderApiResponseDisplayWidget::EdhrecCommanderApiResponseDisplayWidget(QWidget *parent,
EdhrecCommanderApiResponse response)
: QWidget(parent)
{
layout = new QHBoxLayout(this);
setLayout(layout);
cardDisplayLayout = new QVBoxLayout(this);
// Create a QSplitter to hold the ListView and ScrollArea holding CardListdisplayWidgets side by side
auto splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
auto listView = new QListView(splitter);
listView->setMinimumWidth(50);
listView->setMaximumWidth(150);
auto listModel = new QStringListModel(this);
QStringList widgetNames;
// Add commander details
auto commanderPicture =
new EdhrecCommanderResponseCommanderDetailsDisplayWidget(this, response.container.getCommanderDetails());
cardDisplayLayout->addWidget(commanderPicture);
widgetNames.append("Commander Details");
// Add card list widgets
auto edhrec_commander_api_response_card_lists = response.container.getCardlists();
for (const EdhrecCommanderApiResponseCardList &card_list : edhrec_commander_api_response_card_lists) {
auto cardListDisplayWidget = new EdhrecCommanderApiResponseCardListDisplayWidget(this, card_list);
cardDisplayLayout->addWidget(cardListDisplayWidget);
widgetNames.append(cardListDisplayWidget->getBannerText());
}
// Create a QScrollArea to hold the card display widgets
scrollArea = new QScrollArea(splitter);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Set the cardDisplayLayout inside the scroll area
auto scrollWidget = new QWidget(scrollArea);
scrollWidget->setLayout(cardDisplayLayout);
connect(splitter, &QSplitter::splitterMoved, this, &EdhrecCommanderApiResponseDisplayWidget::onSplitterChange);
scrollArea->setWidget(scrollWidget);
// Configure the list view
listModel->setStringList(widgetNames);
listView->setModel(listModel);
listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
// Connect the list view to ensure the corresponding widget is visible
connect(listView, &QListView::clicked, this, [this](const QModelIndex &index) {
int widgetIndex = index.row();
qDebug() << "clicked: " << widgetIndex;
auto targetWidget = cardDisplayLayout->itemAt(widgetIndex)->widget();
if (targetWidget) {
qDebug() << "Found targetWidget" << targetWidget;
// Attempt to cast the parent to QScrollArea
auto scrollArea = qobject_cast<QScrollArea *>(this->scrollArea); // Use the scroll area instance
if (scrollArea) {
qDebug() << "ScrollArea" << scrollArea;
scrollArea->ensureWidgetVisible(targetWidget);
}
}
});
// Add splitter to the main layout
splitter->addWidget(listView);
splitter->addWidget(scrollArea);
layout->addWidget(splitter);
}
void EdhrecCommanderApiResponseDisplayWidget::onSplitterChange()
{
scrollArea->widget()->resize(scrollArea->size());
}
void EdhrecCommanderApiResponseDisplayWidget::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
qDebug() << event->size();
layout->invalidate();
layout->activate();
layout->update();
if (scrollArea && scrollArea->widget()) {
scrollArea->widget()->resize(event->size());
}
}

View File

@@ -0,0 +1,27 @@
#ifndef EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#define EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H
#include "api_response/edhrec_commander_api_response.h"
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class EdhrecCommanderApiResponseDisplayWidget : public QWidget
{
Q_OBJECT
public:
explicit EdhrecCommanderApiResponseDisplayWidget(QWidget *parent, EdhrecCommanderApiResponse response);
void resizeEvent(QResizeEvent *event) override;
public slots:
void onSplitterChange();
private:
QHBoxLayout *layout;
QVBoxLayout *cardDisplayLayout;
QScrollArea *scrollArea;
};
#endif // EDHREC_COMMANDER_API_RESPONSE_DISPLAY_WIDGET_H

View File

@@ -0,0 +1,112 @@
#include "tab_edhrec.h"
#include "api_response/edhrec_commander_api_response.h"
#include "edhrec_commander_api_response_display_widget.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegularExpression>
#include <QResizeEvent>
TabEdhRec::TabEdhRec(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
networkManager = new QNetworkAccessManager(this);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
networkManager->setTransferTimeout(); // Use Qt's default timeout
#endif
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(processApiJson(QNetworkReply *)));
}
void TabEdhRec::retranslateUi()
{
}
void TabEdhRec::setCard(CardInfoPtr _cardToQuery, bool isCommander)
{
cardToQuery = _cardToQuery;
if (!cardToQuery) {
qDebug() << "Invalid card information provided.";
return;
}
QString cardName = cardToQuery->getName();
QString formattedName = cardName.toLower().replace(" ", "-").remove(QRegularExpression("[^a-z0-9\\-]"));
QString url;
if (isCommander) {
url = QString("https://json.edhrec.com/pages/commanders/%1.json").arg(formattedName);
} else {
url = QString("https://json.edhrec.com/pages/cards/%1.json").arg(formattedName);
}
QNetworkRequest request{QUrl(url)};
networkManager->get(request);
}
void TabEdhRec::processApiJson(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Network error occurred:" << reply->errorString();
reply->deleteLater();
return;
}
QByteArray responseData = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
if (!jsonDoc.isObject()) {
qDebug() << "Invalid JSON response received.";
reply->deleteLater();
return;
}
QJsonObject jsonObj = jsonDoc.object();
// qDebug() << jsonObj;
EdhrecCommanderApiResponse deckData;
deckData.fromJson(jsonObj);
displayWidget = new EdhrecCommanderApiResponseDisplayWidget(this, deckData);
// flowWidget->addWidget(displayWidget);
setCentralWidget(displayWidget);
reply->deleteLater();
update();
}
void TabEdhRec::prettyPrintJson(const QJsonValue &value, int indentLevel)
{
const QString indent(indentLevel * 2, ' '); // Adjust spacing as needed for pretty printing
if (value.isObject()) {
QJsonObject obj = value.toObject();
for (auto it = obj.begin(); it != obj.end(); ++it) {
qDebug().noquote() << indent + it.key() + ":";
prettyPrintJson(it.value(), indentLevel + 1);
}
} else if (value.isArray()) {
QJsonArray array = value.toArray();
for (int i = 0; i < array.size(); ++i) {
qDebug().noquote() << indent + QString("[%1]:").arg(i);
prettyPrintJson(array[i], indentLevel + 1);
}
} else if (value.isString()) {
qDebug().noquote() << indent + "\"" + value.toString() + "\"";
} else if (value.isDouble()) {
qDebug().noquote() << indent + QString::number(value.toDouble());
} else if (value.isBool()) {
qDebug().noquote() << indent + (value.toBool() ? "true" : "false");
} else if (value.isNull()) {
qDebug().noquote() << indent + "null";
}
}

View File

@@ -0,0 +1,37 @@
#ifndef TAB_EDHREC_H
#define TAB_EDHREC_H
#include "../../../../game/cards/card_database.h"
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
#include "../../tab.h"
#include "edhrec_commander_api_response_display_widget.h"
#include <QHBoxLayout>
#include <QNetworkAccessManager>
class TabEdhRec : public Tab
{
Q_OBJECT
public:
explicit TabEdhRec(TabSupervisor *_tabSupervisor);
void retranslateUi() override;
QString getTabText() const override
{
auto cardName = cardToQuery.isNull() ? QString() : cardToQuery->getName();
return tr("EDHREC: ") + cardName;
}
QNetworkAccessManager *networkManager;
public slots:
void processApiJson(QNetworkReply *reply);
void prettyPrintJson(const QJsonValue &value, int indentLevel);
void setCard(CardInfoPtr _cardToQuery, bool isCommander = false);
private:
CardInfoPtr cardToQuery;
EdhrecCommanderApiResponseDisplayWidget *displayWidget;
};
#endif // TAB_EDHREC_H

View File

@@ -1,25 +1,29 @@
#include "tab.h"
#include "../ui/widgets/cards/card_info_display_widget.h"
#include "./tab_supervisor.h"
#include <QApplication>
#include <QCloseEvent>
#include <QDebug>
#include <QScreen>
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
Tab::Tab(TabSupervisor *_tabSupervisor)
: QMainWindow(_tabSupervisor), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
{
setAttribute(Qt::WA_DeleteOnClose);
}
void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName)
void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName, const QString &providerId)
{
if (infoPopup) {
infoPopup->deleteLater();
}
currentCardName = cardName;
infoPopup = new CardInfoDisplayWidget(
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
currentProviderId = providerId;
infoPopup = new CardInfoDisplayWidget(cardName, providerId, nullptr,
Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint |
Qt::WindowStaysOnTopHint);
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
auto screenRect = qApp->primaryScreen()->geometry();
@@ -39,3 +43,17 @@ void Tab::deleteCardInfoPopup(const QString &cardName)
}
}
}
/**
* Overrides the closeEvent in order to emit a close signal
*/
void Tab::closeEvent(QCloseEvent *event)
{
emit closed();
event->accept();
}
void Tab::closeRequest(bool /*forced*/)
{
close();
}

View File

@@ -13,6 +13,12 @@ class Tab : public QMainWindow
signals:
void userEvent(bool globalEvent = true);
void tabTextChanged(Tab *tab, const QString &newTabText);
/**
* Emitted when the tab is closed (because Qt doesn't provide a built-in close signal)
* This signal is emitted from this class's overridden Tab::closeEvent method.
* Make sure any subclasses that override closeEvent still emit this signal from there.
*/
void closed();
protected:
TabSupervisor *tabSupervisor;
@@ -21,17 +27,18 @@ protected:
tabMenus.append(menu);
}
protected slots:
void showCardInfoPopup(const QPoint &pos, const QString &cardName);
void showCardInfoPopup(const QPoint &pos, const QString &cardName, const QString &providerId);
void deleteCardInfoPopup(const QString &cardName);
void closeEvent(QCloseEvent *event) override;
private:
QString currentCardName;
QString currentCardName, currentProviderId;
bool contentsChanged;
CardInfoDisplayWidget *infoPopup;
QList<QMenu *> tabMenus;
public:
Tab(TabSupervisor *_tabSupervisor, QWidget *parent = nullptr);
explicit Tab(TabSupervisor *_tabSupervisor);
const QList<QMenu *> &getTabMenus() const
{
return tabMenus;
@@ -50,9 +57,13 @@ public:
}
virtual QString getTabText() const = 0;
virtual void retranslateUi() = 0;
virtual void closeRequest()
{
}
/**
* Sends a request to close the tab.
* Signals for cleanup should be emitted from this method instead of the destructor.
*
* @param forced whether this close request was initiated by the user or forced by the server.
*/
virtual void closeRequest(bool forced = false);
virtual void tabActivated()
{
}

Some files were not shown because too many files have changed in this diff Show More