Add build script.

This commit is contained in:
luxick
2018-02-19 22:56:31 +01:00
parent f90930c617
commit 2e8411c6b4
181 changed files with 288 additions and 284 deletions

View File

@@ -1,2 +0,0 @@
from cardvault import application
application.main()

17
build.py Normal file
View File

@@ -0,0 +1,17 @@
"""
Package cardvault using zipapp into an executable zip archive
"""
import os
import zipapp
INTERPRETER = '/usr/bin/env python3'
TARGET_FILENAME = 'cardvault'
# The bundled file should be placed into the build directory
target_path = os.path.join(os.path.dirname(__file__), 'build')
# Make sure it exists
if not os.path.isdir(target_path):
os.mkdir(target_path)
target = os.path.join(target_path, TARGET_FILENAME)
# Create archive
zipapp.create_archive(source='cardvault', target=target, interpreter=INTERPRETER)

View File

@@ -1 +0,0 @@
from cardvault import application

10
cardvault/__main__.py Normal file
View File

@@ -0,0 +1,10 @@
import sys
import os.path
path = os.path.realpath(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(path))
from cv_gtk3 import gtk_ui
if __name__ == '__main__':
gtk_ui.main()

View File

@@ -1,4 +1,3 @@
import json
import os
import itertools
@@ -8,8 +7,7 @@ from cv_engine.util import EngineConfig, EngineConstants, Utilities
class CardvaultEngine:
def __init__(self, config_file=False):
"""
Create a new cv_engine instance
""" Create a new cv_engine instance
:param config_file: File path of the configuration file
"""
if config_file:
@@ -18,23 +16,20 @@ class CardvaultEngine:
self.database = CardvaultDB(db_file_path)
def get_card(self, card_id):
"""
Load a card object from database
""" Load a card object from database
:param card_id: multiverse id of a card
:return: an cv_engine.model.Card object
"""
return self.database.card_load(card_id)
def get_library(self) -> list:
"""
Get the complete library of cards
""" Get the complete library of cards
:return: Alphabetically ordered list of all cards in library
"""
return self.database.lib_get_all()
def get_all_categories(self) -> dict:
"""
Get all categories an the cards that are contained within them
""" Get all categories an the cards that are contained within them
:return: A dict with the category names and cv_engine.models.Card objects as values
"""
categories = self.database.category_get_all()
@@ -54,25 +49,5 @@ class CardvaultEngine:
if __name__ == "__main__":
# Test code
engine = CardvaultEngine()
# Insert Data into Datasbase
# print("Database insert test:")
# engine.database.db_clear_data_card()
# cards = Utilities.parse_mtgjson_cards(json.load(open("/home/luxick/Downloads/AllSets-x.json")))
# engine.database.card_insert_many(cards)
# Compare JSON Data to Data in Database
# for card in Utilities.parse_mtgjson_cards(json.load(open("/home/luxick/Downloads/AllSets-x.json"))):
# if card.multiverse_id:
# print('From JSON: {}'.format(card.names))
# print('From DB: {}\n'.format(engine.database.card_load(card.multiverse_id).names))
# Search test
# term = 'fire'
# for result in engine.database.card_search_by_name(term):
# print(str(result), end='\n\n')
# Fast load test
# engine.database.card_fast_load()
# all_ids = engine.database.db_all_multiverse_ids()
# print('Loaded IDs: {}'.format(len(all_ids)))

View File

