Example #1
0
    def __init__(self, root, datamodel, config):
        """Initiate the program
        
        Arguments
        root -- the Tk instance of the application
        datamodel -- the data model instance to show
        config -- ConfigParser containing application settings
        
        """
        self._datamodel = datamodel

        #Create string variables        
        self._lblTitle = StringVar()
        self._lblAuthor = StringVar()
        self._activeInPreview = []
        self._activeInPlay = []
        self._datacollector = DataCollector()
        self._userstop = False
        
        #Initiate GUI and data
        self._setupDisplay(root, config)
        self._initData(config)
        
        #Create transparent buttons
        self._setupCategories(config)
        self._setupControls(root, config)

        #Create player
        self._playerFrame = PlayerFrame(root, self._settings.playersize, self._playbackStopped)
        self._playerFrame.setClbClicked(self._clbClicked)
        self._playerwnd = self._canvas.create_window(self._settings.playerpos[0], 
                                                     self._settings.playerpos[1], 
                                                     window = self._playerFrame, 
                                                     anchor = NW)

        #Create preview
        self._previewFrame = PreviewFrame(root, self._datacollector, self._canvas, self._settings)
        self._previewFrame.setClbActivate(self._clbClicked)
        self._previewFrame.previewsubset(self._currentMovies)

        self._updateBrowseButtons()
        
        self._setPreviewMode()

        self._dml = DataModelLoader(root, self._datamodel)
        #after_idle does not work here; 100 ms is an arbitrarily chosen delay time
        root.after(100, self._dml.load)
