def __init__(self, parent, controller): tk.Frame.__init__(self, parent, background=style.color_1) self.exit_callback = threader.exit self.usertext = ThemedLabel(self, text="Exit?", font=style.hugeboldtext, anchor="center", background=style.color_1, foreground=style.w) self.usertext.place(relwidth=1, relheight=1, height=-(style.buttonsize + 2 * style.offset)) self.yesnobuttonframe = tk.Frame(self, background=style.color_1, borderwidth=0, highlightthickness=0) self.yesnobuttonframe.place(relx=0.5, rely=1, y=-(style.buttonsize + style.offset), width=300, x=-150, height=style.buttonsize) self.yesbutton = button(self.yesnobuttonframe, callback=self.on_yes, text_string="Yes", background=style.color_2) self.yesbutton.place(relx=0.33, relwidth=0.34, relheight=1)
def place_buttonversionlabel(): if not self.buttonversionlabel: self.buttonversionlabel = ThemedLabel( self.canvas, self.repo["github_content"][0]["tag_name"], anchor="w", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonversionlabel.place(x=self.base_x, y=label_y)
def __init__(self, parent, controller): self.local_packages_handler = controller.local_packages_handler self.injector = controller.injector self.column_inject_button = None detailPage.__init__(self,parent,controller) self.column_package.place_forget() self.column_installed_version = ThemedLabel(self.column_body,"",anchor="w",label_font=style.smalltext, foreground = style.w, background = style.color_1) self.column_installed_version.place(x = 5, width = - 5, y = 3.666 * style.detailspagemultiplier, relwidth = 1, height = 0.333 * style.detailspagemultiplier) self.releases_listbox.place(relwidth = 1, y=4.00*style.detailspagemultiplier, relheight = 1, height = - (4*style.detailspagemultiplier + 3 * (style.buttonsize + style.offset) + style.offset))
def place_buttonauthorlabel(): if not self.buttonauthorlabel: self.buttonauthorlabel = ThemedLabel( self.canvas, self.repo["author"], anchor="e", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonauthorlabel.place(x=self.base_x, y=label_y, width=self.thumbnailwidth)
def place_buttontitlelabel(): if not self.buttontitlelabel: self.buttontitlelabel = ThemedLabel( self.canvas, self.repo["name"], anchor="e", label_font=style.mediumboldtext, foreground=style.w, background=style.color_2) self.buttontitlelabel.place(x=self.base_x, y=label_y - 1.5 * style.buttontextheight, width=self.thumbnailwidth)
def __init__(self, parent, controller): self.local_packages_handler = local_packages_handler self.injector = injector self.column_inject_button = None detailPage.__init__(self, parent, controller) # self.column_package.place_forget() self.column_installed_version = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_installed_version.place( x=5, width=-5, y=3.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier)
def place_buttonstatuslabel(): if not self.buttonstatuslabel: self.buttonstatuslabel = ThemedLabel( self.canvas, "", anchor="w", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonstatuslabel.place( x=self.base_x, y=label_y - 1.5 * style.buttontextheight + 4) status = None package = self.repo["package"] if self.status_handler.packages: if package in self.status_handler.packages: installed_version = self.status_handler.get_package_version( package) current_version = repo_parser.package_dict[ package]["github_content"][0]["tag_name"] if self.status_handler.clean_version( installed_version, package ) == self.status_handler.clean_version( current_version, package): status = "UPTODATE" elif self.status_handler.clean_version( installed_version, package ) < self.status_handler.clean_version( current_version, package): status = "NEEDSUPDATE" else: status = "UPTODATE" else: status = "NOTINSTALLED" else: status = "NOTINSTALLED" self.buttonstatuslabel.configure( image=self.category_frame.status_map[status])
def place_buttonstatuslabel(): if not self.buttonstatuslabel: self.buttonstatuslabel = ThemedLabel(self.canvas,"",anchor="w",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonstatuslabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonstatuslabel.place(x = self.base_x, y = label_y - 1.5 * style.buttontextheight + 4) status = None package = self.repo["name"] if self.controller.appstore_handler.packages: if package in self.controller.appstore_handler.packages: installed_version = self.controller.appstore_handler.get_package_version(package) if self.controller.appstore_handler.clean_version(installed_version, package) == self.controller.appstore_handler.clean_version(installed_version, package): status = "UPTODATE" elif self.controller.appstore_handler.clean_version(installed_version, package) < self.controller.appstore_handler.clean_version(installed_version, package): status = "NEEDSUPDATE" else: status = "NOTINSTALLED" else: status = "NOTINSTALLED" self.buttonstatuslabel.configure(image=self.category_frame.status_map[status])
class storeAppSquare(ThemedFrame): def __init__(self, parent, controller, framework, category_frame, repo): self.controller = controller self.parent = parent self.framework = framework self.category_frame = category_frame self.repo = repo self.name = repo["name"] self.active = True self.image_sharer = self.controller.image_sharer self.imageset = False self.base_x = None #Stores the base x location to build the button from for dynamic building self.base_y = None #Stores the base y location to build the button from for dynamic building self.canvas = None self.placed = False ThemedFrame.__init__(self, parent, background = style.w) self.buttonobj = button(self,image_object=None,callback=lambda: self.open_details(repo),background = style.w) self.buttonobj.place(relheight=1,relwidth=1) #Placeholders used by the category frame when building the button, fixes the disappearing text issue self.buttontitlelabel = None #Placeholder used for the button title self.buttonauthorlabel = None #Placeholder for the button author self.buttonversionlabel = None #Placeholder for the current cersion self.buttonseparator = None #Placeholder for underline in each button self.buttonstatuslabel = None #Placeholder for download / version status self.items = [ self, self.buttonobj, self.buttontitlelabel, self.buttonauthorlabel, self.buttonversionlabel, self.buttonseparator, self.buttonstatuslabel ] def open_details(self, repo): self.controller.frames["detailPage"].show(repo) def set_image(self): repo = self.repo package = repo["name"] #Checks a shared dict to see if this package already has an image loaded, returns none if not self.button_image = self.image_sharer.get_image(package) if not self.button_image: try: image_file = getPackageIcon(package) or notfoundimage button_image = Image.open(image_file) #Resizes and saves image if it's the wrong size for faster loads in the future if not button_image.size[0] == [style.thumbnailwidth, style.thumbnailheight]: button_image = button_image.resize((style.thumbnailwidth, style.thumbnailheight), Image.ANTIALIAS) self.button_image = ImageTk.PhotoImage(button_image) if not image_file == notfoundimage: self.image_sharer.set_image(package, self.button_image) except Exception as e: self.button_image = self.category_frame.notfoundimage self.image_sharer.set_image(package, self.button_image) self.buttonobj.setimage(self.button_image) self.imageset = True def set_xy_canvas(self, base_x, base_y, canvas): self.base_x = base_x self.base_y = base_y self.canvas = canvas def get_xy(self): return((self.base_x, self.base_y)) def build_button(self): if not self.placed: if self.base_y and self.base_x and self.canvas: self.placed = True repo = self.repo label_y = self.base_y + style.thumbnailheight - style.buttontextheight + 40 def place_button(): self.place(x=self.base_x, y = self.base_y, height = style.thumbnailheight + 2 * style.offset, width = style.thumbnailwidth) self.buttonobj.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.bind("<MouseWheel>", self.canvas.on_mouse_wheel) try: web_dls = repo["web_dls"] except: web_dls = 0 try: app_dls = repo["app_dls"] except: app_dls = 0 ttl_dls = web_dls + app_dls # ttp = "{}\nAuthor: {}\nDownloads: {}".format(repo["description"], repo["author"], ttl_dls) # self.button_ttp = tooltip(self.buttonobj,ttp) def place_buttontitlelabel(): if not self.buttontitlelabel: self.buttontitlelabel = ThemedLabel(self.canvas,self.repo["title"],anchor="e",label_font=style.mediumboldtext,foreground=style.b,background=style.w) self.buttontitlelabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttontitlelabel.place(x = self.base_x, y = label_y - 1.5 * style.buttontextheight, width = style.thumbnailwidth) def place_buttonauthorlabel(): if not self.buttonauthorlabel: self.buttonauthorlabel = ThemedLabel(self.canvas,self.repo["author"],anchor="e",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonauthorlabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonauthorlabel.place(x = self.base_x, y = label_y, width = style.thumbnailwidth) def place_buttonstatuslabel(): if not self.buttonstatuslabel: self.buttonstatuslabel = ThemedLabel(self.canvas,"",anchor="w",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonstatuslabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonstatuslabel.place(x = self.base_x, y = label_y - 1.5 * style.buttontextheight + 4) status = None package = self.repo["name"] if self.controller.appstore_handler.packages: if package in self.controller.appstore_handler.packages: installed_version = self.controller.appstore_handler.get_package_version(package) if self.controller.appstore_handler.clean_version(installed_version, package) == self.controller.appstore_handler.clean_version(installed_version, package): status = "UPTODATE" elif self.controller.appstore_handler.clean_version(installed_version, package) < self.controller.appstore_handler.clean_version(installed_version, package): status = "NEEDSUPDATE" else: status = "NOTINSTALLED" else: status = "NOTINSTALLED" self.buttonstatuslabel.configure(image=self.category_frame.status_map[status]) def place_buttonversionlabel(): if not self.buttonversionlabel: self.buttonversionlabel = ThemedLabel(self.canvas,self.repo["version"],anchor="w",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonversionlabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonversionlabel.place(x = self.base_x, y = label_y) def place_buttonseparator(): if not self.buttonseparator: self.buttonseparator = tk.Label(self.canvas, background=style.lg, borderwidth= 0) self.buttonseparator.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonseparator.place(x = self.base_x, y = label_y + 2 * style.offset + style.buttontextheight, height = 1, width = style.thumbnailwidth) place_button() place_buttonauthorlabel() place_buttontitlelabel() place_buttonstatuslabel() place_buttonversionlabel() place_buttonseparator() if not self.imageset: self.set_image()
def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = controller.appstore_handler self.repo_parser = controller.repo_parser self.repo = None #------------------------------ self.column = ThemedFrame(self, background=style.light_color) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.light_color) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", label_font=style.mediumboldtext, foreground=style.w, background=style.light_color) self.column_title.place(x=5, width=-5, rely=0, relwidth=1, height=style.headerheight) #------------------------------ self.column_author = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_author.place(x=5, width=-5, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_version.place(x=5, width=-5, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_license.place(x=5, width=-5, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_package = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_package.place(x=5, width=-5, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_downloads.place(x=5, width=-5, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_updated.place(x=5, width=-5, y=3.00 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_downloaded = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_downloaded.place(x=5, width=-5, y=3.66 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ self.column_extracted = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_extracted.place(x=5, width=-5, y=4 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.dark_color).place( rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-4 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.dark_color) self.column_install_button.place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-3 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.dark_color) self.back_image = ImageTk.PhotoImage( Image.open(locations.backimage).resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.light_color) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) self.column_backbutton_ttp = tooltip(self.column_backbutton, "Back to list") self.content_frame = ThemedFrame(self, background=style.w) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.w) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.w) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image = ThemedLabel(self.content_frame_body, "", background=style.w, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=0.5) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext) self.content_frame_details.place(rely=0.5, relx=0, relwidth=1, relheight=0.5, x=+style.offset, width=-2 * (style.offset), height=-style.offset) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.giantboldtext, background=style.w, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.smalltext, background=style.w, foreground=style.light_color) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self)
class storeAppSquare(ThemedFrame): def __init__(self, parent, controller, framework, category_frame, repo, callback, status_handler): self.controller = controller self.parent = parent self.framework = framework self.category_frame = category_frame self.repo = repo self.name = repo["name"] self.callback = callback self.status_handler = status_handler self.active = True self.image_sharer = image_sharer self.imageset = False self.base_x = None #Stores the base x location to build the button from for dynamic building self.base_y = None #Stores the base y location to build the button from for dynamic building self.canvas = None self.placed = False self.thumbnailheight = None self.thumbnailwidth = None ThemedFrame.__init__(self, parent, background=style.w) self.buttonobj = button(self, image_object=None, callback=lambda: self.callback(repo), background=style.color_2) self.buttonobj.place(relheight=1, relwidth=1) #Placeholders used by the category frame when building the button, fixes the disappearing text issue self.buttontitlelabel = None #Placeholder used for the button title self.buttonauthorlabel = None #Placeholder for the button author self.buttonversionlabel = None #Placeholder for the current cersion self.buttonseparator = None #Placeholder for underline in each button self.buttonstatuslabel = None #Placeholder for download / version status self.update_button_sizes() def update_button_sizes(self): thumbnail_size_map = { "tiny": (style.tiny_thumbnail_height, style.tiny_thumbnail_width), "small": (style.small_thumbnail_height, style.small_thumbnail_width), "medium": (style.medium_thumbnail_height, style.medium_thumbnail_width), "large": (style.large_thumbnail_height, style.large_thumbnail_width), "huge": (style.huge_thumbnail_height, style.huge_thumbnail_width) } thumbnail_size = settings.get_setting("thumbnail_size") thumbnail_size = thumbnail_size_map.get(thumbnail_size) if thumbnail_size: if not self.thumbnailwidth == thumbnail_size[1]: self.thumbnailheight = thumbnail_size[0] self.thumbnailwidth = thumbnail_size[1] return True def set_image(self): repo = self.repo try: package = repo["package"] except: package = None try: image_file = getPackageIcon(package) or notfoundimage button_image = Image.open(image_file) #Resizes and saves image if it's the wrong size for faster loads in the future if not button_image.size[0] == [ self.thumbnailwidth, self.thumbnailheight ]: button_image = button_image.resize( (self.thumbnailwidth, self.thumbnailheight), Image.ANTIALIAS) self.button_image = ImageTk.PhotoImage(button_image) except Exception as e: print(e) self.button_image = self.category_frame.notfoundimage self.buttonobj.setimage(self.button_image) self.imageset = True def set_xy_canvas(self, base_x, base_y, canvas): self.base_x = base_x self.base_y = base_y self.canvas = canvas def get_xy(self): return ((self.base_x, self.base_y)) def build_button(self): update_button_sizes = self.update_button_sizes() if not self.placed: if self.base_y and self.base_x and self.canvas: self.placed = True repo = self.repo label_y = self.base_y + self.thumbnailheight - style.buttontextheight + 40 def place_button(): self.place(x=self.base_x, y=self.base_y, height=self.thumbnailheight + 2 * style.offset, width=self.thumbnailwidth) # ttp = "{}\nAuthor: {}\nDownloads: {}".format(repo["description"], repo["author"], repo["downloads"]) # self.button_ttp = tooltip(self.buttonobj,ttp) def place_buttontitlelabel(): if not self.buttontitlelabel: self.buttontitlelabel = ThemedLabel( self.canvas, self.repo["name"], anchor="e", label_font=style.mediumboldtext, foreground=style.w, background=style.color_2) self.buttontitlelabel.place(x=self.base_x, y=label_y - 1.5 * style.buttontextheight, width=self.thumbnailwidth) def place_buttonauthorlabel(): if not self.buttonauthorlabel: self.buttonauthorlabel = ThemedLabel( self.canvas, self.repo["author"], anchor="e", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonauthorlabel.place(x=self.base_x, y=label_y, width=self.thumbnailwidth) def place_buttonstatuslabel(): if not self.buttonstatuslabel: self.buttonstatuslabel = ThemedLabel( self.canvas, "", anchor="w", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonstatuslabel.place( x=self.base_x, y=label_y - 1.5 * style.buttontextheight + 4) status = None package = self.repo["package"] if self.status_handler.packages: if package in self.status_handler.packages: installed_version = self.status_handler.get_package_version( package) current_version = repo_parser.package_dict[ package]["github_content"][0]["tag_name"] if self.status_handler.clean_version( installed_version, package ) == self.status_handler.clean_version( current_version, package): status = "UPTODATE" elif self.status_handler.clean_version( installed_version, package ) < self.status_handler.clean_version( current_version, package): status = "NEEDSUPDATE" else: status = "UPTODATE" else: status = "NOTINSTALLED" else: status = "NOTINSTALLED" self.buttonstatuslabel.configure( image=self.category_frame.status_map[status]) def place_buttonversionlabel(): if not self.buttonversionlabel: self.buttonversionlabel = ThemedLabel( self.canvas, self.repo["github_content"][0]["tag_name"], anchor="w", label_font=style.smallboldtext, foreground=style.lg, background=style.color_2) self.buttonversionlabel.place(x=self.base_x, y=label_y) def place_buttonseparator(): if not self.buttonseparator: self.buttonseparator = tk.Label(self.canvas, background=style.lg, borderwidth=0) self.buttonseparator.place(x=self.base_x, y=label_y + 2 * style.offset + style.buttontextheight, height=1, width=self.thumbnailwidth) place_button() place_buttonauthorlabel() place_buttontitlelabel() place_buttonstatuslabel() place_buttonversionlabel() place_buttonseparator() if not self.imageset or update_button_sizes: self.set_image() self.items = [ self, self.buttonobj, self.buttontitlelabel, self.buttonauthorlabel, self.buttonversionlabel, self.buttonseparator, self.buttonstatuslabel ] for item in self.items: try: if platform.system() == 'Windows' or platform.system( ) == "Darwin": item.bind("<MouseWheel>", self.canvas.on_mouse_wheel) elif platform.system() == "Linux": item.bind("<Button-4>", self.canvas.on_mouse_wheel) item.bind("<Button-5>", self.canvas.on_mouse_wheel) except Exception as e: print(e)
def __init__(self, parent, controller): self.controller = controller self.appstore_handler = store_handler self.repo_parser = repo_parser self.current_file_path = None self.originaljson = None self.currentjson = None self.ok_to_load = True self.json_name = None self.changes = None self.progress_string = None self.gui_title = None self.errors = [] ThemedFrame.__init__(self, parent, background=style.color_2) self.bind("<<ShowFrame>>", self.update_apply_frame) #LEFT COLUMN________________________________ self.presets_listbox_label = ThemedLabel( self, label_text="Bundles:", background=style.color_2, foreground=style.lg, label_font=style.largeboldtext) self.presets_listbox_label.place(relx=0.0, relwidth=0.5, height=style.buttonsize - 2 * style.offset, x=+style.offset, width=-2 * style.offset) image_file = os.path.join(assetsfolder, "trash.png") button_image = Image.open(image_file) buttonsize = style.buttonsize - 4 * style.offset #Resizes and saves image if it's the wrong size for faster loads in the future if not button_image.size[0] == [buttonsize, buttonsize]: button_image = button_image.resize((buttonsize, buttonsize), Image.ANTIALIAS) self.trash_image = ImageTk.PhotoImage(button_image) self.delete_preset_button = button(self, callback=self.delete, image_object=self.trash_image, background=style.color_1) self.delete_preset_button.place( relx=0.5, x=-(style.buttonsize - 2 * style.offset), y=+style.offset, width=style.buttonsize - 3 * style.offset, height=style.buttonsize - 3 * style.offset) self.presets_listbox = scrollingTkListbox(self, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False) self.presets_listbox.place( relx=0.0, relwidth=0.5, relheight=1, y=style.buttonsize - style.offset, x=+style.offset, width=-2 * style.offset, height=-(2.5 * style.buttonsize + 2 * style.offset)) self.new_preset_entry = entrybox( self, placeholder="New bundle name (No extension)", callback=self.update_json) self.new_preset_entry.place( relx=0.0, x=+style.offset, relwidth=0.5, height=0.5 * style.buttonsize, rely=1, y=-(2 * style.offset + 1.5 * style.buttonsize), width=-(3 * style.offset + 0.5 * style.buttonsize)) self.new_preset_button = button(self, callback=self.new, text_string="+", background=style.color_1) self.new_preset_button.place( relx=0.5, x=-(style.offset + 0.5 * style.buttonsize), width=0.5 * style.buttonsize, height=0.5 * style.buttonsize, rely=1, y=-(2 * style.offset + 1.5 * style.buttonsize)) self.loadbutton = button(self, callback=self.load, text_string="Load", background=style.color_1) self.loadbutton.place(relx=0.0, x=+style.offset, relwidth=0.5, height=style.buttonsize, rely=1, y=-(style.offset + style.buttonsize), width=-2 * style.offset) self.divider = ThemedFrame(self, background=style.lg) self.divider.place(relx=0.5, width=2, relheight=1, height=-2 * style.offset, y=+style.offset, x=-1) self.column_select_frame = ThemedFrame(self, background=style.color_2) self.column_select_frame.place(relx=0.5, x=+style.offset, width=-2 * style.offset, relwidth=0.5, height=style.buttonsize, y=+style.offset) self.editor_button = button(self.column_select_frame, callback=lambda: self.show_frame("editor"), text_string="Edit", background=style.color_1, borderwidth=1) self.editor_button.place(relheight=1, relwidth=0.33, relx=0, width=-0.5 * style.offset) self.applier_button = button( self.column_select_frame, callback=lambda: self.show_frame("applier"), text_string="Apply", background=style.color_1, borderwidth=1) self.applier_button.place(relheight=1, relwidth=0.34, relx=0.33, x=+0.5 * style.offset, width=-style.offset) self.build_button = button(self.column_select_frame, callback=lambda: self.show_frame("builder"), text_string="Build", background=style.color_1, borderwidth=1) self.build_button.place(relheight=1, relwidth=0.33, relx=0.67, x=+0.5 * style.offset, width=-0.5 * style.offset) self.buttonmap = { "editor": self.editor_button, "applier": self.applier_button, "builder": self.build_button } self.button_divider = ThemedFrame(self, background=style.lg) self.button_divider.place(relx=0.5, x=+style.offset, width=-2 * style.offset, relwidth=0.5, height=1, y=style.buttonsize + 2 * style.offset) self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place( relx=0.5, relwidth=0.5, width=-2 * style.offset, x=+style.offset, relheight=1, y=style.buttonsize + 3 * style.offset + 1, height=-(style.buttonsize + 4 * style.offset + 1)) #EDITOR COLUMN________________________________ self.editor_frame = ThemedFrame(self.content_frame, background=style.color_2) self.preset_name = entrybox(self.editor_frame, placeholder="Bundle Name", callback=self.update_json) self.preset_name.place(height=0.5 * style.buttonsize, relwidth=1) self.author_name = entrybox(self.editor_frame, placeholder="Bundle Author", callback=self.update_json) self.author_name.place(y=1 * (style.offset + 0.5 * style.buttonsize), height=0.5 * style.buttonsize, relwidth=1) self.preset_package_version = entrybox( self.editor_frame, placeholder="Bundle Package Version", callback=self.update_json) self.preset_package_version.place( y=2 * (style.offset + 0.5 * style.buttonsize), height=0.5 * style.buttonsize, relwidth=1) self.packages_listbox_and_json_output_preview_frame = ThemedFrame( self.editor_frame, background=style.color_2) self.packages_listbox_and_json_output_preview_frame.place( y=3 * (style.offset + 0.5 * style.buttonsize), relheight=1, height=-(2 * style.buttonsize + 7 * style.offset), relwidth=1) self.packages_listbox_label = ThemedLabel( self.packages_listbox_and_json_output_preview_frame, label_text="Packages:", background=style.color_2, foreground=style.lg, label_font=style.mediumboldtext) self.packages_listbox_label.place(relwidth=1, height=style.buttonsize - 2 * style.offset) self.packages_listbox = scrollingTkListbox( self.packages_listbox_and_json_output_preview_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.packages_listbox.place( y=style.buttonsize - 2 * style.offset, relwidth=1, relheight=0.5, height=-(style.offset + style.buttonsize - 2 * style.offset)) self.packages_listbox.bind('<<ListboxSelect>>', self.update_json) self.output_divider = ThemedFrame( self.packages_listbox_and_json_output_preview_frame, background=style.lg) self.output_divider.place(relwidth=1, height=1, rely=0.5) self.output_json_label = ThemedLabel( self.packages_listbox_and_json_output_preview_frame, label_text="Output:", background=style.color_2, foreground=style.lg, label_font=style.mediumboldtext) self.output_json_label.place(rely=0.5, y=+style.offset + 1, relwidth=1, height=style.buttonsize - 2 * style.offset) self.output_json = themedScrollingText( self.packages_listbox_and_json_output_preview_frame, font=style.smalltext) self.output_json.place(relwidth=1, rely=0.5, relheight=0.5, height=-(style.buttonsize + style.offset), y=style.buttonsize) self.savebutton = button(self.editor_frame, callback=self.save, text_string="Save", background=style.color_1) self.savebutton.place(relwidth=1, height=style.buttonsize, rely=1, y=-(style.buttonsize)) #APPLIER COLUMN_______________________________ self.applier_frame = ThemedFrame(self.content_frame, background=style.color_2) self.applier_bundle_label = ThemedLabel(self.applier_frame, label_text="BUNDLE: ", anchor="w", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_bundle_label.place(height=0.5 * style.buttonsize - style.offset) self.applier_selected_bundle_label = ThemedLabel( self.applier_frame, label_text="test", anchor="e", background=style.color_2, foreground=style.w, label_font=style.smallboldtext) self.applier_selected_bundle_label.place( x=self.applier_bundle_label.winfo_reqwidth(), height=0.5 * style.buttonsize - 1 * style.offset) self.applier_sd_label = ThemedLabel(self.applier_frame, label_text="SD: ", anchor="w", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_sd_label.place(y=0.5 * style.buttonsize, height=0.5 * style.buttonsize - 1 * style.offset) self.applier_selected_sd_label = ThemedLabel( self.applier_frame, label_text="test", anchor="e", background=style.color_2, foreground=style.w, label_font=style.smallboldtext) self.applier_selected_sd_label.place( y=0.5 * style.buttonsize, x=self.applier_sd_label.winfo_reqwidth(), height=0.5 * style.buttonsize - 1 * style.offset) self.applier_header_divider = ThemedFrame(self.applier_frame, background=style.lg) self.applier_header_divider.place(y=1 * style.buttonsize, relwidth=1, height=1) self.applier_listboxes_frame = ThemedFrame(self.applier_frame, background=style.color_2) self.applier_listboxes_frame.place( y=1 * style.buttonsize + 1 * style.offset + 1, relheight=1, height=-(2 * style.buttonsize + 1 + style.offset), relwidth=1) self.applier_to_be_installed_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_installed_frame.place(relwidth=1, relheight=0.33, height=-style.offset) self.applier_to_be_installed_label = ThemedLabel( self.applier_to_be_installed_frame, label_text="To be installed:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_installed_label.place( relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_installed_listbox = scrollingTkListbox( self.applier_to_be_installed_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_installed_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_to_be_updated_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_updated_frame.place(relwidth=1, relheight=0.34, rely=0.33, height=-style.offset) self.applier_to_be_updated_label = ThemedLabel( self.applier_to_be_updated_frame, label_text="To be updated:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_updated_label.place(relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_updated_listbox = scrollingTkListbox( self.applier_to_be_updated_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_updated_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_to_be_unchanged_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_unchanged_frame.place(relwidth=1, relheight=0.33, rely=0.67, height=-style.offset) self.applier_to_be_unchanged_label = ThemedLabel( self.applier_to_be_unchanged_frame, label_text="Unchanged:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_unchanged_label.place( relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_unchanged_listbox = scrollingTkListbox( self.applier_to_be_unchanged_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_unchanged_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_apply_button = button(self.applier_frame, callback=self.apply, text_string="Apply", background=style.color_1) self.applier_apply_button.place(relwidth=1, height=style.buttonsize, rely=1, y=-(style.buttonsize)) #BUILDER COLUMN_______________________________ self.builder_frame = ThemedFrame(self.content_frame, background=style.color_2) for package in self.repo_parser.all: self.packages_listbox.insert("end", package["package"]) self.frames = [{ "frame": self.editor_frame, "text": "editor", }, { "frame": self.applier_frame, "text": "applier" }, { "frame": self.builder_frame, "text": "builder" }] self.content_frames = {} def make_frames_and_add(frame_list): for f in frame_list: page_name = f["text"] frame = f["frame"] self.content_frames[page_name] = frame frame.place(relx=0, rely=0, relwidth=1, relheight=1) make_frames_and_add(self.frames) self.show_frame("editor") self.yesno = yesnoPage(self) self.usermessage = usermessagePage(self) self.progress_bar = progressFrame(self) self.update_json() self.reload_presets() self.update_sd_path()
class detailPage(activeFrame): def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = controller.appstore_handler self.repo_parser = controller.repo_parser self.repo = None #------------------------------ self.column = ThemedFrame(self, background=style.light_color) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.light_color) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", label_font=style.mediumboldtext, foreground=style.w, background=style.light_color) self.column_title.place(x=5, width=-5, rely=0, relwidth=1, height=style.headerheight) #------------------------------ self.column_author = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_author.place(x=5, width=-5, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_version.place(x=5, width=-5, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_license.place(x=5, width=-5, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_package = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_package.place(x=5, width=-5, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_downloads.place(x=5, width=-5, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_updated.place(x=5, width=-5, y=3.00 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_downloaded = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_downloaded.place(x=5, width=-5, y=3.66 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ self.column_extracted = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.light_color) self.column_extracted.place(x=5, width=-5, y=4 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.dark_color).place( rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-4 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.dark_color) self.column_install_button.place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-3 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.dark_color) self.back_image = ImageTk.PhotoImage( Image.open(locations.backimage).resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.light_color) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) self.column_backbutton_ttp = tooltip(self.column_backbutton, "Back to list") self.content_frame = ThemedFrame(self, background=style.w) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.w) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.w) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image = ThemedLabel(self.content_frame_body, "", background=style.w, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=0.5) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext) self.content_frame_details.place(rely=0.5, relx=0, relwidth=1, relheight=0.5, x=+style.offset, width=-2 * (style.offset), height=-style.offset) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.giantboldtext, background=style.w, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.smalltext, background=style.w, foreground=style.light_color) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self) def update_page(self, repo): self.repo = repo package = repo["name"] try: web_dls = repo["web_dls"] except: web_dls = 0 try: app_dls = repo["app_dls"] except: app_dls = 0 ttl_dls = web_dls + app_dls self.column_title.set("Title: {}".format(repo["title"])) self.column_author.set("Author: {}".format(repo["author"])) self.column_version.set("Version: {}".format(repo["version"])) self.column_license.set("License: {}".format(repo["license"])) self.column_package.set("Package: {}".format(package)) self.column_downloads.set("Downloads: {}".format(ttl_dls)) self.column_updated.set("Updated: {}".format(repo["updated"])) self.column_downloaded.set("Dowloaded size: {} KB".format( repo["filesize"])) self.column_extracted.set("Install size: {} KB".format( repo["extracted"])) self.content_frame_details.configure(state="normal") self.content_frame_details.delete('1.0', "end") #Makes newlines in details print correctly. Hacky but :shrug: details = repo["details"].replace("\\n", """ """) self.content_frame_details.insert("1.0", details) self.content_frame_details.configure(state="disabled") self.header_label.set(repo["title"]) self.header_author.set(repo["author"]) #Hides or places the uninstalll button if not installed or installed respectively #get_package_entry returns none if no package is found or if the sd path is not set if self.appstore_handler.get_package_entry(package): self.column_uninstall_button.place( rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-2 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) if self.column_install_button: if self.appstore_handler.clean_version( self.appstore_handler.get_package_version(package), package) > self.appstore_handler.clean_version( self.appstore_handler.get_package_version( self.repo["version"]), package): self.column_install_button.settext("UPDATE") else: self.column_install_button.settext("REINSTALL") else: self.column_uninstall_button.place_forget() if self.column_install_button: self.column_install_button.settext("INSTALL") def do_update_banner(): self.bannerimage = getScreenImage(package) if self.bannerimage: self.update_banner(self.bannerimage) else: self.update_banner(locations.notfoundimage) print("failed to download screenshot for {}".format(package)) self.controller.async_threader.do_async(do_update_banner, []) def update_banner(self, image_path): art_image = Image.open(image_path) art_image = ImageTk.PhotoImage(art_image) self.content_banner_image.configure(image=art_image) self.content_banner_image.image = art_image def show(self, repo): self.update_banner(locations.notfoundimage) self.controller.async_threader.do_async(self.update_page, [repo], priority="medium") self.tkraise() for child in self.winfo_children(): child.bind("<Escape>", self.leave) def leave(self): self.controller.show_frame("appstorePage") for child in self.winfo_children(): child.unbind("<Escape>") def reload_function(self): self.controller.frames["appstorePage"].reload_category_frames() self.reload() def trigger_install(self): if not self.appstore_handler.check_path(): self.set_sd() if self.appstore_handler.check_path(): if self.appstore_handler.check_if_get_init(): if self.repo: self.controller.async_threader.do_async( self.appstore_handler.install_package, [ self.repo, self.progress_bar.update, self.reload_function, self.progress_bar.set_title ], priority="high") else: self.yesnoPage.getanswer( "The homebrew appstore has not been initiated here yet, would you like to initiate it?", self.init_get_then_continue) def init_get_then_continue(self): self.appstore_handler.init_get() self.trigger_install() def trigger_uninstall(self): if self.repo: self.controller.async_threader.do_async( self.appstore_handler.uninstall_package, [self.repo], priority="high") self.controller.frames["appstorePage"].reload_category_frames() self.schedule_callback(self.reload(), 100) def reload(self): self.controller.async_threader.do_async(self.update_page, [self.repo]) def trigger_open_tab(self): if self.repo: try: url = self.repo["url"] opentab(url) except: print("Failed to open tab for url {}".format(url)) def set_sd(self): chosensdpath = tkinter.filedialog.askdirectory( initialdir="/", title='Please select your SD card') self.appstore_handler.set_path(chosensdpath) self.reload()
class categorylistFrame(tk.Frame): def __init__(self, parent, controller, framework, packages): #list of packages to be displayed by this frame self.packages = packages self.parent = parent self.controller = controller #Frame manager self.framework = framework #**Scheduler self.appstore_handler = Store_handler #Tool to get installed package data etc self.current_search = None self.selected = False self.sort_type = None self.listbox_list = [] tk.Frame.__init__(self, parent, background=style.w, border=0, highlightthickness=0) threader.do_async(self.build_listframe) def build_listframe(self): columnwidth = 0.33 * (self.winfo_width() - style.updated_column_width) self.body_frame = tk.Frame(self, background=style.color_1) self.body_frame.place(relwidth=1, relheight=1) self.scrollbar = tk.Scrollbar(self.body_frame, troughcolor=style.color_1, bg=style.color_2) self.scrollbar.place(relheight=1, width=style.scrollbarwidth, relx=1, x=-style.scrollbarwidth, height=-(style.listbox_footer_height + style.listbox_footer_height), y=+style.listbox_footer_height) self.listbox_frame = tk.Frame(self.body_frame, background=style.color_2) self.listbox_frame.place(relwidth=1, relheight=1, height=-style.listbox_footer_height, width=-style.scrollbarwidth) self.scaling_listboxes_frame = tk.Frame(self.listbox_frame, background=style.color_2) self.scaling_listboxes_frame.place(relwidth=1, relheight=1, width=-style.updated_column_width) self.scaling_listboxes_frame_header = tk.Frame( self.scaling_listboxes_frame, background=style.color_2) self.scaling_listboxes_frame_header.place( relwidth=1, height=style.listbox_header_height) self.scaling_listboxes_frame_body = tk.Frame( self.scaling_listboxes_frame, background=style.color_2) self.scaling_listboxes_frame_body.place( relwidth=1, relheight=1, y=style.listbox_header_height, height=-style.listbox_header_height) self.package_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smallboldtext, borderwidth=1, foreground=style.w) self.package_listbox.place(relx=0, relwidth=0.33333, relheight=1) self.package_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Package", background=style.color_1, font=style.mediumboldtext) self.package_listbox_label.place(relx=0, relwidth=0.33333, relheight=1) self.title_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smalltext, borderwidth=1) self.title_listbox.place(relx=0.33333, relwidth=0.33333, relheight=1) self.title_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Title", background=style.color_1, font=style.mediumboldtext) self.title_listbox_label.place(relx=0.33333, relwidth=0.33333, relheight=1) self.author_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smalltext, borderwidth=1) self.author_listbox.place(relx=0.66666, relwidth=0.33333, relheight=1) self.author_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Author", background=style.color_1, font=style.mediumboldtext) self.author_listbox_label.place(relx=0.66666, relwidth=0.33333, relheight=1) self.updated_listbox = ThemedListbox(self.listbox_frame, background=style.color_2, font=style.smalltext, borderwidth=1) self.updated_listbox.place(relx=1, width=style.updated_column_width, x=-style.updated_column_width, relheight=1, y=style.listbox_header_height, height=-style.listbox_header_height) self.updated_listbox_label = ThemedLabel(self.listbox_frame, text="Updated", background=style.color_1, font=style.mediumboldtext) self.updated_listbox_label.place(relx=1, width=style.updated_column_width, x=-style.updated_column_width, height=style.listbox_header_height) self.listbox_list = [ self.package_listbox, self.title_listbox, self.author_listbox, self.updated_listbox ] self.listbox_frame_footer = tk.Frame(self, background=style.color_1) self.listbox_frame_footer.place(relwidth=1, rely=1, y=-style.listbox_footer_height, height=style.listbox_footer_height) self.installed_label = ThemedLabel(self.listbox_frame_footer, text="Installed - â—†", background=style.color_1, foreground="green", anchor="center") self.installed_label.place(relx=0, relwidth=0.333, relheight=1) self.hasupdate_label = ThemedLabel(self.listbox_frame_footer, text="Update Available - â—†", background=style.color_1, foreground="yellow", anchor="center") self.hasupdate_label.place(relx=0.333, relwidth=0.333, relheight=1) self.notinstalled_label = ThemedLabel(self.listbox_frame_footer, text="Not installed - â—†", background=style.color_1, foreground="white", anchor="center") self.notinstalled_label.place(relx=0.666, relwidth=0.333, relheight=1) self.package_listbox.configure({"selectbackground": style.lg}) self.package_listbox.configure({"selectmode": "single"}) self.package_listbox.bind("<<ListboxSelect>>", self.on_listbox_selection) self.scrollbar.config(command=self.on_scroll_bar) self.package_listbox.config(yscrollcommand=self.scrollbar.set) self.set_sort_type(None) self.rebuild() def get_current_packages(self): packages = self.search_packages(self.current_search) if self.sort_type: packages = self.sort_packages(packages, self.sort_type) return packages def configure(self, event=None): self.rebuild() def search_packages(self, search: str = ""): if search: packages = [] for package in self.packages: try: for field in ["author", "name", "title", "description"]: if search.lower() in package[field].lower(): packages.append(package) break except: pass return packages if packages else [{ "name": "NO RESULTS", "title": "", "author": "", "updated": "" }] else: return self.packages def on_listbox_selection(self, event): selection = self.package_listbox.curselection() picked = self.package_listbox.get(selection[0]) for package in self.packages: if package["name"] == picked: self.open_details(package) def sort_packages(self, packages, sort_method): reverse = False if sort_method.endswith('-'): reverse = True sort_method = sort_method.strip('-') return sorted(packages, key=lambda k: k[sort_method], reverse=reverse) def rebuild(self): self.build_frame(self.get_current_packages()) def build_frame(self, packages): def do_build_frame(): if not packages: return self.clear() if self.listbox_list: for lb in self.listbox_list: lb.configure(state="normal") installed_packages = self.appstore_handler.get_packages( silent=True) for package in packages: if not package: continue self.package_listbox.insert('end', package["name"]) self.title_listbox.insert('end', package["title"]) self.author_listbox.insert('end', package["author"]) self.updated_listbox.insert('end', package["updated"]) if installed_packages: if package["name"] in installed_packages: if self.appstore_handler.get_package_version( package["name"]) == package["version"]: self.package_listbox.itemconfig( 'end', {"fg": "green"}) else: self.package_listbox.itemconfig( 'end', {"fg": "yellow"}) for lb in self.listbox_list: lb.configure(state="disable") self.package_listbox.configure(state='normal') bindlist = [ self, self.package_listbox, self.title_listbox, self.author_listbox, self.updated_listbox ] if platform.system() == 'Windows' or platform.system( ) == "Darwin": for b in bindlist: b.bind("<MouseWheel>", self.on_mouse_wheel) elif platform.system() == "Linux": for b in bindlist: b.bind("<Button-4>", self.on_mouse_wheel) b.bind("<Button-5>", self.on_mouse_wheel) threader.do_async(do_build_frame) def open_details(self, package): self.controller.frames["detailPage"].show(package) def select(self): self.selected = True def deselect(self): self.selected = False def is_selected(self): return self.selected def search(self, searchterm): self.current_search = searchterm self.rebuild() def clear(self): if self.listbox_list: for lb in self.listbox_list: lb.configure(state="normal") lb.delete(0, "end") lb.configure(state="disable") def on_scroll_bar(self, move_type, move_units, __=None): if move_type == "moveto": for lb in self.listbox_list: lb.yview("moveto", move_units) def on_mouse_wheel(self, event): try: if platform.system() == 'Windows': self.package_listbox.yview( "scroll", int(-1 * (event.delta / 120), "units")) elif platform.system() == "Linux": if event.num == 5: self.package_listbox.yview("scroll", 1, "units") if event.num == 4: self.package_listbox.yview("scroll", -1, "units") elif platform.system() == "Darwin": self.package_listbox.yview("scroll", event.delta, "units") for listbox in self.listbox_list: listbox.yview_moveto(self.package_listbox.yview()[0]) return "break" except: pass def set_sort_type(self, sort_type): self.sort_type = sort_type
class detailPage(activeFrame): def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = Store_handler self.package_parser = Parser self.selected_version = None self.version_index = None self.package = None self.bind("<Configure>", self.on_configure) self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", font=style.mediumboldtext, foreground=style.w, background=style.color_1) self.column_title.place(x=style.offset, width=-style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.column_author = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_author.place(x=style.offset, width=-style.offset, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_version.place(x=style.offset, width=-style.offset, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_license.place(x=style.offset, width=-style.offset, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_package = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_package.place(x=style.offset, width=-style.offset, y=2.000 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_downloads.place(x=style.offset, width=-style.offset, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_updated.place(x=style.offset, width=-style.offset, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) # self.column_separator_top = ThemedLabel(self.column_body, "", background=style.lg) # self.column_separator_top.place(rely=1,relwidth = 1, x = + style.offset, y = - 3 * (style.buttonsize + style.offset) - 3 * style.offset - style.buttonsize - 1 - 0.5 * style.buttonsize, width = - 2 * style.offset, height = 1) # self.column_separator_bot = ThemedLabel(self.column_body, "", background=style.lg) # self.column_separator_bot.place(rely=1,relwidth = 1, x = + style.offset, y = - 3 * (style.buttonsize + style.offset) - style.offset - 1, width = - 2 * style.offset, height = 1) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.color_2, ).place(rely=1, relwidth=1, x=+style.offset, y=-3 * (style.buttonsize + style.offset), width=-2 * style.offset, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.color_2) self.column_install_button.place(rely=1, relwidth=1, x=+style.offset, y=-2 * (style.buttonsize + style.offset), width=-2 * style.offset, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.color_2) self.back_image = ImageTk.PhotoImage( Image.open("assets/return.png").resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.color_1) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) # self.column_backbutton_ttp = tooltip(self.column_backbutton,"Back to list") self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image_frame = ThemedFrame(self.content_frame, background=style.color_2) self.content_banner_image_frame.place( x=0, y=+style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=0.4) self.content_banner_image = ThemedLabel( self.content_banner_image_frame, "", background=style.color_2, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=1) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_details.place(rely=0.4, relx=0, relwidth=1, relheight=0.6, x=+style.offset, width=-2 * (style.offset), height=-style.offset) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", font=style.giantboldtext, background=style.color_2, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", font=style.smalltext, background=style.color_2, foreground=style.color_1) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self) def on_menu_update(self, option): self.selected_tag_name.set(option) self.select_version(option) def update_page(self, package): self.selected_version = None self.package = package threader.do_async(self.update_banner) version = package["version"] self.column_title.set("Title: {}".format(package["title"])) self.column_author.set("Author: {}".format(package["author"])) self.column_version.set("Latest Version: {}".format( package["version"])) try: self.column_license.set("License: {}".format(package["license"])) except: self.column_license.set("License: N/A") self.column_package.set("Package: {}".format(package["name"])) ttl_dl = 0 try: ttl_dl += package["web_dls"] except: pass try: ttl_dl += package["app_dls"] except: pass self.column_downloads.set("Downloads: {}".format(ttl_dl)) self.column_updated.set("Updated: {}".format(package["updated"])) self.content_frame_details.configure(state="normal") self.content_frame_details.delete('1.0', "end") #Makes newlines in details print correctly. Hacky but :shrug: details = package["description"].replace("\\n", """ """) self.content_frame_details.insert("1.0", details) self.content_frame_details.configure(state="disabled") self.header_label.set(package["title"]) self.header_author.set(package["author"]) #Hides or places the uninstalll button if not installed or installed respectively #get_package_entry returns none if no package is found or if the sd path is not set if self.appstore_handler.get_package_entry(package["name"]): self.column_uninstall_button.place( rely=1, relwidth=1, x=+style.offset, y=-1 * (style.buttonsize + style.offset), width=-(3 * style.offset + style.buttonsize), height=style.buttonsize) if self.column_install_button: if self.appstore_handler.clean_version( self.appstore_handler.get_package_version( package["name"]), package["title"] ) > self.appstore_handler.clean_version( package["version"], package["title"]): self.column_install_button.settext("UPDATE") else: self.column_install_button.settext("REINSTALL") else: self.column_uninstall_button.place_forget() if self.column_install_button: self.column_install_button.settext("INSTALL") tags = [] def select_version(self, option): try: self.selected_version = option self.version_index = self.controller.appstore_handler.get_tag_index( self.package["github_content"], self.selected_version) self.update_release_notes() except Exception as e: # print(e) pass def on_configure(self, event=None): if self.package: self.after(100, self.update_banner()) def update_banner(self): self.bannerimage = getScreenImage(self.package["name"]) if self.bannerimage: self.do_update_banner(self.bannerimage) else: self.do_update_banner("assets/notfound.png") def do_update_banner(self, image_path): maxheight = self.content_banner_image_frame.winfo_height() maxwidth = self.content_banner_image_frame.winfo_width() if maxwidth > 0 and maxheight > 0: art_image = Image.open(image_path) wpercent = (maxwidth / float(art_image.size[0])) hsize = int((float(art_image.size[1]) * float(wpercent))) w_img = art_image.resize((maxwidth, hsize), Image.ANTIALIAS) if w_img.size[0] > maxheight: hpercent = (maxheight / float(art_image.size[1])) wsize = int((float(art_image.size[0]) * float(hpercent))) art_image = art_image.resize((maxwidth, hsize), Image.ANTIALIAS) else: art_image = w_img art_image = ImageTk.PhotoImage(art_image) self.content_banner_image.configure(image=art_image) self.content_banner_image.image = art_image def show(self, repo): self.do_update_banner("assets/notfound.png") threader.do_async(self.update_page, [repo], priority="medium") self.tkraise() for child in self.winfo_children(): child.bind("<Escape>", self.leave) def leave(self): self.controller.show_frame("appstorePage") for child in self.winfo_children(): child.unbind("<Escape>") def reload_function(self): self.controller.frames["appstorePage"].reload_category_frames() self.reload() def trigger_install(self): index = self.version_index or 0 if not self.appstore_handler.check_path(): self.set_sd() if self.appstore_handler.check_path(): if self.appstore_handler.check_if_get_init(): if self.package: threader.do_async( self.appstore_handler.handler_install_package, [ self.package, self.progress_bar.update, self.reload_function, self.progress_bar.set_title ], priority="high") else: self.yesnoPage.getanswer( "The homebrew appstore has not been initiated here yet, would you like to initiate it?", self.init_get_then_continue) def init_get_then_continue(self): self.appstore_handler.init_get() self.trigger_install() def trigger_uninstall(self): if self.package: threader.do_async(self.appstore_handler.uninstall_package, [self.package], priority="high") self.controller.frames["appstorePage"].reload_category_frames() self.schedule_callback(self.reload(), 100) def reload(self): threader.do_async(self.update_page, [self.package]) def trigger_open_tab(self): if self.package: try: url = self.package["url"] opentab(url) except Exception as e: print("Failed to open tab - {}".format(e)) def set_sd(self): chosensdpath = tkinter.filedialog.askdirectory( initialdir="/", title='Please select your SD card') self.appstore_handler.set_path(chosensdpath) self.reload()
class settingsPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent, background=style.color_2) self.settings = settings self.controller = controller self.settings_page_header = ThemedLabel( self, label_text="Most settings will not take effect until next launch", background=style.color_2, label_font=style.mediumboldtext) self.settings_page_header.place(y=style.offset, x=style.offset, height=style.buttonsize - 2 * style.offset, relwidth=1, width=-2 * style.offset) thumbnail_sizes = ["tiny", "small", "medium", "large", "huge"] self.thumbnail_size_dropdown = customOptionMenu(self, thumbnail_sizes) self.thumbnail_size_dropdown.place(y=style.offset + style.buttonsize, x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.thumbnail_size_dropdown_label = ThemedLabel( self, label_text="~ Tile Size\n(No restart)", background=style.color_2) self.thumbnail_size_dropdown_label.place( y=style.offset + style.buttonsize, x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) thread_levels = [x for x in range(1, 17)] self.gui_threads_dropdown = customOptionMenu(self, thread_levels) self.gui_threads_dropdown.place( y=2 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.gui_threads_dropdown_label = ThemedLabel( self, label_text="~ Max threads\n(No restart)", background=style.color_2) self.gui_threads_dropdown_label.place( y=2 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) maximized_options = ["fullscreen", "maximized", "windowed"] self.maximized_on_launch_dropdown = customOptionMenu( self, maximized_options) self.maximized_on_launch_dropdown.place( y=3 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.maximized_dropdown_label = ThemedLabel( self, label_text="~ Maximized on launch", background=style.color_2) self.maximized_dropdown_label.place( y=3 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.topmost_dropdown = customOptionMenu(self, truefalse_options) self.topmost_dropdown.place(y=4 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.topmost_dropdown_label = ThemedLabel( self, label_text="~ Keep window topmost", background=style.color_2) self.topmost_dropdown_label.place( y=4 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.borderless_dropdown = customOptionMenu(self, truefalse_options) self.borderless_dropdown.place(y=5 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.borderless_dropdown_label = ThemedLabel( self, label_text="~ Borderless window (broken on some systems)", background=style.color_2) self.borderless_dropdown_label.place( y=5 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.clear_cache_button = button(self, callback=self.clear_cache, text_string="- clear cache -", background=style.color_1, font=style.smalltext) self.clear_cache_button.place(y=6 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.clear_cache_label = ThemedLabel( self, label_text="~ Clear image and json cache?", background=style.color_2) self.clear_cache_label.place(y=6 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.savebutton = button(self, callback=self.save, text_string="Save", background=style.color_1) self.savebutton.place(relx=0.5, x=-0.5 * style.sidecolumnwidth, width=style.sidecolumnwidth, height=style.buttonsize, rely=1, y=-(style.offset + style.buttonsize)) #Bind frame raise self.bind("<<ShowFrame>>", self.configure) self.yesno = yesnoPage(self) self.okpage = usermessagePage(self) def configure(self, event): self.thumbnail_size_dropdown.option.set( self.settings.get_setting("thumbnail_size")) self.maximized_on_launch_dropdown.option.set( self.settings.get_setting("maximized")) self.topmost_dropdown.option.set( self.settings.get_setting("keep_topmost")) self.borderless_dropdown.option.set( self.settings.get_setting("borderless")) self.gui_threads_dropdown.option.set( self.settings.get_setting("gui_threads")) def save(self): try: self.settings.set_setting( "thumbnail_size", self.thumbnail_size_dropdown.option.get()) self.settings.set_setting( "maximized", self.maximized_on_launch_dropdown.option.get()) self.settings.set_setting("keep_topmost", self.topmost_dropdown.option.get()) self.settings.set_setting("borderless", self.borderless_dropdown.option.get()) self.settings.set_setting("gui_threads", self.gui_threads_dropdown.option.get()) threader.set_max_threads( int(self.gui_threads_dropdown.option.get())) self.settings.save() self.okpage.telluser("Settings saved successfully") except Exception as e: self.okpage.telluser("Failed to save settings\n{}".format(e)) def clear_cache(self): self.yesno.getanswer("Are you sure you'd like to clear the cache?", self.do_clear_cache) def do_clear_cache(self): for root, dirs, files in os.walk(locations.cachefolder, topdown=False): for f in files: os.remove(os.path.join(root, f))
def place_buttonversionlabel(): if not self.buttonversionlabel: self.buttonversionlabel = ThemedLabel(self.canvas,self.repo["version"],anchor="w",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonversionlabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonversionlabel.place(x = self.base_x, y = label_y)
def place_buttonauthorlabel(): if not self.buttonauthorlabel: self.buttonauthorlabel = ThemedLabel(self.canvas,self.repo["author"],anchor="e",label_font=style.smallboldtext,foreground=style.lg,background=style.w) self.buttonauthorlabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttonauthorlabel.place(x = self.base_x, y = label_y, width = style.thumbnailwidth)
def place_buttontitlelabel(): if not self.buttontitlelabel: self.buttontitlelabel = ThemedLabel(self.canvas,self.repo["title"],anchor="e",label_font=style.mediumboldtext,foreground=style.b,background=style.w) self.buttontitlelabel.bind("<MouseWheel>", self.canvas.on_mouse_wheel) self.buttontitlelabel.place(x = self.base_x, y = label_y - 1.5 * style.buttontextheight, width = style.thumbnailwidth)
def __init__(self, parent, controller): self.controller = controller self.appstore_handler = Store_handler self.repo_parser = Parser self.current_frame = None self.current_frame_name = None self.last_selection = None self.last_sort_option = None self.updater = updater activeFrame.__init__(self, parent, controller) self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=0, rely=0, width=style.sidecolumnwidth, relheight=1) self.column_header = ThemedFrame(self.column, background=style.color_1) self.column_header.place(relx=0, rely=0, relwidth=1, height=style.column_headerheight) self.column_header_title = ThemedLabel(self.column_header, "Appstore\nWorkbench\nGPLv3", anchor="center", font=style.largeboldtext, background=style.color_1) self.column_header_title.place(relx=0, rely=0, relwidth=1, relheight=1, height=-(style.offset + 1), y=+style.offset) self.column_header_separator = ThemedLabel(self.column_header, "", background=style.w) self.column_header_separator.place(x=style.offset, rely=1, y=-1, relwidth=1, width=-2 * style.offset) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place( relx=0, relwidth=1, y=style.column_headerheight, relheight=1, height=-(style.column_headerheight + style.footerheight)) self.category_listbox = ThemedListbox(self.column_body, foreground=style.w) self.category_listbox.configure(activestyle="none") self.category_listbox.place(relwidth=1, relheight=1) self.category_listbox.bind('<<ListboxSelect>>', self.select_frame) self.column_footer = ThemedFrame(self.column, background=style.color_1) self.column_footer.place(relx=0, rely=1, relwidth=1, height=2 * style.listbox_footer_height, y=-2 * style.listbox_footer_height) self.column_set_sd = button(self.column_footer, callback=self.set_sd, text_string="Select SD Root", font=style.mediumtext, background=style.color_2).place( relwidth=1, y=0, x=style.offset, width=-2 * style.offset, height=style.listbox_footer_height) self.column_sd_status_label = ThemedLabel( self.column_footer, "SD - Not Set", anchor="center", font=style.smalltext, background=style.color_1, foreground=style.pathdisplaytextcolor) self.column_sd_status_label.place( x=style.offset, relwidth=1, width=-2 * style.offset, y=-style.listbox_footer_height, height=style.listbox_footer_height, rely=1, ) self.content_frame = ThemedFrame(self) self.content_frame.place(x=style.sidecolumnwidth, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame) self.content_frame_header.place(relx=0, rely=0, relwidth=1, height=style.searchboxheight) self.category_label = ThemedLabel(self.content_frame_header, "", anchor="nw", font=style.giantboldtext, background=style.color_1, foreground=style.lg) self.category_label.place(x=+style.offset, relx=0, rely=0, relheight=1, height=-(style.offset + 1), y=+style.offset) self.content_frame_header_search_bar = searchBox( self.content_frame_header, command=self.search, entry_background=style.color_2, borderwidth=0, entry_foreground=style.w) self.selected_sort_method = tk.StringVar() self.selected_sort_method.set(SORT_OPTIONS[0]) self.content_frame_header_sort_method_dropdown = tk.OptionMenu( self.content_frame_header, self.selected_sort_method, *SORT_OPTIONS) self.content_frame_header_sort_method_dropdown.configure( foreground=style.w) self.content_frame_header_sort_method_dropdown.configure( background=style.color_2) self.content_frame_header_sort_method_dropdown.configure( highlightthickness=0) self.content_frame_header_sort_method_dropdown.configure(borderwidth=0) #The various content gets stacked on top of each other here. self.content_stacking_frame = ThemedFrame(self.content_frame) self.content_stacking_frame.place( relx=0, y=(style.searchboxheight + style.offset), relwidth=1, relheight=1, height=-(style.searchboxheight + style.offset)) all_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.all) tools_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.tools) emus_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.emus) games_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.games) installed_frame = installedcategorylistFrame( self.content_stacking_frame, self.controller, self, self.repo_parser.all) # help_frame = helpFrame(self.content_stacking_frame) # about_frame = aboutFrame(self.content_stacking_frame) # readme_frame = readmeFrame(self.content_stacking_frame) settings_frame = settingsPage(self.content_stacking_frame, self.controller) exit_frame = exitPage(self.content_stacking_frame, self.controller) self.category_frames = [ all_frame, tools_frame, emus_frame, games_frame, installed_frame ] self.frames = [ { "frame": all_frame, "text": "All Apps" }, { "frame": tools_frame, "text": "Tools" }, { "frame": emus_frame, "text": "Emulators" }, { "frame": games_frame, "text": "Games" }, ] if config.CONSOLE in [config.WII, config.WII_OSC]: misc_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.misc) self.category_frames.append(misc_frame) self.frames.extend([ { "frame": misc_frame, "text": "Misc" }, ]) elif config.CONSOLE == config.SWITCH: legacy_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.legacy) themes_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.themes) advanced_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.advanced) self.category_frames.append(legacy_frame) self.category_frames.append(themes_frame) self.category_frames.append(advanced_frame) self.frames.extend([ { "frame": advanced_frame, "text": "Advanced Homebrew" }, { "frame": themes_frame, "text": "Themes" }, { "frame": legacy_frame, "text": "Legacy" }, ]) elif config.CONSOLE == config.WIIU: misc_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.misc) advanced_frame = categorylistFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.advanced) self.category_frames.append(misc_frame) self.category_frames.append(advanced_frame) self.frames.extend([ { "frame": advanced_frame, "text": "Advanced Homebrew" }, { "frame": misc_frame, "text": "Misc" }, ]) else: raise "Invalid Console" self.frames.extend([ { "frame": installed_frame, "text": "Installed" }, # { # "frame" : help_frame, # "text" : "HELP" # }, # { # "frame" : about_frame, # "text" : "ABOUT" # }, # { # "frame" : readme_frame, # "text" : "README", # }, { "frame": settings_frame, "text": "SETTINGS" }, { "frame": exit_frame, "text": "EXIT" } ]) self.all_frames = [] self.content_frames = {} def make_frames_and_add_to_list(frame_list, listbox): for f in frame_list: page_name = f["text"] frame = f["frame"] self.content_frames[page_name] = frame frame.place(relx=0, rely=0, relwidth=1, relheight=1) listbox.insert("end", " {}".format(page_name)) self.all_frames.append(f) threader.do_async(lambda: make_frames_and_add_to_list( self.frames, self.category_listbox)) self.category_listbox.select_set( 0) #sets focus on the first item in listbox self.category_listbox.event_generate("<<ListboxSelect>>") self.show_frame("All Apps") if self.updater.status: print(self.updater.status) self.yesnoPage = yesnoPage(self) self.yesnoPage.getanswer( "An update is available, would you like to download it?\nPatch notes:\n{}" .format(self.updater.status), self.updater.update) self.loaded() self.add_on_refresh_callback(self.update_sd_path) self.add_on_tick_callback(self.update_sd_path) self.sort_check_loop()
class detailPage(activeFrame): def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = controller.appstore_handler self.repo_parser = controller.repo_parser self.selected_version = None self.version_index = None self.repo = None self.bind("<Configure>", self.on_configure) #------------------------------ self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", label_font=style.mediumboldtext, foreground=style.w, background=style.color_1) self.column_title.place(x=5, width=-5, rely=0, relwidth=1, height=style.detailspagemultiplier) #------------------------------ self.column_author = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_author.place(x=5, width=-5, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_version.place(x=5, width=-5, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_license.place(x=5, width=-5, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_package = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_package.place(x=5, width=-5, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_downloads.place(x=5, width=-5, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_updated.place(x=5, width=-5, y=3.00 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ self.releases_listbox = ScrolledThemedListBox(self.column_body) self.releases_listbox.configure(activestyle="none") self.releases_listbox.place( relwidth=1, y=3.66 * style.detailspagemultiplier, relheight=1, height=-(3.66 * style.detailspagemultiplier + 3 * (style.buttonsize + style.offset) + style.offset)) self.releases_listbox.bind('<<ListboxSelect>>', self.select_version) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.color_2, ).place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-3 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.color_2) self.column_install_button.place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-2 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.color_2) self.back_image = ImageTk.PhotoImage( Image.open(locations.backimage).resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.color_1) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) # self.column_backbutton_ttp = tooltip(self.column_backbutton,"Back to list") self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image_frame = ThemedFrame(self.content_frame, background=style.color_2) self.content_banner_image_frame.place( x=0, y=+style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=0.4) self.content_banner_image = ThemedLabel( self.content_banner_image_frame, "", background=style.color_2, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=1) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_details.place(rely=0.4, relx=0, relwidth=1, relheight=0.25, x=+style.offset, width=-2 * (style.offset), height=-style.offset) self.content_frame_patch_notes_label = ThemedLabel( self.content_frame_body, "Release notes:", anchor="w", label_font=style.mediumboldtext, foreground=style.b, background=style.color_2) self.content_frame_patch_notes_label.place( relx=0.5, width=self.content_frame_patch_notes_label.winfo_reqwidth(), rely=0.65, y=+style.offset, x=-0.5 * self.content_frame_patch_notes_label.winfo_reqwidth(), height=0.33 * style.detailspagemultiplier) self.content_frame_version_details = scrolledText( self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_version_details.place( rely=0.65, y=+style.offset + 0.33 * style.detailspagemultiplier, relx=0, relwidth=1, relheight=0.35, height=-(2 * style.offset + 0.33 * style.detailspagemultiplier), x=+style.offset, width=-2 * (style.offset)) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.giantboldtext, background=style.color_2, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.smalltext, background=style.color_2, foreground=style.color_1) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self) def update_page(self, repo): self.selected_version = None self.repo = repo try: package = repo["store_equivalent"] except: package = repo["software"] github_content = repo["github_content"] version = github_content[0]["tag_name"] self.column_title.set("Title: {}".format(repo["name"])) self.column_author.set("Author: {}".format(repo["author"])) self.column_version.set("Latest Version: {}".format( github_content[0]["tag_name"])) try: self.column_license.set("License: {}".format(repo["license"])) except: self.column_license.set("License: N/A") self.column_package.set("Package: {}".format(package)) self.column_downloads.set("Downloads: {}".format(repo["downloads"])) self.column_updated.set("Updated: {}".format( github_content[0]["created_at"])) self.content_frame_details.configure(state="normal") self.content_frame_details.delete('1.0', "end") #Makes newlines in details print correctly. Hacky but :shrug: details = repo["description"].replace("\\n", """ """) self.content_frame_details.insert("1.0", details) self.content_frame_details.configure(state="disabled") self.header_label.set(repo["name"]) self.header_author.set(repo["author"]) #Hides or places the uninstalll button if not installed or installed respectively #get_package_entry returns none if no package is found or if the sd path is not set if self.appstore_handler.get_package_entry(package): self.column_uninstall_button.place( rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-1 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) if self.column_install_button: if self.appstore_handler.clean_version( self.appstore_handler.get_package_version(package), package) > self.appstore_handler.clean_version( self.appstore_handler.get_package_version(version), package): self.column_install_button.settext("UPDATE") else: self.column_install_button.settext("REINSTALL") else: self.column_uninstall_button.place_forget() if self.column_install_button: self.column_install_button.settext("INSTALL") def do_update_banner(): self.bannerimage = getScreenImage(package) if self.bannerimage: self.update_banner(self.bannerimage) else: self.update_banner(locations.notfoundimage) print("failed to download screenshot for {}".format(package)) self.update_releases_listbox() self.controller.async_threader.do_async(do_update_banner, []) def select_version(self, event): try: widget = event.widget selection = widget.curselection() picked = widget.get(selection[0]) self.selected_version = picked self.version_index = self.controller.appstore_handler.get_tag_index( self.repo["github_content"], self.selected_version) self.update_release_notes() except Exception as e: print(e) def on_configure(self, event=None): if self.repo: repo = self.repo try: package = repo["store_equivalent"] except: package = repo["software"] self.bannerimage = getScreenImage(package) if self.bannerimage: self.update_banner(self.bannerimage) else: self.update_banner(locations.notfoundimage) def update_banner(self, image_path): maxheight = self.content_banner_image_frame.winfo_height() maxwidth = self.content_banner_image_frame.winfo_width() if maxwidth > 0 and maxheight > 0: art_image = Image.open(image_path) wpercent = (maxwidth / float(art_image.size[0])) hsize = int((float(art_image.size[1]) * float(wpercent))) w_img = art_image.resize((maxwidth, hsize), Image.ANTIALIAS) if w_img.size[0] > maxheight: hpercent = (maxheight / float(art_image.size[1])) wsize = int((float(art_image.size[0]) * float(hpercent))) art_image = art_image.resize((maxwidth, hsize), Image.ANTIALIAS) else: art_image = w_img art_image = ImageTk.PhotoImage(art_image) self.content_banner_image.configure(image=art_image) self.content_banner_image.image = art_image def update_releases_listbox(self): self.releases_listbox.delete(0, "end") for release in self.repo["github_content"]: tag = release["tag_name"] self.releases_listbox.insert("end", tag) self.releases_listbox.select_set( 0) #sets focus on the first item in listbox self.releases_listbox.event_generate("<<ListboxSelect>>") self.update_release_notes() def update_release_notes(self): notes = self.repo["github_content"][self.version_index]["body"] self.content_frame_version_details.configure(state="normal") self.content_frame_version_details.delete('1.0', "end") #Makes newlines in details print correctly. Hacky but :shrug: notes = notes.replace("\\n", """ """) self.content_frame_version_details.insert("1.0", notes) self.content_frame_version_details.configure(state="disabled") def show(self, repo): self.update_banner(locations.notfoundimage) self.controller.async_threader.do_async(self.update_page, [repo], priority="medium") self.tkraise() for child in self.winfo_children(): child.bind("<Escape>", self.leave) def leave(self): self.controller.show_frame("appstorePage") for child in self.winfo_children(): child.unbind("<Escape>") def reload_function(self): self.controller.frames["appstorePage"].reload_category_frames() self.reload() def trigger_install(self): index = 0 if not self.appstore_handler.check_path(): self.set_sd() if self.appstore_handler.check_path(): if self.appstore_handler.check_if_get_init(): if self.repo: self.controller.async_threader.do_async( self.appstore_handler.install_package, [ self.repo, self.version_index, self.progress_bar.update, self.reload_function, self.progress_bar.set_title ], priority="high") else: self.yesnoPage.getanswer( "The homebrew appstore has not been initiated here yet, would you like to initiate it?", self.init_get_then_continue) def init_get_then_continue(self): self.appstore_handler.init_get() self.trigger_install() def trigger_uninstall(self): if self.repo: self.controller.async_threader.do_async( self.appstore_handler.uninstall_package, [self.repo], priority="high") self.controller.frames["appstorePage"].reload_category_frames() self.schedule_callback(self.reload(), 100) def reload(self): self.controller.async_threader.do_async(self.update_page, [self.repo]) def trigger_open_tab(self): if self.repo: try: url = self.repo["projectpage"] opentab(url) except: print("Failed to open tab for url {}".format(url)) def set_sd(self): chosensdpath = tkinter.filedialog.askdirectory( initialdir="/", title='Please select your SD card') self.appstore_handler.set_path(chosensdpath) self.reload()
def __init__(self, parent, controller): tk.Frame.__init__(self, parent, background=style.color_2) self.settings = settings self.controller = controller self.settings_page_header = ThemedLabel( self, text="Most settings will not take effect until next launch", background=style.color_2, font=style.mediumboldtext) self.settings_page_header.place(y=style.offset, x=style.offset, height=style.buttonsize - 2 * style.offset, relwidth=1, width=-2 * style.offset) consoles = [config.WII, config.WII_OSC, config.WIIU, config.SWITCH] self.console_dropdown = customOptionMenu(self, consoles) self.console_dropdown.place(y=1 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=dropdown_width - style.offset) self.console_dropdown_label = ThemedLabel( self, text="~ Console - Repo\n(Needs restart)", background=style.color_2) self.console_dropdown_label.place( y=1 * (style.offset + style.buttonsize), x=dropdown_width + style.offset, height=style.buttonsize - 2 * style.offset, width=label_width) thread_levels = [x for x in range(1, 17)] self.gui_threads_dropdown = customOptionMenu(self, thread_levels) self.gui_threads_dropdown.place( y=2 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=dropdown_width - style.offset) self.gui_threads_dropdown_label = ThemedLabel( self, text="~ Max threads\n(No restart)", background=style.color_2) self.gui_threads_dropdown_label.place( y=2 * (style.offset + style.buttonsize), x=dropdown_width + style.offset, height=style.buttonsize - 2 * style.offset, width=label_width) maximized_options = ["fullscreen", "maximized", "windowed"] self.maximized_on_launch_dropdown = customOptionMenu( self, maximized_options) self.maximized_on_launch_dropdown.place( y=3 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=dropdown_width - style.offset) self.maximized_dropdown_label = ThemedLabel( self, text="~ Maximized on launch", background=style.color_2) self.maximized_dropdown_label.place( y=3 * (style.offset + style.buttonsize), x=dropdown_width + style.offset, height=style.buttonsize - 2 * style.offset, width=label_width) self.topmost_dropdown = customOptionMenu(self, truefalse_options) self.topmost_dropdown.place(y=4 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=dropdown_width - style.offset) self.topmost_dropdown_label = ThemedLabel(self, text="~ Keep window topmost", background=style.color_2) self.topmost_dropdown_label.place( y=4 * (style.offset + style.buttonsize), x=dropdown_width + style.offset, height=style.buttonsize - 2 * style.offset, width=label_width) self.borderless_dropdown = customOptionMenu(self, truefalse_options) self.borderless_dropdown.place(y=5 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=dropdown_width - style.offset) self.borderless_dropdown_label = ThemedLabel( self, text="~ Borderless window\n(broken on some systems)", background=style.color_2) self.borderless_dropdown_label.place( y=5 * (style.offset + style.buttonsize), x=dropdown_width + style.offset, height=style.buttonsize - 2 * style.offset, width=label_width) self.savebutton = button(self, callback=self.save, text_string="Save", background=style.color_1) self.savebutton.place(relx=0.5, x=-0.5 * style.sidecolumnwidth, width=style.sidecolumnwidth, height=style.buttonsize, rely=1, y=-(style.offset + style.buttonsize)) #Bind frame raise self.bind("<<ShowFrame>>", self.configure) self.yesno = yesnoPage(self) self.okpage = usermessagePage(self)
def __init__(self, parent, controller): tk.Frame.__init__(self, parent, background=style.color_2) self.settings = settings self.controller = controller self.settings_page_header = ThemedLabel( self, label_text="Most settings will not take effect until next launch", background=style.color_2, label_font=style.mediumboldtext) self.settings_page_header.place(y=style.offset, x=style.offset, height=style.buttonsize - 2 * style.offset, relwidth=1, width=-2 * style.offset) thumbnail_sizes = ["tiny", "small", "medium", "large", "huge"] self.thumbnail_size_dropdown = customOptionMenu(self, thumbnail_sizes) self.thumbnail_size_dropdown.place(y=style.offset + style.buttonsize, x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.thumbnail_size_dropdown_label = ThemedLabel( self, label_text="~ Tile Size\n(No restart)", background=style.color_2) self.thumbnail_size_dropdown_label.place( y=style.offset + style.buttonsize, x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) thread_levels = [x for x in range(1, 17)] self.gui_threads_dropdown = customOptionMenu(self, thread_levels) self.gui_threads_dropdown.place( y=2 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.gui_threads_dropdown_label = ThemedLabel( self, label_text="~ Max threads\n(No restart)", background=style.color_2) self.gui_threads_dropdown_label.place( y=2 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) maximized_options = ["fullscreen", "maximized", "windowed"] self.maximized_on_launch_dropdown = customOptionMenu( self, maximized_options) self.maximized_on_launch_dropdown.place( y=3 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.maximized_dropdown_label = ThemedLabel( self, label_text="~ Maximized on launch", background=style.color_2) self.maximized_dropdown_label.place( y=3 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.topmost_dropdown = customOptionMenu(self, truefalse_options) self.topmost_dropdown.place(y=4 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.topmost_dropdown_label = ThemedLabel( self, label_text="~ Keep window topmost", background=style.color_2) self.topmost_dropdown_label.place( y=4 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.borderless_dropdown = customOptionMenu(self, truefalse_options) self.borderless_dropdown.place(y=5 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.borderless_dropdown_label = ThemedLabel( self, label_text="~ Borderless window (broken on some systems)", background=style.color_2) self.borderless_dropdown_label.place( y=5 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.clear_cache_button = button(self, callback=self.clear_cache, text_string="- clear cache -", background=style.color_1, font=style.smalltext) self.clear_cache_button.place(y=6 * (style.offset + style.buttonsize), x=style.offset, height=style.buttonsize - 2 * style.offset, width=200 - style.offset) self.clear_cache_label = ThemedLabel( self, label_text="~ Clear image and json cache?", background=style.color_2) self.clear_cache_label.place(y=6 * (style.offset + style.buttonsize), x=200 + style.offset, height=style.buttonsize - 2 * style.offset, width=401) self.savebutton = button(self, callback=self.save, text_string="Save", background=style.color_1) self.savebutton.place(relx=0.5, x=-0.5 * style.sidecolumnwidth, width=style.sidecolumnwidth, height=style.buttonsize, rely=1, y=-(style.offset + style.buttonsize)) #Bind frame raise self.bind("<<ShowFrame>>", self.configure) self.yesno = yesnoPage(self) self.okpage = usermessagePage(self)
class injectorPage(detailPage): def __init__(self, parent, controller): self.local_packages_handler = controller.local_packages_handler self.injector = controller.injector self.column_inject_button = None detailPage.__init__(self,parent,controller) self.column_package.place_forget() self.column_installed_version = ThemedLabel(self.column_body,"",anchor="w",label_font=style.smalltext, foreground = style.w, background = style.color_1) self.column_installed_version.place(x = 5, width = - 5, y = 3.666 * style.detailspagemultiplier, relwidth = 1, height = 0.333 * style.detailspagemultiplier) self.releases_listbox.place(relwidth = 1, y=4.00*style.detailspagemultiplier, relheight = 1, height = - (4*style.detailspagemultiplier + 3 * (style.buttonsize + style.offset) + style.offset)) def update_page(self,repo): self.selected_version = None self.repo = repo try: package = repo["store_equivalent"] except: package = repo["software"] github_content = repo["github_content"] version = github_content[0]["tag_name"] self.column_title.set("Title: {}".format(repo["name"])) self.column_author.set("Author: {}".format(repo["author"])) self.column_version.set("Latest Version: {}".format(github_content[0]["tag_name"])) try: self.column_license.set("License: {}".format(repo["license"])) except: self.column_license.set("License: N/A") installed = self.local_packages_handler.get_package_version(self.repo["store_equivalent"]) if installed: self.column_installed_version.set("Downloaded: {}".format(installed)) else: self.column_installed_version.set("Not downloaded") self.column_package.set("Package: {}".format(package)) self.column_downloads.set("Downloads: {}".format(repo["downloads"])) self.column_updated.set("Updated: {}".format(github_content[0]["created_at"])) self.content_frame_details.configure(state="normal") self.content_frame_details.delete('1.0', "end") #Makes newlines in details print correctly. Hacky but :shrug: details = repo["description"].replace("\\n", """ """ ) self.content_frame_details.insert("1.0", details) self.content_frame_details.configure(state="disabled") self.header_label.set(repo["name"]) self.header_author.set(repo["author"]) if not self.column_inject_button: self.column_inject_button = button(self.column_body, callback = self.trigger_inject, text_string = "INJECT", font=style.mediumboldtext, background=style.color_2 ) #Hides or places the uninstalll button if not installed or installed respectively #get_package_entry returns none if no package is found or if the sd path is not set if self.local_packages_handler.get_package_entry(package): self.column_inject_button.place(rely=1,relx=0.5,x = - 1.5 * (style.buttonsize), y = - 1 * (style.buttonsize + style.offset), width = 3 * style.buttonsize, height = style.buttonsize) self.column_install_button.settext("CHANGE") else: self.column_inject_button.place_forget() if self.column_install_button: self.column_install_button.settext("Download") def do_update_banner(): self.bannerimage = getScreenImage(package) if self.bannerimage: self.update_banner(self.bannerimage) else: self.update_banner(notfoundimage) print("failed to download screenshot for {}".format(package)) self.update_releases_listbox() self.controller.async_threader.do_async(do_update_banner) def select_version(self, event): try: widget = event.widget selection=widget.curselection() picked = widget.get(selection[0]) self.selected_version = picked self.version_index = self.controller.local_packages_handler.get_tag_index(self.repo["github_content"], self.selected_version) self.update_release_notes() except Exception as e: print(e) def trigger_install(self): self.controller.async_threader.do_async(self.local_packages_handler.install_package, [self.repo, self.version_index, self.progress_bar.update, self.reload_function, self.progress_bar.set_title], priority = "high") def trigger_inject(self): toolsfolder = os.path.join(sys.path[0],"tools") payloadfolder = os.path.join(toolsfolder, self.repo["install_subfolder"]) print(self.repo["payload"]) payload = None for item in os.listdir(payloadfolder): if os.path.isfile(os.path.join(payloadfolder, item)): if item.startswith(self.repo["payload"][0]): if item.endswith(self.repo["payload"][1]): payload = os.path.join(payloadfolder, item) break if payload: print("injecting {}".format(payload)) self.injector.inject(payload) else: print("Failed to find payload")
def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = Store_handler self.package_parser = Parser self.selected_version = None self.version_index = None self.package = None self.bind("<Configure>", self.on_configure) self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", font=style.mediumboldtext, foreground=style.w, background=style.color_1) self.column_title.place(x=style.offset, width=-style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.column_author = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_author.place(x=style.offset, width=-style.offset, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_version.place(x=style.offset, width=-style.offset, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_license.place(x=style.offset, width=-style.offset, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_package = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_package.place(x=style.offset, width=-style.offset, y=2.000 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_downloads.place(x=style.offset, width=-style.offset, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", font=style.smalltext, foreground=style.w, background=style.color_1) self.column_updated.place(x=style.offset, width=-style.offset, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) # self.column_separator_top = ThemedLabel(self.column_body, "", background=style.lg) # self.column_separator_top.place(rely=1,relwidth = 1, x = + style.offset, y = - 3 * (style.buttonsize + style.offset) - 3 * style.offset - style.buttonsize - 1 - 0.5 * style.buttonsize, width = - 2 * style.offset, height = 1) # self.column_separator_bot = ThemedLabel(self.column_body, "", background=style.lg) # self.column_separator_bot.place(rely=1,relwidth = 1, x = + style.offset, y = - 3 * (style.buttonsize + style.offset) - style.offset - 1, width = - 2 * style.offset, height = 1) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.color_2, ).place(rely=1, relwidth=1, x=+style.offset, y=-3 * (style.buttonsize + style.offset), width=-2 * style.offset, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.color_2) self.column_install_button.place(rely=1, relwidth=1, x=+style.offset, y=-2 * (style.buttonsize + style.offset), width=-2 * style.offset, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.color_2) self.back_image = ImageTk.PhotoImage( Image.open("assets/return.png").resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.color_1) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) # self.column_backbutton_ttp = tooltip(self.column_backbutton,"Back to list") self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image_frame = ThemedFrame(self.content_frame, background=style.color_2) self.content_banner_image_frame.place( x=0, y=+style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=0.4) self.content_banner_image = ThemedLabel( self.content_banner_image_frame, "", background=style.color_2, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=1) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_details.place(rely=0.4, relx=0, relwidth=1, relheight=0.6, x=+style.offset, width=-2 * (style.offset), height=-style.offset) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", font=style.giantboldtext, background=style.color_2, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", font=style.smalltext, background=style.color_2, foreground=style.color_1) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self)
class appstorePage(activeFrame): def __init__(self, parent, controller): self.controller = controller self.appstore_handler = store_handler self.repo_parser = repo_parser self.current_frame = None self.current_frame_name = None self.last_selection = None self.last_sort_option = None self.updater = updater activeFrame.__init__(self, parent, controller) self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=0, rely=0, width=style.sidecolumnwidth, relheight=1) self.column_header = ThemedFrame(self.column, background=style.color_1) self.column_header.place(relx=0, rely=0, relwidth=1, height=style.headerheight) self.column_header_title = ThemedLabel(self.column_header, "HBUpdater\nGPLv3", anchor="n", label_font=style.giantboldtext, background=style.color_1) self.column_header_title.place(relx=0, rely=0, relwidth=1, relheight=1, height=-(style.offset + 1), y=+style.offset) self.column_header_separator = ThemedLabel(self.column_header, "", background=style.w) self.column_header_separator.place(x=style.offset, rely=1, y=-1, relwidth=1, width=-2 * style.offset) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place( relx=0, relwidth=1, y=style.headerheight, relheight=1, height=-(style.headerheight + style.footerheight)) self.category_listbox = ThemedListbox(self.column_body, foreground=style.w) self.category_listbox.configure(activestyle="none") self.category_listbox.place(relwidth=1, relheight=1) self.category_listbox.bind('<<ListboxSelect>>', self.select_frame) self.column_footer = ThemedFrame(self.column, background=style.color_1) self.column_footer.place(relx=0, rely=1, relwidth=1, height=style.footerheight, y=-style.footerheight) self.column_set_sd = button(self.column_footer, callback=self.set_sd, text_string="Select SD Root", font=style.mediumtext, background=style.color_2).place( relwidth=1, relheight=0.5, y=style.offset, x=style.offset, width=-2 * style.offset, height=-2 * style.offset) self.column_sd_status_label = ThemedLabel( self.column_footer, "SD: Not Set", anchor="w", label_font=style.giantboldtext, background=style.color_1, foreground=style.pathdisplaytextcolor) self.column_sd_status_label.place(x=style.offset, relheight=0.5, rely=0.5, height=-style.offset, relwidth=1, width=-2 * style.offset) self.content_frame = ThemedFrame(self) self.content_frame.place(x=style.sidecolumnwidth, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame) self.content_frame_header.place(relx=0, rely=0, relwidth=1, height=style.searchboxheight) self.category_label = ThemedLabel(self.content_frame_header, "", anchor="nw", label_font=style.giantboldtext, background=style.color_1, foreground=style.lg) self.category_label.place(x=+style.offset, relx=0, rely=0, relheight=1, height=-(style.offset + 1), y=+style.offset) self.content_frame_header_search_bar = searchBox( self.content_frame_header, command=self.search, entry_background=style.color_2, borderwidth=0, entry_foreground=style.w) self.selected_sort_method = tk.StringVar() self.selected_sort_method.set(SORT_OPTIONS[0]) self.content_frame_header_sort_method_dropdown = tk.OptionMenu( self.content_frame_header, self.selected_sort_method, *SORT_OPTIONS) self.content_frame_header_sort_method_dropdown.configure( foreground=style.w) self.content_frame_header_sort_method_dropdown.configure( background=style.color_2) self.content_frame_header_sort_method_dropdown.configure( highlightthickness=0) self.content_frame_header_sort_method_dropdown.configure(borderwidth=0) #The various content gets stacked on top of each other here. self.content_stacking_frame = ThemedFrame(self.content_frame) self.content_stacking_frame.place( relx=0, y=(style.searchboxheight + style.offset), relwidth=1, relheight=1, height=-(style.searchboxheight + style.offset)) all_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.all) media_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.media) emus_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.emulators) games_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.games) tools_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.homebrew) python_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.nxpythonlist) cfw_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.customfirmwarelist) installed_frame = installed_categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.all) self.presets_frame = presets_frame = presetsPage( self.content_stacking_frame, self.controller) injector_frame = injector_categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.payloadlist) help_frame = helpFrame(self.content_stacking_frame) about_frame = aboutFrame(self.content_stacking_frame) readme_frame = readmeFrame(self.content_stacking_frame) settings_frame = settingsPage(self.content_stacking_frame, self.controller) exit_frame = exitPage(self.content_stacking_frame, self.controller) self.category_frames = [ all_frame, media_frame, emus_frame, games_frame, tools_frame, python_frame, cfw_frame, installed_frame, injector_frame ] self.frames = [ { "frame": all_frame, "text": "All Apps" }, { "frame": games_frame, "text": "Games" }, { "frame": emus_frame, "text": "Emulators" }, { "frame": tools_frame, "text": "Homebrew" }, { "frame": media_frame, "text": "Media" }, { "frame": python_frame, "text": "Python" }, { "frame": cfw_frame, "text": "Custom Firmware" }, { "frame": installed_frame, "text": "Installed" }, # { # "frame" : presets_frame, # "text" : "Bundles (Beta)" # }, { "frame": injector_frame, "text": "RCM Injector" }, { "frame": help_frame, "text": "HELP" }, { "frame": about_frame, "text": "ABOUT" }, { "frame": readme_frame, "text": "README", }, { "frame": settings_frame, "text": "SETTINGS" }, { "frame": exit_frame, "text": "EXIT" } ] self.all_frames = [] self.content_frames = {} def make_frames_and_add_to_list(frame_list, listbox): for f in frame_list: page_name = f["text"] frame = f["frame"] self.content_frames[page_name] = frame frame.place(relx=0, rely=0, relwidth=1, relheight=1) listbox.insert("end", " {}".format(page_name)) self.all_frames.append(f) make_frames_and_add_to_list(self.frames, self.category_listbox) self.category_listbox.select_set( 0) #sets focus on the first item in listbox self.category_listbox.event_generate("<<ListboxSelect>>") self.show_frame("All Apps") if self.updater.status: print(self.updater.status) self.yesnoPage = yesnoPage(self) self.yesnoPage.getanswer( "An update is available, would you like to download it?\nPatch notes:\n{}" .format(self.updater.status), self.updater.update) self.loaded() self.add_on_refresh_callback(self.update_sd_path) self.add_on_tick_callback(self.update_sd_path) self.sort_check_loop() def show_frame(self, page_name): #Show a frame for the given page name frame = self.content_frames[page_name] frame.event_generate("<<ShowFrame>>") frame.tkraise() self.category_label.set(page_name) self.controller.after(100, self.update_search_bar_position) for frm in self.category_frames: frm.deselect() if frame in self.category_frames: frame.select() self.current_frame = frame self.current_frame_name = page_name def update_search_bar_position(self): if not self.current_frame in self.category_frames: self.content_frame_header_search_bar.place_forget() self.content_frame_header_sort_method_dropdown.place_forget() else: category_label_offset = self.category_label.winfo_width() #If the category label has been populated, otherwise the offset is usually just a few pixels (prevents an ugly draw on launch) if category_label_offset > style.offset: self.content_frame_header_sort_method_dropdown.place( relx=1, x=-(style.offset + style.sortdropdownwidth), width=style.sortdropdownwidth, y=+1.5 * style.offset, relheight=1, height=-2 * style.offset) self.content_frame_header_search_bar.place( x=+1.5 * style.offset + category_label_offset, y=+1.5 * style.offset, relheight=1, relwidth=1, width=-(category_label_offset + 3.5 * style.offset + style.sortdropdownwidth), height=-2 * style.offset) else: self.content_frame_header_search_bar.place_forget() self.controller.after(100, self.update_search_bar_position) def select_frame(self, event): try: widget = event.widget selection = widget.curselection() picked = widget.get(selection[0]) if not picked == self.last_selection: frame = None for f in self.all_frames: t = f["text"] if t.strip() == picked.strip(): self.show_frame(t) break self.last_selection = picked except Exception as e: # print(e) pass def search(self, searchterm): self.current_frame.search(searchterm) def reload_category_frames(self): print("Reloading frames") for frame in self.category_frames: frame.configure(None) def set_sd(self): chosensdpath = tkinter.filedialog.askdirectory( initialdir="/", title='Please select your SD card') self.appstore_handler.set_path(chosensdpath) self.reload_category_frames() self.update_sd_path() self.presets_frame.update_apply_frame() def update_sd_path(self): chosensdpath = self.appstore_handler.check_path() if chosensdpath: #Get the basename basepath = os.path.basename(os.path.normpath(chosensdpath)) #If we didn't find it, assume it's a root dir and just return the whole path if not basepath: basepath = chosensdpath else: basepath = "Not Set" self.column_sd_status_label.set("SD: {}".format(basepath)) self.presets_frame.update_sd_path() def update_sort(self): for frame in self.category_frames: frame.set_sort_type(SORT_MAP[self.selected_sort_method.get()]) self.current_frame.rebuild() #loop to check if the sorting methog has been applied yet def sort_check_loop(self): if not self.last_sort_option == self.selected_sort_method.get(): self.last_sort_option = self.selected_sort_method.get() self.update_sort() #schedule self self.schedule_callback(self.sort_check_loop, 100)
def build_listframe(self): columnwidth = 0.33 * (self.winfo_width() - style.updated_column_width) self.body_frame = tk.Frame(self, background=style.color_1) self.body_frame.place(relwidth=1, relheight=1) self.scrollbar = tk.Scrollbar(self.body_frame, troughcolor=style.color_1, bg=style.color_2) self.scrollbar.place(relheight=1, width=style.scrollbarwidth, relx=1, x=-style.scrollbarwidth, height=-(style.listbox_footer_height + style.listbox_footer_height), y=+style.listbox_footer_height) self.listbox_frame = tk.Frame(self.body_frame, background=style.color_2) self.listbox_frame.place(relwidth=1, relheight=1, height=-style.listbox_footer_height, width=-style.scrollbarwidth) self.scaling_listboxes_frame = tk.Frame(self.listbox_frame, background=style.color_2) self.scaling_listboxes_frame.place(relwidth=1, relheight=1, width=-style.updated_column_width) self.scaling_listboxes_frame_header = tk.Frame( self.scaling_listboxes_frame, background=style.color_2) self.scaling_listboxes_frame_header.place( relwidth=1, height=style.listbox_header_height) self.scaling_listboxes_frame_body = tk.Frame( self.scaling_listboxes_frame, background=style.color_2) self.scaling_listboxes_frame_body.place( relwidth=1, relheight=1, y=style.listbox_header_height, height=-style.listbox_header_height) self.package_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smallboldtext, borderwidth=1, foreground=style.w) self.package_listbox.place(relx=0, relwidth=0.33333, relheight=1) self.package_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Package", background=style.color_1, font=style.mediumboldtext) self.package_listbox_label.place(relx=0, relwidth=0.33333, relheight=1) self.title_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smalltext, borderwidth=1) self.title_listbox.place(relx=0.33333, relwidth=0.33333, relheight=1) self.title_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Title", background=style.color_1, font=style.mediumboldtext) self.title_listbox_label.place(relx=0.33333, relwidth=0.33333, relheight=1) self.author_listbox = ThemedListbox(self.scaling_listboxes_frame_body, background=style.color_2, font=style.smalltext, borderwidth=1) self.author_listbox.place(relx=0.66666, relwidth=0.33333, relheight=1) self.author_listbox_label = ThemedLabel( self.scaling_listboxes_frame_header, text="Author", background=style.color_1, font=style.mediumboldtext) self.author_listbox_label.place(relx=0.66666, relwidth=0.33333, relheight=1) self.updated_listbox = ThemedListbox(self.listbox_frame, background=style.color_2, font=style.smalltext, borderwidth=1) self.updated_listbox.place(relx=1, width=style.updated_column_width, x=-style.updated_column_width, relheight=1, y=style.listbox_header_height, height=-style.listbox_header_height) self.updated_listbox_label = ThemedLabel(self.listbox_frame, text="Updated", background=style.color_1, font=style.mediumboldtext) self.updated_listbox_label.place(relx=1, width=style.updated_column_width, x=-style.updated_column_width, height=style.listbox_header_height) self.listbox_list = [ self.package_listbox, self.title_listbox, self.author_listbox, self.updated_listbox ] self.listbox_frame_footer = tk.Frame(self, background=style.color_1) self.listbox_frame_footer.place(relwidth=1, rely=1, y=-style.listbox_footer_height, height=style.listbox_footer_height) self.installed_label = ThemedLabel(self.listbox_frame_footer, text="Installed - â—†", background=style.color_1, foreground="green", anchor="center") self.installed_label.place(relx=0, relwidth=0.333, relheight=1) self.hasupdate_label = ThemedLabel(self.listbox_frame_footer, text="Update Available - â—†", background=style.color_1, foreground="yellow", anchor="center") self.hasupdate_label.place(relx=0.333, relwidth=0.333, relheight=1) self.notinstalled_label = ThemedLabel(self.listbox_frame_footer, text="Not installed - â—†", background=style.color_1, foreground="white", anchor="center") self.notinstalled_label.place(relx=0.666, relwidth=0.333, relheight=1) self.package_listbox.configure({"selectbackground": style.lg}) self.package_listbox.configure({"selectmode": "single"}) self.package_listbox.bind("<<ListboxSelect>>", self.on_listbox_selection) self.scrollbar.config(command=self.on_scroll_bar) self.package_listbox.config(yscrollcommand=self.scrollbar.set) self.set_sort_type(None) self.rebuild()
def __init__(self, parent, controller): activeFrame.__init__(self, parent, controller) self.controller = controller self.appstore_handler = controller.appstore_handler self.repo_parser = controller.repo_parser self.selected_version = None self.version_index = None self.repo = None self.bind("<Configure>", self.on_configure) #------------------------------ self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=1, rely=0, width=style.sidecolumnwidth, relheight=1, x=-style.sidecolumnwidth) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place(relwidth=1, relheight=1) self.column_title = ThemedLabel(self.column_body, "", anchor="w", label_font=style.mediumboldtext, foreground=style.w, background=style.color_1) self.column_title.place(x=5, width=-5, rely=0, relwidth=1, height=style.detailspagemultiplier) #------------------------------ self.column_author = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_author.place(x=5, width=-5, y=style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_version = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_version.place(x=5, width=-5, y=1.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_license = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_license.place(x=5, width=-5, y=1.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ #------------------------------ self.column_package = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_package.place(x=5, width=-5, y=2.333 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_downloads = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_downloads.place(x=5, width=-5, y=2.666 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) self.column_updated = ThemedLabel(self.column_body, "", anchor="w", label_font=style.smalltext, foreground=style.w, background=style.color_1) self.column_updated.place(x=5, width=-5, y=3.00 * style.detailspagemultiplier, relwidth=1, height=0.333 * style.detailspagemultiplier) #------------------------------ self.releases_listbox = ScrolledThemedListBox(self.column_body) self.releases_listbox.configure(activestyle="none") self.releases_listbox.place( relwidth=1, y=3.66 * style.detailspagemultiplier, relheight=1, height=-(3.66 * style.detailspagemultiplier + 3 * (style.buttonsize + style.offset) + style.offset)) self.releases_listbox.bind('<<ListboxSelect>>', self.select_version) self.column_open_url_button = button( self.column_body, callback=self.trigger_open_tab, text_string="VISIT PAGE", font=style.mediumboldtext, background=style.color_2, ).place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-3 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_install_button = button(self.column_body, callback=self.trigger_install, text_string="INSTALL", font=style.mediumboldtext, background=style.color_2) self.column_install_button.place(rely=1, relx=0.5, x=-1.5 * (style.buttonsize), y=-2 * (style.buttonsize + style.offset), width=3 * style.buttonsize, height=style.buttonsize) self.column_uninstall_button = button(self.column_body, callback=self.trigger_uninstall, text_string="UNINSTALL", font=style.mediumboldtext, background=style.color_2) self.back_image = ImageTk.PhotoImage( Image.open(locations.backimage).resize( (style.buttonsize, style.buttonsize), Image.ANTIALIAS)) self.column_backbutton = button(self.column_body, image_object=self.back_image, callback=self.leave, background=style.color_1) self.column_backbutton.place(rely=1, relx=1, x=-(style.buttonsize + style.offset), y=-(style.buttonsize + style.offset)) # self.column_backbutton_ttp = tooltip(self.column_backbutton,"Back to list") self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place(x=0, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_header.place(x=style.offset, width=-2 * style.offset, rely=0, relwidth=1, height=style.detailspagemultiplier) self.content_frame_body = ThemedFrame(self.content_frame, background=style.color_2) self.content_frame_body.place(x=style.offset, width=-2 * style.offset, y=style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=1) self.content_banner_image_frame = ThemedFrame(self.content_frame, background=style.color_2) self.content_banner_image_frame.place( x=0, y=+style.detailspagemultiplier, relwidth=1, height=-style.detailspagemultiplier, relheight=0.4) self.content_banner_image = ThemedLabel( self.content_banner_image_frame, "", background=style.color_2, foreground=style.w, anchor="center", wraplength=None) self.content_banner_image.place(x=0, y=0, relwidth=1, relheight=1) self.content_frame_details = scrolledText(self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_details.place(rely=0.4, relx=0, relwidth=1, relheight=0.25, x=+style.offset, width=-2 * (style.offset), height=-style.offset) self.content_frame_patch_notes_label = ThemedLabel( self.content_frame_body, "Release notes:", anchor="w", label_font=style.mediumboldtext, foreground=style.b, background=style.color_2) self.content_frame_patch_notes_label.place( relx=0.5, width=self.content_frame_patch_notes_label.winfo_reqwidth(), rely=0.65, y=+style.offset, x=-0.5 * self.content_frame_patch_notes_label.winfo_reqwidth(), height=0.33 * style.detailspagemultiplier) self.content_frame_version_details = scrolledText( self.content_frame_body, wrap='word', font=style.smalltext, background=style.lg) self.content_frame_version_details.place( rely=0.65, y=+style.offset + 0.33 * style.detailspagemultiplier, relx=0, relwidth=1, relheight=0.35, height=-(2 * style.offset + 0.33 * style.detailspagemultiplier), x=+style.offset, width=-2 * (style.offset)) #Displays app name self.header_label = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.giantboldtext, background=style.color_2, foreground=style.b) self.header_label.place(rely=0, y=0, relheight=0.65) #Displays app name self.header_author = ThemedLabel(self.content_frame_header, "", anchor="w", label_font=style.smalltext, background=style.color_2, foreground=style.color_1) self.header_author.place(rely=0.65, y=0, relheight=0.35) self.progress_bar = progressFrame(self) self.yesnoPage = yesnoPage(self)
def __init__(self, parent, controller): self.controller = controller self.appstore_handler = store_handler self.repo_parser = repo_parser self.current_frame = None self.current_frame_name = None self.last_selection = None self.last_sort_option = None self.updater = updater activeFrame.__init__(self, parent, controller) self.column = ThemedFrame(self, background=style.color_1) self.column.place(relx=0, rely=0, width=style.sidecolumnwidth, relheight=1) self.column_header = ThemedFrame(self.column, background=style.color_1) self.column_header.place(relx=0, rely=0, relwidth=1, height=style.headerheight) self.column_header_title = ThemedLabel(self.column_header, "HBUpdater\nGPLv3", anchor="n", label_font=style.giantboldtext, background=style.color_1) self.column_header_title.place(relx=0, rely=0, relwidth=1, relheight=1, height=-(style.offset + 1), y=+style.offset) self.column_header_separator = ThemedLabel(self.column_header, "", background=style.w) self.column_header_separator.place(x=style.offset, rely=1, y=-1, relwidth=1, width=-2 * style.offset) self.column_body = ThemedFrame(self.column, background=style.color_1) self.column_body.place( relx=0, relwidth=1, y=style.headerheight, relheight=1, height=-(style.headerheight + style.footerheight)) self.category_listbox = ThemedListbox(self.column_body, foreground=style.w) self.category_listbox.configure(activestyle="none") self.category_listbox.place(relwidth=1, relheight=1) self.category_listbox.bind('<<ListboxSelect>>', self.select_frame) self.column_footer = ThemedFrame(self.column, background=style.color_1) self.column_footer.place(relx=0, rely=1, relwidth=1, height=style.footerheight, y=-style.footerheight) self.column_set_sd = button(self.column_footer, callback=self.set_sd, text_string="Select SD Root", font=style.mediumtext, background=style.color_2).place( relwidth=1, relheight=0.5, y=style.offset, x=style.offset, width=-2 * style.offset, height=-2 * style.offset) self.column_sd_status_label = ThemedLabel( self.column_footer, "SD: Not Set", anchor="w", label_font=style.giantboldtext, background=style.color_1, foreground=style.pathdisplaytextcolor) self.column_sd_status_label.place(x=style.offset, relheight=0.5, rely=0.5, height=-style.offset, relwidth=1, width=-2 * style.offset) self.content_frame = ThemedFrame(self) self.content_frame.place(x=style.sidecolumnwidth, width=-style.sidecolumnwidth, rely=0, relheight=1, relwidth=1) self.content_frame_header = ThemedFrame(self.content_frame) self.content_frame_header.place(relx=0, rely=0, relwidth=1, height=style.searchboxheight) self.category_label = ThemedLabel(self.content_frame_header, "", anchor="nw", label_font=style.giantboldtext, background=style.color_1, foreground=style.lg) self.category_label.place(x=+style.offset, relx=0, rely=0, relheight=1, height=-(style.offset + 1), y=+style.offset) self.content_frame_header_search_bar = searchBox( self.content_frame_header, command=self.search, entry_background=style.color_2, borderwidth=0, entry_foreground=style.w) self.selected_sort_method = tk.StringVar() self.selected_sort_method.set(SORT_OPTIONS[0]) self.content_frame_header_sort_method_dropdown = tk.OptionMenu( self.content_frame_header, self.selected_sort_method, *SORT_OPTIONS) self.content_frame_header_sort_method_dropdown.configure( foreground=style.w) self.content_frame_header_sort_method_dropdown.configure( background=style.color_2) self.content_frame_header_sort_method_dropdown.configure( highlightthickness=0) self.content_frame_header_sort_method_dropdown.configure(borderwidth=0) #The various content gets stacked on top of each other here. self.content_stacking_frame = ThemedFrame(self.content_frame) self.content_stacking_frame.place( relx=0, y=(style.searchboxheight + style.offset), relwidth=1, relheight=1, height=-(style.searchboxheight + style.offset)) all_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.all) media_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.media) emus_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.emulators) games_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.games) tools_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.homebrew) python_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.nxpythonlist) cfw_frame = categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.customfirmwarelist) installed_frame = installed_categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.all) self.presets_frame = presets_frame = presetsPage( self.content_stacking_frame, self.controller) injector_frame = injector_categoryFrame(self.content_stacking_frame, self.controller, self, self.repo_parser.payloadlist) help_frame = helpFrame(self.content_stacking_frame) about_frame = aboutFrame(self.content_stacking_frame) readme_frame = readmeFrame(self.content_stacking_frame) settings_frame = settingsPage(self.content_stacking_frame, self.controller) exit_frame = exitPage(self.content_stacking_frame, self.controller) self.category_frames = [ all_frame, media_frame, emus_frame, games_frame, tools_frame, python_frame, cfw_frame, installed_frame, injector_frame ] self.frames = [ { "frame": all_frame, "text": "All Apps" }, { "frame": games_frame, "text": "Games" }, { "frame": emus_frame, "text": "Emulators" }, { "frame": tools_frame, "text": "Homebrew" }, { "frame": media_frame, "text": "Media" }, { "frame": python_frame, "text": "Python" }, { "frame": cfw_frame, "text": "Custom Firmware" }, { "frame": installed_frame, "text": "Installed" }, # { # "frame" : presets_frame, # "text" : "Bundles (Beta)" # }, { "frame": injector_frame, "text": "RCM Injector" }, { "frame": help_frame, "text": "HELP" }, { "frame": about_frame, "text": "ABOUT" }, { "frame": readme_frame, "text": "README", }, { "frame": settings_frame, "text": "SETTINGS" }, { "frame": exit_frame, "text": "EXIT" } ] self.all_frames = [] self.content_frames = {} def make_frames_and_add_to_list(frame_list, listbox): for f in frame_list: page_name = f["text"] frame = f["frame"] self.content_frames[page_name] = frame frame.place(relx=0, rely=0, relwidth=1, relheight=1) listbox.insert("end", " {}".format(page_name)) self.all_frames.append(f) make_frames_and_add_to_list(self.frames, self.category_listbox) self.category_listbox.select_set( 0) #sets focus on the first item in listbox self.category_listbox.event_generate("<<ListboxSelect>>") self.show_frame("All Apps") if self.updater.status: print(self.updater.status) self.yesnoPage = yesnoPage(self) self.yesnoPage.getanswer( "An update is available, would you like to download it?\nPatch notes:\n{}" .format(self.updater.status), self.updater.update) self.loaded() self.add_on_refresh_callback(self.update_sd_path) self.add_on_tick_callback(self.update_sd_path) self.sort_check_loop()
class presetsPage(ThemedFrame): def __init__(self, parent, controller): self.controller = controller self.appstore_handler = store_handler self.repo_parser = repo_parser self.current_file_path = None self.originaljson = None self.currentjson = None self.ok_to_load = True self.json_name = None self.changes = None self.progress_string = None self.gui_title = None self.errors = [] ThemedFrame.__init__(self, parent, background=style.color_2) self.bind("<<ShowFrame>>", self.update_apply_frame) #LEFT COLUMN________________________________ self.presets_listbox_label = ThemedLabel( self, label_text="Bundles:", background=style.color_2, foreground=style.lg, label_font=style.largeboldtext) self.presets_listbox_label.place(relx=0.0, relwidth=0.5, height=style.buttonsize - 2 * style.offset, x=+style.offset, width=-2 * style.offset) image_file = os.path.join(assetsfolder, "trash.png") button_image = Image.open(image_file) buttonsize = style.buttonsize - 4 * style.offset #Resizes and saves image if it's the wrong size for faster loads in the future if not button_image.size[0] == [buttonsize, buttonsize]: button_image = button_image.resize((buttonsize, buttonsize), Image.ANTIALIAS) self.trash_image = ImageTk.PhotoImage(button_image) self.delete_preset_button = button(self, callback=self.delete, image_object=self.trash_image, background=style.color_1) self.delete_preset_button.place( relx=0.5, x=-(style.buttonsize - 2 * style.offset), y=+style.offset, width=style.buttonsize - 3 * style.offset, height=style.buttonsize - 3 * style.offset) self.presets_listbox = scrollingTkListbox(self, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False) self.presets_listbox.place( relx=0.0, relwidth=0.5, relheight=1, y=style.buttonsize - style.offset, x=+style.offset, width=-2 * style.offset, height=-(2.5 * style.buttonsize + 2 * style.offset)) self.new_preset_entry = entrybox( self, placeholder="New bundle name (No extension)", callback=self.update_json) self.new_preset_entry.place( relx=0.0, x=+style.offset, relwidth=0.5, height=0.5 * style.buttonsize, rely=1, y=-(2 * style.offset + 1.5 * style.buttonsize), width=-(3 * style.offset + 0.5 * style.buttonsize)) self.new_preset_button = button(self, callback=self.new, text_string="+", background=style.color_1) self.new_preset_button.place( relx=0.5, x=-(style.offset + 0.5 * style.buttonsize), width=0.5 * style.buttonsize, height=0.5 * style.buttonsize, rely=1, y=-(2 * style.offset + 1.5 * style.buttonsize)) self.loadbutton = button(self, callback=self.load, text_string="Load", background=style.color_1) self.loadbutton.place(relx=0.0, x=+style.offset, relwidth=0.5, height=style.buttonsize, rely=1, y=-(style.offset + style.buttonsize), width=-2 * style.offset) self.divider = ThemedFrame(self, background=style.lg) self.divider.place(relx=0.5, width=2, relheight=1, height=-2 * style.offset, y=+style.offset, x=-1) self.column_select_frame = ThemedFrame(self, background=style.color_2) self.column_select_frame.place(relx=0.5, x=+style.offset, width=-2 * style.offset, relwidth=0.5, height=style.buttonsize, y=+style.offset) self.editor_button = button(self.column_select_frame, callback=lambda: self.show_frame("editor"), text_string="Edit", background=style.color_1, borderwidth=1) self.editor_button.place(relheight=1, relwidth=0.33, relx=0, width=-0.5 * style.offset) self.applier_button = button( self.column_select_frame, callback=lambda: self.show_frame("applier"), text_string="Apply", background=style.color_1, borderwidth=1) self.applier_button.place(relheight=1, relwidth=0.34, relx=0.33, x=+0.5 * style.offset, width=-style.offset) self.build_button = button(self.column_select_frame, callback=lambda: self.show_frame("builder"), text_string="Build", background=style.color_1, borderwidth=1) self.build_button.place(relheight=1, relwidth=0.33, relx=0.67, x=+0.5 * style.offset, width=-0.5 * style.offset) self.buttonmap = { "editor": self.editor_button, "applier": self.applier_button, "builder": self.build_button } self.button_divider = ThemedFrame(self, background=style.lg) self.button_divider.place(relx=0.5, x=+style.offset, width=-2 * style.offset, relwidth=0.5, height=1, y=style.buttonsize + 2 * style.offset) self.content_frame = ThemedFrame(self, background=style.color_2) self.content_frame.place( relx=0.5, relwidth=0.5, width=-2 * style.offset, x=+style.offset, relheight=1, y=style.buttonsize + 3 * style.offset + 1, height=-(style.buttonsize + 4 * style.offset + 1)) #EDITOR COLUMN________________________________ self.editor_frame = ThemedFrame(self.content_frame, background=style.color_2) self.preset_name = entrybox(self.editor_frame, placeholder="Bundle Name", callback=self.update_json) self.preset_name.place(height=0.5 * style.buttonsize, relwidth=1) self.author_name = entrybox(self.editor_frame, placeholder="Bundle Author", callback=self.update_json) self.author_name.place(y=1 * (style.offset + 0.5 * style.buttonsize), height=0.5 * style.buttonsize, relwidth=1) self.preset_package_version = entrybox( self.editor_frame, placeholder="Bundle Package Version", callback=self.update_json) self.preset_package_version.place( y=2 * (style.offset + 0.5 * style.buttonsize), height=0.5 * style.buttonsize, relwidth=1) self.packages_listbox_and_json_output_preview_frame = ThemedFrame( self.editor_frame, background=style.color_2) self.packages_listbox_and_json_output_preview_frame.place( y=3 * (style.offset + 0.5 * style.buttonsize), relheight=1, height=-(2 * style.buttonsize + 7 * style.offset), relwidth=1) self.packages_listbox_label = ThemedLabel( self.packages_listbox_and_json_output_preview_frame, label_text="Packages:", background=style.color_2, foreground=style.lg, label_font=style.mediumboldtext) self.packages_listbox_label.place(relwidth=1, height=style.buttonsize - 2 * style.offset) self.packages_listbox = scrollingTkListbox( self.packages_listbox_and_json_output_preview_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.packages_listbox.place( y=style.buttonsize - 2 * style.offset, relwidth=1, relheight=0.5, height=-(style.offset + style.buttonsize - 2 * style.offset)) self.packages_listbox.bind('<<ListboxSelect>>', self.update_json) self.output_divider = ThemedFrame( self.packages_listbox_and_json_output_preview_frame, background=style.lg) self.output_divider.place(relwidth=1, height=1, rely=0.5) self.output_json_label = ThemedLabel( self.packages_listbox_and_json_output_preview_frame, label_text="Output:", background=style.color_2, foreground=style.lg, label_font=style.mediumboldtext) self.output_json_label.place(rely=0.5, y=+style.offset + 1, relwidth=1, height=style.buttonsize - 2 * style.offset) self.output_json = themedScrollingText( self.packages_listbox_and_json_output_preview_frame, font=style.smalltext) self.output_json.place(relwidth=1, rely=0.5, relheight=0.5, height=-(style.buttonsize + style.offset), y=style.buttonsize) self.savebutton = button(self.editor_frame, callback=self.save, text_string="Save", background=style.color_1) self.savebutton.place(relwidth=1, height=style.buttonsize, rely=1, y=-(style.buttonsize)) #APPLIER COLUMN_______________________________ self.applier_frame = ThemedFrame(self.content_frame, background=style.color_2) self.applier_bundle_label = ThemedLabel(self.applier_frame, label_text="BUNDLE: ", anchor="w", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_bundle_label.place(height=0.5 * style.buttonsize - style.offset) self.applier_selected_bundle_label = ThemedLabel( self.applier_frame, label_text="test", anchor="e", background=style.color_2, foreground=style.w, label_font=style.smallboldtext) self.applier_selected_bundle_label.place( x=self.applier_bundle_label.winfo_reqwidth(), height=0.5 * style.buttonsize - 1 * style.offset) self.applier_sd_label = ThemedLabel(self.applier_frame, label_text="SD: ", anchor="w", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_sd_label.place(y=0.5 * style.buttonsize, height=0.5 * style.buttonsize - 1 * style.offset) self.applier_selected_sd_label = ThemedLabel( self.applier_frame, label_text="test", anchor="e", background=style.color_2, foreground=style.w, label_font=style.smallboldtext) self.applier_selected_sd_label.place( y=0.5 * style.buttonsize, x=self.applier_sd_label.winfo_reqwidth(), height=0.5 * style.buttonsize - 1 * style.offset) self.applier_header_divider = ThemedFrame(self.applier_frame, background=style.lg) self.applier_header_divider.place(y=1 * style.buttonsize, relwidth=1, height=1) self.applier_listboxes_frame = ThemedFrame(self.applier_frame, background=style.color_2) self.applier_listboxes_frame.place( y=1 * style.buttonsize + 1 * style.offset + 1, relheight=1, height=-(2 * style.buttonsize + 1 + style.offset), relwidth=1) self.applier_to_be_installed_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_installed_frame.place(relwidth=1, relheight=0.33, height=-style.offset) self.applier_to_be_installed_label = ThemedLabel( self.applier_to_be_installed_frame, label_text="To be installed:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_installed_label.place( relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_installed_listbox = scrollingTkListbox( self.applier_to_be_installed_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_installed_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_to_be_updated_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_updated_frame.place(relwidth=1, relheight=0.34, rely=0.33, height=-style.offset) self.applier_to_be_updated_label = ThemedLabel( self.applier_to_be_updated_frame, label_text="To be updated:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_updated_label.place(relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_updated_listbox = scrollingTkListbox( self.applier_to_be_updated_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_updated_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_to_be_unchanged_frame = ThemedFrame( self.applier_listboxes_frame, background=style.color_2) self.applier_to_be_unchanged_frame.place(relwidth=1, relheight=0.33, rely=0.67, height=-style.offset) self.applier_to_be_unchanged_label = ThemedLabel( self.applier_to_be_unchanged_frame, label_text="Unchanged:", background=style.color_2, foreground=style.lg, label_font=style.smallboldtext) self.applier_to_be_unchanged_label.place( relwidth=1, height=0.5 * style.buttonsize - style.offset) self.applier_to_be_unchanged_listbox = scrollingTkListbox( self.applier_to_be_unchanged_frame, borderwidth=0, highlightthickness=0, background=style.w, foreground=style.b, exportselection=False, selectmode='multiple') self.applier_to_be_unchanged_listbox.place( y=0.5 * style.buttonsize - 1 * style.offset, relwidth=1, relheight=1, height=-(0.5 * style.buttonsize - 3 * style.offset)) # self.applier_to_be_installed_listbox.bind('<<ListboxSelect>>', self.update_json) self.applier_apply_button = button(self.applier_frame, callback=self.apply, text_string="Apply", background=style.color_1) self.applier_apply_button.place(relwidth=1, height=style.buttonsize, rely=1, y=-(style.buttonsize)) #BUILDER COLUMN_______________________________ self.builder_frame = ThemedFrame(self.content_frame, background=style.color_2) for package in self.repo_parser.all: self.packages_listbox.insert("end", package["package"]) self.frames = [{ "frame": self.editor_frame, "text": "editor", }, { "frame": self.applier_frame, "text": "applier" }, { "frame": self.builder_frame, "text": "builder" }] self.content_frames = {} def make_frames_and_add(frame_list): for f in frame_list: page_name = f["text"] frame = f["frame"] self.content_frames[page_name] = frame frame.place(relx=0, rely=0, relwidth=1, relheight=1) make_frames_and_add(self.frames) self.show_frame("editor") self.yesno = yesnoPage(self) self.usermessage = usermessagePage(self) self.progress_bar = progressFrame(self) self.update_json() self.reload_presets() self.update_sd_path() def show_frame(self, page_name): #Show a frame for the given page name frame = self.content_frames[page_name] frame.event_generate("<<ShowFrame>>") frame.tkraise() for button in self.buttonmap.keys(): self.buttonmap[button].configure(background=style.color_1) self.buttonmap[page_name].select() def reload_presets(self): self.presets_listbox.delete(0, "end") files = [] for file in os.listdir(presetsfolder): if file.endswith(".json"): files.append(file) for file in files: self.presets_listbox.insert("end", file) #preset is the path to a json def load(self): #If new json is empty and hasn't been edited. if self.update_json() == self.currentjson or self.currentjson == None: self.ok_to_load = True if not self.ok_to_load: self.yesno.getanswer( "You have unsaved changes, would you like to discard them and load a new preset?", self.do_load) else: self.do_load() self.ok_to_load = False def do_load(self, json_name=None): if json_name: self.json_name = json_name else: self.json_name = self.presets_listbox.get("active") preset = os.path.join(presetsfolder, self.json_name) self.current_file_path = preset self.packages_listbox.selection_clear(0, "end") try: with open(preset) as preset_file: preset_object = json.load(preset_file) self.originaljson = preset_object except: #Inform user via gui print("Error loading preset json ") # try: self.currentjson = json.dumps(preset_object, indent=4) self.author_name.set_text(preset_object.get("author")) self.preset_name.set_text(preset_object.get("title")) self.preset_package_version.set_text(preset_object.get("version")) for package in preset_object.get("packages"): self.packages_listbox.selection_set( self.packages_listbox.get(0, "end").index(package)) self.applier_selected_bundle_label.set(preset_object.get("title")) # except Exception as e: # print("Error setting entry fields - {}".format(e)) self.update_json() self.update_apply_frame() def save(self): if self.current_file_path: print("Saving preset - {}".format(self.current_file_path)) output = self.update_json() with open(self.current_file_path, "w+") as preset_file: preset_file.writelines(output) self.do_load() else: print("Select a file first") #Gets the page ready to make a new repo def new(self): new_file_name = self.new_preset_entry.get_text() self.json_name = new_file_name.strip() + ".json" if self.json_name: self.clear() self.current_file_path = os.path.join(presetsfolder, self.json_name) new_json = { "title": new_file_name.strip(), "author": "", "version": "", "packages": [] } output = json.dumps(new_json, indent=4) with open(self.current_file_path, "w+") as preset_file: preset_file.writelines(output) self.reload_presets() self.do_load(self.json_name) def clear(self): self.author_name.set_text("") self.preset_name.set_text("") self.preset_package_version.set_text("") self.packages_listbox.selection_clear(0, "end") self.new_preset_entry.set_text("") def update_json(self, event=None): j = {} j["title"] = self.preset_name.get_text() j["author"] = self.author_name.get_text() j["version"] = self.preset_package_version.get_text() selected = self.packages_listbox.curselection() j["packages"] = [ self.packages_listbox.get(selection) for selection in selected if selected ] j_text = json.dumps(j, indent=4) self.output_json.set(j_text) return j_text def delete(self): self.yesno.getanswer( "Delete preset - {}?".format(self.presets_listbox.get("active")), self.do_delete) def do_delete(self): try: os.remove( os.path.join(presetsfolder, self.presets_listbox.get("active"))) except Exception as e: print("Failed to delete preset - {}\n ~ {}".format( self.presets_listbox.get("active"), e)) self.clear() self.reload_presets() self.current_file_path = None self.currentjson = None self.json_name = None self.update_json() def apply(self): if not self.appstore_handler.check_path(): self.set_sd() if self.appstore_handler.check_path(): self.yesno.getanswer(warning_label, self.do_apply, follow_up=True) def do_apply(self): selected_to_be_installed = self.applier_to_be_installed_listbox.curselection( ) to_be_installed = [ self.applier_to_be_installed_listbox.get(selection) for selection in selected_to_be_installed if selected_to_be_installed ] selected_to_be_updated = self.applier_to_be_updated_listbox.curselection( ) to_be_updated = [ self.applier_to_be_updated_listbox.get(selection) for selection in selected_to_be_updated if selected_to_be_updated ] to_be_unchanged = self.applier_to_be_unchanged_listbox.get(0, "end") outstring = "" outstring += "Applying bundle {}\n".format(self.originaljson["title"]) changes = [] if to_be_installed: for package in to_be_installed: changes.append(package) outstring += "The following packages will be INSTALLED: {}\n".format( json.dumps(to_be_installed, indent=4)) if to_be_updated: for package in to_be_updated: changes.append(package) outstring += "The following packages will be UPDATED: {}\n".format( json.dumps(to_be_updated, indent=4)) if to_be_unchanged: outstring += "The following packages will remain UNCHANGED: {}\n".format( json.dumps(to_be_unchanged, indent=4)) outstring += "Please confirm." if not changes: self.yesno.getanswer( "No packages will be changed, please select packages you would like to add.", self.yesno.hide()) else: self.changes = changes self.yesno.getanswer(outstring, lambda: self.do_do_apply(self.changes), follow_up=True) def do_do_apply(self, package_list): print("Applying bundle") packages = [ self.repo_parser.get_package(package) for package in package_list ] for package in package_list: threader.do_unique(self.appstore_handler.install_package_list, [ packages, 0, self.progress_function, self.reset_title, self.title_function, False, self.error_function, self.complete_function ]) self.controller.frames["appstorePage"].reload_category_frames() def title_function(self, string): self.gui_title = string self.update_title() def progress_function(self, string, percent_complete): self.progress_string = "{} ~ {}%".format(string, percent_complete) self.update_title() def update_title(self): if self.gui_title and self.progress_string: self.controller.wm_title("{}: {}".format(self.gui_title, self.progress_string)) else: self.reset_title() def error_function(self, erring_repo): self.errors.append(erring_repo) def clear_title(self): self.reset_title() self.progress_string = None self.gui_title = None def complete_function(self): self.usermessage.telluser( "The following packages errored during install: {}".format( self.errors)) self.errors = [] def reset_title(self): self.controller.wm_title(self.controller.version) def check_if_installer_running(self): if not threader.is_unique_running(): self.reset_title() def set_sd(self): chosensdpath = tkinter.filedialog.askdirectory( initialdir="/", title='Please select your SD card') self.appstore_handler.set_path(chosensdpath) self.update_sd_path() self.update_apply_frame() def update_sd_path(self): chosensdpath = self.appstore_handler.check_path() if chosensdpath: #Get the basename basepath = os.path.basename(os.path.normpath(chosensdpath)) #If we didn't find it, assume it's a root dir and just return the whole path if not basepath: basepath = chosensdpath else: basepath = "Not Set" self.applier_selected_sd_label.set(basepath) def update_apply_frame(self, event=None): if self.appstore_handler.check_path(): packages = self.appstore_handler.get_packages(silent=True) if packages: to_be_installed = [] to_be_updated = [] unchanged = [] if self.originaljson: for package in self.originaljson["packages"]: installed_version = self.appstore_handler.get_package_version( package) if not installed_version or installed_version == "not installed": to_be_installed.append(package) continue latest_version = self.appstore_handler.clean_version( self.repo_parser.get_latest_version(package), package) if not self.appstore_handler.clean_version( installed_version, package) == latest_version: to_be_updated.append(package) continue else: unchanged.append(package) self.clear_apply_listboxes() if to_be_installed: for package in to_be_installed: self.applier_to_be_installed_listbox.insert( "end", package) if to_be_updated: for package in to_be_updated: self.applier_to_be_updated_listbox.insert( "end", package) if unchanged: self.applier_to_be_unchanged_listbox.config( state="normal") for package in unchanged: self.applier_to_be_unchanged_listbox.insert( "end", package) self.applier_to_be_unchanged_listbox.config( state="disable") self.applier_to_be_installed_listbox.selection_set( 0, "end") self.applier_to_be_updated_listbox.selection_set(0, "end") def clear_apply_listboxes(self): for listbox in (self.applier_to_be_installed_listbox, self.applier_to_be_updated_listbox, self.applier_to_be_unchanged_listbox): listbox.config(state="normal") listbox.delete(0, "end") self.applier_to_be_unchanged_listbox.config(state="disabled")