Пример #1
0
class exitPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent,background=style.color_1)
        self.exit_callback = threader.exit

        self.usertext = ThemedLabel(self, label_text="Exit?", label_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 on_yes(self):
        print("Exiting...")
        self.exit_callback()
        sys.exit()
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
Пример #3
0
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)
Пример #4
0
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))
Пример #5
0
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()
Пример #6
0
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")
Пример #7
0
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)
Пример #8
0
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")
Пример #9
0
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,
            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 configure(self, event):
        self.console_dropdown.option.set(self.settings.get_setting("console"))
        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("console",
                                      self.console_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())
            self.settings.save()
            self.okpage.telluser("Settings saved successfully")
        except Exception as e:
            self.okpage.telluser("Failed to save settings\n{}".format(e))
Пример #10
0
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()
Пример #11
0
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()
Пример #12
0
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()