Example #2
0
class PlayerGui:
    """The main GUI of the Digitala sagor player"""
    def __init__(self, root, datamodel, config):
        """Initiate the program
        
        Arguments
        root -- the Tk instance of the application
        datamodel -- the data model instance to show
        config -- ConfigParser containing application settings
        
        """
        self._datamodel = datamodel

        #Create string variables        
        self._lblTitle = StringVar()
        self._lblAuthor = StringVar()
        self._activeInPreview = []
        self._activeInPlay = []
        self._datacollector = DataCollector()
        self._userstop = False
        
        #Initiate GUI and data
        self._setupDisplay(root, config)
        self._initData(config)
        
        #Create transparent buttons
        self._setupCategories(config)
        self._setupControls(root, config)

        #Create player
        self._playerFrame = PlayerFrame(root, self._settings.playersize, self._playbackStopped)
        self._playerFrame.setClbClicked(self._clbClicked)
        self._playerwnd = self._canvas.create_window(self._settings.playerpos[0], 
                                                     self._settings.playerpos[1], 
                                                     window = self._playerFrame, 
                                                     anchor = NW)

        #Create preview
        self._previewFrame = PreviewFrame(root, self._datacollector, self._canvas, self._settings)
        self._previewFrame.setClbActivate(self._clbClicked)
        self._previewFrame.previewsubset(self._currentMovies)

        self._updateBrowseButtons()
        
        self._setPreviewMode()

        self._dml = DataModelLoader(root, self._datamodel)
        #after_idle does not work here; 100 ms is an arbitrarily chosen delay time
        root.after(100, self._dml.load)

    def _setupDisplay(self, root, config):
        """Set screen size and add background image
        
        root -- the Tk instance of the application
        config -- ConfigParser containing application settings

        """
        fullscreen = config.getboolean(ini.general, ini.fullscreen)
        bgimage = ini.getPath(config.get(ini.general, ini.bgimage))
        
        image = Image.open(bgimage)
        backgroundIm = ImageTk.PhotoImage(image)        
        
        if(fullscreen):
            screenwidth = root.winfo_screenwidth()
            screenheight = root.winfo_screenheight()
            (w, h) = image.size
            self._scalefactor = (screenwidth / float(w), screenheight / float(h))
            image = image.resize((screenwidth, screenheight))
        else:
            (screenwidth, screenheight) = image.size
            self._scalefactor = (1, 1)
            
        geom = "{}x{}+{}+{}".format(screenwidth, screenheight, 0, 0)
        root.geometry(geom)
        root.overrideredirect(1)
        
        background = Canvas(root, width = screenwidth, height = screenheight)
        self._canvas = background
        background.pack()
        backgroundIm = ImageTk.PhotoImage(image)
        self._backgroundIm = backgroundIm
        background.create_image(0,0, image = backgroundIm, anchor = NW)
        
    def _setupCategories(self, config):
        """Add buttons to browse between categories
        
        config -- ConfigParser containing application settings
        
        """
        #Get all button data
        lines = []
        ctr = 1
        option = ini.image + str(ctr)
        
        while(config.has_option(ini.year, option)):
            line = config.get(ini.year, option)
            lines.append(line)
            ctr += 1
            option = ini.image + str(ctr)
            
        #Create as many buttons as needed
        buttondata = zip(lines, self._years)
        
        if(len(buttondata) < len(self._years)):
            print('Warning! There are more categories than category buttons - some categories will not be shown')
            
        ctr = 0
        
        for (line, year) in buttondata:
            tb = TransparentButton(self._canvas, self._settings.generalfont, line, self._scalefactor)
            tb.setText(year)
            tb.setCommand(self._ehYear)
            tb.index = ctr
            ctr += 1
            self._activeInPreview.append(tb)

    def _setupControls(self, root, config):
        """Initiate control buttons        
        
        root -- the Tk instance of the application
        config -- ConfigParser containing application settings

        """
        iniline = config.get(ini.controls, ini.prev)
        tb = TransparentButton(self._canvas, self._settings.generalfont, iniline, self._scalefactor)
        tb.setCommand(self._ehPrev)
        self._btnPrev = tb
        self._activeInPreview.append(tb)
        
        iniline = config.get(ini.controls, ini.next)
        tb = TransparentButton(self._canvas, self._settings.generalfont, iniline, self._scalefactor)
        tb.setCommand(self._ehNext)
        self._btnNext = tb
        self._activeInPreview.append(tb)

        iniline = config.get(ini.controls, ini.start)
        tb = TransparentButton(self._canvas, self._settings.generalfont, iniline, self._scalefactor)
        self._btnPlay = tb

    def _initData(self, config):
        """Initiate internal variables        
        
        config -- ConfigParser containing application settings

        """
        #Check that there are movies
        if(self._datamodel.isEmpty()):
            showerror(lang[lng.txtNoMoviesTitle], lang[lng.txtNoMovies])
            raise Exception(lang[lng.txtNoMoviesTitle])

        #Initiate variables
        self._settings = HylteSettings(config, self._scalefactor)
        self._subsetSize = self._settings.previewcolumns * 2

        self._currentYearIx = 0
        self._years = sorted(self._datamodel.allMovies.iterkeys())
        self._updateYearState()

    def _updateBrowseButtons(self):
        """Set the text of the browse buttons to indicate current subsets"""
        prev = self._currentSubsetIndex
        next = self._currentSubsetIndex + 2
        
        if(prev == 0):
            prev = self._currentSubsetCount
            
        if(next > self._currentSubsetCount):
            next = 1
               
        text = lang[lng.txtPage] + " {}/{}".format(prev, self._currentSubsetCount)
        self._btnPrev.setText(text)
        
        text = lang[lng.txtPage] + " {}/{}".format(next, self._currentSubsetCount)
        self._btnNext.setText(text)

    def _updateYearState(self):
        """Update internal variables that depend on the selected category"""
        self._currentMovies = self._datamodel.allMovies.get(self._years[self._currentYearIx])
        self._currentMovieCount = len(self._currentMovies)
        self._currentSubsetIndex = 0
        self._currentSubsetCount = (len(self._currentMovies) + self._subsetSize - 1) / self._subsetSize

    def _setPlayMode(self):
        """Enable player, disable preview"""
        for button in self._activeInPreview:
            button.setEnabled(False)

        self._btnPlay.setText(lang[lng.txtStop])
        self._btnPlay.setCommand(self._ehStop)

        self._canvas.itemconfigure(self._playerwnd, state = NORMAL)
        self._previewFrame.setVisible(False)
        self._mode = _play

    def _setPreviewMode(self):
        """Enable preview, disable player"""
        for button in self._activeInPreview:
            button.setEnabled(True)

        self._btnPlay.setText(lang[lng.txtPlay])
        self._btnPlay.setCommand(self._ehPlay)
        
        self._canvas.itemconfigure(self._playerwnd, state = HIDDEN)
        self._previewFrame.setVisible(True)
        self._mode = _preview

    def _setSubset(self):
        """Display a subset of the available media items"""
        self._updateBrowseButtons()
        start = self._subsetSize * self._currentSubsetIndex
        stop = min(start + self._subsetSize + 1, self._currentMovieCount)
        self._previewFrame.previewsubset(self._currentMovies[start:stop])
        
    def _play(self):
        """Start playback"""
        self._setPlayMode()
        self._datacollector.addStatisticLine(lng.txtPlaybackStarted)
        
        try:
            self._playerFrame.play(self._previewFrame.selecteditem)
        except:
            self._playbackStopped()

    def _stop(self):
        """Stop playback"""
        #Update time to ensure that the session doesn't end because of the movie length
        self._datacollector.reset()
        self._datacollector.addStatisticLine(lng.txtUserStoppedPlayback)
        self._userstop = True
        self._playerFrame.stop()

    #Callbacks
    def _playbackStopped(self):
        """Handle user data collection and set preview mode"""
        if(not self._userstop):
            self._datacollector.reset()
            self._datacollector.addStatisticLine(lng.txtPlaybackFinished)
            self._userstop = False

        self._setPreviewMode()

    def _clbClicked(self):
        """Switch between playback and preview depending on mode"""
        if(self._mode == _preview):
            self._play()
        elif(self._mode == _play):
            self._stop()

    #Event handlers
    def _ehPlay(self, event, tb):
        """Handle play event
        
        Arguments
        event -- event object
        tb -- transparent button instance
        
        """
        self._play()
        
    def _ehStop(self, event, tb):
        """Handle stop event
        
        Arguments
        event -- event object
        tb -- transparent button instance
        
        """
        self._stop()

    def _ehYear(self, event, tb):
        """Handle an event from one of the category buttons
        
        Arguments
        event -- event object
        tb -- transparent button instance
        
        """
        self._datacollector.detect()
        
        self._currentYearIx = tb.index
        self._updateYearState()
        self._updateBrowseButtons()
        self._previewFrame.previewsubset(self._currentMovies[:self._subsetSize])

    def _ehPrev(self, event, tb):
        """Handle an event from the browse backward button
        
        Arguments
        event -- event object
        tb -- transparent button instance
        
        """
        self._datacollector.detect()
        if(self._currentSubsetIndex > 0):
            self._currentSubsetIndex -= 1
        else:
            self._currentSubsetIndex = self._currentSubsetCount - 1
            
        self._setSubset()
                    
    def _ehNext(self, event, tb):
        """Handle an event from the browse forward button
        
        Arguments
        event -- event object
        tb -- transparent button instance
        
        """
        
        self._datacollector.detect()
        if(self._currentSubsetIndex < (self._currentSubsetCount - 1)):
            self._currentSubsetIndex += 1
        else:
            self._currentSubsetIndex = 0
            
        self._setSubset()