Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region Import the necessary modules from the Kodi framework and external libraries
- import os
- import xbmc
- import xbmcaddon
- import xbmcgui
- import xbmcvfs
- import requests
- from PIL import Image, ImageDraw, ImageFont, ImageOps, ImageColor
- from io import BytesIO
- #endregion
- #region Define the SportsAPI class
- class SportsAPI:
- def __init__(self, api_url):
- self.api_url = api_url
- def get_sports_data(self):
- response = requests.get(self.api_url)
- data = response.json()
- sports_data = []
- for sport in data['sports']:
- if 'strSportThumb' in sport:
- sports_data.append(sport)
- sports_data.sort(key=lambda x: x['strSport'])
- return sports_data
- #endregion
- #region Define a class that extends the WindowXML class from the Kodi framework
- class AllSportsWindow(xbmcgui.WindowXML):
- API_URL = "https://www.thesportsdb.com/api/v1/json/60130162/all_sports.php"
- def __init__(self, *args, **kwargs):
- # Call the parent class's constructor
- xbmcgui.WindowXML.__init__(self, *args, **kwargs)
- # Set the path to the custom font and the font size
- self.font_path = "special://home/addons/plugin.sportsview/resources/fonts/ariblk.ttf"
- self.font_size = 40
- # Set the line spacing between words
- self.line_spacing = 1
- def onInit(self):
- xbmc.log("AllSportsWindow - onInit")
- # Retrieve sports data from an API
- sports_data = self.getSportsData()
- # Populate the sports grid with the retrieved data
- self.populate_sports_grid(sports_data)
- def tempPath(self):
- # Get the temporary path in the Kodi file system
- return xbmcvfs.translatePath("special://temp")
- def getSportsData(self):
- sports_api = SportsAPI(self.API_URL)
- return sports_api.get_sports_data()
- def populate_sports_grid(self, sports_data):
- # Define parameters for the sports grid layout
- numcolumns = 4
- vertgapsize = 50
- horizgapsize = 50
- totalgapsize = vertgapsize * (numcolumns + 1)
- screenwidth = self.getWidth()
- buttonwidth = (screenwidth - totalgapsize) // numcolumns
- buttonheight = int(buttonwidth / 1.7777777777777)
- # Load the custom font
- font = ImageFont.truetype(self.font_path, self.font_size)
- # Iterate through the sports data and create controls for each sport
- for index, sport in enumerate(sports_data):
- # Retrieve the sport label and image URL
- button_label = sport['strSport']
- button_image = sport['strSportThumb']
- # Set self.sports_data to the populated sports_data list
- self.sports_data = sports_data
- # Calculate the position of the control
- button_x = vertgapsize + (index % numcolumns) * (buttonwidth + vertgapsize)
- button_y = horizgapsize + (index // numcolumns) * (buttonheight + horizgapsize)
- # Create an image control for the sport thumbnail
- image = xbmcgui.ControlImage(button_x, button_y, buttonwidth, buttonheight, filename=button_image)
- self.addControl(image)
- # Download the unfocused button image
- response = requests.get(button_image)
- unfocused_image = Image.open(BytesIO(response.content))
- # Convert the unfocused button image to grayscale
- focused_image_gray = ImageOps.grayscale(unfocused_image)
- # Convert the grayscale image to RGB
- focused_image_rgb = focused_image_gray.convert('RGB')
- # Set the border color as an RGB tuple
- border_color_rgb = (18, 101, 196) # Red color
- # Set the width of the border
- border_width = 10 # Adjust as needed
- # Create a new image with the colored border
- bordered_image = ImageOps.expand(focused_image_rgb, border=border_width, fill=border_color_rgb)
- # Save the grayscale image to a temporary file
- focused_gray_path = os.path.join(self.tempPath(), f"focused_gray_{index}.png")
- focused_image_gray.save(focused_gray_path)
- # Save the bordered image to a temporary file
- focused_texture_path = os.path.join(self.tempPath(), f"focused_image_{index}.png")
- bordered_image.save(focused_texture_path)
- # Convert the border color tuple to a single integer value
- border_color_int = (0)
- # Set the width of the border
- border_width = 10 # Adjust as needed
- # Create a new image with the border
- bordered_image = ImageOps.expand(bordered_image, border=border_width, fill=border_color_int)
- # Create an image control for the custom font button label
- label_image = Image.new("RGBA", (buttonwidth, buttonheight), (0, 0, 0, 0))
- label_draw = ImageDraw.Draw(label_image)
- # Split the button label into individual words
- words = button_label.split()
- # Join the words with line breaks
- label_text = '\n'.join(words)
- # Split the label text into lines
- lines = label_text.split('\n')
- # Get the width and height of the text
- text_width, text_height = label_draw.textsize(label_text, font=font)
- # Calculate the button's y-axis to center align the text
- if len(lines) > 1:
- line_height = (buttonheight - text_height) // 2
- else:
- line_height = (buttonheight - text_height) // 2
- # Create a new image with the button label
- label_image = Image.new("RGBA", (buttonwidth, buttonheight), (0, 0, 0, 0))
- label_draw = ImageDraw.Draw(label_image)
- # Draw the text on multiple lines
- for line in lines:
- # Calculate the button's x-axis to center align each line
- buttonx = (buttonwidth - label_draw.textsize(line, font=font)[0]) // 2
- # Draw the line of text
- label_draw.text((buttonx, line_height), line, font=font, fill=(255, 255, 255, 255), anchor='mm')
- # Increment the line height for the next line
- line_height += label_draw.textsize(line, font=font)[1] + self.line_spacing
- # Save the label image to a temporary file
- label_image_path = os.path.join(self.tempPath(), f"label_image_{index}.png")
- label_image.save(label_image_path)
- # Create a button control for the sport
- button = xbmcgui.ControlButton(button_x, button_y, buttonwidth, buttonheight, label="", focusTexture=focused_texture_path)
- self.addControl(button)
- # Store the control ID in the sports_data list
- sport['control_id'] = button.getId()
- # Create an image control for the custom font button label
- label_image_control = xbmcgui.ControlImage(button_x, button_y, buttonwidth, buttonheight, filename=label_image_path)
- self.addControl(label_image_control)
- # Set focus on the first button control
- if index == 0:
- self.setFocus(button)
- def onAction(self, action):
- # Handle keyboard events for navigation
- if action == xbmcgui.ACTION_MOVE_LEFT:
- self.moveFocus(-1, 0)
- elif action == xbmcgui.ACTION_MOVE_RIGHT:
- self.moveFocus(1, 0)
- elif action == xbmcgui.ACTION_MOVE_UP:
- self.moveFocus(0, -1)
- elif action == xbmcgui.ACTION_MOVE_DOWN:
- self.moveFocus(0, 1)
- else:
- # Handle other actions here
- pass
- # Call the parent onAction method to handle other actions
- xbmcgui.WindowXML.onAction(self, action)
- def moveFocus(self, x, y):
- # Get the current focused button
- focused_control_id = self.getFocusId()
- # Find the index of the focused control in the controls list
- focused_index = None
- for index, sport in enumerate(self.sports_data):
- if 'control_id' in sport and sport['control_id'] == focused_control_id:
- focused_index = index
- break
- if focused_index is None:
- # Focused button not found or control_id not present, return
- return
- # Calculate the new index after navigation
- num_columns = 4
- num_rows = (len(self.sports_data) - 1) // num_columns + 1
- new_index = focused_index + x + y * num_columns
- # Check if the new index is within the range of buttons
- if 0 <= new_index < len(self.sports_data):
- # Get the control_id of the new button based on the new index
- new_control_id = self.sports_data[new_index].get('control_id')
- if new_control_id is not None:
- # Set the focus on the new button control
- self.setFocusId(new_control_id)
- # Check if the new button is off the visible screen area
- visible_index = focused_index // num_columns
- new_visible_index = new_index // num_columns
- if new_visible_index != visible_index:
- # Calculate the vertical scroll position
- scroll_position = self.getScrollPosition()[1]
- max_scroll = num_rows - self.getHeight() // self.getListItemHeight()
- new_scroll_position = min(max(scroll_position + y, 0), max_scroll) * self.getListItemHeight()
- # Set the new vertical scroll position
- self.setScrollPosition(0, new_scroll_position)
- else:
- # New index is out of range, return
- return
- # Call the parent onAction method to handle other actions
- super().onAction(xbmcgui.Action(self.getFocusId()))
- #region Run it
- # Entry point function to run the AllSportsWindow
- def allsportsrun():
- # Get the current working directory of the add-on
- cwd = xbmcaddon.Addon().getAddonInfo('path')
- # Create an instance of the AllSportsWindow and run it
- window = AllSportsWindow('allsports.xml', cwd, 'default', '1080i')
- window.doModal()
- del window
- #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement