Ejemplo n.º 1
0
 def fade(self):
     if self.windowOpacity() == 1:
         self.animationTimer = RepeatTimer(0.025, self.fadeOut, 40)
         self.animationTimer.start()
     else:
         self.animationTimer = RepeatTimer(0.025, self.fadeIn, 40)
         self.animationTimer.start()
Ejemplo n.º 2
0
    def beginCountdown(self):
        self.trayIcon.setToolTip('Quiz in progress!')
        self.pauseAction.setText('&Pause')
        self.pauseAction.setShortcut('P')

        self.countdownTimer.start(self.options.getCountdownInterval() * 1000)

        self.progressTimer = RepeatTimer(
            0.01, self.updateCountdownBar,
            self.options.getCountdownInterval() * 100)
        self.progressTimer.start()
Ejemplo n.º 3
0
class Quiz(QFrame):
    def __init__(self, parent=None):
        super(Quiz, self).__init__(parent)
        """Session Info"""
        self.status = QFrame()
        ##session message
        self.status.message = QLabel(u'')
        self.status.layout = QHBoxLayout()
        self.status.layout.addWidget(self.status.message)
        self.status.setLayout(self.status.layout)
        ##mouse event filter
        #self.status.filter = StatusFilter()
        self.status.setAttribute(Qt.WA_Hover, True)
        #self.status.installEventFilter(self.status.filter)
        """Items Info"""
        self.info = QFrame()
        self.info.reading = QLabel(u'')
        self.info.item = QLabel(u'')
        self.info.components = QLabel(u'')

        self.info.translation = QLabel(u'')
        self.info.translation.setAlignment(Qt.AlignCenter)
        self.info.translation.setWordWrap(True)

        #        separator_one = QFrame()
        #        separator_one.setFrameShape(QFrame.HLine)
        #        separator_one.setFrameShadow(QFrame.Sunken)
        #
        #        separator_two = QFrame()
        #        separator_two.setFrameShape(QFrame.HLine)
        #        separator_two.setFrameShadow(QFrame.Sunken)

        self.info.layout = QVBoxLayout()
        self.info.layout.addWidget(self.info.translation)
        #        self.info.layout.addWidget(self.info.reading)
        #        self.info.layout.addWidget(separator_one)
        #        self.info.layout.addWidget(self.info.item)
        #        self.info.layout.addWidget(separator_two)
        #        self.info.layout.addWidget(self.info.components)
        self.info.setLayout(self.info.layout)
        """Verbose Info"""
        self.allInfo = QFrame()
        self.allInfo.layout = QGridLayout()
        self.allInfo.setLayout(self.allInfo.layout)
        #the rest is (should be) generated on the fly
        """Global Flags"""
        #self.correct = False
        """Quiz Dialog"""
        self.filter = Filter()
        ####    visual components    ###
        self.countdown = QProgressBar()
        self.sentence = QLabel(u'')

        #        self.var_1st = QPushButton(u'')
        #        self.var_2nd = QPushButton(u'')
        #        self.var_3rd = QPushButton(u'')
        #        self.var_4th = QPushButton(u'')

        self.isKnown = QPushButton(u'Good')
        self.isNotKnown = QPushButton(u'Again')

        self.answered = QPushButton(u'')
        self.answered.hide()

        ###    layouts    ####
        self.layout_vertical = QVBoxLayout()  #main
        self.layout_horizontal = QHBoxLayout()  #buttons

        #        self.layout_horizontal.addWidget(self.var_1st)
        #        self.layout_horizontal.addWidget(self.var_2nd)
        #        self.layout_horizontal.addWidget(self.var_3rd)
        #        self.layout_horizontal.addWidget(self.var_4th)

        self.layout_horizontal.addWidget(self.isKnown)
        self.layout_horizontal.addWidget(self.isNotKnown)

        self.layout_vertical.addWidget(self.countdown)
        self.layout_vertical.addWidget(self.sentence)
        self.layout_vertical.addLayout(self.layout_horizontal)

        self.layout_horizontal.addWidget(self.answered)

        self.setLayout(self.layout_vertical)

        ###    utility components    ###
        self.trayIcon = QSystemTrayIcon(self)
        self.trayMenu = QMenu()

        self.gifLoading = QMovie('../res/cube.gif')
        self.gifLoading.frameChanged.connect(self.updateTrayIcon)

        self.nextQuizTimer = QTimer()
        self.nextQuizTimer.setSingleShot(True)
        self.nextQuizTimer.timeout.connect(self.showQuiz)

        self.countdownTimer = QTimer()
        self.countdownTimer.setSingleShot(True)
        self.countdownTimer.timeout.connect(self.timeIsOut)

        ### initializing ###
        self.initializeResources()
        """Start!"""
        if self.options.isQuizStartingAtLaunch():
            self.waitUntilNextTimeslot()
            self.trayIcon.setToolTip('Quiz has started automatically!')
            self.pauseAction.setText('&Pause')
            self.trayIcon.showMessage(
                'Loading complete! (took ~' + str(self.loadingTime.seconds) +
                ' seconds) Quiz underway.', 'Lo! Quiz already in progress!',
                QSystemTrayIcon.MessageIcon.Warning, 10000)
        else:
            self.trayIcon.setToolTip('Quiz is not initiated!')
            self.trayIcon.showMessage(
                'Loading complete! (took ~' + str(self.loadingTime.seconds) +
                ' seconds) Standing by.',
                'Quiz has not started yet! If you wish, you could start it manually or enable autostart by default.',
                QSystemTrayIcon.MessageIcon.Information, 10000)
        """Test calls here:"""
        ###    ...    ###
        #self.connect(self.hooker, SIGNAL('noQdict'), self.noQdict)

    def noQdict(self):
        self.showSessionMessage(
            'Nope, cannot show quick dictionary during actual quiz.')

####################################
#    Initialization procedures     #
####################################

    def initializeResources(self):
        """Pre-initialization"""
        self.animationTimer = ()
        self.progressTimer = ()
        self.grid_layout = ()
        """Initialize Options"""
        self.options = Options()
        """Initialize Statistics"""
        self.stats = Stats()
        """Config Here"""
        self.initializeComposition()
        self.initializeComponents()
        self.setMenus()
        self.trayIcon.show()
        #self.startTrayLoading()
        """"Initialize Dictionaries    (will take a some time!)"""
        time_start = datetime.now()
        self.dict = EdictParser()
        self.dict.loadDict()

        self.morphy = get_morph(PATH_TO_RES + DICT_EN)

        self.trayIcon.showMessage(
            'Loading...', 'Initializing dictionaries',
            QSystemTrayIcon.MessageIcon.Information,
            20000)  #TODO: change into loading dialog... or not
        """Initializing srs system"""
        self.trayIcon.showMessage('Loading...', 'Initializing databases',
                                  QSystemTrayIcon.MessageIcon.Information,
                                  20000)
        self.srs = srsScheduler()
        self.srs.initializeAll()
        self.srs.initializeCurrentSession(self.options.getSessionSize())
        """Global hotkeys hook"""
        #TODO: add multiple hotkeys and fix stop()
        #self.hooker = GlobalHotkeyManager(toggleQDictFlag, 'Q')
        #        self.hooker = GlobalHotkeyManager(toggleWidgetFlag(self.qdict), 'Q')
        #        self.hooker.setDaemon(True) #temporarily, should work using stop()
        #        self.hooker.start()

        time_end = datetime.now()
        self.loadingTime = time_end - time_start

