def checkifhelperdownloaded(helper): if guicore.checkguisetting( helper, "version") == "not installed" or guicore.checkguisetting( helper, "version") == None: return False else: print(guicore.checkguisetting(helper, "version")) return True return False
def injectpayload(self, payload): if not os.path.isdir(locations.injectorfolder): print("initializing folder {}".format(locations.injectorfolder)) os.mkdir(locations.injectorfolder) fuseestatus = guicore.checkguisetting("fusee-launcher", "version") if fuseestatus == "not installed" or fuseestatus == "none" or fuseestatus == None: with open(self.pjlist[0]["githubjson"] ) as json_file: #jsonfile is path, json_file is file obj jfile = json.load(json_file) downloadurl = jfile[0]["zipball_url"] file = webhandler.download(downloadurl) file = os.path.join(locations.downloadsfolder, file) version = jfile[0]["tag_name"] with ZipFile(file, 'r') as zipObj: zipObj.extractall(locations.injectorfolder) self.printtoboth( "Sucessfully extracted {} to payloads folder".format(file)) files = zipObj.namelist() injector = None for possiblepayloadfile in files: if possiblepayloadfile.startswith(files[0] + "fusee"): injector = possiblepayloadfile if injector == None: self.printtoboth( "Could not find injector in extracted files") return newentry = { "fusee-launcher": { "version": version, "location": injector, } } guicore.setguisetting(newentry) script_file = guicore.checkguisetting("fusee-launcher", "location") script_file = os.path.join(locations.injectorfolder, script_file) if payload: p = subprocess.Popen( [sys.executable, '-u', script_file, payload], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, ) with p.stdout: for line in iter(p.stdout.readline, b''): self.printtoboth(line) p.wait() else: print("failed to find payload")
def updateAuthorImage(self): if not self.noimage: if guicore.checkguisetting("guisettings", "display_author_image"): sel = self.softwarelist[self.currentselection] #Variable to track if we have found the author image yet photopath = None notfound = os.path.join(guicore.assetfolder, notfoundimage) #Check if we have already set the photopath, if so return the file if not sel["photopath"] == None: photopath = sel["photopath"] try: self.infobox.updateimage(image_path=photopath) except Exception as e: #if encountered an error with given photo path (wrong type, corrupt etc) if type(e) == 'TclError': self.infobox.updateimage(image_path=notfound) sel["photopath"] = notfound return #If gotten this far, check and see if we have already downloaded an image for this author authorname = sel["author"] #If authorname isn't none if authorname: photopath = self.checkphoto(locations.imagecachefolder, authorname) if photopath: if sel["photopath"] == None: sel["photopath"] = photopath self.infobox.updateimage(image_path=photopath) return #If it wasn't already set, AND it hasn't been downloaded yet #Try getting it from the associated json try: with open( sel["githubjson"], encoding="utf-8" ) as json_file: #jsonfile is path, json_file is file obj jfile = json.load(json_file) url = jfile[0]["author"]["avatar_url"] if url: photopath = webhandler.cacheimage(url, authorname) sel["photopath"] = photopath except: #If that failed, take a stab in the dark with their github avatar image, this is useful for data sets without github jsons photopath = webhandler.guessgithubavatar(authorname) if photopath: sel["photopath"] = photopath #If the photopath is still none, use the not-found image if not photopath: photopath = notfound if sel["photopath"] == None: sel["photopath"] = photopath self.infobox.updateimage(image_path=photopath)
def CheckForUpdates(): if guicore.checkguisetting("guisettings", "check_for_app_updates"): try: updatefile = webhandler.getJson("HBUpdater", locations.updateapi) if not updatefile: print( "Failed to download HBU update file. A new version may be avaialable." ) return else: with open( updatefile, encoding="utf-8" ) as json_file: #jsonfile is path, json_file is file obj jfile = json.load(json_file) newestversion = jfile[0]["tag_name"] description = jfile[0]["body"] if float(stripversion(newestversion)) > float( stripversion(version)): # print("A new update to HBUpdater is avaialable, go to https://www.github.com/LyfeOnEdge/HBUpdater/releases to download it.") return newestversion, description else: print("HBUpdater is up to date") except Exception as e: print("checkforupdateserror - {}".format(e)) else: "update checking disabled" return None, None
def __init__(self, parent, controller, page_name, back_command): pt.page.__init__(self, parent=parent, controller=controller, back_command=back_command, primary_button_command=self.injectpayload, primary_button_text="INJECT", secondary_button_command=lambda: self. getordownloadpayload(force_update=True), secondary_button_text="DOWNLOAD", version_function=self.checkpayloadversion, status_column="DOWNLOADED", page_title="PAYLOAD INJECTOR", page_name=page_name) self.ijlist = self.populatesoftwarelist(locations.payloadlist) self.setlist(self.ijlist) self.pjlist = self.populatesoftwarelist(locations.payloadinjector) buttonlist = [{ "image": self.returnimage, "callback": back_command, "tooltip": "Back to home screen", }] self.setbuttons(buttonlist) #hide the uninstall button and move in project page button to fill self.uninstall_button.place_forget() self.project_page_button.place_forget() #Re-place the table to make room for the console self.maintable.place(relx=0, rely=0, relheight=0.7, relwidth=1) self.console = cw.consolebox(self.content_frame) self.console.place(relx=0, rely=.7, relwidth=1, relheight=.3) self.printtoconsolebox( "Connect switch, select payload, and press inject.\nThe payload and injector will be downloaded from github if they haven't been already.\n" ) self.printtoconsolebox( "Injector backend: fusee-launcher, written by ktempkin\n") #Check if fusee launcher is download, display status for user fuseestatus = guicore.checkguisetting("fusee-launcher", "version") notinstalled = [None, "not installed"] if fuseestatus in notinstalled: fuseestatus = "needs downloaded" else: fuseestatus = "downloaded" self.printtoconsolebox("Injector status: {}\n".format(fuseestatus)) self.updatetable(None) self.setguidetext(details_guide_text)
def checkpayloadversion(self, chunk): softwarename = chunk["software"] version = guicore.checkguisetting(softwarename, "version") if version == None or version == "not installed": return ("needs download") else: version = appstore.parse_version_to_store_equivalent( version, softwarename) return version return version
def starthelper(helper): if not checkifhelperdownloaded(helper): nutnotdownloadedwarningframe.tkraise() print("not installed") return script_file = guicore.checkguisetting(helper, "location") # script_path = os.path.dirname(os.path.realpath(script_file)) print("starting {} server at {}".format(helper, script_file)) if script_file == None: print("invalid path") return #Starts the script in the config folder so config files aren't lost when the helpers get updated subprocess.Popen([sys.executable, script_file], cwd=locations.configfolder)
def on_show_frame(self, event): self.currentselection = guicore.checkguisetting( "last_payload", "selection") #Update with user repos if self.softwaregroup: self.softwarelist = self.basesoftwarelist[:] user_repos = self.controller.user_repos user_repos = guicore.getreposbygroupfromlist( self.softwaregroup, user_repos) #Add repos if they are found if user_repos: self.softwarelist.extend(user_repos) self.refreshwindow() self.updateinfobox()
def populatesoftwarelist(self, list): if guicore.checkguisetting("guisettings", "automatically_check_for_repo_updates"): populatedlist = webhandler.getUpdatedSoftwareLinks( list) #use this to download new json (required to get updates) else: populatedlist = webhandler.getJsonSoftwareLinks( list) #use this to use only pre-downloaded json files for softwarechunk in populatedlist: softwarechunk["photopath"] = None try: se = softwarechunk["store_equivalent"] if not se: softwarechunk["store_equivalent"] = softwarechunk[ "software"] except: softwarechunk["store_equivalent"] = softwarechunk["software"] return (populatedlist)
def getordownloadpayload(self, force_update=False): if not os.path.isdir(locations.payloadsfolder): os.mkdir(locations.payloadsfolder) #Get the current software chunk sc = self.softwarelist[self.currentselection] softwarename = sc["software"] #Check if payload already download, if not set it to download status = guicore.checkguisetting(softwarename, "version") if status == None or status == "not installed": pass #If it's already downloaded, get it, unless force_update is set else: if not force_update: payload = guicore.checkguisetting(softwarename, "location") return payload softwarename = sc["software"] try: with open(sc["githubjson"] ) as json_file: #jsonfile is path, json_file is file obj jfile = json.load(json_file) version = jfile[self.currenttagselection]["tag_name"] except: self.printtoboth( "Failed to find repo json file, can't download payload.") return assets = jfile[self.currenttagselection]["assets"] #Find the correct asset using HBUpdater core method for finding assets downloadurl = HBUpdater.findasset(sc["pattern"], assets) self.printtoboth("downloading payload from {}".format(downloadurl)) #file yielded by the download file = webhandler.download(downloadurl) file = os.path.join(locations.downloadsfolder, file) #get absolute path to it #if downloaded file is already .bin, set the payload path to it. if file.endswith(".bin"): payload = file elif file.endswith(".zip"): #if file is zip, unzip it and find the payload based on the pattern set in its entry in #locations with ZipFile(file, 'r') as zipObj: zipObj.extractall(locations.payloadsfolder) self.printtoboth( "Sucessfully extracted {} to payloads folder\n\n".format( file)) files = zipObj.namelist() payload = None pattern = sc["zip_items"] for possiblepayloadfile in files: for fp in pattern[0]: if fp.lower() in possiblepayloadfile.lower(): if possiblepayloadfile.endswith( pattern[1].lower()): payload = possiblepayloadfile break if payload == None: self.printtoboth( "Could not find payload in extracted files") return payload = os.path.join(locations.payloadsfolder, payload) else: self.printtoboth("file handling method not found") return #prep new entry to the gui log newentry = { softwarename: { "version": version, "location": payload, } } guicore.setguisetting(newentry) self.updatetable(None) return payload
def __init__(self, parent, controller,page_name,back_command): self.back_command = back_command self.controller = controller width = guicore.checkguisetting("dimensions","guiwidth") height = guicore.checkguisetting("dimensions","guiheight") cw.ThemedFrame.__init__(self,parent,background_color= style.about_page_background_color) self.outer_frame = cw.ThemedFrame(self,background_color=style.about_page_background_color) self.outer_frame.place(relx=0.5,rely=0.5,x=-(width/2),y=-(height/2),width=width,height=height) #Credits and stuff self.devlabel = cw.ThemedLabel(self.outer_frame, "DEVELOPERS", label_font = columnlabelfont, background = style.about_page_background_color, foreground = columnlabelcolor, anchor="center") self.devlabel.place(y=+separatorwidth,x=(2*separatorwidth+0.5*navbuttonheight),relwidth=1,width=-2*(2*separatorwidth+0.5*navbuttonheight)) self.devframe = cw.ThemedFrame(self.outer_frame, background_color=style.about_page_background_color) self.devframe.place(y=+4*separatorwidth+0.5*navbuttonheight,x=separatorwidth,relwidth=1,width=-2*separatorwidth,height=3*navbuttonheight) self.lyfeframe = cw.ThemedFrame(self.devframe, background_color=style.about_page_background_color) self.lyfeframe.place(relx=0,rely=0,relwidth=0.5,relheight=1) self.mintframe = cw.ThemedFrame(self.devframe, background_color=style.about_page_background_color) self.mintframe.place(relx=0.5,rely=0,relwidth=0.5,relheight=1) try: lyfeimage = webhandler.getcachedimage("lyfeonedge") or webhandler.grabgravatar("lyfeonedge") or os.path.join(guicore.assetfolder,notfoundimage) except: lyfeimage = os.path.join(guicore.assetfolder,notfoundimage) #I get an object named after me :D self.lyfeonedgeimage = tk.PhotoImage(file=lyfeimage) self.lyfeonedge = cw.devbox(self.lyfeframe,"LyfeOnEdge",developers["LyfeOnEdge"]["dev_flavor_text"],self.lyfeonedgeimage,command_name=lambda: webhandler.opentab(developers["LyfeOnEdge"]["project_page_url"]),background=dark_color) self.lyfeonedge.place(relx=0.125, relheight=1,relwidth=0.875) try: pprmntimage = webhandler.getcachedimage("npprmint") or webhandler.grabgravatar("npprmint") or os.path.join(guicore.assetfolder,notfoundimage) except: pprmntimage = os.path.join(guicore.assetfolder,notfoundimage) self.pprmintimage = tk.PhotoImage(file=pprmntimage) self.pprmint = cw.devbox(self.mintframe,"pprmint",developers["pprmint"]["dev_flavor_text"],self.pprmintimage,command_name=lambda: webhandler.opentab(developers["pprmint"]["project_page_url"]),background=dark_color) self.pprmint.place(relx=0.125, relheight=1,relwidth=0.875) self.creditsseparator = cw.Separator(self.outer_frame,color=style.about_page_separator_color) self.creditsseparator.place(y=+1*separatorwidth+3*navbuttonheight,x=+separatorwidth,relwidth=1,width=-2*separatorwidth,height=separatorwidth) self.thankslabel = cw.ThemedLabel(self.outer_frame,"SPECIAL THANKS", label_font = columnlabelfont, background = style.about_page_background_color, foreground = columnlabelcolor,anchor="center") self.thankslabel.place(y=+2*separatorwidth+3*navbuttonheight,x=(2*separatorwidth+0.5*navbuttonheight),relwidth=1,width=-(2*separatorwidth+0.5*navbuttonheight),height=navbuttonheight) self.thankstext = cw.ScrolledText(self.outer_frame,background=style.about_page_background_color,borderwidth=0,highlightthickness=0,foreground=lgray,font=smallboldtext,wrap="word") self.thankstext.place(y=+0*separatorwidth+4*navbuttonheight,x=separatorwidth,relwidth=1,width=-(2*separatorwidth),relheight=1,height=-(+0*separatorwidth+4*navbuttonheight)) self.thankstext.insert(END, thankyoutext) self.thankstext.config(state=DISABLED) #back to main page image and button self.returnimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder,"returnbutton.png")) self.returnimage = self.returnimage.zoom((3)).subsample(5) self.return_button = cw.navbutton(self.outer_frame, image_object=self.returnimage, command_name=back_command) self.return_button.place(relx=1, rely=1, x=-(separatorwidth+navbuttonheight), y=-(separatorwidth+navbuttonheight), height=navbuttonheight, width=navbuttonheight)
def __init__(self, frame): cw.ThemedFrame.__init__(self, frame, background_color=light_color, frame_borderwidth=0) #holds author picture self.project_art_label = cw.ThemedLabel(self, label_text="project_art", anchor="n") #Homebrew Title self.titlevar = tk.StringVar() self.titlevar.set("title_var") self.project_title_label = cw.ThemedLabel( self, label_text="project_title", text_variable=self.titlevar, foreground=info_softwarename_color, label_font=info_softwarename_font, anchor="n") #Description self.project_description = cw.ScrolledText( self, background=light_color, foreground=info_description_color, font=info_description_font, borderwidth=0, state=NORMAL, wrap="word", ) #author name self.authorvar = tk.StringVar() self.authorvar.set("author_var") self.author_name_label = cw.ThemedLabel(self, label_text="author_name", text_variable=self.authorvar, foreground=info_author_color, label_font=info_author_font, anchor="n") #Separator self.topsep = cw.ThemedFrame( self, background_color=lgray, frame_borderwidth=2, ) self.botsep = cw.ThemedFrame( self, background_color=lgray, frame_borderwidth=2, ) #Check if author image is disabled if guicore.checkguisetting("guisettings", "display_author_image"): self.topsep.place(x=(infoframewidth / 2), y=infoframewidth + 52, height=4, relwidth=0.9, anchor="center") self.project_art_label.place(relx=0.0, rely=0.0, height=infoframewidth, relwidth=1) self.project_title_label.place(relx=0.0, rely=0.0, y=infoframewidth, relwidth=1.0) self.author_name_label.place(relx=0.0, rely=0, y=infoframewidth + 25, relwidth=1.0) self.project_description.place(relx=0.5, rely=0.0, y=+infoframewidth + 55, relheight=1, height=-(infoframewidth + 55 + 100), relwidth=0.85, anchor="n") else: self.topsep.place(x=(infoframewidth / 2), y=separatorwidth + 50, height=4, relwidth=0.9, anchor="center") self.project_title_label.place(relx=0.0, rely=0.0, y=+separatorwidth, relwidth=1.0) self.author_name_label.place(relx=0.0, rely=0, y=separatorwidth + 25, relwidth=1.0) self.project_description.place(relx=0.5, rely=0.0, y=separatorwidth + 55, relheight=1, height=-(separatorwidth + 55 + 100), relwidth=0.85, anchor="n") self.project_art_label.place_forget() self.botsep.place(x=(infoframewidth / 2), rely=1, y=-95, height=4, relwidth=0.9, anchor="center") self.project_description.delete('1.0', END) self.project_description.insert(END, "Project description") self.project_description.configure(state=DISABLED)
def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) # self.resizable(False,False) width = guicore.checkguisetting("dimensions", "guiwidth") height = guicore.checkguisetting("dimensions", "guiheight") minwidth = guicore.checkguisetting("dimensions", "minguiwidth") minheight = guicore.checkguisetting("dimensions", "minguiheight") self.geometry("{}x{}".format(width, height)) self.minsize(width=minwidth, height=minheight) #minimum size currently supported # the container is where we'll stack a bunch of frames # on top of each other, then the one we want visible # will be raised above the others container = cw.ThemedFrame(self) container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) ##Import pages #App pages import pages.addrepopage as ar import pages.cfwpage as fw import pages.emulatorpage as eu import pages.gamespage as gp import pages.homebrewpage as hb import pages.pythonnxpage as py #Functional Pages: import pages.backuppage as bp import pages.injectorpage as ip import pages.serialpage as cp #Navigation Pages import pages.aboutpage as ap import pages.errorpage as ep import pages.homepage as lp import pages.settingspage as sp ##Test pages, #Uncomment this to see what I'm working on sometimes, especially in source builds. # import pages.test_page as tp # import pages.dbviewer as db # import pages.usbhelper as ub # import pages.nut_tk.nut_tk as nk #Add pages to list pages = [ ep. errorPage, #<- Needs to be inited before most pages, used for error handling to the user ar. addrepoPage, #<- Needs to be inited before list pages, used for adding repos ap.aboutPage, #<- No precedence bp.backupPage, #<- List Page cp.serialPage, #<- No precedence eu.emuPage, #<- List Page fw.cfwPage, #<- List Page gp.gamesPage, #<- List Page hb.homebrewPage, #<- List Page ip.injectorScreen, #<- List Page lp.homePage, #<- No precedence py.pynxPage, #<- List Page sp.settingsPage, #<- No precedence ] #Try to add test page try: pages.append(tp.testPage) #<- List Page print("Test page added") except: pass #Add pages as frames to dict, with keyword being the name of the frame self.frames = {} for F in (pages): page_name = F.__name__ frame = F(parent=container, controller=self, page_name=page_name, back_command=lambda: self.show_frame("homePage")) self.frames[page_name] = frame frame.grid(row=0, column=0, sticky="nsew") softwarelists = [ self.frames["homebrewPage"].softwarelist, self.frames["gamesPage"].softwarelist, self.frames["emuPage"].softwarelist, self.frames["cfwPage"].softwarelist, self.frames["pynxPage"].softwarelist ] mastersoftwarelist = [] for lixlix in softwarelists: for lix in lixlix: mastersoftwarelist.append(lix) self.user_repos = self.frames["addrepoPage"].softwarelist #Set icon if platform.system() == 'Windows': try: print("Windows detected, setting icon") self.iconbitmap( os.path.join(guicore.assetfolder, 'HBUpdater.ico')) except: print("Failed to set icon") elif platform.system() == "Linux": try: print("Linux detected, setting icon") self.iconbitmap( os.path.join(guicore.assetfolder, 'HBUpdater.xbm')) except: print("Failed to set icon") latest_version, latest_notes = CheckForUpdates() if latest_version: self.frames["errorPage"].getanswer( "homePage", "New release version {}\n\n{}\n Would you like to update?". format(latest_version, latest_notes), update) else: self.show_frame("homePage") #Show the main page frame
def __init__(self, parent, controller,page_name,back_command): global home_page_separator_color self.back_command = back_command self.controller = controller width = guicore.checkguisetting("dimensions","guiwidth") height = guicore.checkguisetting("dimensions","guiheight") cw.ThemedFrame.__init__(self,parent,background_color= style.homepage_background_color) self.outerframe = cw.ThemedFrame(self, background_color = style.homepage_background_color) self.outerframe.place(relx=0.5,rely=0.5,x=-(width/2),y=-(height/2),width=width,height=height) self.settingsimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder,"settings.png")) self.injectimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder,"injector.png")) self.nutimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder,"nut.png")) self.fluffyimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "fluffy.png")) self.pythonimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "python.png")) self.cfwimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "cfw.png")) self.betaimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "beta.png")) self.homebrewimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "homebrew.png")) self.gameimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "games.png")) self.githubimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "github.png")) # self.appstoreimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "hbappstore.png")) self.serialimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "serialchecker.png")) self.emuimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "emu.png")) # self.experimentalimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "experimental.png")) self.profileimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "profile.png")) self.backupsimage = tk.PhotoImage(file=os.path.join(guicore.assetfolder, "backups.png")) homebrewbuttonlist = [ { "image" : self.homebrewimage, "callback" : lambda: self.controller.show_frame("homebrewPage"), "tooltip" : "Install homebrew apps", "shorttip" : "Homebrew" }, { "image" : self.gameimage, "callback" : lambda: self.controller.show_frame("gamesPage"), "tooltip" : "Install homebrew games", "shorttip" : "Games" }, { "image" : self.emuimage, "callback" : lambda: self.controller.show_frame("emuPage"), "tooltip" : "Emulators", "shorttip" : "Emulators" }, { "image" : self.cfwimage, "callback" : lambda: self.controller.show_frame("cfwPage"), "tooltip" : "Custom Firmware Manager", "shorttip" : "CFW Manager" }, { "image" : self.pythonimage, "callback" : lambda: self.controller.show_frame("pynxPage"), "tooltip" : "Homebrew python script for use with NX Python", "shorttip" : "Python Scripts" }, ] toolbuttonlist = [ { "image" : self.injectimage, "callback" : lambda: self.controller.show_frame("injectorScreen"), "tooltip" : "Built-in RCM injector GUI", "shorttip" : "RCM Injector" }, { "image" : self.nutimage, "callback" : self.checknutandstart, "tooltip" : "Open NUT server", "shorttip" : "NUT Client" }, { "image" : self.fluffyimage, "callback" : self.checkfluffyandstart, "tooltip" : "Open fluffy", "shorttip" : "Fluffy" }, { "image" : self.backupsimage, "callback" : lambda: self.controller.show_frame("backupPage"), "tooltip" : "Beta SD card backup manager", "shorttip" : "SD Backup" }, { "image" : self.serialimage, "callback" : lambda: self.controller.show_frame("serialPage"), "tooltip" : "Built-in Switch serial number checker GUI", "shorttip" : "Serial Checker" }, ] otherbuttonlist = [ { "image" : self.settingsimage, "callback" : lambda: self.controller.show_frame("settingsPage"), "tooltip" : "Open settings page", "shorttip" : "Settings" }, { "image" : self.profileimage, "callback" : lambda: self.controller.show_frame("aboutPage"), "tooltip" : "Open about page", "shorttip" : "About" }, { "image" : self.githubimage, "callback" : lambda: webhandler.opentab("https://www.github.com/LyfeOnEdge/HBUpdater"), "tooltip" : "Open HBUpdater Github", "shorttip" : "HBU Github" }, # { # "image" : self.betaimage, # "callback" : lambda: self.controller.show_frame("addrepoPage"), # "tooltip" : "delete me", # "shorttip" : "repo pages" # }, # { # "image" : self.betaimage, # "callback" : lambda: self.controller.show_frame("dbPage"), # "tooltip" : "delete me", # "shorttip" : "titledb" # }, # { # "image" : self.betaimage, # "callback" : lambda: self.controller.show_frame("usbPage"), # "tooltip" : "delete me", # "shorttip" : "nutpage" # }, ] self.homebrewbox = cw.ThemedFrame(self.outerframe,background_color=style.homepage_background_color) self.homebrewbox.place(relx=0,rely=0,relwidth=1,relheight=0.33) self.buildbuttonrow("HOMEBREW",homebrewbuttonlist,self.homebrewbox) self.toolsbox = cw.ThemedFrame(self.outerframe,background_color=style.homepage_background_color) self.toolsbox.place(relx=0,rely=0.33,relwidth=1,relheight=0.33) self.buildbuttonrow("SWITCH TOOLS",toolbuttonlist,self.toolsbox) self.otherbox = cw.ThemedFrame(self.outerframe,background_color=style.homepage_background_color) self.otherbox.place(relx=0,rely=0.66,relwidth=1,relheight=0.33) self.buildbuttonrow("MORE",otherbuttonlist,self.otherbox)