@@ -35,14 +35,6 @@ class EngineConstants:
config_path = os.path.join(os.path.expanduser('~'), '.config', 'cardvault')
class GTKConstants:
"""
Constants for the GTK Ui
"""
# Directory in witch glade ui files are stored
glade_files = '/gui'
class MTGConstants:
"""
This class contains constants that can be used within the whole program
@@ -98,13 +90,3 @@ class Utilities:
cards.append(c)
output = output + cards
return output
@staticmethod
def expand_file_path(base_file, sub_dirs) -> str:
"""
Get absolute file path relative to another file
:param base_file: Current file from witch to expand
:param sub_dirs: List of sub directories to desired file
:return: Full file path of chosen file
"""
return os.path.join(os.path.dirname(base_file), *sub_dirs)

View File

@@ -8,9 +8,8 @@ from cv_engine.util import MTGConstants
class CardView(Gtk.ScrolledWindow):
""" Class for displaying a list of cards in an GTKTreeView """
def __init__(self, ui_file, filtered):
def __init__(self, filtered):
""" Constructor for a card list display
:param ui_file: Full path to an CardView glade file
:param filtered: Should the card list be filterable
"""
self.filtered = filtered
@@ -21,12 +20,13 @@ class CardView(Gtk.ScrolledWindow):
self.set_vexpand(True)
# Build UI
self.ui = Gtk.Builder()
self.ui.add_from_file(ui_file)
self.ui.add_from_string(GTKUtilities.load_ui_resource('cardtree.glade'))
self.tree = self.ui.get_object('cardTree')
self.store = self.ui.get_object('cardStore')
self.store.set_sort_func(4, self.compare_rarity, None)
# Add the TreeView
self.add(self.tree)
#self.tree.connect("row-activated", self.on_row_double_click)
def get_selected_cards(self):
""" Get the currently selected cards in the TreeView

View File