####################################
#    Composition and appearance    #
####################################

    def initializeComposition(self):
        """Main Dialog"""
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        #Font will appear in buttons
        self.setFont(
            QFont(self.options.getQuizFont(), self.options.getQuizFontSize()))

        desktop = QApplication.desktop().screenGeometry()
        self.setGeometry(
            QRect(desktop.width() - H_INDENT,
                  desktop.height() - V_INDENT, D_WIDTH, D_HEIGHT))

        self.setStyleSheet("QWidget { background-color: rgb(255, 255, 255); }")
        """Info dialog"""
        self.info.setWindowFlags(Qt.FramelessWindowHint
                                 | Qt.WindowStaysOnTopHint)
        self.info.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        self.info.setGeometry(
            QRect(desktop.width() - H_INDENT - I_WIDTH - I_INDENT,
                  desktop.height() - V_INDENT, I_WIDTH, I_HEIGHT))
        self.info.setFixedSize(I_WIDTH, I_HEIGHT)

        self.info.setStyleSheet(
            "QWidget { background-color: rgb(255, 255, 255); }")
        """Verbose info dialog"""
        self.allInfo.setWindowFlags(Qt.FramelessWindowHint
                                    | Qt.WindowStaysOnTopHint)
        self.allInfo.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        self.allInfo.setGeometry(
            QRect(desktop.width() - H_INDENT - I_WIDTH - I_INDENT,
                  desktop.height() - V_INDENT, I_WIDTH, I_HEIGHT))

        self.allInfo.setStyleSheet(
            "QWidget { background-color: rgb(255, 255, 255); }")
        """Session message"""
        self.status.setWindowFlags(Qt.FramelessWindowHint
                                   | Qt.WindowStaysOnTopHint)
        self.status.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        self.status.setGeometry(
            QRect(
                desktop.width() - H_INDENT,
                desktop.height() - V_INDENT - S_HEIGHT - S_INDENT -
                S_CORRECTION, S_WIDTH, S_HEIGHT))

        self.status.setStyleSheet(
            "QWidget { background-color: rgb(255, 255, 255); }")

        self.setMask(roundCorners(self.rect(), 5))
        self.status.setMask(roundCorners(self.status.rect(), 5))
        #self.info.setMask(roundCorners(self.info.rect(),5))
        #self.allInfo.setMask(roundCorners(self.allInfo.rect(),5))

    def initializeComponents(self):
        self.countdown.setMaximumHeight(6)
        self.countdown.setRange(0, self.options.getCountdownInterval() * 100)
        self.countdown.setTextVisible(False)
        self.countdown.setStyleSheet(
            "QProgressbar { background-color: rgb(255, 255, 255); }")

        #self.setFont(QFont(Fonts.SyoutyouProEl, 40))#self.options.getQuizFontSize()))

        self.sentence.setAlignment(Qt.AlignmentFlag.AlignCenter)
        #self.sentence.setFont(QFont(Fonts.HiragiNoMarugotoProW4, self.options.getSentenceFontSize()))
        self.sentence.setFont(
            QFont(self.options.getSentenceFont(),
                  self.options.getSentenceFontSize()))

        self.sentence.setWordWrap(True)
        self.trayIcon.setIcon(QIcon(PATH_TO_RES + TRAY + 'active.png'))

        self.status.message.setFont(
            QFont('Cambria', self.options.getMessageFontSize()))
        self.status.layout.setAlignment(Qt.AlignCenter)
        self.status.message.setWordWrap(False)
        self.status.layout.setMargin(0)

        self.info.item.setFont(QFont(Fonts.HiragiNoMyoutyouProW3, 36))
        self.info.reading.setFont(QFont(Fonts.HiragiNoMyoutyouProW3, 16))
        self.info.components.setFont((QFont(Fonts.HiragiNoMyoutyouProW3, 14)))
        #self.info.item.setWordWrap(True)
        self.info.components.setWordWrap(True)
        #self.info.layout.setAlignment(Qt.AlignCenter)
        self.info.layout.setMargin(0)
        #self.info.layout.setSizeConstraint(self.info.layout.SetFixedSize)       #NB: would work nice, if the anchor point was in right corner

        self.info.reading.setAlignment(Qt.AlignCenter)
        self.info.item.setAlignment(Qt.AlignCenter)
        self.info.components.setAlignment(Qt.AlignCenter)

        #self.info.setLayoutDirection(Qt.RightToLeft)

        self.info.reading.setStyleSheet(
            "QLabel { color: rgb(155, 155, 155); }")
        self.info.components.setStyleSheet(
            "QLabel { color: rgb(100, 100, 100); }")

        self.info.gem = self.info.saveGeometry()

####################################
#        Updating content          #
####################################

    def updateContent(self):
        """Resetting multi-label sentence"""
        if self.grid_layout != ():
            for i in range(0, self.grid_layout.count()):
                self.grid_layout.itemAt(i).widget().hide()
            self.layout_vertical.removeItem(self.grid_layout)
            self.grid_layout.setParent(None)
            self.update()
        if self.sentence.isHidden():
            self.sentence.show()
        self.showButtonsQuiz()
        """Getting actual content"""
        self.srs.getNextItem()

        start = datetime.now()  #testing
        #example = self.srs.getCurrentExample().replace(self.srs.getWordFromExample(), u"<font color='blue'>" + self.srs.getWordFromExample() + u"</font>")
        example = self.srs.getCurrentExample().replace(
            self.srs.getCurrentItem(),
            u"<font color='blue'>" + self.srs.getCurrentItem() + u"</font>")
        print datetime.now() - start  #testing
        self.sentence.setText(example)

        #        start = datetime.now()  #testing
        #        readings = self.srs.getQuizVariants()
        #        print datetime.now() - start    #testing
        '''
        changeFont = False
        for item in readings:
            if len(item) > 5 : changeFont = True
            
        if changeFont: self.setStyleSheet('QWidget { font-size: 11pt; }')
        else:   self.setStyleSheet('QWidget { font-size: %spt; }' % self.options.getQuizFontSize())
        '''
        '''
        if len(readings) == 4:                  #NB: HERE LIES THE GREAT ERROR
            self.var_1st.setText(readings[0])
            self.var_2nd.setText(readings[1])
            self.var_3rd.setText(readings[2])
            self.var_4th.setText(readings[3])
        '''

