Esempio n. 1
0
class DownloadedMangaDisplay(ScrollView):
    def __init__(self, master, language, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.effect_cls = "ScrollEffect"
        self.bar_width = "10dp"
        self.pos_hint = {"top": .9}
        self.do_scroll_y = True

        self.language_folder = self.master.japanese_manga_dir if language == "Japanese" else self.master.english_manga_dir

        self.manga_folders = [
            resource_path(str(dir))
            for dir in glob(os.path.join(self.language_folder, "*/"))
            if os.path.isdir(dir)
        ]
        self.manga_cover_imgs = [
            resource_path(str(img_path))
            for img_path in glob(os.path.join(self.language_folder, "*/*.jpg"))
            if os.path.isfile(img_path)
        ]
        self.manga_tile_data = list(
            zip(self.manga_folders, self.manga_cover_imgs))

        # This grid acts as a container for the number of manga found and the table with the clickable tiles
        self.outer_gird = MDGridLayout(rows=2,
                                       adaptive_height=True,
                                       padding=("0dp", "20dp", "0dp", "20dp"),
                                       pos_hint={"top": .8})
        self.outer_gird.add_widget(
            MDLabel(text=f"{len(self.manga_folders)} manga were found",
                    halign="center",
                    pos_hint={
                        "center_x": .5,
                        "y": .9
                    }))

        self.grid = MDStackLayout(adaptive_height=True,
                                  orientation="lr-tb",
                                  spacing=("20dp", "20dp"),
                                  padding=("5dp", "30dp", "5dp", "30dp"))

        for i in self.manga_tile_data:
            title, manga_path = os.path.basename(os.path.realpath(
                i[0])), resource_path(i[0])
            print("i: ", i, "title", title, "manga_path: ", manga_path)
            reload_func = lambda title=title, manga_path=manga_path: self.master.create_manga_reader_chapter_selection(
                title, manga_path)
            self.btn = MangaCoverTile(source=i[1],
                                      text=title,
                                      size_hint=(.25, .25),
                                      on_release=partial(
                                          kill_screen,
                                          "Manga Reader Chapter Selection",
                                          reload_func))
            self.grid.add_widget(self.btn)

        self.outer_gird.add_widget(self.grid)
        self.add_widget(self.outer_gird)
Esempio n. 2
0
    def __init__(self, master, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.manga_data = self.master.manga_data
        self.downloader_links_methods = {
            "manganelo": MangaNelo.download_manga,
            "kissmanga": KissManga.download_manga,
            "rawdevart": RawDevArt.download_manga,
            "senmanga": SenManga.download_manga
        }
        self.effect_cls = "ScrollEffect"
        self.bar_width = "10dp"
        self.pos_hint = {"top": .9}

        # This grid acts as a container for the number of manga found and the table with the clickable tiles
        self.outer_gird = MDGridLayout(rows=2,
                                       adaptive_height=True,
                                       padding=("0dp", "20dp", "0dp", "20dp"),
                                       pos_hint={"top": .8})
        self.outer_gird.add_widget(
            MDLabel(text=f"{len(self.manga_data)} manga were found",
                    halign="center",
                    pos_hint={
                        "center_x": .5,
                        "y": .9
                    }))

        # This grid acts a table to store all found manga
        self.grid = MDStackLayout(adaptive_height=True,
                                  orientation="lr-tb",
                                  spacing=("20dp", "20dp"),
                                  padding=("5dp", "30dp", "5dp", "30dp"))

        for title, links_tuple in self.manga_data.items():
            self.btn = MangaCoverTile(source=links_tuple[1],
                                      text=title,
                                      on_release=partial(
                                          self.make_request, title),
                                      size_hint=(.25, .25))
            self.grid.add_widget(self.btn)

        # Checks to see if any manga were found; An empty dict means no manga were found with the inputted text
        if self.manga_data == {}:
            self.grid.add_widget(
                MDLabel(text="No Manga found",
                        halign="center",
                        pos_hint={
                            "center_x": .5,
                            "center_y": .5
                        }))

        self.outer_gird.add_widget(self.grid)
        self.add_widget(self.outer_gird)
Esempio n. 3
0
class MangaReaderChapterSelection(ScrollView):
    def __init__(self, master, title, manga_path, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.manga_path = resource_path(manga_path)
        self.manga_title = title
        self.effect_cls = "ScrollEffect"
        self.bar_width = "10dp"
        self.pos_hint = {"top": .9}
        self.padding = (
            "20dp", "0dp", "20dp", "0dp"
        )  # padding: [padding_left, padding_top, padding_right, padding_bottom]

        # Get all the chapter directories and sort them alphanumerically
        self.chapter_dirs = os_sorted([
            os.path.abspath(resource_path(dir))
            for dir in glob(os.path.join(self.manga_path, "*/"))
            if os.path.isdir(dir)
        ])
        self.grid = MDStackLayout(adaptive_height=True,
                                  padding=("30dp", "50dp", "30dp", "0dp"),
                                  spacing="20dp",
                                  pos_hint={"center_x": .5})

        # Loop to create buttons for each chapter of a manga
        for chapter_dir in self.chapter_dirs:
            chapter_name = os.path.basename(resource_path(chapter_dir))

            def reload_func(manga_title=self.manga_title,
                            name=chapter_name,
                            path=chapter_dir):
                self.master.create_manga_reader(manga_title, name, path)

            self.chapter_btn = MDRectangleFlatButton(
                text=chapter_name,
                pos_hint={
                    "center_x": .5,
                    "center_y": .8
                },
                on_release=partial(kill_screen, "Manga Reader Carousel",
                                   reload_func),
            )
            self.grid.add_widget(self.chapter_btn)
        self.add_widget(self.grid)
Esempio n. 4
0
    def Name_changed(self, val, *args):
        ''' Name is changed as soon as the text is altered to allow lookup
            while other properties are changed on defocus.
        '''

        # don't do any lookups if we are initialising
        if not self.check_ambiguity:
            return

        # lookup
        OTs = Component.get('ObservingList').lookup_OTs(val)

        # if unique match, fill in
        if len(OTs) == 1:
            self.exact_match(val + '/' + OTs[0])
            return

        # clear all but name field to signal ambiguity
        for p in set(self.props) - {'Name'}:
            setattr(self, p, '')

        if len(OTs) == 0:
            # no match so set name
            self.Name = val
            self.new_values['Name'] = val
            self.check_for_change()
            return

        self.choose_OT = MDStackLayout(pos_hint={
            'x': .1,
            'top': 1
        },
                                       spacing=[20, 20])
        self.app.gui.add_widget(self.choose_OT)
        for ot in OTs:
            self.choose_OT.add_widget(
                MDTextButton(text=ot,
                             on_press=partial(self.exact_match,
                                              val + '/' + ot)))
Esempio n. 5
0
class DSO(Component):

    save_settings = ['show_DSO']

    Name = StringProperty('')
    Con = StringProperty('')
    RA = StringProperty('')
    Dec = StringProperty('')
    OT = StringProperty('')
    Mag = StringProperty('')
    Diam = StringProperty('')
    Other = StringProperty('')
    otypes = DictProperty({})

    props = ['Name', 'Con', 'OT', 'RA', 'Dec', 'Mag', 'Diam', 'Other']

    show_DSO = BooleanProperty(False)
    check_ambiguity = BooleanProperty(
        False)  # check for ambiguous Names e.g. PN/GG

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.app = App.get_running_app()
        otypes = Component.get('Catalogues').get_object_types()
        self.otypes = {k: v['name'] for k, v in otypes.items()}
        self.dso_panel = DSO_panel(self)
        self.app.gui.add_widget(self.dso_panel)
        self.initial_values = {}

    def on_new_object(self):
        ''' Called when user clicks new
        '''

        # empty DSO details & store initial values
        self.update_props()
        self.initial_values = {p: getattr(self, p) for p in self.props}

    def on_previous_object(self):
        ''' Called when user selected object in observations table
        '''

        # Data for new object is in Metadata
        settings = Component.get('Metadata').get({'Name', 'OT'})

        # lookup rest from name and object type
        full_settings = Component.get('ObservingList').lookup_name(
            '{:}/{:}'.format(settings.get('Name', ''), settings.get('OT', '')))

        # update props if we managed a lookup, else use metadata values
        if full_settings.get('Name', ''):
            self.update_props(settings=full_settings)
        else:
            self.update_props(settings=settings)

        # store initial values so we can check for changes
        self.initial_values = {p: getattr(self, p) for p in self.props}

    def new_DSO_name(self, settings):
        ''' Called when user selects a name from the DSO table. What we do depends
            on whether we already have an object loaded, in which case we note the
            change of name so that it can be confirmed on save.
        '''

        # lookup rest
        full_settings = Component.get('ObservingList').lookup_name(
            '{:}/{:}'.format(settings.get('Name', ''), settings.get('OT', '')))

        # update DSO properties
        self.update_props(settings=full_settings)

        # if stack is empty, treat this as a new observation
        if Component.get('Stacker').is_empty():
            logger.info('new DSO from table {:}'.format(full_settings))
            self.initial_values = {p: getattr(self, p) for p in self.props}
        else:
            logger.info('user changes DSO name {:}'.format(full_settings))

    @logger.catch()
    def Name_changed(self, val, *args):
        ''' Name is changed as soon as the text is altered to allow lookup
            while other properties are changed on defocus.
        '''

        # don't do any lookups if we are initialising
        if not self.check_ambiguity:
            return

        # lookup
        OTs = Component.get('ObservingList').lookup_OTs(val)

        # if unique match, fill in
        if len(OTs) == 1:
            self.exact_match(val + '/' + OTs[0])
            return

        # clear all but name field to signal ambiguity
        for p in set(self.props) - {'Name'}:
            setattr(self, p, '')

        if len(OTs) == 0:
            # no match so set name
            self.Name = val
            self.new_values['Name'] = val
            self.check_for_change()
            return

        self.choose_OT = MDStackLayout(pos_hint={
            'x': .1,
            'top': 1
        },
                                       spacing=[20, 20])
        self.app.gui.add_widget(self.choose_OT)
        for ot in OTs:
            self.choose_OT.add_widget(
                MDTextButton(text=ot,
                             on_press=partial(self.exact_match,
                                              val + '/' + ot)))

    def exact_match(self, m, *args):
        if hasattr(self, 'choose_OT'):
            self.choose_OT.clear_widgets()
            del self.choose_OT
        logger.debug('Found match: {:}'.format(m))
        self.update_props(
            settings=Component.get('ObservingList').lookup_name(m),
            update_name_field=False,
            initialising=False)
        self.new_values['Name'] = self.Name
        self.check_for_change()

    @logger.catch()
    def update_props(self,
                     settings=None,
                     update_name_field=True,
                     initialising=True):
        ''' update DSO properties, causing display update
        '''

        if initialising:
            self.check_ambiguity = False

        if settings is None:
            settings = {}

        self.Name = settings.get('Name', '')
        self.RA = str(RA(settings.get('RA', math.nan)))
        self.Dec = str(Dec(settings.get('Dec', math.nan)))
        self.Con = settings.get('Con', '')
        self.OT = settings.get('OT', '')
        self.Mag = float_to_str(settings.get('Mag', ''))
        self.Other = settings.get('Other', '')

        self.Diam = arcmin_to_str(str_to_arcmin(str(settings.get('Diam', ''))))
        # update new values to reflect changes
        self.new_values = {p: getattr(self, p) for p in self.props}
        if update_name_field:
            self.dso_panel.name_field.text = self.Name
        self.check_for_change()

        self.check_ambiguity = True

    def OT_changed(self, widget):
        ''' For the moment we allow any object type but in the future
            could check if one of known types and allow user to
            introduce a new type via a dialog
        '''

        widget.current_hint_text_color = self.app.hint_color
        ot = widget.text.upper()
        if len(ot) > 3:
            widget.current_hint_text_color = [1, 0, 0, 1]
        else:
            self.OT = ot
            self.new_values['OT'] = ot
            self.check_for_change()

    def Con_changed(self, widget):
        ''' Likewise, we should check constellations in future
        '''
        widget.current_hint_text_color = self.app.hint_color
        con = widget.text.upper()
        if len(con) > 3:
            widget.current_hint_text_color = [1, 0, 0, 1]
        else:
            self.Con = con
            self.new_values['Con'] = con
            self.check_for_change()

    @logger.catch()
    def RA_changed(self, widget):
        '''
        '''
        widget.current_hint_text_color = self.app.hint_color
        RA_str = widget.text.strip()
        if not RA_str:
            return
        ra_deg = RA.parse(RA_str)
        if ra_deg is None:
            widget.current_hint_text_color = [1, 0, 0, 1]
        else:
            self.RA = '-'  # need to force an update
            self.RA = str(RA(ra_deg))
            self.new_values['RA'] = self.RA
            self.check_for_change()

    def Dec_changed(self, widget):
        widget.current_hint_text_color = self.app.hint_color
        Dec_str = widget.text.strip()
        if not Dec_str:
            return
        dec_deg = Dec.parse(Dec_str)
        if dec_deg is None:
            widget.current_hint_text_color = [1, 0, 0, 1]
        else:
            self.Dec = '-'  # need to force an update
            self.Dec = str(Dec(dec_deg))
            self.new_values['Dec'] = self.Dec
            self.check_for_change()

    def Mag_changed(self, widget):
        ''' should be a int or float
        '''
        mag_str = widget.text.strip()
        if not mag_str:
            return
        try:
            mag = str(float(mag_str))
            self.Mag = '-'
            self.Mag = mag
            self.new_values['Mag'] = mag_str
            self.check_for_change()
        except:
            widget.invalid = True

    def Diam_changed(self, widget):
        ''' Suffix can be d or degree symbol, ' or "
            assume arcmin if no suffix
        '''

        diam = widget.text.strip()
        if not diam:
            return
        try:
            # normalise diam by converting to arcmin then back to string
            diam = arcmin_to_str(str_to_arcmin(diam))
            self.new_values['Diam'] = diam
            self.Diam = diam
            self.check_for_change()
        except:
            logger.warning('invalid format for diameter {:}'.format(diam))
            widget.invalid = True

    def Other_changed(self, widget):
        self.Other = widget.text.strip()
        self.new_values['Other'] = self.Other
        self.check_for_change()

    @logger.catch()
    def check_for_change(self):
        ''' Check if any property has changed
        '''
        changes = []
        for k, v in self.initial_values.items():
            if k in self.new_values and self.new_values[k] != v:
                changes += [True]

        # tell gui about any changes
        self.app.gui.has_changed('DSO', any(changes))

    @logger.catch()
    def on_save_object(self):
        ''' On saving we ensure that Name, OT and Con is saved as these 
            appear in the previous object table; other props don't need to
            be saved as they are looked up from the DSO database on each
            load.
        '''

        Component.get('Metadata').set({
            'Name': self.Name.strip(),
            'OT': self.OT,
            'Con': self.Con
        })

        # prepare props in canonical format
        props = {
            'Name': self.Name.strip(),
            'OT': self.OT.strip(),
            'Con': self.Con.strip(),
            'RA': RA.parse(self.RA),
            'Dec': Dec.parse(self.Dec),
            'Diam': str_to_arcmin(self.Diam),
            'Mag': str_to_float(self.Mag),
            'Other': self.Other
        }

        # get catalogue to check if anything has changed and update user objects if necc.
        Component.get('Catalogues').check_update(props)

    def current_object_coordinates(self):
        ''' Called by platesolver
        '''
        if self.RA and self.Dec:
            return (float(RA(self.RA)), float(Dec(self.Dec)))
        return None, None
Esempio n. 6
0
    def goToStreams(self, *a):

        "Go to a page wherein we can list user-modifiable services."
        self.streamsEditPanel.clear_widgets()

        layout = self.streamsEditPanel

        bar = BoxLayout(spacing=10, adaptive_height=True, size_hint=(1, None))

        stack = StackLayout(spacing=10,
                            adaptive_height=True,
                            size_hint=(1, None))
        layout.add_widget(bar)
        layout.add_widget(MDToolbar(title="My Streams"))

        layout.add_widget(stack)

        def upOne(*a):
            self.gotoMainScreen()

        btn1 = Button(text='Up')

        btn1.bind(on_press=upOne)

        bar.add_widget(btn1)
        bar.add_widget(self.makeBackButton())

        btn2 = Button(text='Create a Stream')

        btn2.bind(on_press=self.promptAddStream)
        stack.add_widget(btn2)

        def f(selection):
            if selection:
                dn = 'file:' + os.path.basename(selection)
                while dn in daemonconfig.userDatabases:
                    dn = dn + '2'
                try:
                    daemonconfig.loadUserDatabase(selection, dn)
                    self.editStream(dn)
                except:
                    logging.exception(dn)

            self.openFM.close()

        #This lets us view notebook files that aren't installed.
        def promptOpen(*a):

            try:
                #Needed for android
                self.getPermission('files')
            except:
                logging.exception("cant ask permission")

            from .kivymdfmfork import MDFileManager
            from . import directories
            self.openFM = MDFileManager(select_path=f)

            if os.path.exists("/storage/emulated/0/Documents") and os.access(
                    "/storage/emulated/0/Documents", os.W_OK):
                self.openFM.show("/storage/emulated/0/Documents")
            elif os.path.exists(
                    os.path.expanduser("~/Documents")) and os.access(
                        os.path.expanduser("~/Documents"), os.W_OK):
                self.openFM.show(os.path.expanduser("~/Documents"))
            else:
                self.openFM.show(directories.externalStorageDir
                                 or directories.settings_path)

        btn1 = Button(text='Open Book File')

        btn1.bind(on_press=promptOpen)

        stack.add_widget(btn1)

        def goHere():
            self.screenManager.current = "Streams"

        self.backStack.append(goHere)
        self.backStack = self.backStack[-50:]

        layout.add_widget(MDToolbar(title="Open Streams:"))

        try:
            s = daemonconfig.userDatabases
            time.sleep(0.5)
            for i in s:
                layout.add_widget(self.makeButtonForStream(i))
                try:
                    for j in daemonconfig.userDatabases[i].connectedServers:
                        if daemonconfig.userDatabases[i].connectedServers[
                                j] > (time.time() - (10 * 60)):
                            w = 'online'
                        else:
                            w = 'idle/offline'
                        layout.add_widget(
                            self.saneLabel(j[:28] + ": " + w, layout))
                except:
                    logging.exception("Error showing node status")

        except Exception:
            logging.info(traceback.format_exc())

        self.screenManager.current = "Streams"
Esempio n. 7
0
    def editStream(self, name):
        if not name in daemonconfig.userDatabases:
            self.goToStreams()
        db = daemonconfig.userDatabases[name]
        c = db.config
        try:
            c.add_section("Service")
        except:
            pass
        try:
            c.add_section("Info")
        except:
            pass

        self.streamEditPanel.clear_widgets()
        topbar = BoxLayout(size_hint=(1, None),
                           adaptive_height=True,
                           spacing=5)

        stack = StackLayout(size_hint=(1, None),
                            adaptive_height=True,
                            spacing=5)

        def upOne(*a):
            self.goToStreams()

        btn1 = Button(text='Up')

        btn1.bind(on_press=upOne)

        topbar.add_widget(btn1)

        topbar.add_widget(self.makeBackButton())

        self.streamEditPanel.add_widget(topbar)
        self.streamEditPanel.add_widget(MDToolbar(title=name))

        def goHere():
            self.editStream(name)

        self.backStack.append(goHere)
        self.backStack = self.backStack[-50:]

        btn2 = Button(text='Notebook View')

        def goPosts(*a):
            self.gotoStreamPosts(name)

        btn2.bind(on_press=goPosts)
        stack.add_widget(btn2)

        btn2 = Button(text='Feed View')

        def goPosts(*a):
            self.gotoStreamPosts(name, parent=None)

        btn2.bind(on_press=goPosts)
        stack.add_widget(btn2)

        btn2 = Button(text='Stream Settings')

        def goSettings(*a):
            self.editStreamSettings(name)

        btn2.bind(on_press=goSettings)
        stack.add_widget(btn2)

        if name.startswith('file:'):
            btn2 = Button(text='Close Stream')

            def close(*a):
                daemonconfig.closeUserDatabase(name)
                self.goToStreams()

            btn2.bind(on_press=close)
            stack.add_widget(btn2)

        importData = Button(text="Import Data File")

        def promptSet(*a):
            try:
                #Needed for android
                self.getPermission('files')
            except:
                logging.exception("cant ask permission")

            def f(selection):
                if selection:

                    def f2(x):
                        if x:
                            with daemonconfig.userDatabases[name]:
                                with open(selection) as f:
                                    daemonconfig.userDatabases[
                                        name].importFromToml(f.read())
                            daemonconfig.userDatabases[name].commit()

                    self.askQuestion("Really import?", "yes", cb=f2)
                self.openFM.close()

            from .kivymdfmfork import MDFileManager
            from . import directories
            self.openFM = MDFileManager(select_path=f)

            if os.path.exists("/storage/emulated/0/Documents") and os.access(
                    "/storage/emulated/0/Documents", os.W_OK):
                self.openFM.show("/storage/emulated/0/Documents")
            elif os.path.exists(
                    os.path.expanduser("~/Documents")) and os.access(
                        os.path.expanduser("~/Documents"), os.W_OK):
                self.openFM.show(os.path.expanduser("~/Documents"))
            else:
                self.openFM.show(directories.externalStorageDir
                                 or directories.settings_path)

        importData.bind(on_release=promptSet)
        stack.add_widget(importData)

        export = Button(text="Export All Posts")

        def promptSet(*a):
            from .kivymdfmfork import MDFileManager
            from .. import directories
            try:
                #Needed for android
                self.getPermission('files')
            except:
                logging.exception("cant ask permission")

            def f(selection):
                if selection:
                    if not selection.endswith(".toml"):
                        selection = selection + ".toml"

                    def g(a):
                        if a == 'yes':

                            r = daemonconfig.userDatabases[
                                name].getDocumentsByType('post', parent='')
                            data = daemonconfig.userDatabases[
                                name].exportRecordSetToTOML(
                                    [i['id'] for i in r])

                            logging.info("Exporting data to:" + selection)
                            with open(selection, 'w') as f:
                                f.write(data)
                        self.openFM.close()

                    if os.path.exists(selection):
                        self.askQuestion("Overwrite?", 'yes', g)
                    else:
                        g('yes')

            #Autocorrect had some fun with the kivymd devs
            self.openFM = MDFileManager(select_path=f,
                                        save_mode=(name + '.toml'))

            if os.path.exists("/storage/emulated/0/Documents") and os.access(
                    "/storage/emulated/0/Documents", os.W_OK):
                self.openFM.show("/storage/emulated/0/Documents")
            elif os.path.exists(
                    os.path.expanduser("~/Documents")) and os.access(
                        os.path.expanduser("~/Documents"), os.W_OK):
                self.openFM.show(os.path.expanduser("~/Documents"))
            else:
                self.openFM.show(directories.externalStorageDir
                                 or directories.settings_path)

        export.bind(on_release=promptSet)

        stack.add_widget(export)

        self.streamEditPanel.add_widget(stack)

        #Show recent changes no matter where they are in the tree.
        #TODO needs to be hideable for anti-spoiler purposes in fiction.
        self.streamEditPanel.add_widget(MDToolbar(title="Recent Changes:"))

        for i in daemonconfig.userDatabases[name].getDocumentsByType(
                'post', orderBy='arrival DESC', limit=5):
            x = self.makePostWidget(name, i, includeParent=True)
            self.streamEditPanel.add_widget(x)

        self.screenManager.current = "EditStream"
Esempio n. 8
0
    def gotoMainScreen(self):
        self.mainScreenlayout.clear_widgets()
        layout=self.mainScreenlayout

    
        label = MDToolbar(title="Drayer Journal")
        label.icon=os.path.join(os.path.dirname(os.path.abspath("__file__")),'assets','icons',"Craftpix.net",'medival','cart.jpg')
        layout.add_widget(label)

        stack = StackLayout(size_hint=(1,None),adaptive_height=True,spacing=5)

      
        l = self.saneLabel("Notice: streams may be stored on the SD card. Some other apps may be able to read them",layout)
        layout.add_widget(l)
            
        btn1 = Button(text='My Streams')

        stack.add_widget(btn1)

        btn1.bind(on_press=self.goToStreams)

        btn1 = Button(text='Discover Services')
     

        btn1.bind(on_press=self.goToDiscovery)
        stack.add_widget(btn1)

        btn5 = Button(text='Settings+Tools')

        btn5.bind(on_press=self.goToSettings)

        stack.add_widget(btn5)


        btn6 = Button(text='Help')

        btn6.bind(on_press=self.goToHelp)

        stack.add_widget(btn6)

        layout.add_widget(stack)

        label = MDToolbar(title="Bookmarks")
        layout.add_widget(label)

        for i in sorted(list(daemonconfig.getBookmarks().keys())):
            bw =BoxLayout(orientation='horizontal',
                           spacing=10, size_hint=(1, None),adaptive_height=True)
            b = Button(text=i[:32])
            bd = Button(text="Del")


            def dlbm(*a,i=i):
                def f(a):
                    if a:
                        daemonconfig.setBookmark(a,None,None)
                        self.gotoMainScreen()
                self.askQuestion("Delete Bookmark?",i,f)
            bd.bind(on_press=dlbm)

            def bm(*a,i=i):
                self.gotoBookmark(i)
            b.bind(on_press=bm)
            bw.add_widget(b)
            bw.add_widget(bd)
            layout.add_widget(bw)

        self.screenManager.current = "Main"
 def callback_1(self, *args, **kwargs):
     sl = MDStackLayout()
     sl.add_widget(MDTextField(hint_text='Enter something'))
     sl.add_widget(MDRaisedButton(text="I AM A BUTTON"))
     self.boxlayout2.add_widget(sl)
Esempio n. 10
0
class MangaCoverContainer(ScrollView):
    def __init__(self, master, **kwargs):
        super().__init__(**kwargs)
        self.master = master
        self.manga_data = self.master.manga_data
        self.downloader_links_methods = {
            "manganelo": MangaNelo.download_manga,
            "kissmanga": KissManga.download_manga,
            "rawdevart": RawDevArt.download_manga,
            "senmanga": SenManga.download_manga
        }
        self.effect_cls = "ScrollEffect"
        self.bar_width = "10dp"
        self.pos_hint = {"top": .9}

        # This grid acts as a container for the number of manga found and the table with the clickable tiles
        self.outer_gird = MDGridLayout(rows=2,
                                       adaptive_height=True,
                                       padding=("0dp", "20dp", "0dp", "20dp"),
                                       pos_hint={"top": .8})
        self.outer_gird.add_widget(
            MDLabel(text=f"{len(self.manga_data)} manga were found",
                    halign="center",
                    pos_hint={
                        "center_x": .5,
                        "y": .9
                    }))

        # This grid acts a table to store all found manga
        self.grid = MDStackLayout(adaptive_height=True,
                                  orientation="lr-tb",
                                  spacing=("20dp", "20dp"),
                                  padding=("5dp", "30dp", "5dp", "30dp"))

        for title, links_tuple in self.manga_data.items():
            self.btn = MangaCoverTile(source=links_tuple[1],
                                      text=title,
                                      on_release=partial(
                                          self.make_request, title),
                                      size_hint=(.25, .25))
            self.grid.add_widget(self.btn)

        # Checks to see if any manga were found; An empty dict means no manga were found with the inputted text
        if self.manga_data == {}:
            self.grid.add_widget(
                MDLabel(text="No Manga found",
                        halign="center",
                        pos_hint={
                            "center_x": .5,
                            "center_y": .5
                        }))

        self.outer_gird.add_widget(self.grid)
        self.add_widget(self.outer_gird)

    # Note: the param tile acts as a button instance
    def make_request(self, title, tile):
        # Calls the appropriate downloader based on the selected site and starts a thread to prevent kivy event loop from locking
        download_thread_target = partial(
            self.downloader_links_methods.get(self.master.downloader), tile,
            title, self.manga_data.get(title))
        download_thread = Thread(name=f"Download Thread {title}",
                                 target=download_thread_target)

        # Flag used to ensure that the same manga is not downloaded while it is already being downloaded
        if self.master.download_threads.get(
                title, None
        ) == None:  # If a manga is already being downloaded it will not return None
            self.master.download_threads.update({title: download_thread})
            self.master.currently_downloading = True
            tile.progressbar.opacity = 1

            # Creates the directory for that manga within the manga root and changes to it
            create_manga_dirs(self.master.downloader, title)
            download_thread.start()
        else:
            display_message(f"{title} is already downloading")