@@ -1,6 +1,7 @@
import gi
import os
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
@@ -17,13 +18,11 @@ class CardvaultGTK(MainWindowFunctions):
def __init__(self):
# Start engine (without config file)
self.engine = engine.CardvaultEngine()
# Set Glade file location
GUISettings.glade_file_path = os.path.join(os.path.dirname(__file__), 'gui')
# Load Glade files
glade_files = ['mainwindow.glade', 'search.glade', 'overlays.glade']
self.ui = Gtk.Builder()
for file in glade_files:
self.ui.add_from_file(os.path.join(GUISettings.glade_file_path, file))
self.ui.add_from_string(GTKUtilities.load_ui_resource(file))
# Set pages for the ui to use
GUISettings.pages = {
"search": self.ui.get_object("searchView"),
@@ -34,8 +33,7 @@ class CardvaultGTK(MainWindowFunctions):
if not os.path.isdir(util.EngineConfig.icon_cache_path):
os.mkdir(util.EngineConfig.icon_cache_path)
# Load single mana icons
GTKUtilities.mana_icons = GTKUtilities.load_icon_cache(os.path.join(os.path.dirname(__file__), 'resources',
'mana'))
GTKUtilities.mana_icons = GTKUtilities.load_icon_cache(os.path.join(GTKUtilities.resources_path, 'mana'))
# Load the the pre constructed icon cache
GTKUtilities.precon_icon_cache = GTKUtilities.load_icon_cache(util.EngineConfig.icon_cache_path)
# Call constructor of superclasses
@@ -48,7 +46,12 @@ class CardvaultGTK(MainWindowFunctions):
self.hide_initial_widgets()
self.switch_page('search')
if __name__ == '__main__':
def main():
CardvaultGTK()
Gtk.main()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,176 @@
import os
import re
from gi.repository import GdkPixbuf
from zipfile import ZipFile
try:
from PIL import Image
except ImportError as err:
print('PIL imaging library is not installed')
from cv_engine.util import EngineConfig
class GTKUtilities:
""" Access to image caches and utilities for use in the GTK application """
# Loaded mana symbols Format: {'B': GDKPixbuf, '3': GDKPixbuf}
mana_icons = {}
# Cache for combined mana cost icons
precon_icon_cache = {}
# Path of Gtk resources relative to cardvault base package
resources_path = os.path.join('cv_gtk3', 'resources')
@staticmethod
def get_path_from_base_dir(*dirs):
return os.path.join(os.path.dirname(os.path.dirname(__file__)), *dirs)
@staticmethod
def get_mana_icons(mana_string):
""" Return the combined mana symbols for a mana string
:param mana_string: String in the format '{3}{U}{B}'
:return: GdkPixbuf containing the combined symbols
"""
if not mana_string:
return
icon_list = re.findall("{(.*?)}", mana_string.replace("/", "-"))
icon_name = "_".join(icon_list)
try:
icon = GTKUtilities.precon_icon_cache[icon_name]
except KeyError:
icon = GTKUtilities.create_mana_icons(mana_string)
GTKUtilities.precon_icon_cache[icon_name] = icon
# Scale icon for display
if icon:
icon = icon.scale_simple(icon.get_width() / 5, icon.get_height() / 5, GdkPixbuf.InterpType.HYPER)
return icon
@staticmethod
def create_mana_icons(mana_string):
# Convert the string to a List
glyphs = re.findall("{(.*?)}", mana_string)
if len(glyphs) == 0:
return
# Compute horizontal size for the final image
size = len(glyphs) * 105
image = Image.new("RGBA", (size, 105))
for index, icon in enumerate(glyphs):
x_pos = index * 105
try:
# Try loading mana icon and converting to PIL.Image for combining
loaded = GTKUtilities.pixbuf_to_image(GTKUtilities.mana_icons[icon])
except KeyError:
print('Mana icon "{}" is not loaded.'.format(icon))
return
image.paste(loaded, (x_pos, 0))
# Save pre build icon file
path = os.path.join(EngineConfig.icon_cache_path, "_".join(glyphs) + ".png")
image.save(path)
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
except Exception as ex:
print(ex)
return
return pixbuf
@staticmethod
def pixbuf_to_image(pix):
"""Convert gdkpixbuf to PIL image"""
data = pix.get_pixels()
w = pix.props.width
h = pix.props.height
stride = pix.props.rowstride
mode = "RGB"
if pix.props.has_alpha:
mode = "RGBA"
im = Image.frombytes(mode, (w, h), data, "raw", mode, stride)
return im
@staticmethod
def load_ui_resource(resource_name):
""" Load GUI resource depending on the execution mode (from a directory or from a zip file)
:param resource_name: Name of the glade file
:return: String content of the resource file
"""
if os.path.isdir(os.path.dirname(__file__)):
return GTKUtilities.load_ui_resource_file(os.path.join(GTKUtilities.resources_path, 'gui', resource_name))
else:
zip_path = os.path.dirname(os.path.dirname(__file__))
return GTKUtilities.load_ui_resource_zip(zip_path,
os.path.join(GTKUtilities.resources_path, 'gui', resource_name))
@staticmethod
def load_ui_resource_file(resource_path):
""" LOad GUI resource from file path
:param resource_path: Relative path of the resource based on the cardvault base package
:return: String content of the resource file
"""
full_path = GTKUtilities.get_path_from_base_dir(resource_path)
with open(full_path, 'r') as file:
return file.read()
@staticmethod
def load_ui_resource_zip(archive_file, resource_path):
""" Load GUI resource from a zip archive (for usage in release mode)
:param archive_file: Full path of the archive file
:param resource_path: Path of the resources within the archive
:return: String representation of the file content
"""
with ZipFile(archive_file, 'r') as archive:
return archive.read(resource_path).decode('utf-8')
@staticmethod
def load_icon_cache(icon_path):
""" Get a dictionary with all available mana icons
:param icon_path: Relative path of icon resource files
:return: Dict with icon names and Gdkpixbuf objects
"""
if os.path.isdir(GTKUtilities.get_path_from_base_dir(icon_path)):
return GTKUtilities.load_icon_cache_file(GTKUtilities.get_path_from_base_dir(icon_path))
else:
zip_path = os.path.dirname(os.path.dirname(__file__))
return GTKUtilities.load_icon_cache_zip(zip_path)
@staticmethod
def load_icon_cache_file(icon_path):
""" Load icon cache from absolute paths at file system
:param icon_path: Relative path of icon resource files
:return: Dict with icon names and Gdkpixbuf object
"""
icons = {}
files = os.listdir(icon_path)
for file in files:
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(os.path.join(icon_path, file))
# Strip filename extension
icon_name = os.path.splitext(file)[0]
icons[icon_name] = pixbuf
except Exception as ex:
print('Error while loading icon file "{}"'.format(ex))
return icons
@staticmethod
def load_icon_cache_zip(zip_path):
""" Load icon cache from zipped archive
:param zip_path: Full path of the zip archive
:return: Dict with icon names and Gdkpixbuf object
"""
with ZipFile(zip_path, 'r') as archive:
icon_path = os.path.join('cv_gtk3', 'resources', 'mana')
files = [path for path in archive.namelist() if os.path.isfile(path.startswith(icon_path))]
icons = {}
for file in files:
with archive.open(file) as data:
try:
loader = GdkPixbuf.PixbufLoader()
loader.write(data.read())
pixbuf = loader.get_pixbuf()
loader.close()
# Strip filename extension
icon_name = os.path.splitext(file)[0]
icons[icon_name] = pixbuf
except Exception as ex:
print('Error while loading icon file "{0}"\n{1}'.format(file, ex))
return icons

View File

@@ -6,7 +6,7 @@
<property name="name">Card Vault</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Card Vault</property>
<property name="default_width">900</property>
<property name="default_width">1200</property>
<property name="default_height">700</property>
<property name="icon_name">cardvault</property>
<signal name="delete-event" handler="do_delete_event" swapped="no"/>

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

View File

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,14 +1,12 @@
import os
from cv_gtk3.card_view import CardView
from cv_gtk3.setting import GUISettings
from cv_gtk3.gtkui import CardvaultGTK
from cv_gtk3.gtk_util import GTKUtilities
class SearchPageHandlers:
""" Class for handling Signals from the search page """
def __init__(self, app: 'CardvaultGTK'):
def __init__(self, app):
""" Constructor
:param app: Reference to an CardvaultGTK object
"""
@@ -16,7 +14,7 @@ class SearchPageHandlers:
# Build the card view
overlay = self.app.ui.get_object("searchResults")
self.card_list = CardView(ui_file=os.path.join(GUISettings.glade_file_path, 'cardtree.glade'), filtered=False)
self.card_list = CardView(filtered=False)
self.card_list.set_name("resultsScroller")
# TODO Context menu for card view
# card_list.tree.connect("row-activated", self.on_search_card_selected)

View File

@@ -1,8 +0,0 @@
[Desktop Entry]
Version=0.5
Type=Application
Name=Card Vault
Comment=Organize and plan your MTG card collection
TryExec=cardvault
Exec=cardvault
Icon=cardvault

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,95 +0,0 @@
import re
import os
from gi.repository import GdkPixbuf
try:
from PIL import Image as PImage
except ImportError as err:
print('PIL imaging library is not installed')
from cv_engine.util import EngineConfig
class GTKUtilities:
""" Access to image caches and utilities for use in the GTK application """
# Loaded mana symbols Format: {'B': GDKPixbuf, '3': GDKPixbuf}
mana_icons = {}
# Cache for combined mana cost icons
precon_icon_cache = {}
@staticmethod
def load_icon_cache(path):
icons = {}
if not os.path.isdir(path):
os.mkdir(path)
files = os.listdir(path)
for file in files:
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(os.path.join(path, file))
# Strip filename extension
icon_name = os.path.splitext(file)[0]
icons[icon_name] = pixbuf
except Exception as ex:
print('Error while loading icon file "{}"'.format(ex))
return icons
@staticmethod
def get_mana_icons(mana_string):
""" Return the combined mana symbols for a mana string
:param mana_string: String in the format '{3}{U}{B}'
:return: GdkPixbuf containing the combined symbols
"""
if not mana_string:
return
icon_list = re.findall("{(.*?)}", mana_string.replace("/", "-"))
icon_name = "_".join(icon_list)
try:
icon = GTKUtilities.precon_icon_cache[icon_name]
except KeyError:
icon = GTKUtilities.create_mana_icons(mana_string)
GTKUtilities.precon_icon_cache[icon_name] = icon
# Scale icon for display
if icon:
icon = icon.scale_simple(icon.get_width() / 5, icon.get_height() / 5, GdkPixbuf.InterpType.HYPER)
return icon
@staticmethod
def create_mana_icons(mana_string):
# Convert the string to a List
glyphs = re.findall("{(.*?)}", mana_string)
if len(glyphs) == 0:
return
# Compute horizontal size for the final image
size = len(glyphs) * 105
image = PImage.new("RGBA", (size, 105))
for index, icon in enumerate(glyphs):
x_pos = index * 105
try:
# Try loading mana icon and converting to PIL.Image for combining
loaded = GTKUtilities.pixbuf_to_image(GTKUtilities.mana_icons[icon])
except KeyError:
print('Mana icon "{}" is not loaded.'.format(icon))
return
image.paste(loaded, (x_pos, 0))
# Save pre build icon file
path = os.path.join(EngineConfig.icon_cache_path, "_".join(glyphs) + ".png")
image.save(path)
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
except Exception as err:
print(err)
return
return pixbuf
@staticmethod
def pixbuf_to_image(pix):
"""Convert gdkpixbuf to PIL image"""
data = pix.get_pixels()
w = pix.props.width
h = pix.props.height
stride = pix.props.rowstride
mode = "RGB"
if pix.props.has_alpha:
mode = "RGBA"
im = PImage.frombytes(mode, (w, h), data, "raw", mode, stride)
return im

View File

@@ -1,5 +1,3 @@
from collections import OrderedDict
import gi
import os
import copy
@@ -56,8 +54,8 @@ class Application:
self.wants = Dict[str, List[Type[mtgsdk.Card]]]
self.load_user_data()
self.ui.get_object('statusbar_icon').set_from_icon_name(
util.online_icons[self.is_online()], Gtk.IconSize.BUTTON)
self.ui.get_object('statusbar_icon').set_from_icon_name(util.online_icons[self.is_online()],
Gtk.IconSize.BUTTON)
self.ui.get_object('statusbar_icon').set_tooltip_text(util.online_tooltips[self.is_online()])
self.handlers = handlers.Handlers(self)
@@ -95,35 +93,34 @@ class Application:
builder.add_from_file(util.get_ui_filename("detailswindow.glade"))
builder.add_from_file(util.get_ui_filename("overlays.glade"))
window = builder.get_object("cardDetails")
window.set_title(card.name)
window.set_title(card.get('name'))
# Card Image
container = builder.get_object("imageContainer")
pixbuf = util.load_card_image(card, 63 * 5, 88 * 5, self.image_cache)
image = Gtk.Image().new_from_pixbuf(pixbuf)
container.add(image)
# Name
builder.get_object("cardName").set_text(card.name)
builder.get_object("cardName").set_text(card.get('name'))
# Types
supertypes = ""
if card.subtypes is not None:
supertypes = " - " + " ".join(card.subtypes)
types = " ".join(card.types) + supertypes
if card.get('subtypes'):
supertypes = " - " + " ".join(card.get('subtypes'))
types = " ".join(card.get('types')) + supertypes
builder.get_object("cardTypes").set_text(types)
# Rarity
builder.get_object("cardRarity").set_text(card.rarity if card.rarity else "")
builder.get_object("cardRarity").set_text(card.get('rarity') or "")
# Release
builder.get_object("cardReleaseDate").set_text(card.release_date if card.release_date else "")
builder.get_object("cardReleaseDate").set_text(card.get('release_date') or "")
# Set
builder.get_object("cardSet").set_text(card.set_name)
builder.get_object("cardSet").set_text(card.get('set_name'))
# Printings
prints = []
for set in card.printings:
prints.append(self.get_all_sets()[set].name)
all_sets = self.get_all_sets()
prints = [all_sets[set_name].get('name') for set_name in card.get('printings')]
builder.get_object("cardPrintings").set_text(", ".join(prints))
# Legalities
grid = builder.get_object("legalitiesGrid")
rows = 1
for legality in card.legalities if card.legalities else {}:
for legality in card.get('legalities') or {}:
date_label = Gtk.Label()
date_label.set_halign(Gtk.Align.END)
text_label = Gtk.Label()
@@ -140,9 +137,9 @@ class Application:
grid.show_all()
# Rulings
if card.rulings:
if card.get('rulings'):
store = builder.get_object("rulesStore")
for rule in card.rulings:
for rule in card.get('rulings'):
store.append([rule["date"], rule["text"]])
else:
builder.get_object("ruleBox").set_visible(False)
@@ -330,7 +327,7 @@ class Application:
def get_wanted_card_ids(self) -> List[str]:
all_ids = []
for cards in self.wants.values():
next_ids = [card.multiverse_id for card in cards]
next_ids = [card['multiverse_id'] for card in cards]
all_ids = list(set(all_ids) | set(next_ids))
return all_ids
@@ -442,10 +439,7 @@ class Application:
def get_all_sets(self) -> dict:
if not self.is_online():
l = self.db.set_get_all()
out = {}
for s in l:
out[s.code] = s
out = {s['code']: s for s in self.db.set_get_all()}
else:
out = util.load_sets(util.get_root_filename('sets'))
return out

View File

@@ -6,7 +6,6 @@ from cardvault import application
from gi.repository import Gtk, GdkPixbuf, Gdk
from typing import Dict, Type
from mtgsdk import Card
import time
gi.require_version('Gtk', '3.0')
@@ -14,7 +13,7 @@ gi.require_version('Gdk', '3.0')
class CardList(Gtk.ScrolledWindow):
def __init__(self, filtered, app: 'application.Application', row_colors: Dict[str, str]):
def __init__(self, filtered, app, row_colors: Dict[str, str]):
Gtk.ScrolledWindow.__init__(self)
self.set_hexpand(True)
self.set_vexpand(True)
@@ -49,7 +48,7 @@ class CardList(Gtk.ScrolledWindow):
output[card_id] = card
return output
def update(self, library: Dict[str, Type[Card]]):
def update(self, library: Dict[str, dict]):
self.store.clear()
if library is None:
return
@@ -63,22 +62,24 @@ class CardList(Gtk.ScrolledWindow):
all_wants = self.app.get_wanted_card_ids()
for card in library.values():
if card.multiverse_id is not None:
if card['multiverse_id'] is not None:
color = self.get_row_color(card, self.app.library, all_wants, self.row_colors)
mana_cost = None if card.types.__contains__("Land") else self.app.get_mana_icons(card.mana_cost)
item = [card.multiverse_id,
card.name,
" ".join(card.supertypes if card.supertypes else ""),
" ".join(card.types),
card.rarity,
card.power,
card.toughness,
", ".join(card.printings),
mana_cost = None
if not card.get('types').__contains__("Land"):
mana_cost = self.app.get_mana_icons(card.get('mana_cost'))
item = [card['multiverse_id'],
card['name'],
" ".join(card.get('supertypes') or ""),
" ".join(card.get('types') or ""),
card.get('rarity'),
card.get('power'),
card.get('toughness'),
", ".join(card.get('printings') or ""),
mana_cost,
card.cmc,
card.set_name,
card.get('cmc'),
card.get('set_name'),
color,
card.original_text]
card.get('original_text')]
self.store.append(item)
end = time.time()
util.log("Time to build Table: " + str(round(end - start, 3)) + "s", util.LogLevel.Info)
@@ -103,9 +104,9 @@ class CardList(Gtk.ScrolledWindow):
@staticmethod
def get_row_color(card, lib: dict, wants: dict, colors: dict) -> str:
if lib.__contains__(card.multiverse_id):
if lib.__contains__(card.get('multiverse_id')):
return colors["owned"]
elif wants.__contains__(card.multiverse_id):
elif wants.__contains__(card.get('multiverse_id')):
return colors["wanted"]
else:
return colors["unowned"]

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