#        try:
#            for i in range(0, self.layout_horizontal.count()):
#                    if i > 3: break
#                    self.layout_horizontal.itemAt(i).widget().setText(u'')
#                    #self.layout_horizontal.itemAt(i).setStyleSheet('QPushButton { font-size: 11pt; }')
#                    self.layout_horizontal.itemAt(i).widget().setText(readings[i])
#        except:
#            print 'Not enough quiz variants'
#TODO: log this

    def getReadyPostLayout(self):
        self.sentence.hide()
        self.update()

        self.grid_layout = QGridLayout()
        self.grid_layout.setSpacing(0)
        self.labels = []

        columns_mod = 0

        if len(self.srs.currentExample['eng']) > SENTENCE_MAX:
            font = QFont(self.options.getSentenceFont(), MIN_FONT_SIZE)
            columns_mod = 6
        else:
            font = QFont(self.options.getSentenceFont(),
                         self.options.getSentenceFontSize())

        #row, column, rows span, columns span, max columns
        i = 0
        j = 0
        r = 1
        c = 1
        n = COLUMNS_MAX + columns_mod
        for word in self.srs.parseCurrentExample():
            label = QLabel(word)
            #            label.setFont(QFont(self.options.getSentenceFont(), self.options.getSentenceFontSize()))
            label.setFont(font)

            label.setAttribute(Qt.WA_Hover, True)
            label.installEventFilter(self.filter)
            self.labels.append(label)

            if len(label.text()) > 1: c = len(label.text())
            else: c = 1
            #Don't ask, really
            if j + c > n:
                i = i + 1
                j = 0

            self.grid_layout.addWidget(self.labels.pop(), i, j, r, c)

            if j <= n: j = j + c
            else:
                j = 0
                i = i + 1

        self.grid_layout.setAlignment(Qt.AlignCenter)
        self.layout_vertical.insertLayout(1, self.grid_layout)

        self.update()

    def hideButtonsQuiz(self):
        self.isKnown.hide()
        self.isNotKnown.hide()

        self.answered.clicked.connect(self.hideQuizAndWaitForNext)
        self.answered.show()

    def showButtonsQuiz(self):
        self.isKnown.show()
        self.isNotKnown.show()

        self.answered.hide()
        self.answered.disconnect()

####################################
#        Timers and animations     #
####################################

    def waitUntilNextTimeslot(self):
        #if self.nextQuizTimer.isActive():   self.nextQuizTimer.stop()
        self.nextQuizTimer.start(
            self.options.getRepetitionInterval() * 60 * 1000
        )  #options are in minutes    NB: how do neatly I convert minutes to ms?

    def beginCountdown(self):
        self.trayIcon.setToolTip('Quiz in progress!')
        self.pauseAction.setText('&Pause')
        self.pauseAction.setShortcut('P')

        self.countdownTimer.start(self.options.getCountdownInterval() * 1000)

        self.progressTimer = RepeatTimer(
            0.01, self.updateCountdownBar,
            self.options.getCountdownInterval() * 100)
        self.progressTimer.start()

    def updateCountdownBar(self):
        self.countdown.setValue(self.countdown.value() - 1)
        #print self.countdown.value()
        self.countdown.update(
        )  #NB: without .update() recursive repaint crushes qt

    def fade(self):
        if self.windowOpacity() == 1:
            self.animationTimer = RepeatTimer(0.025, self.fadeOut, 40)
            self.animationTimer.start()
        else:
            self.animationTimer = RepeatTimer(0.025, self.fadeIn, 40)
            self.animationTimer.start()

    def fadeIn(self):
        self.setWindowOpacity(self.windowOpacity() + 0.1)

    def fadeOut(self):
        self.setWindowOpacity(self.windowOpacity() - 0.1)

    def stopCountdown(self):
        self.progressTimer.cancel()
        self.countdownTimer.stop()
        self.countdown.setValue(0)

####################################
#        Actions and events        #
####################################

    def setMenus(self):
        self.trayMenu.addAction(
            QAction('&Quiz me now!',
                    self,
                    shortcut="Q",
                    triggered=self.showQuiz))
        self.pauseAction = QAction('&Start quiz!',
                                   self,
                                   shortcut="S",
                                   triggered=self.pauseQuiz)
        self.trayMenu.addAction(self.pauseAction)
        self.trayMenu.addSeparator()
        self.trayMenu.addAction(
            QAction('Quick &dictionary',
                    self,
                    shortcut="D",
                    triggered=self.showQuickDict))
        self.trayMenu.addAction(
            QAction('&Global &statistics',
                    self,
                    shortcut="G",
                    triggered=self.showGlobalStatistics))
        self.trayMenu.addAction(
            QAction('&Options', self, shortcut="O",
                    triggered=self.showOptions))
        self.trayMenu.addAction(
            QAction('&About', self, shortcut="A", triggered=self.showAbout))
        self.trayMenu.addSeparator()
        self.trayMenu.addAction(
            QAction('&Exit', self, shortcut="E", triggered=self.saveAndExit))

        self.trayIcon.setContextMenu(self.trayMenu)
        self.trayIcon.activated.connect(self.onTrayIconActivated)

    #TODO: show session statistics
    def onTrayIconActivated(self, reason):
        '''
        if reason == QSystemTrayIcon.DoubleClick:
            print 'tray icon double clicked'
        '''
        if reason == QSystemTrayIcon.Trigger:
            if self.isHidden():
                self.trayIcon.showMessage(
                    'Current session statistics:',
                    'Running time:\t\t' + self.stats.getRunningTime() +
                    '\nItems seen:\t\t' + str(self.stats.totalItemSeen) +
                    '\nCorrect answers:\t\t' +
                    str(self.stats.answeredCorrect) + '\nWrong answers:\t\t' +
                    self.stats.getIncorrectAnswersCount() +
                    '\nCorrect ratio:\t\t' +
                    self.stats.getCorrectRatioPercent() +
                    #'\nQuiz total time:\t\t' + self.stats.getQuizActive() +
                    '\nQuiz paused time:\t\t' + self.stats.getPausedTime() +
                    '\nTotal pondering time:\t' + self.stats.getMusingsTime() +
                    '\nTotal post-quiz time:\t' + self.stats.getQuizTime() +
                    '\nAverage pondering:\t' +
                    self.stats.getAverageMusingTime() +
                    '\nAverage post-quiz:\t' +
                    self.stats.getAveragePostQuizTime(),
                    QSystemTrayIcon.MessageIcon.Information,
                    20000)

    def setButtonsActions(self):
        self.isKnown.clicked.connect(self.correctAnswer)
        self.isNotKnown.clicked.connect(self.wrongAnswer)

    def resetButtonsActions(self):
        self.isKnown.disconnect()
        self.isNotKnown.disconnect()

    def postAnswerActions(self):
        self.stats.musingsStopped()
        self.stats.postQuizStarted()

        self.stopCountdown()
        self.hideButtonsQuiz()

        self.getReadyPostLayout()

    def checkTranslationSize(self, translation):
        if len(translation) > TRANSLATION_CHARS_LIMIT:
            self.answered.setStyleSheet('QPushButton { font-size: 9pt; }')

            space_indices = [
                i for i, value in enumerate(translation) if value == ' '
            ]
            find_nearest_index = lambda value, list: min(
                list, key=lambda x: abs(x - value))
            nearest_index = find_nearest_index(TRANSLATION_CHARS_LIMIT,
                                               space_indices)
            translation = translation[:nearest_index] + '\n' + translation[
                nearest_index + 1:]
        else:
            self.answered.setStyleSheet('QPushButton { font-size: 11pt; }')

        self.answered.setText(translation)

    def correctAnswer(self):
        '''
        self.stats.musingsStopped()
        self.stats.postQuizStarted()
        
        self.stopCountdown()
        self.hideButtonsQuiz()
        
        self.getReadyPostLayout()
        '''
        self.postAnswerActions()

        self.srs.answeredCorrect()
        self.stats.quizAnsweredCorrect()
        #self.answered.setText(u"<font='Cambria'>" + self.srs.getCurrentSentenceTranslation() + "</font>")
        #        self.answered.setText(self.srs.getCurrentSentenceTranslation())

        self.checkTranslationSize(self.srs.getCurrentSentenceTranslation())

        #self.answered.setFont(QFont('Calibri', 11))
        self.showSessionMessage(
            u'<font color=green>Correct: OK</font>\t|\tNext quiz: ' +
            self.srs.getNextQuizTime() + '\t|\t<font color=' +
            self.srs.getLeitnerGradeAndColor()['color'] + '>Grade: ' +
            self.srs.getLeitnerGradeAndColor()['grade'] + ' (' +
            self.srs.getLeitnerGradeAndColor()['name'] + ')<font>')

        #self.answered.setShortcut('5')
        #self.setFocus()

    def wrongAnswer(self):
        '''
        self.stats.musingsStopped()
        self.stats.postQuizStarted()
        
        self.stopCountdown()
        self.hideButtonsQuiz()
        
        self.getReadyPostLayout()
        '''
        self.postAnswerActions()

        self.srs.answeredWrong()
        self.stats.quizAnsweredWrong()

        #        self.answered.setText(self.srs.getCurrentSentenceTranslation())

        self.checkTranslationSize(self.srs.getCurrentSentenceTranslation())

        #self.answered.setFont(QFont('Calibri', 11))
        #self.showSessionMessage(u"Wrong! Should be: <font style='font-family:" + Fonts.MSMyoutyou + "'>"
        #+ self.srs.getCorrectAnswer() + "</font> - Next quiz: " + self.srs.getNextQuizTime())
        self.showSessionMessage(
            u'<font color=tomato>Bad</font>\t|\tNext quiz: ' +
            self.srs.getNextQuizTime() + '\t|\t<font color=' +
            self.srs.getLeitnerGradeAndColor()['color'] + '>Grade: ' +
            self.srs.getLeitnerGradeAndColor()['grade'] + ' (' +
            self.srs.getLeitnerGradeAndColor()['name'] + ')<font>')

    def timeIsOut(self):
        self.stats.musingsStopped()
        self.stats.postQuizStarted()

        QTimer.singleShot(
            50, self.hideButtonsQuiz
        )  #NB: slight artificial lag to prevent recursive repaint crush, when mouse is suddenly over appearing button
        self.getReadyPostLayout()

        self.srs.answeredWrong()
        self.stats.quizAnsweredWrong()

        #self.showSessionMessage(u'Time is out! Correct answer is:' + self.srs.getCorrectAnswer())
        #        self.answered.setFont(QFont('Calibri', 11))
        #        self.answered.setText(self.srs.getCurrentSentenceTranslation())

        self.checkTranslationSize(self.srs.getCurrentSentenceTranslation())

        self.showSessionMessage(
            u'<font color=tomato>Timeout!</font>\t|\tNext quiz: ' +
            self.srs.getNextQuizTime() + '\t|\t<font color=' +
            self.srs.getLeitnerGradeAndColor()['color'] + '>Grade: ' +
            self.srs.getLeitnerGradeAndColor()['grade'] + ' (' +
            self.srs.getLeitnerGradeAndColor()['name'] + ')<font>')

    def hideQuizAndWaitForNext(self):
        self.stats.postQuizEnded()

        self.status.hide()
        self.info.hide()
        self.allInfo.hide()
        self.resetButtonsActions()

        self.setWindowOpacity(1)
        self.fade()
        QTimer.singleShot(1000, self.hide)
        self.waitUntilNextTimeslot()
        #self.updater.mayUpdate = True

    def pauseQuiz(self):
        if self.isHidden():
            if self.pauseAction.text() == '&Pause':
                self.nextQuizTimer.stop()
                self.pauseAction.setText('&Unpause')
                self.pauseAction.setShortcut('U')
                self.trayIcon.setToolTip('Quiz paused!')

                self.trayIcon.setIcon(
                    QIcon(PATH_TO_RES + TRAY + 'inactive.png'))
                self.stats.pauseStarted()

                #self.updater.mayUpdate = True

            elif self.pauseAction.text() == '&Start quiz!':
                self.waitUntilNextTimeslot()
                self.pauseAction.setText('&Pause')
                self.pauseAction.setShortcut('P')
                self.trayIcon.setToolTip('Quiz in progress!')

                self.trayIcon.setIcon(QIcon(PATH_TO_RES + TRAY + 'active.png'))
            else:
                self.waitUntilNextTimeslot()
                self.pauseAction.setText('&Pause')
                self.pauseAction.setShortcut('P')
                self.trayIcon.setToolTip('Quiz in progress!')

                self.trayIcon.setIcon(QIcon(PATH_TO_RES + TRAY + 'active.png'))
                self.stats.pauseEnded()

                #self.updater.mayUpdate = False
        else:
            self.showSessionMessage(
                u'Sorry, cannot pause while quiz in progress!')

    def showQuiz(self):
        if self.isHidden():
            self.updateContent()
            self.setButtonsActions()

            self.show()
            self.setWindowOpacity(0)
            self.fade()

            self.countdown.setValue(self.options.getCountdownInterval() * 100)
            self.beginCountdown()
            self.stats.musingsStarted()

            if self.nextQuizTimer.isActive(): self.nextQuizTimer.stop()
            #self.updater.mayUpdate = False
        else:
            self.showSessionMessage(u'Quiz is already underway!')

    def showOptions(self):
        self.optionsDialog.show()

    def showAbout(self):
        self.about.show()

    def showQuickDict(self):
        self.qdict.showQDict = True

    def showGlobalStatistics(self):
        print '...'

    def startTrayLoading(self):
        self.gifLoading.start()
        #self.iconTimer = QTimer()
        #self.iconTimer.timeout.connect(self.updateTrayIcon)
        #self.iconTimer.start(100)

    def stopTrayLoading(self):
        self.gifLoading.stop()

    def updateTrayIcon(self):
        self.trayIcon.setIcon(self.gifLoading.currentPixmap())

    def showSessionMessage(self, message):
        """Shows info message"""
        self.status.message.setText(message)
        self.status.show()
        #self.setFocus() #NB: does not work

    def saveAndExit(self):
        self.hide()
        self.status.hide()
        self.allInfo.hide()
        self.trayIcon.showMessage('Shutting down...', 'Saving session',
                                  QSystemTrayIcon.MessageIcon.Information,
                                  20000)
        #self.startTrayLoading()

        if self.countdownTimer.isActive():
            self.countdownTimer.stop()
        if self.nextQuizTimer.isActive():
            self.nextQuizTimer.stop()
        if self.progressTimer != () and self.progressTimer.isAlive():
            self.progressTimer.cancel()

        self.srs.endCurrentSession()
        self.trayIcon.hide()

        #        self.hooker.stop()

        #self.updater.stop()
        self.optionsDialog.close()
        self.about.close()
        #self.qdict.close()
        self.close()

    def addReferences(self, about, options, qdict, updater):
        self.about = about
        self.optionsDialog = options
        self.qdict = qdict
        self.updater = updater

    def initGlobalHotkeys(self):
        def toggleWidgetFlag():
            self.qdict.showQDict = True

        self.hooker = GlobalHotkeyManager(toggleWidgetFlag, 'Q')
        self.hooker.setDaemon(True)
        self.hooker.start()
Ejemplo n.º 4
0
class OptionsDialog(QFrame):
    def __init__(self, db, freq, options, parent=None):
        super(OptionsDialog, self).__init__(parent)
        # db & options handlers
        self.db = db
        self.freq = freq
        self.options = options
        self.dbItems = self.db.countTotalItemsInDb()
        self.totalItemsInRange = 0

        # status info
        self.status = QFrame()
        self.status.info = QLabel(u'')
        self.status.layout = QHBoxLayout()
        self.status.layout.addWidget(self.status.info)
        self.status.setLayout(self.status.layout)

        # all items info
        self.items = QDialog()
        self.items.layout = QGridLayout()
        self.items.infoLayout = QHBoxLayout()
        # filter
        self.filter = StatusFilter()

        ### runtime group ###
        self.appOptionsGroup = QGroupBox('Runtime')
        self.appOptionsGroup.setAlignment(Qt.AlignCenter)
        self.checkAutostart = QCheckBox('Begin quiz on application start')
        self.checkEnableLog = QCheckBox('Enable errors logging')
        self.checkEnableFade = QCheckBox('Enable fade effect')
        self.checkAlwaysOnTop = QCheckBox('Always on top')
        self.checkSoundSignal = QCheckBox('Announce quiz with sound')
        self.checkSplashScreen = QCheckBox('Splash screen on launch')
        self.checkGlobalHotkeys = QCheckBox('Enable global hotkeys')
        self.checkItemsBackground = QCheckBox('Show colorful background')
        self.checkPlastiqueTheme = QCheckBox("Use 'plastique' theme")
        self.checkPreloadDictionary = QCheckBox(
            "Load jmdict into memory on start")

        self.appLayout = QVBoxLayout()
        self.appLayout.addWidget(self.checkAutostart)
        self.appLayout.addWidget(self.checkSplashScreen)
        self.appLayout.addWidget(self.checkAlwaysOnTop)
        self.appLayout.addWidget(self.checkSoundSignal)
        self.appLayout.addWidget(self.checkEnableFade)
        self.appLayout.addWidget(self.checkEnableLog)
        self.appLayout.addWidget(self.checkGlobalHotkeys)
        self.appLayout.addWidget(self.checkItemsBackground)
        self.appLayout.addWidget(self.checkPlastiqueTheme)
        self.appLayout.addWidget(self.checkPreloadDictionary)

        self.appOptionsGroup.setLayout(self.appLayout)

        ### fonts group ###
        self.appFontsGroup = QGroupBox('Fonts')
        self.appFontsGroup.setAlignment(Qt.AlignCenter)
        self.sentenceFontLabel = QLabel(u'Sentence:')
        self.selectSentenceFont = QFontComboBox()
        self.quizFontLabel = QLabel(u'Quiz:')
        self.selectQuizFont = QFontComboBox()
        self.infoFontLabel = QLabel(u'Kanji info:')
        self.selectInfoFont = QFontComboBox()
        self.statusFontLabel = QLabel(u'Status message:')
        self.selectStatusFont = QFontComboBox()

        self.fontsLayout = QVBoxLayout()
        self.fontsLayout.addWidget(self.sentenceFontLabel)
        self.fontsLayout.addWidget(self.selectSentenceFont)
        self.fontsLayout.addWidget(self.quizFontLabel)
        self.fontsLayout.addWidget(self.selectQuizFont)
        self.fontsLayout.addWidget(self.infoFontLabel)
        self.fontsLayout.addWidget(self.selectInfoFont)
        self.fontsLayout.addWidget(self.statusFontLabel)
        self.fontsLayout.addWidget(self.selectStatusFont)

        self.appFontsGroup.setLayout(self.fontsLayout)

        ### srs group ###
        self.srsGroup = QGroupBox('SRS Tweaks')
        self.srsGroup.setAlignment(Qt.AlignCenter)

        self.intervalLabel = QLabel(u'Interval between quizzes (minutes):')
        self.countdownlLabel = QLabel(u'Time for answer (seconds):')
        self.intervalSpin = QSpinBox()
        self.intervalDial = QDial()

        self.countdownSpin = QSpinBox()
        self.countdownDial = QDial()

        self.sessionItemsLabel = QLabel(u'Sample size:')
        self.sessionItemsLabel.setToolTip(
            u'Maximum number of unique items, selected for current session from active database.'
        )
        self.sessionItemsSpin = QSpinBox()
        self.sessionLengthLabel = QLabel(u'Session limit:')
        self.sessionLengthLabel.setToolTip(
            u'Maximum allowed repetitions/day, including non-unique items.')
        self.sessionLengthSpin = QSpinBox()

        #        self.sessionModeLabel = QLabel(u'Quiz mode:')
        #        self.sessionModeCombo = QComboBox()

        #TODO: add leitner coefficient tweak (0.1 ~ 2.0)

        self.srsLayout = QGridLayout()
        self.srsLayout.addWidget(self.intervalLabel, 0, 0, 1, 2)
        self.srsLayout.addWidget(self.intervalDial, 1, 0)
        self.srsLayout.addWidget(self.intervalSpin, 1, 1)
        self.srsLayout.addWidget(self.countdownlLabel, 2, 0, 1, 2)
        self.srsLayout.addWidget(self.countdownDial, 3, 0)
        self.srsLayout.addWidget(self.countdownSpin, 3, 1)
        self.srsLayout.addWidget(self.sessionItemsLabel, 4, 0)
        self.srsLayout.addWidget(self.sessionItemsSpin, 4, 1)
        self.srsLayout.addWidget(self.sessionLengthLabel, 5, 0)
        self.srsLayout.addWidget(self.sessionLengthSpin, 5, 1)
        #        self.srsLayout.addWidget(self.sessionModeLabel, 6, 0)
        #        self.srsLayout.addWidget(self.sessionModeCombo, 6, 1)

        self.srsGroup.setLayout(self.srsLayout)

        ### dictionary group ###
        self.dictGroup = QGroupBox('JMdict')
        self.dictGroup.setAlignment(Qt.AlignCenter)

        self.languageLabel = QLabel(u'Translation lookup in:')
        self.languageCombo = QComboBox()

        self.shortcutLabel = QLabel(u'Hotkey: Ctrl + Alt + ')
        self.shortcutCombo = QComboBox()

        self.dictLayout = QGridLayout()
        self.dictLayout.addWidget(self.languageLabel, 0, 0)
        self.dictLayout.addWidget(self.languageCombo, 0, 1)
        self.dictLayout.addWidget(self.shortcutLabel, 1, 0)
        self.dictLayout.addWidget(self.shortcutCombo, 1, 1)

        self.dictGroup.setLayout(self.dictLayout)

        ### database group ###
        self.dbGroup = QGroupBox('Database')
        self.dbGroup.setAlignment(Qt.AlignCenter)

        #        self.totalLabel = QLabel(u'Kanji: <b>' + str(self.dbItems['kanji']) + '</b>\tWords: <b>' + str(self.dbItems['words']) + '</b>\tTotal: <b>%s</b>'
        #                                 % (self.dbItems['kanji'] + self.dbItems['words'])  )
        self.totalLabel = QLabel(u'Items: ' + str(self.dbItems['items']))
        self.totalLabel.setWordWrap(True)
        self.viewAll = QToolButton()
        separator_one = QFrame()
        separator_one.setFrameShape(QFrame.HLine)
        separator_one.setFrameShadow(QFrame.Sunken)
        self.viewAll.setText(u'View all')
        self.addLabel = QLabel(u'Batch-add items to studying list:')
        #        self.comboTag = QComboBox()
        #        self.comboLevel = QComboBox()
        #        self.comboCompare = QComboBox()
        #        self.inputFrequency = QLineEdit()
        #        self.inputFrequency.setToolTip(u'Enter character frequency (from 1 to 6265)')
        #        self.addButton = QPushButton(u'Add by grade')
        #        self.addButton.setToolTip(u'Update db according to specified criteria (duplicates will be ignored)')
        #        self.addButtonFrequency = QPushButton(u'Add by frequency')

        self.frequencyRange = RangeSlider(Qt.Horizontal)
        self.valueLow = QDoubleSpinBox()
        self.valueHigh = QDoubleSpinBox()
        self.addItemInRange = QPushButton(u'Add items in db')
        self.totalItemsLabel = QLabel(u'')

        self.purgeButton = QPushButton(u'Purge all data from database')
        self.purgeButtonCustom = QPushButton(u'Partial purge')
        #self.progressDb = QProgressBar()

        self.tagsView = QTableWidget()

        self.dbLayout = QGridLayout()
        self.dbLayout.addWidget(self.totalLabel, 0, 0, 1, 3)
        self.dbLayout.addWidget(self.viewAll, 0, 3, 1, 1)
        self.dbLayout.addWidget(separator_one, 1, 0, 1, 4)
        self.dbLayout.addWidget(self.addLabel, 2, 0, 1, 4)

        self.dbLayout.addWidget(self.valueLow, 3, 0, 1, 2)
        self.dbLayout.addWidget(self.valueHigh, 3, 2, 1, 2)
        self.dbLayout.addWidget(self.frequencyRange, 4, 0, 1, 4)
        self.dbLayout.addWidget(self.totalItemsLabel, 5, 0, 1, 4)
        self.dbLayout.addWidget(self.addItemInRange, 6, 0, 1, 4)

        #        self.dbLayout.addWidget(self.comboTag, 3, 0)
        #        self.dbLayout.addWidget(self.comboLevel, 3, 1)
        #        self.dbLayout.addWidget(self.comboCompare, 4, 0)
        #        self.dbLayout.addWidget(self.inputFrequency, 4, 1)
        #        self.dbLayout.addWidget(self.addButton, 3, 2, 1, 2)
        #        self.dbLayout.addWidget(self.addButtonFrequency, 4, 2, 1, 2)

        #        self.dbLayout.addWidget(self.tagsView, 5, 0, 1, 4)
        self.dbLayout.addWidget(self.purgeButton, 7, 0, 1, 4)
        self.dbLayout.addWidget(self.purgeButtonCustom, 8, 0, 1, 4)

        self.dbGroup.setLayout(self.dbLayout)

        ### toolbox ###
        self.toolbox = QToolBox()
        self.toolbox.addItem(self.appOptionsGroup, 'Application')
        self.toolbox.addItem(self.appFontsGroup, 'Fonts')
        self.toolbox.addItem(self.srsGroup, 'Spaced Repetition System')
        self.toolbox.addItem(self.dictGroup, 'Dictionaries')
        self.toolbox.addItem(self.dbGroup, 'Studying items')

        ### main layout ###
        self.mainLayout = QVBoxLayout()

        self.bBox = QDialogButtonBox(
            QDialogButtonBox.Save | QDialogButtonBox.Reset
            | QDialogButtonBox.Close)  #| QDialogButtonBox.Help)
        self.saveRestart = QPushButton(u'Save/Restart')
        self.bBox.addButton(self.saveRestart, QDialogButtonBox.ResetRole)

        self.mainLayout.addWidget(self.toolbox)
        self.mainLayout.addWidget(self.bBox)
        #self.mainLayout.addWidget(self.progressDb)

        self.setLayout(self.mainLayout)

        self.initializeComposition()
        self.initializeComponents()
        self.initializeActions()

        ### additional preparations ###
        self.updateComboLevel()
        self.updateDbTable()
        self.animationTimer = ()

        self.roundCorners()
        self.items.backgroundFlag = False

        self.updateFrequencyRange()

    def roundCorners(self):
        self.status.setMask(roundCorners(self.status.rect(), 5))
        self.setMask(roundCorners(self.rect(), 5))

    def initializeComposition(self):

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        desktop = QApplication.desktop().screenGeometry()

        self.setGeometry(
            QRect((desktop.width() - O_WIDTH) / 2,
                  (desktop.height() - O_HEIGHT) / 2, O_WIDTH, O_HEIGHT))

        self.setStyleSheet("QWidget { background-color: rgb(255, 255, 255) }")

        self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Maximum))

        self.status.setWindowFlags(Qt.FramelessWindowHint
                                   | Qt.WindowStaysOnTopHint)
        self.status.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)

        self.status.setGeometry((desktop.width() - O_WIDTH) / 2,
                                (desktop.height() + O_HEIGHT) / 2 + OS_INDENT,
                                O_WIDTH, OS_HEIGTH)
        self.status.setStyleSheet(
            "QWidget { background-color: rgb(255, 255, 255) }")

        self.status.layout.setAlignment(Qt.AlignCenter)
        self.status.layout.setMargin(0)

        self.items.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.items.setStyleSheet(
            "QDialog { background-color: rgb(255, 255, 255) }")

    def initializeComponents(self):

        self.status.info.setFont(
            QFont('Cambria', self.options.getMessageFontSize()))
        #        self.progressDb.setMaximumHeight(6)
        #        self.progressDb.setRange(0,0)
        #        self.progressDb.hide()

        self.appLayout.setAlignment(Qt.AlignCenter)
        self.mainLayout.setAlignment(Qt.AlignCenter)

        self.intervalDial.setNotchesVisible(True)
        self.intervalDial.setRange(1, 30)
        self.intervalDial.setSingleStep(1)

        self.intervalSpin.setRange(1, 30)

        self.countdownDial.setNotchesVisible(True)
        self.countdownDial.setRange(5, 45)
        self.countdownDial.setSingleStep(1)

        self.countdownSpin.setRange(5, 45)

        self.countdownSpin.setValue(self.options.getCountdownInterval())
        self.intervalSpin.setValue(self.options.getRepetitionInterval())

        #        self.sessionItemsSpin.setRange(1, self.dbItems['kanji'] + self.dbItems['words'])
        #        self.sessionLengthSpin.setRange(1, 4 * (self.dbItems['kanji'] + self.dbItems['words']))

        self.sessionItemsSpin.setRange(1, self.dbItems['items'])
        self.sessionLengthSpin.setRange(1, 4 * self.dbItems['items'])

        self.intervalDial.setValue(self.options.getRepetitionInterval())
        self.countdownDial.setValue(self.options.getCountdownInterval())

        self.sessionItemsSpin.setValue(self.options.getSessionSize())
        self.sessionLengthSpin.setValue(self.options.getSessionLength())

        self.checkAutostart.setChecked(self.options.isQuizStartingAtLaunch())
        self.checkSplashScreen.setChecked(self.options.isSplashEnabled())
        self.checkAlwaysOnTop.setChecked(self.options.isAlwaysOnTop())
        self.checkGlobalHotkeys.setChecked(self.options.isGlobalHotkeyOn())
        self.checkEnableLog.setChecked(self.options.isLoggingOn())
        self.checkEnableFade.setChecked(self.options.isFadeEffectOn())
        self.checkSoundSignal.setChecked(self.options.isSoundOn())
        self.checkItemsBackground.setChecked(self.options.isBackgroundOn())
        self.checkPlastiqueTheme.setChecked(self.options.isPlastique())
        self.checkPreloadDictionary.setChecked(self.options.isPreloading())

        #self.sessionModeCombo.addItems(['kanji', 'compounds', 'all'])
        self.languageCombo.addItems(['eng', 'rus'])
        self.shortcutCombo.addItems(['Q', 'D', 'J'])
        #self.comboTag.addItems(['jlpt', 'grade'])
        #self.comboCompare.addItems(['=', '>', '<', '>=', '<='])

        #self.tagsView.setColumnCount(4) #jlpt/grade level count active
        #self.tagsView.setHorizontalHeaderLabels(['Grade', 'Level', 'Items', 'Active'])
        #self.tagsView.setFixedSize(310,130)

        self.selectSentenceFont.setCurrentFont(
            QFont(self.options.getSentenceFont()))
        self.selectQuizFont.setCurrentFont(QFont(self.options.getQuizFont()))
        self.selectStatusFont.setCurrentFont(
            QFont(self.options.getMessageFont()))
        self.selectInfoFont.setCurrentFont(QFont(self.options.getInfoFont()))

        #self.intervalDial.setStyleSheet("QDial { background-color: rgb(255, 170, 0) ; }")

        #self.frequencyRange.setTickPosition(QSlider.TicksBelow)
        fRange = self.freq.getFrequencyRangeLimits()
        self.frequencyRange.setRange(fRange['min'], fRange['max'])
        self.frequencyRange.setLow(fRange['min'] * 2)
        self.frequencyRange.setHigh(fRange['max'] / 2)
        #self.frequencyRange.setValue(fRange['max']/2)

    def initializeActions(self):
        self.bBox.accepted.connect(self.saveOptions)
        self.bBox.rejected.connect(self.discardOptions)

        self.bBox.button(QDialogButtonBox.Reset).clicked.connect(
            self.resetOptions)

        self.intervalDial.valueChanged.connect(self.updateCountdown)
        self.intervalSpin.valueChanged.connect(self.updateInterval)

        self.countdownDial.valueChanged.connect(self.updateCountdownSpin)
        self.countdownSpin.valueChanged.connect(self.updateCountdownDial)

        #self.comboTag.currentIndexChanged.connect(self.updateComboLevel)

        self.viewAll.clicked.connect(self.showAll)
        #self.addButton.clicked.connect(self.updateDB)
        self.purgeButton.clicked.connect(self.purgeDB)

        self.frequencyRange.sliderReleased.connect(self.updateFrequencyRange)
        self.valueLow.valueChanged.connect(self.updateLow)
        self.valueHigh.valueChanged.connect(self.updateHigh)

        self.addItemInRange.clicked.connect(self.addItemsToDb)

        #self.frequencyRange.valueChanged.connect(self.updateFrequencyRange)

        #self.tagsView.itemChanged.connect(self.updateActiveItems)

    def saveOptions(self):
        """Saving all options"""
        ### flags ###
        self.options.setAlwaysOnTop(self.checkAlwaysOnTop.isChecked())
        self.options.setSplashEnabled(self.checkSplashScreen.isChecked())
        self.options.setQuizStartingAtLaunch(self.checkAutostart.isChecked())
        self.options.setSoundOn(self.checkSoundSignal.isChecked())
        self.options.setGlobalHotkeyOn(self.checkGlobalHotkeys.isChecked())
        self.options.setLoggingOn(self.checkEnableLog.isChecked())
        self.options.setFadeEffectOn(self.checkEnableFade.isChecked())
        self.options.setBackgroundOn(self.checkItemsBackground.isChecked())
        self.options.setPlastique(self.checkPlastiqueTheme.isChecked())
        ### session ###
        self.options.setRepetitionInterval(self.intervalDial.value())
        self.options.setCountdownInterval(self.countdownDial.value())
        self.options.setSessionSize(self.sessionItemsSpin.value())
        self.options.setSessionLength(self.sessionLengthSpin.value())
        ### dictionary ###
        self.options.setLookupLang(self.languageCombo.currentText())
        self.options.setPreloading(self.checkPreloadDictionary.isChecked())

        self.showInfo(u'All options saved!')

    def resetOptions(self):
        #TODO: ...
        print 'reset'

    def discardOptions(self):
        if self.status.isVisible(): self.status.hide()
        self.hide()

    def showInfo(self, message):
        self.status.info.setText(message)
        self.status.show()
        self.status.setWindowOpacity(0)
        self.fadeStatus()
        QTimer.singleShot(3000, self.fadeStatus)

    def updateCountdown(self):
        self.intervalSpin.setValue(self.intervalDial.value())
        self.update()

    def updateCountdownSpin(self):
        self.countdownSpin.setValue(self.countdownDial.value())
        self.update()

    def updateInterval(self):
        self.intervalDial.setValue(self.intervalSpin.value())
        self.update()

    def updateCountdownDial(self):
        self.countdownDial.setValue(self.countdownSpin.value())
        self.update()

    def updateComboLevel(self):
        pass
#        if self.comboTag.currentText()=='jlpt':         #TODO: move to constants
#            self.comboLevel.clear()
#            self.comboLevel.addItems(['1','2','3','4'])
#        elif self.comboTag.currentText()=='grade':
#            self.comboLevel.clear()
#            self.comboLevel.addItems(['1','2','3','4','5','6','7','8','9','10'])

    def updateDbTable(self):
        self.tagsView.clearContents()
        self.tagsView.setRowCount(0)
        #TODO: scan db for all possible tags, not just predefined
        #        dbStats = self.db.countItemsByGrades()
        #        i = 0
        #        for item in dbStats:
        #            if dbStats[item] != 0:
        #                self.tagsView.insertRow(i)
        #                grade = item[-1:];  level = u''
        #                if grade == 0:
        #                    grade = 10; level = item[:-2]
        #                else:
        #                    level = item[:-1]
        #
        #                self.tagsView.setItem(i, 0, QTableWidgetItem(level));
        #                self.tagsView.setItem(i, 1, QTableWidgetItem(str(grade)))
        #                self.tagsView.setItem(i, 2, QTableWidgetItem(str(dbStats[item])))
        #
        #                checkedItem = QTableWidgetItem();  checkedItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable);
        #
        #                if self.db.checkIfActive(item):  checkedItem.setCheckState(Qt.Checked)
        #                else: checkedItem.setCheckState(Qt.Unchecked)
        #
        #                self.tagsView.setItem(i, 3, checkedItem)
        #                i = i + 1
        #
        #        for row in range(0, self.tagsView.rowCount()):
        #            column = 0
        #            for column in range(0, self.tagsView.columnCount()):
        #                self.tagsView.item(row, column).setTextAlignment(Qt.AlignCenter)

        self.tagsView.resizeColumnsToContents()
        self.tagsView.resizeRowsToContents()

    def updateTotalItemsLabel(self):
        self.totalLabel.setText(
            u'Kanji: <b>' + str(self.dbItems['kanji']) + '</b>\tWords: <b>' +
            str(self.dbItems['words']) + '</b>\tTotal: <b>%s</b>' %
            (self.dbItems['kanji'] + self.dbItems['words']))

    def updateSessionLimits(self):
        self.sessionItemsSpin.setRange(
            1, self.dbItems['kanji'] + self.dbItems['words'])
        self.sessionLengthSpin.setRange(
            1, 4 * (self.dbItems['kanji'] + self.dbItems['words']))

    def updateTotalItems(self):
        self.dbItems = self.db.countTotalItemsInDb()
        self.updateTotalItemsLabel()
        self.updateSessionLimits()

    def updateDB(self):
        #self.progressDb.show()
        #self.showInfo('Updating database, please wait...')
        if self.comboTag.currentText() == 'jlpt':
            if self.db.addItemsToDbJlpt(int(self.comboLevel.currentText())):
                self.showInfo('Successfully updated database.')
        elif self.comboTag.currentText() == 'grade':
            print 'unimplemented, yet'

        self.updateDbTable()
        self.updateTotalItems()
        #self.progressDb.hide()

    def updateActiveItems(self):
        for i in range(0, self.tagsView.rowCount()):
            try:
                self.db.updateActive(
                    self.tagsView.item(i, 0).text() +
                    self.tagsView.item(i, 1).text(),
                    self.tagsView.item(
                        i, 3).checkState() == Qt.CheckState.Checked)
            except:
                #pass
                sys.exc_clear()

    def updateDbByTags(self):
        print '...'

    def purgeDB(self):
        self.db.clearDB()
        self.updateDbTable()
        self.updateTotalItems()
        self.showInfo('All data purged, database compacted.')

    def showAll(self):

        unfillLayout(self.items.infoLayout)
        unfillLayout(self.items.layout)
        self.items.infoLayout = QHBoxLayout()

        self.items.backgroundFlag = self.options.isBackgroundOn()

        #self.items.scrollArea = QScrollArea(self.items)
        #self.items.groupItems = QGroupBox()
        #TODO: implement using group box: QScrollArea <- QGroupBox <- a layout () <- widgets ( created with the group box as parent and added to the layout )

        studyItems = self.db.getAllItemsInFull()

        if len(studyItems) == 0:
            QMessageBox.information(self, 'No items',
                                    'Currently no items in db')
        else:
            #progress = QProgressDialog('Loading items list...', 'Cancel', 0, len(studyItems), self)
            progress = QProgressDialog('Loading items list...', None, 0,
                                       len(studyItems), self)
            progress.setWindowModality(Qt.WindowModal)
            progress.show()
            count = 0

            i = 0
            j = 0
            max_c = 20  #; max_r =50
            for item in studyItems:
                element = QLabel(item.item)
                element.setFont(QFont(self.options.getInfoFont(), 13))

                #if item.active:  element.setStyleSheet("QLabel { color:" + Leitner.correspondingColor(item.leitner_grade) + "}")
                #else: element.setStyleSheet("QLabel { color:gray }")
                if item.active:
                    color = Leitner.correspondingColor(item.leitner_grade)
                else:
                    color = 'gray'

                if self.options.isBackgroundOn():
                    element.setStyleSheet(
                        "QLabel { color: black; background-color:" + color +
                        "; border: 1px solid white; }")
                    #element.setStyleSheet("QLabel { color: blue; }")
                else:
                    element.setStyleSheet("QLabel { color:" + color + "}")

                element.setAttribute(Qt.WA_Hover, True)
                element.installEventFilter(self.filter)

                #                words = []; examples = {}
                #                for el in item.word:
                #                    words.append(el.word)
                #                for el in item.example:
                #                    examples[el.sentence] = el.translation

                element.params = {
                    'color': color,
                    'next': item.next_quiz.strftime('%d %b %H:%M:%S'),
                    'inSession': item.been_in_session,
                    'leitner': Leitner.grades[item.leitner_grade].key
                }
                #'words': words, 'examples': examples,

                self.items.layout.addWidget(element, i, j)

                count = count + 1
                progress.setValue(count)
                if progress.wasCanceled():
                    break

                if j > max_c:
                    i = i + 1
                    j = 0
                else:
                    j = j + 1

            separator_two = QFrame()
            separator_two.setFrameShape(QFrame.HLine)
            separator_two.setFrameShadow(QFrame.Sunken)
            self.items.layout.addWidget(separator_two, i + 1, 0, 1,
                                        self.items.layout.columnCount())

            self.items.kanjiLarge = QLabel(u'')
            self.items.kanjiLarge.setFont(
                QFont(self.options.getSentenceFont(), 56))
            self.items.words = QLabel(u'')
            self.items.words.setWordWrap(True)
            self.items.words.setFont(QFont(Fonts.MSMyoutyou, 14))
            self.items.next = QLabel(u'')
            self.items.leitner = QLabel(u'')

            self.items.infoLayout.addWidget(self.items.kanjiLarge)
            self.items.infoLayout.addWidget(self.items.next)
            self.items.infoLayout.addWidget(self.items.leitner)
            self.items.infoLayout.addWidget(self.items.words)

            #self.items.infoLayout.setAlignment(Qt.AlignCenter)
            '''
            #NB: or, may be, add horizontal layout?
            self.items.layout.addWidget(self.items.kanjiLarge, i + 2, 0, 2, 2)
            self.items.layout.addWidget(self.items.next, i + 2, 3, 1, 1)
            self.items.layout.addWidget(self.items.leitner, i + 3, 3, 1, 1)
            
            #self.items.layout.addWidget(self.items.kanjiLarge, i + 2, 9, 1, 4)
            '''

            if self.options.isBackgroundOn(): self.items.layout.setSpacing(0)
            else: self.items.layout.setSpacing(6)

            #self.items.layout.addLayout(self.items.infoLayout, i + 2, 0, 1, self.items.layout.columnCount())
            #self.items.layout.addLayout(self.items.infoLayout, i + 2, 0, 1, 8)
            self.items.layout.addLayout(self.items.infoLayout, i + 2,
                                        self.items.layout.columnCount() / 2, 1,
                                        8)

            #self.items.scrollArea.setLayout(self.items.layout)

            #self.groupItems.setLayout(self.items.layout)
            #self.scrollArea.setWidget(self.groupItems)

            self.items.setLayout(self.items.layout)
            self.items.show()

    def updateFrequencyRange(self):
        self.totalItemsInRange = self.freq.getItemsCountInRange(
            self.frequencyRange.low(), self.frequencyRange.high())
        self.totalItemsLabel.setText(u'Total items in range: ' +
                                     str(self.totalItemsInRange))
        self.valueLow.setValue(self.frequencyRange.low())
        self.valueHigh.setValue(self.frequencyRange.high())

    def updateLow(self):
        self.frequencyRange.setLow(self.valueLow.value())

    def updateHigh(self):
        self.frequencyRange.setHigh(self.valueHigh.value())

    def addItemsToDb(self):
        if self.db.addItemsToDb(self.frequencyRange.low(),
                                self.frequencyRange.high()):
            #self.showInfo('Added ' + str(self.totalItemsInRange) + ' items to db')
            self.showInfo('Added ' + str(self.db.count) + ' items to db')

#------------------- Fading methods ---------------------#

    def fadeStatus(self):
        if self.status.windowOpacity() == 1:
            self.animationTimer = RepeatTimer(0.025, self.fadeOut, 40)
            self.animationTimer.start()
        else:
            self.animationTimer = RepeatTimer(0.025, self.fadeIn, 40)
            self.animationTimer.start()

    def fadeIn(self):
        self.status.setWindowOpacity(self.status.windowOpacity() + 0.1)

    def fadeOut(self):
        self.status.setWindowOpacity(self.status.windowOpacity() - 0.1)