예제 #1
0
def update_typer_html(typer,errors):
    '''Organizational function.

Given a Typer, updates its html based on settings (not including invisible mode)'''
    #dict : str -> str ; original and displacement strs in error region (for easier display)
    v = unicode(typer.toPlainText())
    v_err_replacements = {}
    if Settings.get('text_area_replace_spaces'):
        #if want to make replacements change spaces in text area as well (risky!)
        v_err_replacements.update(space_replacement_dict_from_setting('text_area_mistakes_space_char'))
        
    if Settings.get('text_area_replace_return'):
        #want to make replacements change returns in text area as well (a little less risky since there's usually fewer)
        v_err_replacements["\n"] = Settings.get('text_area_return_replacement')
    
    error_colors = {} #dict : int -> str, mapping errors to color
    v_replaced_list = list(v)  #list of strs, initially one char each, to operate on
    v_replaced_list = html_list_process_spaces(v_replaced_list)

    if Settings.get("show_text_area_mistakes"):
        error_colors = dict(map(lambda i : (i,Settings.get('text_area_mistakes_color')),errors))
        v_replaced_list = replace_at_locs(v_replaced_list,v_err_replacements,errors)

    v_colored_list = html_color_strs(v_replaced_list,error_colors)
    htmlized = "".join(v_colored_list).replace("\n","<BR>")
    set_typer_html(typer,htmlized)
예제 #2
0
 def setPalettes(self):
     self.palettes = {
         "wrong": QPalette(
             Qt.black,
             Qt.lightGray,
             Qt.lightGray,
             Qt.darkGray,
             Qt.gray,
             Settings.getColor("quiz_wrong_fg"),
             Qt.white,
             Settings.getColor("quiz_wrong_bg"),
             Qt.yellow,
         ),
         "right": QPalette(
             Qt.black,
             Qt.lightGray,
             Qt.lightGray,
             Qt.darkGray,
             Qt.gray,
             Settings.getColor("quiz_right_fg"),
             Qt.yellow,
             Settings.getColor("quiz_right_bg"),
             Qt.yellow,
         ),
         "inactive": QPalette(
             Qt.black,
             Qt.lightGray,
             Qt.lightGray,
             Qt.darkGray,
             Qt.gray,
             Qt.black,
             Qt.lightGray,
         ),
     }
     self.setPalette(self.palettes["inactive"])
예제 #3
0
def to_lessons(sentences):
    backlog = []
    backlen = 0
    min_chars = Settings.get('min_chars')
    max_chars = Settings.get('max_chars')
    sweet_size = 3*(min_chars + max_chars) // 4

    for s in sentences:
        ssplit = []
        while len(s) > sweet_size:
            idx = s.find(' ', sweet_size)
            if idx == -1:
                break
            if idx != -1:
                ssplid.append(s[:idx])
                s = s[idx+1:]
        ssplit.append(s)
        for xs in ssplit:
            backlog.append(xs)
            backlen += len(xs)
            if backlen >= min_chars:
                yield u' '.join(backlog)
                backlog = []
                backlen = 0
    if backlen > 0:
        yield u' '.join(backlog)
예제 #4
0
 def __init__(self, fname):
     super(LessonMiner, self).__init__()
     with codecs.open(fname, "r", "utf_8_sig") as f:
         self.text = f.read()
     self.lessons = None
     self.min_chars = Settings.get('min_chars')
     self.split_regex = Settings.get('sentence_regex')
     self.split = re.compile(self.split_regex).split(self.text)
예제 #5
0
 def setPalettes(self):
     self.palettes = {
         'wrong': QPalette(Qt.black,
             Qt.lightGray, Qt.lightGray, Qt.darkGray, Qt.gray,
             Settings.getColor("quiz_wrong_fg"), Qt.white, Settings.getColor("quiz_wrong_bg"), Qt.yellow),
         'right': QPalette(Qt.black,
             Qt.lightGray, Qt.lightGray, Qt.darkGray, Qt.gray,
             Settings.getColor("quiz_right_fg"), Qt.yellow, Settings.getColor("quiz_right_bg"), Qt.yellow),
         'inactive': QPalette(Qt.black, Qt.lightGray, Qt.lightGray, Qt.darkGray,
                              Qt.gray, Qt.black, Qt.lightGray)}
     self.setPalette(self.palettes['inactive'])
예제 #6
0
        def color_position(settings_color_var, use_space_var, space_var):
            '''Colors position with the color stored in settings_color_var.
            
strs use_space_var and space_var are settings variables to look up.
If [setting] use_space_var, space at position is replaced with [setting] space_var

Returns the new text_strs list (for assignment).'''
            colors[position] = Settings.get(settings_color_var)

            if Settings.get(use_space_var):
                return replace_at_locs(text_strs,space_replacement_dict_from_setting(space_var),[position])
            else:
                return text_strs
예제 #7
0
def generate_automatic_insertion_regex():
    '''From settings info, returns the regex for which to re.match the automatically inserted chars

Or None if no chars are to be automatically inserted.'''
    #the str of characters (in regex-escaped form, but not regex) to automatically insert
    automatically_inserted_chars = ""
    if Settings.get('use_automatic_other_insertion'):
        automatically_inserted_chars += re.escape(Settings.get('automatic_other_insertion'))
    for s,c in ('automatic_space_insertion',u" "),('automatic_return_insertion',u"\n"):
        if Settings.get(s):
            automatically_inserted_chars += re.escape(c)

    return "[{0}]+".format(automatically_inserted_chars) if automatically_inserted_chars else None
예제 #8
0
    def paras(self, f):
        p = []
        ps = []
        previous_line_empty = True
        for l in f:
            #designated replacements for unicode text
            if Settings.get('transliteration_manual_unicode'):
                for orig, repl in unicode_replacements:
                    l = l.replace(orig, repl)
                    
            ascii_line = l
            if unidecode_imported and Settings.get('transliteration_method') == INDEX_TRANSLITERATION_UNIDECODE:
                #tries to use unidecode if it exists
                ascii_line = unidecode.unidecode(ascii_line)
            elif Settings.get('transliteration_method') == INDEX_TRANSLITERATION_DELETE:
                #deletes all remaining non-ascii chars
                try:
                    ascii_line = ascii_line.decode('ascii')
                except UnicodeEncodeError:
                    ascii_line = ''
                    for c in l:
                        if ord(c) < 128:
                            ascii_line += c
                        else:
                            ascii_line += ""

            #replaces any 1+ adjacent whitespace chars (spaces, tabs, newlines, etc) with one ascii space
            if Settings.get('single_space_only'): 
                ascii_line = re.sub("\s+"," ",ascii_line)               

            #designated replacements for ascii text
            if Settings.get('transliteration_manual_ascii'):
                for orig, repl in ascii_replacements:
                    ascii_line = ascii_line.replace(orig, repl) 

            l = ascii_line.strip()
            current_line_empty = not l
           
            #the current line is empty: insert empty line 
            #or the current line and previous line both nonempty: need to insert empty line between them
            if (current_line_empty or not previous_line_empty) and len(p) > 0:
                ps.append(SentenceSplitter(u" ".join(p)))
                p = []

            if not current_line_empty:
                p.append(l)
                
            previous_line_empty = current_line_empty
        if len(p) > 0:
            ps.append(SentenceSplitter(u" ".join(p)))
        return ps
예제 #9
0
    def __init__(self, *args):
        super(Quizzer, self).__init__(*args)

        self.result = QLabel()
        self.typer = Typer()
        self.label = WWLabel()
        self.result.setVisible(Settings.get("show_last"))
        #self.label.setFrameStyle(QFrame.Raised | QFrame.StyledPanel)
        #self.typer.setBuddy(self.label)
        #self.info = QLabel()
        self.connect(self.typer,  SIGNAL("done"), self.done)
        self.connect(self.typer,  SIGNAL("textChanged"), self.checkText)
        self.connect(self.typer,  SIGNAL("cancel"), SIGNAL("wantText"))
        self.connect(Settings, SIGNAL("change_typer_font"), self.readjust)
        self.connect(Settings, SIGNAL("change_show_last"), self.result.setVisible)

        self.text = ('','', 0, None)

        layout = QVBoxLayout()
        #layout.addWidget(self.info)
        #layout.addSpacing(20)
        layout.addWidget(self.result, 0, Qt.AlignRight)
        layout.addWidget(self.label, 1, Qt.AlignBottom)
        layout.addWidget(self.typer, 1)
        self.setLayout(layout)
        self.readjust()
예제 #10
0
 def readjust(self):
     f = Settings.getFont("typer_font")
     f.setKerning(False)
     #TODO: get rid of "vertical kerning"
     #  f.setFixedPitch(True) didn't work
     self.label.setFont(f)
     self.typer.setFont(f)
예제 #11
0
 def __init__(self, fname):
     super(LessonMiner, self).__init__()
     #print time.clock()
     with codecs.open(fname, "r", "utf_8_sig") as f:
         self.paras = self.paras(f)
     self.lessons = None
     self.min_chars = Settings.get('min_chars')
예제 #12
0
    def __init__(self, x, y, *args):
        super(Plot, self).__init__(*args)

        # self.connect(self, SIGNAL("sceneRectChanged(QRectF)"), self.setSceneRect)

        if len(x) < 2:
            return

        min_x, max_x = min(x), max(x)
        min_y, max_y = min(y), max(y)

        p = QPen(Qt.blue)
        p.setCosmetic(True)
        p.setWidthF(2.0)
        p.setCapStyle(Qt.RoundCap)
        for i in range(0, len(x) - 1):
            self.addLine(x[i], -y[i], x[i + 1], -y[i + 1], p)

        # Add axes
        if Settings.get("show_xaxis"):
            if min_y > 0:
                min_y = 0
            elif max_y < 0:
                max_y = 0
        if min_y <= 0 <= min_y:
            self.addLine(min_x, 0, max_x, 0)
        if min_x <= 0 <= max_x:
            self.addLine(0, -min_y, 0, -max_y)

        w, h = max_x - min_x, max_y - min_y

        if h <= 0 or w <= 0:
            return

        # Add background lines
        spc = math.pow(10.0, math.ceil(math.log10(h) - 1))
        while h / spc < 5:
            spc /= 2

        ns = int(min_y / spc) * spc
        start = ns

        qp = QPen(QColor(Qt.lightGray))
        qp.setStyle(Qt.DotLine)

        while start < max_y + spc:
            lin = self.addLine(min_x, -start, max_x, -start, qp)
            lin.setZValue(-1.0)

            lbl = QGraphicsSimpleTextItem("%g" % start)
            th, tw = lbl.boundingRect().height(), lbl.boundingRect().width()
            lbl.scale(0.026 * w / tw, spc / th)
            lbl.setPos(QPointF(min_x - 0.03 * w, -start - spc / 2))
            self.addItem(lbl)

            start += spc

        qr = QRectF(min_x - 0.03 * w, -start + spc / 2, 1.03 * w, start - ns)
        self.setSceneRect(qr)
예제 #13
0
 def getWaitText(self):
     if Settings.get("req_space"):
         return (
             "Press SPACE and then immediately start typing the text\n"
             + "Press ESCAPE to restart with a new text at any time"
         )
     else:
         return "Press ESCAPE to restart with a new text at any time"
예제 #14
0
파일: Text.py 프로젝트: lalopmak/amphetype
    def paras(self, f):
        p = []
        ps = []
        previous_line_empty = True
        for l in f:
            #designated replacements for unicode text
            if Settings.get('transliteration_manual_unicode'):
                for orig, repl in unicode_replacements:
                    l = l.replace(orig, repl)
                    
            ascii_line = l
            if unidecode_imported and Settings.get('transliteration_method') == INDEX_TRANSLITERATION_UNIDECODE:
                #tries to use unidecode if it exists
                ascii_line = unidecode.unidecode(ascii_line)
            elif Settings.get('transliteration_method') == INDEX_TRANSLITERATION_DELETE:
                #deletes all remaining non-ascii chars
                try:
                    ascii_line = ascii_line.decode('ascii')
                except UnicodeEncodeError:
                    ascii_line = filter(lambda c : ord(c) < 128, ascii_line) 

            #replaces any 1+ adjacent whitespace chars (spaces, tabs, newlines, etc) with one ascii space
            if Settings.get('single_space_only'): 
                ascii_line = re.sub("\s+"," ",ascii_line)               

            #TODO: newlines doesn't work since all this is done line-by-line
            #replaces multiple adjacent instances (possibly including spaces, newlines) of those characters 
            #in list multiple_replacements (e.g. "start ! !!!!! ! ! !!\n !\nend" might get replaced with
            #"start !\nend")
            if Settings.get('multiple_replacement_enabled'): 
                additional_chars = (" " if Settings.get('multiple_replacement_allow_spaces') else "") + ("\n" if Settings.get('multiple_replacement_allow_newlines') else "")
                for m in Settings.get('multiple_replacement_chars'): 
                    ascii_line = re.sub("{0}[{0}{1}]*{0}".format(re.escape(m),additional_chars), m, ascii_line)               

            #designated replacements for ascii text
            if Settings.get('transliteration_manual_ascii'):
                for orig, repl in ascii_replacements:
                    ascii_line = ascii_line.replace(orig, repl) 

            l = ascii_line.strip()
            current_line_empty = not l
           
            #the current line is empty: insert empty line 
            #or the current line and previous line both nonempty: need to insert empty line between them
            if (current_line_empty or not previous_line_empty) and len(p) > 0:
                ps.append(SentenceSplitter(u" ".join(p)))
                p = []

            if not current_line_empty:
                p.append(l)
                
            previous_line_empty = current_line_empty
        if len(p) > 0:
            ps.append(SentenceSplitter(u" ".join(p)))
        return ps
예제 #15
0
    def updateLabel(self,position,errors):
        '''Populates the label with colors depending on current position and errors.'''
        #dict : str -> str ; original and displacement strs in error region (for easier display)
        err_replacements = {"\n":u"{0}<BR>".format(Settings.get('label_return_symbol'))}

        colors = {}  #dict : int -> str, mapping errors to color
        
        if Settings.get('show_label_mistakes'):
            #showing mistakes; need to populate color
            colors = dict([(i,Settings.get('label_mistakes_color')) for i in errors])

            if Settings.get('label_replace_spaces_in_mistakes'):
                err_replacements.update(space_replacement_dict_from_setting('label_mistakes_space_char'))

        text_strs = list(self.text[2]) #list of strs, initially one char each, to operate on
        text_strs = html_list_process_spaces(text_strs)
        text_strs = replace_at_locs(text_strs,err_replacements,errors)

        def color_position(settings_color_var, use_space_var, space_var):
            '''Colors position with the color stored in settings_color_var.
            
strs use_space_var and space_var are settings variables to look up.
If [setting] use_space_var, space at position is replaced with [setting] space_var

Returns the new text_strs list (for assignment).'''
            colors[position] = Settings.get(settings_color_var)

            if Settings.get(use_space_var):
                return replace_at_locs(text_strs,space_replacement_dict_from_setting(space_var),[position])
            else:
                return text_strs
            
        #designates colors and replacements of position
        if Settings.get('show_label_position_with_prior_mistake') and position - 1 in errors:
            text_strs = color_position('label_position_with_prior_mistake_color',
                                       'label_replace_spaces_in_position_with_prior_mistake',
                                       'label_position_with_prior_mistake_space_char')
        elif Settings.get('show_label_position_with_mistakes') and errors:
            text_strs = color_position('label_position_with_mistakes_color',
                                       'label_replace_spaces_in_position_with_mistakes',
                                       'label_position_with_mistakes_space_char')
        elif Settings.get('show_label_position'): 
            text_strs = color_position('label_position_color',
                                       'label_replace_spaces_in_position',
                                       'label_position_space_char') 

        htmlized = "".join(html_color_strs(text_strs,colors))
        htmlized = htmlized.replace(u"\n", u"{0}<BR>".format(Settings.get('label_return_symbol')))
        
        self.label.setText(htmlized) 
예제 #16
0
    def checkText(self):
        if self.target is None or self.editflag:
            return

        v = unicode(self.toPlainText())
        if self.when[0] == 0:
            space = len(v) > 0 and v[-1] == u" "
            req = Settings.get('req_space')

            self.editflag = True
            if space:
                self.when[0] = timer()
                self.clear()
                self.setPalette(self.palettes['right'])
            elif req:
                self.setText(self.getWaitText())
                self.selectAll()
            self.editflag = False

            if req or space:
                return
            else:
                self.when[0] = -1

        y = 0
        for y in xrange(min(len(v), len(self.target)), -1, -1):
            if v[0:y] == self.target[0:y]:
                break
        lcd = v[0:y]
        self.where = y

        if self.when[y] == 0 and y == len(v):
            self.when[y] = timer()
            if y > 0:
                self.times[y-1] = self.when[y] - self.when[y-1]

        if lcd == self.target:
            self.emit(SIGNAL("done"))
            return

        if y < len(v) and y < len(self.target):
            self.mistake[y] = True
            self.mistakes[y] = self.target[y] + v[y]

        if v == lcd:
            self.setPalette(self.palettes['right'])
        else:
            self.setPalette(self.palettes['wrong'])
예제 #17
0
    def __init__(self):
        GtkUtil.AmphBoxLayout.__init__(self)
        self.model = WordModel()
        treeview = GtkUtil.AmphTreeView(self.model)

        self.update()

        which = SettingsCombo('ana_which', [
            ('wpm asc', 'slowest'),
            ('wpm desc', 'fastest'),
            ('viscosity desc', 'least fluid'),
            ('viscosity asc', 'most fluid'),
            ('accuracy asc', 'least accurate'),
            ('misses desc', 'most mistyped'),
            ('total desc', 'most common'),
            ('damage desc', 'most damaging'),
        ])

        what = SettingsCombo('ana_what', ['keys', 'trigrams', 'words'])
        lim = SettingsEdit('ana_many')
        mincount = SettingsEdit('ana_count')

        # XXX why are sometimes no args provided, sometimes Config.Settings?
        Settings.connect("change_ana_which", lambda *_: self.update())
        Settings.connect("change_ana_what", lambda *_: self.update())
        Settings.connect("change_ana_many", lambda *_: self.update())
        Settings.connect("change_ana_count", lambda *_: self.update())

        # TODO send lessons to generator
        send_to_generator = lambda: None

        self.append_layout([
            [
                "Display statistics about the", which, what, None,
                GtkUtil.new_button("Update list", self.update),
                GtkUtil.new_button("Send list to Lesson Generator",
                                   send_to_generator)
            ],
            [
                "Limit list to", lim,
                "items and don't show items with a count less than", mincount
            ],
            (treeview, ),
        ])
예제 #18
0
파일: call.py 프로젝트: KoleckOLP/yt-dl
def loadpath(s="show"):
    # old mess
    global settings, fdir
    pffmpeg = glob.glob(f"{spath}/ffmpeg*")
    pffprobe = glob.glob(f"{spath}/ffprobe*")
    if (not pffmpeg and not pffprobe):
        fdir = False
    else:
        fdir = True
    # new stuff
    if (os.path.exists(settingsPath)):
        settings = Settings.fromJson(settingsPath)
    else:
        firstrun()

    if (s == "show"):
        print(Style.BRIGHT + "audio is saved to: " + Style.RESET_ALL, end="")
        print(settings.Youtubedl.audioDir)
        print(Style.BRIGHT + "video is saved to: " + Style.RESET_ALL, end="")
        print(settings.Youtubedl.videoDir + "\n")
예제 #19
0
 def updatePalette(self):
     self.setPalette(
         QPalette(
             Settings.getColor("main_text_color"),  #color of typing text
             Settings.getColor(
                 "widgets_background_color"
             ),  #label tab gets part of it color from here
             Settings.getColor("main_borders_color"),  #borders
             Settings.getColor(
                 "widgets_text_color"),  #rectangles in sources
             Qt.gray,  #tab arrow
             Settings.getColor(
                 "widgets_text_color"),  #color of widgets text
             Qt.white,
             Settings.getColor(
                 "main_text_area_color"),  #most text areas' backgrounds
             Settings.getColor(
                 "main_background_color"
             )  #most backgrounds.  label tab gets part of its color from here. 
         ))
예제 #20
0
    def __init__(self, *args):
        super(Quizzer, self).__init__(*args)

        self.result = QLabel()
        self.typer = Typer()
        self.label = WWLabel()
        self.tryout_label = QLabel()
        self.tryout_label.setText("Tryout layout: ")
        self.tryout_layout = QComboBox()
        self.result.setVisible(Settings.get("show_last"))
        #self.label.setFrameStyle(QFrame.Raised | QFrame.StyledPanel)
        #self.typer.setBuddy(self.label)
        #self.info = QLabel()
        self.connect(self.typer,  SIGNAL("done"), self.done)
        self.connect(self.typer,  SIGNAL("cancel"), SIGNAL("wantText"))
        self.connect(Settings, SIGNAL("change_typer_font"), self.readjust)
        self.connect(Settings, SIGNAL("change_show_last"), self.result.setVisible)
        self.connect(self.tryout_layout, SIGNAL("currentIndexChanged(int)"), self.changeTryoutLayout)

        self.text = ('','', '', None)
        self.originalText = ('','', '', None)
        self.keyboardLayouts = []

        layout = QVBoxLayout()
        #layout.addWidget(self.info)
        #layout.addSpacing(20)
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.tryout_label, 0, Qt.AlignLeft)
        hlayout.addWidget(self.tryout_layout, 0, Qt.AlignLeft)
        hlayout.addStretch()
        hlayout.addWidget(self.result, 0, Qt.AlignRight)
        layout.addLayout(hlayout)
        layout.addWidget(self.label, 1, Qt.AlignBottom)
        layout.addWidget(self.typer, 1)
        self.setLayout(layout)
        self.readjust()
        self.addLayouts()
예제 #21
0
    def __init__(self):
        self.strings = StringListWidget()
        self.sample = Gtk.TextView(
            wrap_mode=Gtk.WrapMode.WORD,
            editable=False
            )
        self.lesson_name_field = Gtk.Entry()

        scroll_sample = Gtk.ScrolledWindow()
        scroll_sample.add(self.sample)
        combo_what = SettingsCombo('str_what',
                                   [('e', 'encompassing'), ('s', 'similar'), ('r', 'random')])
        layout = [
            "Welcome to Amphetype's automatic lesson generator!",

            "You can retrieve a list of words/keys/trigrams to practice from the Analysis tab,"
            " import from an external file, or even type in your own (separated by space).\n",
            10,
            ["In generating lessons, I will make", SettingsEdit("gen_copies"),
             "copies of the list below and divide them into sublists of size",
             SettingsEdit("gen_take"), "(0 for all)"],
            ["I will then", SettingsCombo("gen_mix", [('c', "concatenate"), ('m', "commingle")]),
             "corresponding sublists into atomic building blocks which are fashioned into lessons"
             " according to your lesson size preferences."],
            [["Input words", self.strings, [
                SettingsCombo("str_clear", [('s', "Supplement"), ('r', "Replace")]),
                "list with", SettingsEdit("str_extra"), combo_what, "words from",
                GtkUtil.new_button("a file", self.strings.add_from_file), "or",
                GtkUtil.new_button("analysis database", self.strings.add_from_typed)]],
              ["Lessons", scroll_sample, [
                  GtkUtil.new_button("Add to sources", self.accept_lessons), "with name",
                  self.lesson_name_field]]
             ],
            ]

        GtkUtil.AmphBoxLayout.__init__(self, layout)
        Settings.connect("change_gen_take", lambda: self.generate_preview())
        Settings.connect("change_gen_copies", lambda: self.generate_preview())
        Settings.connect("change_gen_mix", lambda: self.generate_preview())
        self.strings.connect("updated", lambda _: self.generate_preview())
예제 #22
0
def space_replacement_dict_from_setting(replacement_var):
    '''Returns a dict that assigns to html spaces the value in the setting replacement_var'''
    return space_replacement_dict(Settings.get(replacement_var))
예제 #23
0
 def setText(self, text):
     self.text = text
     self.label.setText(self.text[2].replace(
         u"\n", u"{0}\n".format(Settings.get('label_return_symbol'))))
     self.typer.setTarget(self.text[2])
     self.typer.setFocus()
예제 #24
0
    def fetchall(self, *args):
        return sqlite3.Connection.execute(self, *args).fetchall()

    def fetchone(self, sql, default, *args):
        x = sqlite3.Connection.execute(self, sql, *args)
        g = x.fetchone()
        if g is None:
            return default
        return g

    def getSource(self, source, lesson=None):
        v = self.fetchall('select rowid from source where name = ? limit 1',
                          (source, ))
        if len(v) > 0:
            sqlite3.Connection.execute(
                self, 'update source set disabled = NULL where rowid = ?',
                v[0])
            sqlite3.Connection.commit(self)
            return v[0][0]
        sqlite3.Connection.execute(
            self, 'insert into source (name, discount) values (?, ?)',
            (source, lesson))
        return self.getSource(source)


dbname = Settings.get("db_name")

# GLOBAL
DB = sqlite3.connect(dbname, 5, 0, "DEFERRED", False, AmphDatabase)
예제 #25
0
 def readjust(self):
     f = Settings.getFont("typer_font")
     self.label.setFont(f)
     self.typer.setFont(f)
예제 #26
0
    def done(self):
        print("DONE")
        # TODO split into smaller bits
        now = timer()
        elapsed, chars, times, mis, mistakes = self.typer.get_stats()
        text = self.text[2]

        assert chars == len(text)

        accuracy = 1.0 - sum(1 for f in mis if f) / chars
        spc = elapsed / chars
        viscosity = sum((t / spc - 1)**2 for t in times) / chars

        DB.execute(
            """insert into result (w, text_id, source, wpm, accuracy, viscosity)
                   values (?,?,?,?,?,?)""",
            (now, self.text[0], self.text[1], 12.0 / spc, accuracy, viscosity))

        wpm_median, acc_median = DB.fetchone(
            f"""select agg_median(wpm),agg_median(acc) from
            (select wpm,100.0*accuracy as acc from result order by w desc limit
             {Settings.get("def_group_by")})""", (0.0, 100.0))

        self.result.set_text(
            "Last: {:.1f}wpm ({:.1f}%), last 10 average: {:.1f}wpm ({:.1f}%)".
            format(12.0 / spc, 100.0 * accuracy, wpm_median, acc_median))

        self.emit("stats-changed")

        stats = collections.defaultdict(Statistic)
        viscs = collections.defaultdict(Statistic)

        for char, time, mistake in zip(text, times, mis):
            stats[char].append(time, mistake)
            viscs[char].append((time / spc - 1)**2)

        def gen_tup(start, end):
            span = end - start
            char_avg = sum(times[start:end]) / span
            visc = sum((t / char_avg - 1)**2 for t in times[start:end]) / span
            return (text[start:end], char_avg,
                    sum(1 for f in mis[start:end] if f), visc)

        for trigraph, time, mist, visc in [
                gen_tup(i, i + 3) for i in range(0, chars - 2)
        ]:
            stats[trigraph].append(time, mist > 0)
            viscs[trigraph].append(visc)

        regex = re.compile(r"(\w|'(?![A-Z]))+(-\w(\w|')*)*")
        for word, time, mist, visc in [
                gen_tup(*m.span()) for m in regex.finditer(text)
                if m.end() - m.start() > 3
        ]:
            stats[word].append(time, mist > 0)
            viscs[word].append(visc)

        def kind(key):
            if len(key) == 1:
                return 0
            if len(key) == 3:
                return 1
            return 2

        vals = []
        for key, stat in stats.items():
            visc = viscs[key].median()
            vals.append((stat.median(), visc * 100.0, now, len(stat),
                         stat.flawed(), kind(key), key))

        is_lesson = DB.fetchone("select discount from source where rowid=?",
                                (None, ), (self.text[1], ))[0]

        if Settings.get("use_lesson_stats") or not is_lesson:
            DB.executemany(
                """insert into statistic (time,viscosity,w,count,mistakes,type,data)
                    values (?,?,?,?,?,?,?)""", vals)
            DB.executemany(
                "insert into mistake (w,target,mistake,count) values (?,?,?,?)",
                [(now, k[0], k[1], v) for k, v in mistakes.items()])

        if is_lesson:
            mins = (Settings.get("min_lesson_wpm"),
                    Settings.get("min_lesson_acc"))
        else:
            mins = (Settings.get("min_wpm"), Settings.get("min_acc"))

        if 12.0 / spc < mins[0] or accuracy < mins[1] / 100.0:
            self.set_target(self.text)
        elif not is_lesson and Settings.get('auto_review'):
            words = [x for x in vals if x[5] == 2]
            if not words:
                self.emit("want-text")
                return
            words.sort(key=lambda x: (x[4], x[0]), reverse=True)
            i = 0
            while words[i][4] != 0:
                i += 1
            i += (len(words) - i) // 4

            # TODO support want-review
            # self.emit("want-review", [x[6] for x in words[0:i]])
        else:
            self.emit("want-text")
예제 #27
0
    def checkText(self):
        if self.typer.target is None or self.typer.editflag:
            return

        v = unicode(self.typer.toPlainText())

        if Settings.get('allow_mistakes') and len(v) >= len(self.typer.target):
            v = self.typer.target

        if not self.typer.started:
            if Settings.get('req_space'):
                #space is required before beginning the passage proper
                if v == u" ":
                    #the first char typed was space
                    #the first space only starts the session; clear the typer
                    set_typer_text(self.typer, "", cursor_position=0)
                    self.typer.when[0] = timer()
                    self.typer.started = True
                    return
                else:
                    #reset the wait text
                    set_typer_text(self.typer, self.typer.getWaitText())
                    self.typer.selectAll()
                    return
            else:
                self.typer.when[0] = -1
                self.typer.when[1] = timer(
                )  #have to set starting time regardless of correctness
                self.typer.started = True

        old_cursor = self.typer.textCursor()
        old_position = old_cursor.position()
        old_str_position = old_position - 1  #the position that has (presumably) just been typed

        #colors text in typer depending on errors
        errors = disagreements(v,
                               self.typer.target,
                               case_sensitive=Settings.get('case_sensitive'))
        first_error = errors[0] if errors else None

        #records time that any char was correctly hit
        #except that if we've already been correct farther, we don't record
        if self.typer.farthest_correct < old_str_position < len(
                self.typer.target) and not old_str_position in errors:
            self.typer.when[old_str_position +
                            1] = timer()  #zeroth position is original space
            self.typer.farthest_correct = old_str_position

        automatic_insertion_regex = generate_automatic_insertion_regex()
        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #TODO: change statistics to account for this
        #Automatically insert characters into the text area
        if automatic_insertion_regex and old_position == len(
                v):  #only works if cursor is at the end
            automatic_insertion = re.match(automatic_insertion_regex,
                                           self.typer.target[old_position:])
            if automatic_insertion:
                new_end = old_position + automatic_insertion.end()
                set_typer_text(self.typer,
                               v[:old_position] +
                               self.typer.target[old_position:new_end],
                               cursor_position=new_end)
                self.checkText()  #recovers the formatting
                return

        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #Prevent advancement until user correctly types space
        if Settings.get('ignore_until_correct_space') and self.typer.target[
                old_str_position] == u" " and old_str_position in errors:
            #gets rid of new character (sets as plaintext)
            set_typer_text(self.typer,
                           v[:old_str_position] + v[old_str_position + 1:],
                           cursor_position=old_position - 1)
            self.checkText()  #recovers the formatting
            return

        if len(v) >= len(self.typer.target) and (
                not first_error or first_error >= len(self.typer.target)):
            self.done()
            return

        if new_error(old_str_position, errors):
            self.typer.mistake[old_str_position] = True
            self.typer.mistakes[old_str_position] = self.typer.target[
                old_str_position] + v[old_str_position]

        if Settings.get('quiz_invisible'):
            self.typer.activate_invisibility()
        else:
            if Settings.get("quiz_use_wrong_palette") and errors:
                self.typer.setPalette(self.typer.palettes['wrong'])
            else:
                self.typer.setPalette(self.typer.palettes['right'])
            update_typer_html(self.typer, errors)

        #updates the label depending on errors
        self.updateLabel(old_position, errors)
예제 #28
0
    def checkText(self, automatically_inserted = False):
        if self.typer.target is None or self.typer.editflag:
            return

        v = unicode(self.typer.toPlainText())
        
        if Settings.get('allow_mistakes') and len(v) >= len(self.typer.target):
            v = self.typer.target
 
        if self.typer.start_time == None and Settings.get('req_space'):
            #space is required before beginning the passage proper
            if v == u" ":
                #the first char typed was space
                #the first space only starts the session; clear the typer
                set_typer_text(self.typer,"",cursor_position=0)
                self.typer.start_time = 0
                return
            else:
                #reset the wait text
                set_typer_text(self.typer,self.typer.getWaitText())
                self.typer.selectAll()
                return
                
        if not self.typer.start_time:
            self.typer.start_time = timer()
            if 1 < len(v) < len(self.typer.target): 
                #checks whether wait text was accidentally left in
                diff = list(difflib.Differ().compare(list(self.typer.getWaitText()),list(v)))

                #the vast majority of the wait text is still there
                wait_text_present = len(filter(lambda line : line[0] == "-", diff)) <= 1

                if wait_text_present:
                    #leave only the additional typed text
                    new_str = "".join(line[2:] for line in diff if line[0] == "+")
                    set_typer_text(self.typer,new_str,cursor_position=len(new_str))
                    v = new_str 

        old_cursor = self.typer.textCursor()
        old_position = old_cursor.position()
        old_str_position = old_position - 1  #the position that has (presumably, unless delete was used) just been typed
     
        #colors text in typer depending on errors
        errors = disagreements(v,self.typer.target,case_sensitive=Settings.get('case_sensitive'))
        first_error = errors[0] if errors else None

        #records time that any char was hit
        #except that if we've already been correct farther, we don't record
        if self.typer.farthest_correct < old_str_position < len(self.typer.target):
            if old_str_position not in errors:
                self.typer.farthest_correct = old_str_position

            #invalidates all farther-out times that might have previously been written
            if old_str_position < self.typer.farthest_data:
                for i in xrange(old_str_position+1, self.typer.farthest_data + 1):
                    self.typer.data[i].when = None

            self.typer.farthest_data = old_str_position
            self.typer.data[old_str_position] = Letter(char=self.typer.target[old_str_position],
                                                       when=timer(),
                                                       automatically_inserted=automatically_inserted)

        automatic_insertion_regex = generate_automatic_insertion_regex()
        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #TODO: change statistics to account for this
        #Automatically insert characters into the text area
        if automatic_insertion_regex and old_position == len(v): #only works if cursor is at the end
            automatic_insertion = re.match(automatic_insertion_regex,self.typer.target[old_position:])
            if automatic_insertion:
                new_end = old_position + automatic_insertion.end()
                set_typer_text(self.typer, v[:old_position] + self.typer.target[old_position:new_end], cursor_position = new_end)
                self.checkText(automatically_inserted=True)  #recovers the formatting
                return

        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #Prevent advancement until user correctly types space
        if Settings.get('ignore_until_correct_space') and self.typer.target[old_str_position] == u" " and old_str_position in errors:
            #gets rid of new character (sets as plaintext)
            set_typer_text(self.typer,v[:old_str_position] + v[old_str_position+1:],cursor_position = old_position - 1) 
            self.checkText()    #recovers the formatting 
            return

        if len(v) >= len(self.typer.target) and (not first_error or first_error >= len(self.typer.target)):
            self.done()
            return
       
        if new_error(old_str_position,errors): 
            self.typer.mistake[old_str_position] = True
            self.typer.mistakes[old_str_position] = self.typer.target[old_str_position] + v[old_str_position]

        if Settings.get('quiz_invisible'):
            self.typer.activate_invisibility()
        else:
            if Settings.get("quiz_use_wrong_palette") and errors:
                self.typer.setPalette(self.typer.palettes['wrong'])
            else:
                self.typer.setPalette(self.typer.palettes['right'])
            update_typer_html(self.typer,errors)
        
        #updates the label depending on errors
        self.updateLabel(old_position,errors)
예제 #29
0
 def readjust(self):
     f = Settings.getFont("typer_font")
     self.label.setFont(f)
     self.typer.setFont(f)
예제 #30
0
파일: Data.py 프로젝트: maxme/amphetype
    def executemany_(self, *args):
        sqlite3.Connection.executemany(self, *args)
    def executemany(self, *args):
        sqlite3.Connection.executemany(self, *args)
        #self.commit()

    def fetchall(self, *args):
        return sqlite3.Connection.execute(self, *args).fetchall()

    def fetchone(self, sql, default, *args):
        x = sqlite3.Connection.execute(self, sql, *args)
        g = x.fetchone()
        if g is None:
            return default
        return g

    def getSource(self, source, lesson=None):
        v = self.fetchall('select rowid from source where name = ? limit 1', (source, ))
        if len(v) > 0:
            sqlite3.Connection.execute(self, 'update source set disabled = NULL where rowid = ?', v[0])
            sqlite3.Connection.commit(self)
            return v[0][0]
        sqlite3.Connection.execute(self, 'insert into source (name, discount) values (?, ?)', (source, lesson))
        return self.getSource(source)

dbname = Settings.get("db_name")

# GLOBAL
DB = sqlite3.connect(dbname, 5, 0, "DEFERRED", False, AmphDatabase)
예제 #31
0
import os
import sys

# Get command-line --database argument before importing
# modules which count on database support
from Config import Settings

import optparse

opts = optparse.OptionParser()
opts.add_option("-d", "--database", metavar="FILE", help="use database FILE")
v = opts.parse_args()[0]

if v.database is not None:
    Settings.set('db_name', v.database)

from Data import DB
from Quizzer import Quizzer
from StatWidgets import StringStats
from TextManager import TextManager
from Performance import PerformanceHistory
from Config import PreferenceWidget
from Lesson import LessonGenerator
from Widgets.Database import DatabaseWidget

from PyQt4.QtCore import *
from PyQt4.QtGui import *

QApplication.setStyle('cleanlooks')
예제 #32
0
    def done(self):
        now = time.time()
        elapsed, chars, times, mis, mistakes = self.typer.getStats()

        assert chars == len(self.text[2])

        accuracy = 1.0 - len(filter(None, mis)) / chars
        spc = elapsed / chars

        viscosity = sum(map(lambda x: ((x - spc) / spc)**2, times)) / chars

        DB.execute(
            'insert into result (w,text_id,source,wpm,accuracy,viscosity) values (?,?,?,?,?,?)',
            (now, self.text[0], self.text[1], 12.0 / spc, accuracy, viscosity))

        v2 = DB.fetchone(
            """select agg_median(wpm),agg_median(acc) from
            (select wpm,100.0*accuracy as acc from result order by w desc limit %d)"""
            % Settings.get('def_group_by'), (0.0, 100.0))
        self.result.setText(
            "Last: %.1fwpm (%.1f%%), last 10 average: %.1fwpm (%.1f%%)" %
            ((12.0 / spc, 100.0 * accuracy) + v2))

        self.emit(SIGNAL("statsChanged"))

        stats = collections.defaultdict(Statistic)
        visc = collections.defaultdict(Statistic)
        text = self.text[2]

        for c, t, m in zip(text, times, mis):
            stats[c].append(t, m)
            visc[c].append(((t - spc) / spc)**2)

        def gen_tup(s, e):
            perch = sum(times[s:e]) / (e - s)
            visc = sum(map(lambda x:
                           ((x - perch) / perch)**2, times[s:e])) / (e - s)
            return (text[s:e], perch, len(filter(None, mis[s:e])), visc)

        for tri, t, m, v in [gen_tup(i, i + 3) for i in xrange(0, chars - 2)]:
            stats[tri].append(t, m > 0)
            visc[tri].append(v)

        regex = re.compile(r"(\w|'(?![A-Z]))+(-\w(\w|')*)*")

        for w, t, m, v in [
                gen_tup(*x.span()) for x in regex.finditer(text)
                if x.end() - x.start() > 3
        ]:
            stats[w].append(t, m > 0)
            visc[w].append(v)

        def type(k):
            if len(k) == 1:
                return 0
            elif len(k) == 3:
                return 1
            return 2

        vals = []
        for k, s in stats.iteritems():
            v = visc[k].median()
            vals.append(
                (s.median(), v * 100.0, now, len(s), s.flawed(), type(k), k))

        is_lesson = DB.fetchone("select discount from source where rowid=?",
                                (None, ), (self.text[1], ))[0]

        if Settings.get('use_lesson_stats') or not is_lesson:
            DB.executemany_(
                '''insert into statistic
                (time,viscosity,w,count,mistakes,type,data) values (?,?,?,?,?,?,?)''',
                vals)
            DB.executemany_(
                'insert into mistake (w,target,mistake,count) values (?,?,?,?)',
                [(now, k[0], k[1], v) for k, v in mistakes.iteritems()])

        if is_lesson:
            mins = (Settings.get("min_lesson_wpm"),
                    Settings.get("min_lesson_acc"))
        else:
            mins = (Settings.get("min_wpm"), Settings.get("min_acc"))

        if 12.0 / spc < mins[0] or accuracy < mins[1] / 100.0:
            self.setText(self.text)
        elif not is_lesson and Settings.get('auto_review'):
            ws = filter(lambda x: x[5] == 2, vals)
            if len(ws) == 0:
                self.emit(SIGNAL("wantText"))
                return
            ws.sort(key=lambda x: (x[4], x[0]), reverse=True)
            i = 0
            while ws[i][4] != 0:
                i += 1
            i += (len(ws) - i) // 4

            self.emit(SIGNAL("wantReview"), map(lambda x: x[6], ws[0:i]))
        else:
            self.emit(SIGNAL("wantText"))
예제 #33
0
def space_replacement_dict_from_setting(replacement_var):
    '''Returns a dict that assigns to html spaces the value in the setting replacement_var'''
    return space_replacement_dict(Settings.get(replacement_var))
예제 #34
0
import os
import sys


# Get command-line --database argument before importing
# modules which count on database support
from Config import Settings

import optparse

opts = optparse.OptionParser()
opts.add_option("-d", "--database", metavar="FILE", help="use database FILE")
v = opts.parse_args()[0]

if v.database is not None:
    Settings.set("db_name", v.database)

from Data import DB
from Quizzer import Quizzer
from StatWidgets import StringStats
from TextManager import TextManager
from Performance import PerformanceHistory
from Config import PreferenceWidget
from Lesson import LessonGenerator
from Widgets.Database import DatabaseWidget

from PyQt4.QtCore import *
from PyQt4.QtGui import *

QApplication.setStyle("cleanlooks")
예제 #35
0
    def setPalettes(self):
        inactive_palette = QPalette(Qt.black,
                Settings.getColor("quiz_inactive_bd"), Qt.lightGray, Qt.darkGray, Qt.gray,
                Settings.getColor("quiz_inactive_fg"), Qt.yellow, Settings.getColor("quiz_inactive_bg"), Qt.yellow)

        inactive_palette.setColor(QPalette.Highlight, Settings.getColor("quiz_inactive_hl"))
        inactive_palette.setColor(QPalette.HighlightedText, Settings.getColor("quiz_inactive_hl_text"))
        self.palettes = {
            'wrong': QPalette(Qt.black,
                Settings.getColor("quiz_wrong_bd"), Qt.lightGray, Qt.darkGray, Qt.gray,
                Settings.getColor("quiz_wrong_fg"), Qt.white, Settings.getColor("quiz_wrong_bg"), Qt.yellow),
            'right': QPalette(Qt.black,
                Settings.getColor("quiz_right_bd"), Qt.lightGray, Qt.darkGray, Qt.gray,
                Settings.getColor("quiz_right_fg"), Qt.yellow, Settings.getColor("quiz_right_bg"), Qt.yellow),
            'invisible': QPalette(Qt.black,
                Settings.getColor("quiz_invisible_bd"), Qt.lightGray, Qt.darkGray, Qt.gray,
                Settings.getColor("quiz_invisible_color"), Qt.yellow, Settings.getColor("quiz_invisible_color"), Qt.yellow),
            'inactive':inactive_palette }
        self.setPalette(self.palettes['inactive']) 
예제 #36
0
def new_error(position,errors):
    '''Given list of error positions and current position, 
returns whether or there's a new error at position'''
    #considers adjacent errors to be part of the same error if the setting is toggled
    return position in errors and not (Settings.get('adjacent_errors_not_counted') and position - 1 in errors)
예제 #37
0
 def activate_invisibility(self):
     '''Turns on invisible mode'''
     self.setPalette(self.palettes['invisible'])
     set_colored_typer_text(self,Settings.get('quiz_invisible_color'))  #flushes out html with plaintext
예제 #38
0
    def done(self):
        now = time.time()
        elapsed, chars, times, mis, mistakes = self.typer.getStats()

        assert chars == len(self.text[2])

        accuracy = 1.0 - len(filter(None, mis)) / chars
        spc = elapsed / chars
        
        viscosity = sum(map(lambda x: ((x-spc)/spc)**2, times)) / chars

        DB.execute('insert into result (w,text_id,source,wpm,accuracy,viscosity) values (?,?,?,?,?,?)',
                   (now, self.text[0], self.text[1], 12.0/spc, accuracy, viscosity))

        v2 = DB.fetchone("""select agg_median(wpm),agg_median(acc) from
            (select wpm,100.0*accuracy as acc from result order by w desc limit %d)""" % Settings.get('def_group_by'), (0.0, 100.0))
        self.result.setText("Last: %.1fwpm (%.1f%%), last 10 average: %.1fwpm (%.1f%%)"
            % ((12.0/spc, 100.0*accuracy) + v2))

        self.emit(SIGNAL("statsChanged"))

        stats = collections.defaultdict(Statistic)
        visc = collections.defaultdict(Statistic)
        text = self.text[2]

        for c, t, m in zip(text, times, mis):
            stats[c].append(t, m)
            visc[c].append(((t-spc)/spc)**2)

        def gen_tup(s, e):
            perch = sum(times[s:e])/(e-s)
            visc = sum(map(lambda x: ((x-perch)/perch)**2, times[s:e]))/(e-s)
            return (text[s:e], perch, len(filter(None, mis[s:e])), visc)

        for tri, t, m, v in [gen_tup(i, i+3) for i in xrange(0, chars-2)]:
            stats[tri].append(t, m > 0)
            visc[tri].append(v)

        regex = re.compile(r"(\w|'(?![A-Z]))+(-\w(\w|')*)*")

        for w, t, m, v in [gen_tup(*x.span()) for x in regex.finditer(text) if x.end()-x.start() > 3]:
            stats[w].append(t, m > 0)
            visc[w].append(v)

        def type(k):
            if len(k) == 1:
                return 0
            elif len(k) == 3:
                return 1
            return 2

        vals = []
        for k, s in stats.iteritems():
            v = visc[k].median()
            vals.append( (s.median(), v*100.0, now, len(s), s.flawed(), type(k), k) )

        is_lesson = DB.fetchone("select discount from source where rowid=?", (None,), (self.text[1], ))[0]

        if Settings.get('use_lesson_stats') or not is_lesson:
            DB.executemany_('''insert into statistic
                (time,viscosity,w,count,mistakes,type,data) values (?,?,?,?,?,?,?)''', vals)
            DB.executemany_('insert into mistake (w,target,mistake,count) values (?,?,?,?)',
                    [(now, k[0], k[1], v) for k, v in mistakes.iteritems()])

        if is_lesson:
            mins = (Settings.get("min_lesson_wpm"), Settings.get("min_lesson_acc"))
        else:
            mins = (Settings.get("min_wpm"), Settings.get("min_acc"))

        if 12.0/spc < mins[0] or accuracy < mins[1]/100.0:
            self.setText(self.text)
        elif not is_lesson and Settings.get('auto_review'):
            ws = filter(lambda x: x[5] == 2, vals)
            if len(ws) == 0:
                self.emit(SIGNAL("wantText"))
                return
            ws.sort(key=lambda x: (x[4],x[0]), reverse=True)
            i = 0
            while ws[i][4] != 0:
                i += 1
            i += (len(ws) - i) // 4

            self.emit(SIGNAL("wantReview"), map(lambda x:x[6], ws[0:i]))
        else:
            self.emit(SIGNAL("wantText"))
예제 #39
0
 def activate_invisibility(self):
     '''Turns on invisible mode'''
     self.setPalette(self.palettes['invisible'])
     set_colored_typer_text(self, Settings.get(
         'quiz_invisible_color'))  #flushes out html with plaintext
예제 #40
0
def get_wait_text():
    if Settings.get("req_space"):
        return ("Press SPACE and then immediately start typing the text\n"
                "Press ESCAPE to restart with a new text at any time")
    return "Press ESCAPE to restart with a new text at any time"
예제 #41
0
    def checkText(self):
        if self.typer.target is None or self.typer.editflag:
            return

        v = unicode(self.typer.toPlainText())
        
        if Settings.get('allow_mistakes') and len(v) >= len(self.typer.target):
            v = self.typer.target

        if not self.typer.started:
            if Settings.get('req_space'):
            #space is required before beginning the passage proper
                if v == u" ":
                    #the first char typed was space
                    #the first space only starts the session; clear the typer
                    set_typer_text(self.typer,"",cursor_position=0)
                    self.typer.when[0] = timer()
                    self.typer.started = True
                    return
                else:
                    #reset the wait text
                    set_typer_text(self.typer,self.typer.getWaitText())
                    self.typer.selectAll()
                    return
            else:
                self.typer.when[0] = -1
                self.typer.when[1] = timer()  #have to set starting time regardless of correctness
                self.typer.started = True

        old_cursor = self.typer.textCursor()
        old_position = old_cursor.position()
        old_str_position = old_position - 1  #the position that has (presumably) just been typed
     
        #colors text in typer depending on errors
        errors = disagreements(v,self.typer.target,case_sensitive=Settings.get('case_sensitive'))
        first_error = errors[0] if errors else None

        #records time that any char was correctly hit
        #except that if we've already been correct farther, we don't record
        if self.typer.farthest_correct < old_str_position < len(self.typer.target) and not old_str_position in errors:
            self.typer.when[old_str_position+1] = timer() #zeroth position is original space
            self.typer.farthest_correct = old_str_position

        automatic_insertion_regex = generate_automatic_insertion_regex()
        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #TODO: change statistics to account for this
        #Automatically insert characters into the text area
        if automatic_insertion_regex and old_position == len(v): #only works if cursor is at the end
            automatic_insertion = re.match(automatic_insertion_regex,self.typer.target[old_position:])
            if automatic_insertion:
                new_end = old_position + automatic_insertion.end()
                set_typer_text(self.typer, v[:old_position] + self.typer.target[old_position:new_end], cursor_position = new_end)
                self.checkText()  #recovers the formatting
                return

        #TODO: refactor so this doesn't rely on text setting then re-calling gimmick
        #Prevent advancement until user correctly types space
        if Settings.get('ignore_until_correct_space') and self.typer.target[old_str_position] == u" " and old_str_position in errors:
            #gets rid of new character (sets as plaintext)
            set_typer_text(self.typer,v[:old_str_position] + v[old_str_position+1:],cursor_position = old_position - 1) 
            self.checkText()    #recovers the formatting 
            return

        if len(v) >= len(self.typer.target) and (not first_error or first_error >= len(self.typer.target)):
            self.done()
            return
       
        if new_error(old_str_position,errors): 
            self.typer.mistake[old_str_position] = True
            self.typer.mistakes[old_str_position] = self.typer.target[old_str_position] + v[old_str_position]

        if Settings.get('quiz_invisible'):
            self.typer.activate_invisibility()
        else:
            if Settings.get("quiz_use_wrong_palette") and errors:
                self.typer.setPalette(self.typer.palettes['wrong'])
            else:
                self.typer.setPalette(self.typer.palettes['right'])
            update_typer_html(self.typer,errors)
        
        #updates the label depending on errors
        self.updateLabel(old_position,errors)
예제 #42
0
파일: Amphetype.py 프로젝트: Alok/amphetype
import os
import sys


# Get command-line --database argument before importing
# modules which count on database support
from Config import Settings

import optparse
opts = optparse.OptionParser()
opts.add_option("-d", "--database", metavar="FILE", help="use database FILE")
v = opts.parse_args()[0]

if v.database is not None:
    Settings.set('db_name', v.database)

from Data import DB
from Quizzer import Quizzer
from StatWidgets import StringStats
from TextManager import TextManager
from Performance import PerformanceHistory
from Config import PreferenceWidget
from Lesson import LessonGenerator
from Widgets.Database import DatabaseWidget

from PyQt4.QtCore import *
from PyQt4.QtGui import *

QApplication.setStyle('cleanlooks')
예제 #43
0
 def setText(self, text):
     self.text = text 
     self.label.setText(self.text[2].replace(u"\n", u"{0}\n".format(Settings.get('label_return_symbol')))) 
     self.typer.setTarget(self.text[2])
     self.typer.setFocus()
예제 #44
0
 def getWaitText(self):
     if Settings.get('req_space'):
         return "Press SPACE and then immediately start typing the text\n" + \
                 "Press ESCAPE to restart with a new text at any time"
     else:
         return "Press ESCAPE to restart with a new text at any time"
예제 #45
0
 def __init__(self, fname):
     GObject.Object.__init__(self)
     with codecs.open(fname, "r", "utf_8_sig") as file:
         self.paras = self.get_paras(file)
     self.lessons = None
     self.min_chars = Settings.get("min_chars")
예제 #46
0
    def updateLabel(self, position, errors):
        '''Populates the label with colors depending on current position and errors.'''
        #dict : str -> str ; original and displacement strs in error region (for easier display)
        err_replacements = {
            "\n": u"{0}<BR>".format(Settings.get('label_return_symbol'))
        }

        colors = {}  #dict : int -> str, mapping errors to color

        if Settings.get('show_label_mistakes'):
            #showing mistakes; need to populate color
            colors = dict([(i, Settings.get('label_mistakes_color'))
                           for i in errors])

            if Settings.get('label_replace_spaces_in_mistakes'):
                err_replacements.update(
                    space_replacement_dict_from_setting(
                        'label_mistakes_space_char'))

        text_strs = list(
            self.text[2]
        )  #list of strs, initially one char each, to operate on
        text_strs = html_list_process_spaces(text_strs)
        text_strs = replace_at_locs(text_strs, err_replacements, errors)

        def color_position(settings_color_var, use_space_var, space_var):
            '''Colors position with the color stored in settings_color_var.
            
strs use_space_var and space_var are settings variables to look up.
If [setting] use_space_var, space at position is replaced with [setting] space_var

Returns the new text_strs list (for assignment).'''
            colors[position] = Settings.get(settings_color_var)

            if Settings.get(use_space_var):
                return replace_at_locs(
                    text_strs, space_replacement_dict_from_setting(space_var),
                    [position])
            else:
                return text_strs

        #designates colors and replacements of position
        if Settings.get('show_label_position_with_prior_mistake'
                        ) and position - 1 in errors:
            text_strs = color_position(
                'label_position_with_prior_mistake_color',
                'label_replace_spaces_in_position_with_prior_mistake',
                'label_position_with_prior_mistake_space_char')
        elif Settings.get('show_label_position_with_mistakes') and errors:
            text_strs = color_position(
                'label_position_with_mistakes_color',
                'label_replace_spaces_in_position_with_mistakes',
                'label_position_with_mistakes_space_char')
        elif Settings.get('show_label_position'):
            text_strs = color_position('label_position_color',
                                       'label_replace_spaces_in_position',
                                       'label_position_space_char')

        htmlized = "".join(html_color_strs(text_strs, colors))
        htmlized = htmlized.replace(
            u"\n", u"{0}<BR>".format(Settings.get('label_return_symbol')))

        self.label.setText(htmlized)
예제 #47
0
def main(players_list, player, username, config_level: Settings):
    # Auxiliary variables
    difficulty_level = config_level.getLevel()
    difficulty_level_spanish = ''
    if difficulty_level == 'easy':
        difficulty_level_spanish = 'Fácil'
    elif difficulty_level == 'medium':
        difficulty_level_spanish = 'Medio'
    elif difficulty_level == 'hard':
        difficulty_level_spanish = 'Difícil'
    letter_changes_available = LETTER_CHANGES_AVAILABLE
    # Setting savefile name
    savefile_name = 'user_' + username + '-level_{}-saved_game'.format(difficulty_level) + '.pkl'
    # Data structures for the interface to be updated with
    all_letters = []
    for k, v in config_level.getLetterPool().items():
        for i in range(v):
            all_letters.append(k)
    user_letter_array = []
    ai_letter_array = []
    # Assign letters
    for i in range(ARRAY_LENGTH):
        # For the user
        letter = random.choice(all_letters).upper()
        user_letter_array.append(letter)
        all_letters.remove(letter)
        # For the AI
        letter = random.choice(all_letters).upper()
        ai_letter_array.append(letter)
        all_letters.remove(letter)
    # Association between letter positions and colors for scoring in a matrix
    letter_matrix = [[[annotate_button((i, j), difficulty_level), colorize_button((i, j), difficulty_level)] for i in range(BOARD_WIDTH)] for j in range(BOARD_HEIGHT)]
    # Positions for the AI to choose from
    board_positions = [(i, j) for i in range(BOARD_WIDTH) for j in range(BOARD_HEIGHT)]
    # Random initial turn
    user_turn = random.choice([True, False])
    # Initializing scores
    user_total_score = 0
    ai_total_score = 0
    #### Layouts ####
    # Board column layout
    ColumnBoard= [ [sg.Button(key=(i, j), button_text='{}'.format(letter_matrix[i][j][0]), button_color=(None, letter_matrix[i][j][1]), size=BUTTON_SIZE, pad=(BUTTON_PADDING, BUTTON_PADDING), enable_events=True) for i in range(BOARD_WIDTH)] for j in range(BOARD_HEIGHT)
    ]
    Column1= [ [sg.Button(key=i + ARRAY_LENGTH, button_text='?', size=(5,2), pad=((BUTTON_PADDING, BUTTON_PADDING), (8, BUTTON_PADDING)), enable_events=True, disabled=True) for i in range(ARRAY_LENGTH)],
               [sg.Text('Puntaje del ordenador:', key='-AI_TOTAL_SCORE_TEXT-', size=(19, 1), font=('Verdana', 10)),sg.Text(key='-AI_TOTAL_SCORE-', size=(8, 1), font=('Verdana', 11))],
               [sg.Text('_' * ((BUTTON_WIDTH + BUTTON_PADDING) * BOARD_WIDTH + 4), key='-BOTTOM_H_SEPARATOR1-')],
               [sg.Column(ColumnBoard, key='-C1-')],
               [sg.Text('_' * ((BUTTON_WIDTH + BUTTON_PADDING) * BOARD_WIDTH + 4), key='-BOTTOM_H_SEPARATOR2-')],
               [sg.Text('Puntaje del usuario:', key='-USER_TOTAL_SCORE_TEXT-', size=(19, 1), font=('Verdana', 10)), sg.Text(key='-USER_TOTAL_SCORE-', size=(8, 1), font=('Verdana', 11))],
               [sg.Button(key=i, button_text=user_letter_array[i], size=(5,2), pad=((BUTTON_PADDING, BUTTON_PADDING), (8, BUTTON_PADDING)), enable_events=True) for i in range(ARRAY_LENGTH)] ]
    Column2=[ [sg.T(' ' * 10, key='-t1-')],
              [sg.T(' ' * 10, key='-t2-')],
              [sg.Text('Nivel:',font=("Verdana", "9"),text_color='black', key='-t3-')],
              [sg.Text(difficulty_level_spanish, size=(15, 1), justification='center', font=("Verdana", "30", "bold"), text_color='#d7191c', key='-t4-')],
              [sg.T(' ' * 10, key='-t5-')],
              [sg.T(' ' * 10, key='-t6-')],
              [sg.Text('Tiempo restante de juego:', justification='center', key='-CLOCK_TEXT-')],
              [sg.Text(key='-CLOCK-', size=(8, 2), font=('Verdana', 10), justification='center')],
              [sg.T(' ' * 10, key='-t7-')],
              [sg.T(' ' * 10, key='-t8-')],
              [sg.T(' ' * 5),sg.Button('Regresar letras al atril', key='-RETURN_LETTERS-', pad=((28, BUTTON_PADDING), (4, BUTTON_PADDING)))],
              [sg.T(' ' * 10, key='-t9-')],
              [sg.T(' ' * 20),sg.Button('Puntuar', key='-SCORE-', pad=((0, BUTTON_PADDING), (8, BUTTON_PADDING)))],
              [sg.T(' ' * 10, key='-t10_save-')],
              [sg.Button('Guardar', key='-SAVE-', pad=((50, BUTTON_PADDING), (8, BUTTON_PADDING))), sg.Button('Cargar', key='-LOAD-', pad=((50, BUTTON_PADDING), (8, BUTTON_PADDING)))],
              [sg.T(' ' * 10, key='-t10-')],
              [sg.T(' ' * 8),sg.Button('Terminar', key='-FINISH-', pad=((50, BUTTON_PADDING), (8, BUTTON_PADDING)))],
              [sg.T(' ' * 10, key='-t11-')],
              [sg.T(' ' * 8),sg.Button(f'Cambiar letras ({letter_changes_available})', key='-CHANGE_LETTERS-', pad=((28, BUTTON_PADDING), (8, BUTTON_PADDING)))] ]
    layout= [ [sg.Column(Column1, key='-C3-'),sg.VerticalSeparator(),sg.Column(Column2, key='-C4-')]]
    window = sg.Window('ScrabbleAR', layout, grab_anywhere=True, no_titlebar=True)
    # Auxiliary variables
    letter_grabbed = ''
    user_word = ''
    user_word_score = 0
    ai_word_score = 0
    first_letter_placement_ever = True
    first_letter_placement = True
    moves_horizontally = True
    moves_vertically = True
    pos = ()
    changing_letters = False
    user_chose_letter_to_change = False
    # These three variables are for keeping track of letters and positions in play
    letter_matrix_positions_updated = []
    user_letter_array_positions_updated = []
    letters_in_use = []
    # Time variables
    game_duration = config_level.getGameDuration()
    start_time = time.time()
    finish_time = start_time + game_duration
    endgame = False
    # Loop
    while True:
        event, values = window.read(timeout=10)
        if event == None:
            break
        if endgame:
            sg.PopupOK(f'Juego finalizado. Tus puntos: {user_total_score}. Puntos del ordenador: {ai_total_score}', no_titlebar=True, grab_anywhere=True)
            # Saves max points for the user
            if user_total_score > player.get_puntos():
                player.set_score(user_total_score)
                players_list.agregar_jugador(player)
                Database.guardo_base(players_list)
                sg.PopupOK(f'Has quedado en nuestro ranking!', no_titlebar=True, grab_anywhere=True)
            window.close()
            break
        # Updating time
        current_time = time.time()
        remaining_time = finish_time - current_time
        hours, rem = divmod(remaining_time, 3600)
        minutes, seconds = divmod(rem, 60)
        window['-CLOCK-'].Update('{:0>2}:{:0>2}:{:02d}'.format(int(hours),int(minutes),int(seconds)))
        # Checks for endtime
        if remaining_time <= 0:
            sg.PopupOK('Se acabó el tiempo', no_titlebar=True, grab_anywhere=True)
            endgame = True
        # Checks if save/load feature can be enabled
        if not changing_letters and user_turn and '' not in user_letter_array:
            window['-SAVE-'].Update(disabled=False)
            window['-LOAD-'].Update(disabled=False)
        else:
            window['-SAVE-'].Update(disabled=True)
            window['-LOAD-'].Update(disabled=True)
        # Checks for save button
        if event == '-SAVE-':
            if path.exists(savefile_name):
                sg.PopupOK(f'Se sobreescribirá la partida anterior.', no_titlebar=True, grab_anywhere=True)
            game_state = [letter_matrix, all_letters, user_letter_array, ai_letter_array, user_total_score, ai_total_score, remaining_time, letter_changes_available, config_level]
            with open(savefile_name, 'wb') as f:
                pickle.dump(game_state, f)
            sg.PopupOK(f'Juego guardado.', no_titlebar=True, grab_anywhere=True)
        # Checks for load button
        if event == '-LOAD-':
            # game_state = [letter_matrix, all_letters, user_letter_array, ai_letter_array, user_total_score, ai_total_score, remaining_time, letter_changes_available, config_level]
            try:
                with open(savefile_name, 'rb') as f:
                    game_state = pickle.load(f)
                # loads game state variables
                letter_matrix = game_state[0]
                all_letters = game_state[1]
                user_letter_array = game_state[2]
                ai_letter_array = game_state[3]
                user_total_score = game_state[4]
                ai_total_score = game_state[5]
                remaining_time = game_state[6]
                letter_changes_available = game_state[7]
                config_level = game_state[8]
                # Resetting the time
                game_duration = remaining_time
                start_time = time.time()
                finish_time = start_time + game_duration
                # Updates board
                for pos in board_positions:
                    window[pos].Update('{}'.format(letter_matrix[pos[0]][pos[1]][0]))
                # Updates user array
                for i in range(ARRAY_LENGTH):
                    window[i].Update('{}'.format(user_letter_array[i]))
                # Updates letter changes available button
                window['-CHANGE_LETTERS-'].Update(f'Cambiar letras ({letter_changes_available})')
                # Popup confirmation
                sg.PopupOK(f'Juego cargado.', no_titlebar=True, grab_anywhere=True)
            except FileNotFoundError:
                sg.PopupOK(f'No se encontró partida guardada.', no_titlebar=True, grab_anywhere=True)
        # Checks for exit button
        if event == '-FINISH-':
            endgame = True
        # Updates score in the display
        window['-USER_TOTAL_SCORE-'].Update(user_total_score)
        window['-AI_TOTAL_SCORE-'].Update(ai_total_score)


        # AI play
        if not user_turn:
            # Lists valid words
            ai_word = ''
            ai_words = []
            for i in range(len(ai_letter_array)):
                ai_words += [ai_word.join(ai_letter) for ai_letter in permutations(ai_letter_array, i + 1)]
            ai_unique_words = set(ai_words)
            ai_valid_words = [word for word in filter(valid, ai_unique_words)]
            # Tries to make a word
            try:
                # Chooses a valid word
                # Sorts them by length
                ai_valid_words.sort(key=lambda x: len(x))
                if difficulty_level == 'easy':
                    # Picks the shortest
                    ai_word_choice = ai_valid_words.pop(0)
                elif difficulty_level == 'medium':
                    # Picks the word in the middle
                    ai_word_choice = ai_valid_words.pop(len(ai_valid_words) // 2)
                elif difficulty_level == 'hard':
                    # Picks the longest
                    ai_word_choice = ai_valid_words.pop()
                # Finds place to put the word
                positions_needed = len(ai_word_choice)
                while positions_needed:
                    if first_letter_placement_ever:
                        first_letter_placement_ever = False
                        first_letter_placement = False
                        # First letter ever to the center of the board
                        pos = (BOARD_WIDTH // 2, BOARD_HEIGHT // 2)
                        direction = random.choice(['downwards', 'rightwards'])
                        positions_needed -= 1
                        letter_matrix_positions_updated.append(pos)
                    elif first_letter_placement:
                        first_letter_placement = False
                        # First letter of a word is random
                        pos = random.choice(board_positions)
                        direction = random.choice(['downwards', 'rightwards'])
                        positions_needed -= 1
                        letter_matrix_positions_updated.append(pos)
                    else:
                        if direction == 'downwards':
                            for i in range(positions_needed):
                                pos = list(pos)
                                pos[1] += 1
                                pos = tuple(pos)
                                letter_matrix_positions_updated.append(pos)
                                positions_needed -= 1
                        else:
                            # direction is rightwards
                            for i in range(positions_needed):
                                pos = list(pos)
                                pos[0] += 1
                                pos = tuple(pos)
                                letter_matrix_positions_updated.append(pos)
                                positions_needed -= 1
                    if positions_needed == 0:
                        # Checks if it's all available spots
                        for p in letter_matrix_positions_updated:
                            if p[0] >= BOARD_WIDTH or p[1] >= BOARD_HEIGHT or not board_is_empty(letter_matrix[p[0]][p[1]][0]):
                                # Preparing for the next search
                                positions_needed = len(ai_word_choice)
                                first_letter_placement = True
                                letter_matrix_positions_updated = []
                                break
                # Places the letters in the board
                for i in range(len(ai_word_choice)):
                    # Grabs a letter
                    ai_letter = ai_word_choice[i]
                    # Erases it from the ai letter array
                    ai_letter_array[ai_letter_array.index(ai_letter)] = ''
                    # Gets the corresponding position
                    pos = letter_matrix_positions_updated[i]
                    # Updates association matrix
                    letter_matrix[pos[0]][pos[1]][0] = ai_letter
                    # Reflects it on the display
                    window[pos].Update('{}'.format(letter_matrix[pos[0]][pos[1]][0]))
                # Scores the AI word
                ai_word_score = score(ai_word_choice, letter_matrix, letter_matrix_positions_updated, config_level)
                ai_total_score += ai_word_score
                # Checks for endgame if there aren't enough letters in the pool to replace the last used
                if len(ai_word_choice) > len(all_letters):
                    sg.PopupOK('No hay más letras en la bolsa', no_titlebar=True, grab_anywhere=True)
                    endgame = True
                else:
                    # Assign more letters for the ai
                    for i in range(len(ai_word_choice)):
                        letter = random.choice(all_letters).upper()
                        ai_letter_array[ai_letter_array.index('')] = letter
                        all_letters.remove(letter)
                    # The turn goes back to the user
                    user_turn = not user_turn
                    # Resets for the user
                    first_letter_placement = True
                    letter_matrix_positions_updated = []
            # Handles .pop() at line 208 if no valid words were found
            except IndexError:
                sg.PopupOK('El ordenador no ha encontrado palabra', no_titlebar=True, grab_anywhere=True)
                endgame = True

        # Interaction with user's set of letters
        if type(event) == int and not changing_letters and user_turn:
            # Grabs the letter from the array
            if user_letter_array[event] != '' and letter_grabbed == '':
                letter_grabbed = user_letter_array[event]
                letters_in_use.append(letter_grabbed)
                user_letter_array[event] = ''
                window[event].Update('')
                user_letter_array_positions_updated.append(event)
            # Puts the letter back in the array
            elif user_letter_array[event] == '' and letter_grabbed != '':
                user_letter_array[event] = letter_grabbed
                letters_in_use.remove(letter_grabbed)
                letter_grabbed = ''
                window[event].Update('{}'.format(user_letter_array[event]))
                user_letter_array_positions_updated.remove(event)
        # Interaction with game board
        if type(event) == tuple and board_is_empty(letter_matrix[event[0]][event[1]][0]) and letter_grabbed != '' and not changing_letters and user_turn:
            # The first ever letter placement goes in the center
            if first_letter_placement_ever:
                pos = (BOARD_WIDTH // 2, BOARD_HEIGHT // 2)
                # Checks whether the first letter is positioned correctly
                if event[0] == pos[0] and event[1] == pos[1]:
                    first_letter_placement_ever = False
                    first_letter_placement = False
                    letter_matrix[event[0]][event[1]][0] = letter_grabbed
                    window[event].Update('{}'.format(letter_matrix[event[0]][event[1]][0]))
                    user_word += letter_grabbed
                    letter_grabbed = ''
                    pos = event[0], event[1]
                    letter_matrix_positions_updated.append(event)
                # Gives a hint to where should the letter go
                else:
                    window[(pos[0], pos[1])].Update('{}'.format(letter_grabbed))
                    window.Refresh()
                    time.sleep(0.1)
                    window[(pos[0], pos[1])].Update(annotate_button((pos[0], pos[1]), difficulty_level))
            else:
                # The subsequent first letter placement are free
                if first_letter_placement:
                    # Updates board
                    letter_matrix[event[0]][event[1]][0] = letter_grabbed
                    window[event].Update('{}'.format(letter_matrix[event[0]][event[1]][0]))
                    user_word += letter_grabbed
                    letter_grabbed = ''
                    pos = event[0], event[1]
                    letter_matrix_positions_updated.append(event)
                    first_letter_placement = False
                # If it's not the first letter placement, restrains the placements to exclusively rightwards or downwards
                elif (event[0] - 1 == pos[0] and event[1] == pos[1]) or (event[0] == pos[0] and event[1] - 1 == pos[1]):
                    if moves_horizontally and event[0] - 1 == pos[0] and event[1] == pos[1]:
                        moves_vertically = False
                        # Updates board
                        letter_matrix[event[0]][event[1]][0] = letter_grabbed
                        window[event].Update('{}'.format(letter_matrix[event[0]][event[1]][0]))
                        user_word += letter_grabbed
                        letter_grabbed = ''
                        pos = event[0], event[1]
                        letter_matrix_positions_updated.append(event)
                    # Gives a hint to where should the letter go (the exception could raise if the movement would be illegal)
                    elif moves_horizontally and not moves_vertically:
                        try:
                            window[(pos[0] + 1, pos[1])].Update('{}'.format(letter_grabbed))
                            window.Refresh()
                            time.sleep(0.1)
                            window[(pos[0] + 1, pos[1])].Update(annotate_button((pos[0] + 1, pos[1]), difficulty_level))
                        except AttributeError:
                            pass
                    elif moves_vertically and event[0] == pos[0] and event[1] - 1 == pos[1]:
                        moves_horizontally = False
                        # Updates board
                        letter_matrix[event[0]][event[1]][0] = letter_grabbed
                        window[event].Update('{}'.format(letter_matrix[event[0]][event[1]][0]))
                        user_word += letter_grabbed
                        letter_grabbed = ''
                        pos = event[0], event[1]
                        letter_matrix_positions_updated.append(event)
                    # Gives a hint to where should the letter go (the exception could raise if the movement would be illegal)
                    elif moves_vertically and not moves_horizontally:
                        try:
                            window[(pos[0], pos[1] + 1)].Update('{}'.format(letter_grabbed))
                            window.Refresh()
                            time.sleep(0.1)
                            window[(pos[0], pos[1] + 1)].Update(annotate_button((pos[0], pos[1] + 1), difficulty_level))
                        except AttributeError:
                            pass
                # Gives a hint to where should the letter go (the exception could raise if the movement would be illegal)
                elif moves_horizontally and not moves_vertically:
                    try:
                        window[(pos[0] + 1, pos[1])].Update('{}'.format(letter_grabbed))
                        window.Refresh()
                        time.sleep(0.1)
                        window[(pos[0] + 1, pos[1])].Update(annotate_button((pos[0] + 1, pos[1]), difficulty_level))
                    except AttributeError:
                        pass
                # Gives a hint to where should the letter go (the exception could raise if the movement would be illegal)
                elif moves_vertically and not moves_horizontally:
                    try:
                        window[(pos[0], pos[1] + 1)].Update('{}'.format(letter_grabbed))
                        window.Refresh()
                        time.sleep(0.1)
                        window[(pos[0], pos[1] + 1)].Update(annotate_button((pos[0], pos[1] + 1), difficulty_level))
                    except AttributeError:
                        pass

        # Resetting current word
        if event == '-RETURN_LETTERS-' and user_turn:
            letter_grabbed = ''
            # Reverses current play
            # Clears movement flags
            first_letter_placement = True
            moves_horizontally = True
            moves_vertically = True
            pos = ()
            for t in letter_matrix_positions_updated:
                letter_matrix[t[0]][t[1]][0] = annotate_button(t, difficulty_level)
                window[t].Update('{}'.format(letter_matrix[t[0]][t[1]][0]))
            while user_letter_array_positions_updated:
                i = user_letter_array_positions_updated.pop()
                user_letter_array[i] = letters_in_use.pop()
                window[i].Update('{}'.format(user_letter_array[i]))
            # Checks if the first word has been placed
            if user_total_score == 0 and ai_total_score == 0:
                first_letter_placement_ever = True

        # User starts changing letters
        if event == '-CHANGE_LETTERS-' and not changing_letters and user_turn:
            changing_letters = True
            window['-CHANGE_LETTERS-'].Update('Selecciónalas')
        # User chooses letters to change
        if type(event) == int and changing_letters:
            user_chose_letter_to_change = True
            window['-CHANGE_LETTERS-'].Update('Hacer el cambio')
            # Grabs the letter from the array
            if user_letter_array[event] != '':
                letter_grabbed = user_letter_array[event]
                letters_in_use.append(letter_grabbed)
                user_letter_array[event] = ''
                window[event].Update('')
                user_letter_array_positions_updated.append(event)
            # Puts the letter back in the array
            elif user_letter_array[event] == '' and letter_grabbed != '':
                user_letter_array[event] = letter_grabbed
                letters_in_use.remove(letter_grabbed)
                letter_grabbed = ''
                window[event].Update('{}'.format(user_letter_array[event]))
                user_letter_array_positions_updated.remove(event)
        # User finishes changing letters
        if event == '-CHANGE_LETTERS-' and changing_letters and user_chose_letter_to_change:
            letter_changes_available -= 1
            letter_grabbed = ''
            # Resetting the flags
            user_chose_letter_to_change = False
            changing_letters = False
            # Putting back the chosen letters
            quantity_chosen = len(letters_in_use)
            for i in range(quantity_chosen):
                all_letters.append(letters_in_use.pop())
            # Assign new letters
            new_letters = []
            for i in range(quantity_chosen):
                letter = random.choice(all_letters).upper()
                new_letters.append(letter)
                all_letters.remove(letter)
            # Update the user letter array
            for i in user_letter_array_positions_updated:
                user_letter_array[i] = new_letters.pop()
            # Update the display of the user letter array
            while user_letter_array_positions_updated:
                i = user_letter_array_positions_updated.pop()
                window[i].Update('{}'.format(user_letter_array[i]))
            window['-CHANGE_LETTERS-'].Update(f'Cambiar letras ({letter_changes_available})')
            if letter_changes_available == 0:
                window['-CHANGE_LETTERS-'].Update(disabled=True)
            # When the user changes their letters, their turn finishes
            user_turn = not user_turn

        # Score the created word
        if event == '-SCORE-' and user_turn:
            if valid(user_word):
                user_word_score = score(user_word, letter_matrix, letter_matrix_positions_updated, config_level)
                user_total_score += user_word_score
                user_word_score = 0
                # Check if there are enough letters in the pool to replace the last used
                if len(user_word) > len(all_letters):
                    sg.PopupOK('No hay más letras en la bolsa', no_titlebar=True, grab_anywhere=True)
                    endgame = True
                # Assign more letters for the user
                for i in range(len(user_word)):
                    letter = random.choice(all_letters).upper()
                    user_letter_array[user_letter_array.index('')] = letter
                    all_letters.remove(letter)
                # Updates user letter array display with the new and the remaining letters
                for i in range(len(user_letter_array)):
                    window[i].Update('{}'.format(user_letter_array[i]))
                # Resets variables for next invalid word
                letter_matrix_positions_updated = []
                user_letter_array_positions_updated = []
                letters_in_use = []
                # When the user scores a valid word, their turn finishes
                user_turn = not user_turn
            else:
                # Reverses current play
                for t in letter_matrix_positions_updated:
                    letter_matrix[t[0]][t[1]][0] = annotate_button(t, difficulty_level)
                    window[t].Update('{}'.format(letter_matrix[t[0]][t[1]][0]))
                while user_letter_array_positions_updated:
                    i = user_letter_array_positions_updated.pop()
                    user_letter_array[i] = letters_in_use.pop()
                    window[i].Update('{}'.format(user_letter_array[i]))
                sg.PopupOK('Tu palabra era inválida', no_titlebar=True, grab_anywhere=True)
                # Checks if the first word has been placed
                if user_total_score == 0 and ai_total_score == 0:
                    first_letter_placement_ever = True
            # Clears movement flags
            first_letter_placement = True
            moves_horizontally = True
            moves_vertically = True
            pos = ()
            user_word = ''
예제 #48
0
    def setPalettes(self):
        inactive_palette = QPalette(Qt.black,
                                    Settings.getColor("quiz_inactive_bd"),
                                    Qt.lightGray, Qt.darkGray, Qt.gray,
                                    Settings.getColor("quiz_inactive_fg"),
                                    Qt.yellow,
                                    Settings.getColor("quiz_inactive_bg"),
                                    Qt.yellow)

        inactive_palette.setColor(QPalette.Highlight,
                                  Settings.getColor("quiz_inactive_hl"))
        inactive_palette.setColor(QPalette.HighlightedText,
                                  Settings.getColor("quiz_inactive_hl_text"))
        self.palettes = {
            'wrong':
            QPalette(Qt.black, Settings.getColor("quiz_wrong_bd"),
                     Qt.lightGray, Qt.darkGray, Qt.gray,
                     Settings.getColor("quiz_wrong_fg"), Qt.white,
                     Settings.getColor("quiz_wrong_bg"), Qt.yellow),
            'right':
            QPalette(Qt.black, Settings.getColor("quiz_right_bd"),
                     Qt.lightGray, Qt.darkGray, Qt.gray,
                     Settings.getColor("quiz_right_fg"), Qt.yellow,
                     Settings.getColor("quiz_right_bg"), Qt.yellow),
            'invisible':
            QPalette(Qt.black, Settings.getColor("quiz_invisible_bd"),
                     Qt.lightGray, Qt.darkGray, Qt.gray,
                     Settings.getColor("quiz_invisible_color"), Qt.yellow,
                     Settings.getColor("quiz_invisible_color"), Qt.yellow),
            'inactive':
            inactive_palette
        }
        self.setPalette(self.palettes['inactive'])
예제 #49
0
파일: gui5.py 프로젝트: KoleckOLP/yt-dl
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        uic.loadUi("gui5.ui", self)

        self.show()

        self.setAcceptDrops(True)

        def messagePopup(title, icon, text, callf=None):
            msg = QMessageBox(
            )  # Pylance is being stupid, I had to disable Type checking.
            msg.setWindowTitle(title)
            msg.setIcon(icon)
            msg.setText(text)
            if callf is not None:
                msg.setStandardButtons(
                    QMessageBox.Ok | QMessageBox.Cancel
                )  # F**k pylance it says that this line is wrong anf that int can't bd a button, there is not int.
                msg.buttonClicked.connect(callf)
            msg.exec_()

        def SaveDefaultConfig(i):
            text: str = i.text().lower()
            if "ok" in text:
                nonlocal settings
                settings = Settings.loadDefault()
                settings.toJson(settingsPath)
            else:
                exit()

        def status(
                s=""
        ):  # shows status message and changes color of the status bar.
            self.statusBar().showMessage(s)
            if s == "Ready.":
                self.statusBar().setStyleSheet("background-color: #00BB00")
            elif s == "Busy.":
                self.statusBar().setStyleSheet("background-color: #FF6600")
            else:
                self.statusBar().setStyleSheet("background-color: #A9A9A9")

        def process_start(cmd: List[str], output_console):
            if (sys.platform.startswith("win")):  # (os.name == "nt"):
                process = subprocess.Popen(
                    cmd,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT,
                    creationflags=0x08000000,
                    universal_newlines=True,
                    encoding="utf8"
                )  # this one does not check if another process is running
            else:  # (sys.platform.startswith(("linux", "darwin", "freebsd"))): #(os.name == "posix"): #other oeses should be fine with this
                process = subprocess.Popen(cmd,
                                           stdout=subprocess.PIPE,
                                           stderr=subprocess.STDOUT,
                                           universal_newlines=True,
                                           errors="ignore")
            while True:
                test = process.stdout.readline()
                if not test:
                    break
                test = str(test)
                if "\\n" in test:
                    test = test.replace("\\n", "\n")
                output_console.insertPlainText(test)
                self.scrollbar = output_console.verticalScrollBar()
                self.scrollbar.setValue(self.scrollbar.maximum())
                QtWidgets.QApplication.processEvents()
            print("\a")
            output_console.insertPlainText("#yt-dl# Process has finished.\n\n")
            QtWidgets.QApplication.processEvents()
            self.scrollbar = output_console.verticalScrollBar()
            self.scrollbar.setValue(self.scrollbar.maximum())

        def openFolder(loc=""):
            if (sys.platform.startswith("win")):
                os.system(f"start {loc}")
            elif (sys.platform.startswith(
                ("darwin", "haiku"))):  # haiku support :3
                os.system(f"open {loc}")
            else:  # (sys.platform.startswith(("linux", "freebsd"))): #hoping that other OSes use xdg-open
                os.system(f"xdg-open {loc}")

        # region ===== startup =====
        pffmpeg = glob.glob(f"{spath}/ffmpeg*")
        pffprobe = glob.glob(f"{spath}/ffprobe*")
        if (not pffmpeg and not pffprobe):
            fdir = False
        else:
            fdir = True

        if (os.path.exists(settingsPath)):
            settings = Settings.fromJson(settingsPath)
        else:
            messagePopup(
                "Settings error", QMessageBox.Critical,
                "You are missing a config file,\nPress OK to load default config.",
                SaveDefaultConfig)

        self.setWindowTitle(f"yt-dl {ver}")

        self.tabWidget.setCurrentIndex(
            settings.defaultTab
        )  # the code will not get here if settings is undefined.

        global running
        running = False
        status("Ready.")

        # endregion

        # region ==========🎶AUDIO🎶==========
        def Audio():
            global running
            if not running:
                running = True
                status("Busy.")
                self.tabWidget.setTabText(0, "*Audio")

                self.aud_output_console.setHtml(
                    "")  # clearing the output_console

                url = self.aud_url_bar.text()
                if self.aud_playlist_checkbox.isChecked():
                    numb = self.aud_playlist_bar.text()
                else:
                    numb = None

                if (numb is None):
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.audioDir}%(title)s.%(ext)s",
                        "--no-playlist", "-x", "--prefer-ffmpeg"
                    ], ["--audio-format", "mp3", f"{url}"]]
                elif (numb == ""):
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.audioDir}%(playlist_index)s. %(title)s.%(ext)s",
                        "--yes-playlist", "-i", "-x", "--prefer-ffmpeg"
                    ], ["--audio-format", "mp3", f"{url}"]]
                else:
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.audioDir}%(playlist_index)s. %(title)s.%(ext)s",
                        "--yes-playlist", "-i", "--playlist-items", f"{numb}",
                        "-x", "--prefer-ffmpeg"
                    ], ["--audio-format", "mp3", f"{url}"]]

                floc = [f"--ffmpeg-location", f"{spath}"]
                if (fdir is True):
                    cmd = cmd[0] + floc + cmd[1]
                else:
                    cmd = cmd[0] + cmd[1]

                self.aud_output_console.insertPlainText(
                    "#yt-dl# starting youtube-dl please wait...\n")

                process_start(cmd, self.aud_output_console)

                running = False
                status("Ready.")
                self.tabWidget.setTabText(0, "Audio")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def aud_playlist_bar_toggle():
            self.aud_playlist_bar.setEnabled(
                self.aud_playlist_checkbox.isChecked())
            if (self.aud_playlist_checkbox.isChecked()):
                self.aud_playlist_bar.setStyleSheet(
                    "background-color: #909090;")
            else:
                self.aud_playlist_bar.setStyleSheet(
                    "background-color: #707070;")

        def aud_open():
            openFolder(settings.Youtubedl.audioDir)

        # =====aud_controls=====#
        self.aud_folder_button.clicked.connect(aud_open)
        self.aud_download_button.clicked.connect(Audio)
        self.aud_playlist_checkbox.clicked.connect(aud_playlist_bar_toggle)
        self.aud_output_console.setHtml(
            "#yt-dl# Welcome to yt-dl-gui (Audio) paste a link and hit download."
        )

        # endregion

        # region ==========📼VIDEO📼==========
        def Video():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.tabWidget.setTabText(1, "*Video")

                self.vid_output_console.setHtml(
                    "")  # clearing the output_console.

                url = self.vid_url_bar.text()
                if self.vid_playlist_checkbox.isChecked():
                    numb = self.vid_playlist_bar.text()
                else:
                    numb = None

                if (numb is None):
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.videoDir}%(title)s.%(ext)s", "-f"
                    ], ["--no-playlist", f"{url}"]]
                elif (numb == ""):
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.videoDir}%(playlist_index)s. %(title)s.%(ext)s",
                        "-f"
                    ], ["--yes-playlist", f"{url}"]]
                else:
                    cmd = [[
                        "youtube-dl", "-o",
                        f"{settings.Youtubedl.videoDir}%(playlist_index)s. %(title)s.%(ext)s",
                        "-f"
                    ],
                           [
                               "--yes-playlist", "--playlist-items", f"{numb}",
                               f"{url}"
                           ]]

                if self.vid_best_radio.isChecked():
                    qual = ["bestvideo+bestaudio"]
                elif self.vid_custom_radio.isChecked():
                    qual = [self.vid_quality_bar.text()]
                else:
                    qual = ["best"]

                floc = [f"--ffmpeg-location", f"{spath}"]
                if (fdir is True):
                    cmd = cmd[0] + qual + floc + cmd[1]
                else:
                    cmd = cmd[0] + qual + cmd[1]

                self.vid_output_console.insertPlainText(
                    "#yt-dl# starting youtube-dl please wait...\n")

                process_start(cmd, self.vid_output_console)

                running = False
                status("Ready.")
                self.tabWidget.setTabText(1, "Video")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def vid_quality():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.vid_output_console.setHtml(
                    "")  # clearing the output_console

                url = self.vid_url_bar.text()
                cmd = ["youtube-dl", "-F", "--no-playlist", f"{url}"]

                self.vid_output_console.insertPlainText(
                    "#yt-dl# starting yt-dl please wait...\n")

                process_start(cmd, self.vid_output_console)

                running = False
                status("Ready.")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def vid_playlist_bar_toggle():
            self.vid_playlist_bar.setEnabled(
                self.vid_playlist_checkbox.isChecked())
            if (self.vid_playlist_checkbox.isChecked()):
                self.vid_playlist_bar.setStyleSheet(
                    "background-color: #909090;")
            else:
                self.vid_playlist_bar.setStyleSheet(
                    "background-color: #707070;")

        def vid_quality_bar_toggle():
            self.vid_quality_bar.setEnabled(self.vid_custom_radio.isChecked())
            if (self.vid_custom_radio.isChecked()):
                self.vid_quality_bar.setStyleSheet(
                    "background-color: #909090;")
            else:
                self.vid_quality_bar.setStyleSheet(
                    "background-color: #707070;")

        def vid_open():
            openFolder(settings.Youtubedl.videoDir)

        # =====vid_controls=====#
        self.vid_folder_button.clicked.connect(vid_open)
        self.vid_download_button.clicked.connect(Video)
        self.vid_quality_button.clicked.connect(vid_quality)
        self.vid_playlist_checkbox.clicked.connect(vid_playlist_bar_toggle)
        self.vid_custom_radio.toggled.connect(vid_quality_bar_toggle)
        self.vid_output_console.setHtml(
            "#yt-dl# Welcome to yt-dl-gui (Video) paste a link and hit download."
        )

        # endregion

        # region ==========📑SUBS📑==========
        def Subs():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.tabWidget.setTabText(2, "*Subs")

                temp = tempfile.mkdtemp() + os.path.sep

                self.sub_output_console.setHtml(
                    "")  # clearing the output_console.

                url = self.sub_url_bar.text()

                cmd = [[], []]

                if self.sub_playlist_checkbox.isChecked():
                    if self.sub_playlist_bar.text() == "":
                        cmd[0] = [
                            "youtube-dl", "-o", f"{temp}%(title)s.%(ext)s",
                            "--yes-playlist", "--write-sub", "--write-auto-sub"
                        ]
                    else:
                        numb = self.sub_playlist_bar.text()
                        cmd[0] = [
                            "youtube-dl", "-o", f"{temp}%(title)s.%(ext)s",
                            "--yes-playlist", "--playlist-items", f"{numb}",
                            "--write-sub", "--write-auto-sub"
                        ]
                else:
                    cmd[0] = [
                        "youtube-dl", "-o", f"{temp}%(title)s.%(ext)s",
                        "--no-playlist", "--write-sub", "--write-auto-sub"
                    ]

                cmd[1] = ["--sub-format", "vtt", "--skip-download", f"{url}"]

                lang = None

                if self.sub_lang_checkbox.isChecked():
                    lang = self.sub_lang_bar.text()

                floc = [f"--ffmpeg-location", f"{spath}"]
                if (fdir is True):
                    if lang is not None:
                        cmd = cmd[0] + lang + floc + cmd[1]
                    else:
                        cmd = cmd[0] + floc + cmd[1]
                else:
                    if lang is not None:
                        cmd = cmd[0] + lang + cmd[1]
                    else:
                        cmd = cmd[0] + cmd[1]

                self.sub_output_console.insertPlainText(
                    "#yt-dl# starting yt-dl please wait...\n")

                process_start(cmd, self.sub_output_console)

                subpath = glob.glob(f"{temp}*.vtt")
                os.makedirs(settings.Youtubedl.videoDir, exist_ok=True)

                for item in subpath:
                    namei = os.path.basename(item)
                    namei = namei[:-3]
                    newsubpath = f"{settings.Youtubedl.videoDir}{namei}srt"  # I don't like this fix to a complain about var type
                    if os.path.isfile(newsubpath):
                        self.sub_output_console.insertPlainText(
                            f"#yt-dl# file {item} already exists skipping...\n"
                        )
                    else:
                        cmd = ["-i", f"{item}", f"{newsubpath}"]

                        floc = [
                            f"{spath+os.path.sep+'ffmpeg'}", "-hide_banner"
                        ]
                        if (fdir is True):
                            cmd = floc + cmd
                        else:
                            cmd = ["ffmpeg", "-hide_banner"] + cmd

                        self.sub_output_console.insertPlainText(
                            "#yt-dl# starting ffmpeg please wait...\n")

                        process_start(cmd, self.sub_output_console)

                running = False
                status("Ready.")
                self.tabWidget.setTabText(2, "Subs")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def sub_lang():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.sub_output_console.setHtml(
                    "")  # clearing the output_console

                url = self.sub_url_bar.text()
                cmd = ["youtube-dl", "--list-subs", "--no-playlist", f"{url}"]

                process_start(cmd, self.sub_output_console)

                running = False
                status("Ready.")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def sub_playlist_bar_toggle():
            self.sub_lang_button.setEnabled(
                not self.sub_playlist_checkbox.isChecked())
            self.sub_playlist_bar.setEnabled(
                self.sub_playlist_checkbox.isChecked())
            if (self.sub_playlist_checkbox.isChecked()):
                self.sub_playlist_bar.setStyleSheet(
                    "background-color: #909090;")
            else:
                self.sub_playlist_bar.setStyleSheet(
                    "background-color: #707070;")

        def sub_lang_bar_toggle():
            self.sub_lang_bar.setEnabled(self.sub_lang_checkbox.isChecked())
            if (self.sub_lang_checkbox.isChecked()):
                self.sub_lang_bar.setStyleSheet("background-color: #909090;")
            else:
                self.sub_lang_bar.setStyleSheet("background-color: #707070;")

        # =====sub_controls=====#
        self.sub_folder_button.clicked.connect(vid_open)
        self.sub_download_button.clicked.connect(Subs)
        self.sub_lang_button.clicked.connect(sub_lang)
        self.sub_playlist_checkbox.toggled.connect(sub_playlist_bar_toggle)
        self.sub_lang_checkbox.toggled.connect(sub_lang_bar_toggle)
        self.sub_output_console.setHtml(
            "#yt-dl# Welcome to yt-dl-gui (Subtitles) paste a link and hit download."
        )

        # endregion

        # region ==========💿RE-ENCODE💿==========
        def Reencode():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.tabWidget.setTabText(3, "*Re-encode")

                self.ree_output_console.setHtml(
                    "")  # clearing the output_console

                location = self.ree_location_bar.text()
                videoc = self.ree_videoc_bar.text()
                videoq = self.ree_videoq_bar.text()
                audioc = self.ree_audioc_bar.text()
                audiob = self.ree_audiob_bar.text()
                append = self.ree_append_bar.text()

                if location[-2:] == os.path.sep + "*":  # whole folder
                    VidsToRender = glob.glob(location)
                else:
                    VidsToRender = [f"{location}"]
                for video in VidsToRender:
                    if os.path.isfile(os.path.splitext(video)[0] + append):
                        self.ree_output_console.insertPlainText(
                            f"#yt-dl# file {video} already exists skipping...\n"
                        )
                    else:
                        cmd = [[
                            "-hwaccel", "auto", "-i", f"{video}", "-map",
                            "0:v?", "-map", "0:a?", "-map", "0:s?"
                        ], ["-max_muxing_queue_size", "9999", "-b:v", "0K"],
                               [f"{os.path.splitext(video)[0]+append}"]]

                        # //Video Quality\\#
                        if "," in videoq:
                            VQsplit = videoq.split(",")
                        else:
                            VQsplit = [videoq, videoq, videoq]
                        # //Video Codec\\#
                        if (videoc == "libx265"):
                            VideoCodec = ["-c:v", f"{videoc}"]
                            quality = [
                                "-crf", f"{int(VQsplit[0])-1}", "-qmin",
                                f"{int(VQsplit[1])-1}", "-qmax",
                                f"{int(VQsplit[2])-1}"
                            ]
                            Vformat = ["-vf", "format=yuv420p"]
                            cmd = [
                                cmd[0] + VideoCodec + quality + cmd[1] +
                                Vformat, cmd[2]
                            ]
                        elif (videoc == "copy"):
                            VideoCodec = [f"-c:v", f"{videoc}"]
                            cmd = [cmd[0] + VideoCodec + cmd[1], cmd[2]]
                        elif (videoc == "remove"):
                            VideoCodec = ["-vn"]
                            cmd = [cmd[0] + VideoCodec + cmd[1], cmd[2]]
                        elif (videoc == "hevc_nvenc"):
                            VideoCodec = ["-c:v", f"{videoc}"]
                            quality = [
                                "-rc:v", "vbr", "-qmin", f"{int(VQsplit[1])}",
                                "-qmax", f"{int(VQsplit[2])}", "-bf", "1"
                            ]
                            Vformat = ["-vf", "format=yuv420p"]
                            cmd = [
                                cmd[0] + VideoCodec + quality + cmd[1] +
                                Vformat, cmd[2]
                            ]
                        elif (videoc == "h264_nvenc"):
                            VideoCodec = ["-c:v", f"{videoc}"]
                            quality = [
                                "-rc:v", "vbr", "-qmin", f"{int(VQsplit[1])}",
                                "-qmax", f"{int(VQsplit[2])}"
                            ]
                            Vformat = ["-vf", "format=yuv420p"]
                            cmd = [
                                cmd[0] + VideoCodec + quality + cmd[1] +
                                Vformat, cmd[2]
                            ]
                        else:
                            VideoCodec = ["-c:v", f"{videoc}"]
                            quality = [
                                "-cq", f"{int(VQsplit[0])-1}", "-qmin",
                                f"{int(VQsplit[1])-1}", "-qmax",
                                f"{int(VQsplit[2])-1}"
                            ]
                            Vformat = ["-vf", "format=yuv420p"]
                            cmd = [
                                cmd[0] + VideoCodec + quality + cmd[1] +
                                Vformat, cmd[2]
                            ]
                        # //Audio\\#
                        if (audioc == "remove"):
                            AudioEverything = ["-an"]
                            cmd = [cmd[0] + AudioEverything, cmd[1]]
                        else:
                            AudioEverything = [
                                "-c:a", f"{audioc}", "-strict", "-2", "-b:a",
                                f"{audiob}"
                            ]
                            cmd = [cmd[0] + AudioEverything, cmd[1]]
                        # //Subtitles\\#
                        if (videoc == "remove"):
                            cmd = cmd[0] + cmd[1]
                        else:
                            SubsC = ["-c:s", "copy"]
                            cmd = cmd[0] + SubsC + cmd[1]

                        floc = [
                            f"{spath+os.path.sep+'ffmpeg'}", "-hide_banner"
                        ]
                        if (fdir is True):
                            cmd = floc + cmd
                        else:
                            cmd = ["ffmpeg", "-hide_banner"] + cmd

                        process_start(cmd, self.ree_output_console)
                        # print(cmd)

                running = False
                status("Ready.")
                self.tabWidget.setTabText(3, "Re-encode")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def ree_settings():
            if self.ree_settings_combobox.currentIndex() == 4:  # custom
                self.ree_videoc_bar.setText(settings.Ffmpeg.videoCodec)
                self.ree_videoq_bar.setText(settings.Ffmpeg.videoQuality)
                self.ree_audioc_bar.setText(settings.Ffmpeg.audioCodec)
                self.ree_audiob_bar.setText(settings.Ffmpeg.audioBitrate)
                self.ree_append_bar.setText(settings.Ffmpeg.append)
            elif self.ree_settings_combobox.currentIndex() == 0:  # hevc_opus
                self.ree_videoc_bar.setText("libx265")
                self.ree_videoq_bar.setText("24,24,24")
                self.ree_audioc_bar.setText("opus")
                self.ree_audiob_bar.setText("190k")
                self.ree_append_bar.setText("_hevcopus.mkv")
            elif self.ree_settings_combobox.currentIndex() == 1:  # h264_nvenc
                self.ree_videoc_bar.setText("h264_nvenc")
                self.ree_videoq_bar.setText("24,24,24")
                self.ree_audioc_bar.setText("aac")
                self.ree_audiob_bar.setText("190k")
                self.ree_append_bar.setText("_nvenc.mov")
            elif self.ree_settings_combobox.currentIndex() == 2:  # hevc_nvenc
                self.ree_videoc_bar.setText("hevc_nvenc")
                self.ree_videoq_bar.setText("24,24,24")
                self.ree_audioc_bar.setText("opus")
                self.ree_audiob_bar.setText("190k")
                self.ree_append_bar.setText("_henc.mkv")
            elif self.ree_settings_combobox.currentIndex() == 3:  # mp3
                self.ree_videoc_bar.setText("remove")
                self.ree_videoq_bar.setText("none")
                self.ree_audioc_bar.setText("mp3")
                self.ree_audiob_bar.setText("190k")
                self.ree_append_bar.setText(".mp3")

        def ree_settings_save():
            settings.Ffmpeg.videoCodec = self.ree_videoc_bar.text()
            settings.Ffmpeg.audioCodec = self.ree_audioc_bar.text()
            settings.Ffmpeg.videoQuality = self.ree_videoq_bar.text()
            settings.Ffmpeg.audioBitrate = self.ree_audiob_bar.text()
            settings.Ffmpeg.append = self.ree_append_bar.text()
            settings.defaultCodec = self.ree_settings_combobox.currentIndex()
            settings.toJson(settingsPath)

        def ree_choose():
            self.ree_location_bar.setText(QFileDialog.getOpenFileName()[0])

        def ree_open():
            location = self.ree_location_bar.text()
            openFolder(os.path.dirname(location))

        # =====ree_controls=====#
        self.ree_settings_combobox.addItem(
            "hevc_opus")  # setting up items in combo list
        self.ree_settings_combobox.addItem("h264_nvenc")
        self.ree_settings_combobox.addItem("hevc_nvenc")
        self.ree_settings_combobox.addItem("mp3")
        self.ree_settings_combobox.addItem("custom")
        self.ree_settings_combobox.setCurrentIndex(settings.defaultCodec)
        ree_settings()  # load option on startup
        self.ree_choose_button.clicked.connect(ree_choose)
        self.ree_reencode_button.clicked.connect(Reencode)
        self.ree_folder_button.clicked.connect(ree_open)
        self.ree_settings_combobox.activated.connect(ree_settings)
        self.ree_settings_button.clicked.connect(ree_settings_save)
        self.ree_output_console.setHtml(
            "#yt-dl# Welcome to yt-dl-gui (Re-encode) paste a link and hit download."
        )
        # self.ree_location_bar.setDragEnabled(True)
        self.ree_location_bar.setAcceptDrops(True)

        # endregion

        # region ==========🔄UPDATE🔄==========
        def update_yt_dl():
            cmd = ["git", "pull", "--recurse-submodules"]
            process_start(cmd, self.upd_output_console)

        def update_depend():
            pips = settings.Python.pip.split(" ")
            cmd = [
                f"{settings.Python.python}", "-m", "pip", "install", "-U",
                "pip"
            ]
            process_start(cmd, self.upd_output_console)
            cmd = pips + ["install", "-U", "-r", "req-gui5.txt"]
            process_start(cmd, self.upd_output_console)

        def Update():
            global running
            if running is False:
                running = True
                status("Busy.")

                self.tabWidget.setTabText(4, "*Update")

                self.upd_output_console.setHtml(
                    "")  # clearing the output_console

                if self.upd_update_combobox.currentIndex() == 1:
                    update_yt_dl()
                elif self.upd_update_combobox.currentIndex() == 2:
                    update_depend()
                else:
                    update_yt_dl()
                    update_depend()

                running = False
                status("Ready.")
                self.tabWidget.setTabText(4, "Update")
            else:
                messagePopup("Process warning", QMessageBox.Warning,
                             "One process already running!")

        def upd_auto_toggle():  # autoupdate is not a thing tho
            settings.autoUpdate = not settings.autoUpdate
            settings.toJson(settingsPath)
            self.upd_auto_button.setText(
                f"Autoupdate=\"{settings.autoUpdate}\"")

        # ======upd_controls======#
        self.upd_update_combobox.addItem(
            "All")  # setting up items in combo list
        self.upd_update_combobox.addItem("yt-dl")
        self.upd_update_combobox.addItem("dependencies")
        if (sys.platform.startswith("haiku")):
            self.upd_update_combobox.setCurrentIndex(1)
        '''
        #region (branch switching code)
        branches = os.listdir(spath+".git/refs/heads")
        for branch in branches:
            self.upd_branch_combobox.addItem(branch)
        
        process = subprocess.Popen(["git", "rev-parse", "--abbrev-ref", "HEAD"], stdout=subprocess.PIPE)
        gcurb = str(process.stdout.read())
        curb = "Current branch: "+curb[2:-3]
        self.upd_branch_label.setText(curb)
        #endregion
        '''

        QtWidgets.QApplication.processEvents()
        if settings.autoUpdate:
            self.tabWidget.setCurrentIndex(4)
            Update()

        self.upd_update_button.clicked.connect(Update)
        # self.upd_branch_button.clicked.connect(upd_branch)
        self.upd_auto_button.setText(f"Autoupdate=\"{settings.autoUpdate}\"")
        self.upd_auto_button.clicked.connect(upd_auto_toggle)

        # endregion

        # region ==========📈SETTINGS📈==========
        def set_save():
            settings.Youtubedl.audioDir = self.set_audio_bar.text()
            settings.Youtubedl.videoDir = self.set_videos_bar.text()
            settings.Python.python = self.set_py_bar.text()
            settings.Python.pip = self.set_pip_bar.text()
            settings.Youtubedl.fromPip = self.set_ydpip_checkbox.isChecked()
            settings.autoUpdate = self.set_aup_checkbox.isChecked()
            settings.Ffmpeg.audioCodec = self.set_Acodec_bar.text()
            settings.Ffmpeg.videoCodec = self.set_Vcodec_bar.text()
            settings.Ffmpeg.audioBitrate = self.set_Abit_bar.text()
            settings.Ffmpeg.videoQuality = self.set_Vqual_bar.text()
            settings.Ffmpeg.append = self.set_Append_bar.text()
            settings.defaultTab = self.set_Tab_combobox.currentIndex()

            settings.toJson(settingsPath)

        def set_load(audio, video, py, pip, ydpip, aup, acodec, vcodec, abit,
                     vqual, append, tab):
            self.set_audio_bar.setText(audio)
            self.set_videos_bar.setText(video)
            self.set_py_bar.setText(py)
            self.set_pip_bar.setText(pip)
            self.set_ydpip_checkbox.setChecked(ydpip)
            self.set_aup_checkbox.setChecked(aup)
            self.set_Acodec_bar.setText(acodec)
            self.set_Vcodec_bar.setText(vcodec)
            self.set_Abit_bar.setText(abit)
            self.set_Vqual_bar.setText(vqual)
            self.set_Append_bar.setText(append)
            self.set_Tab_combobox.setCurrentIndex(tab)

        def set_makeScript(
        ):  # I had an issue getting the venv working with gui
            if (sys.platform.startswith("win")):
                f = open("yt-dl_gui.vbs", "w")
                f.write(
                    f"Set WshShell = CreateObject(\"WScript.Shell\")\nWshShell.Run \"cmd /c cd /d {spath} & pythonw.exe gui.py\", 0\nSet WshShell = Nothing"
                )
                f.close()
                f = open("yt-dl_gui.bat", "w")
                f.write(f"@echo off\n\nstart /b pythonw.exe gui5.py")
                f.close()
            else:  # (sys.platform.startswith(("linux", "darwin", "freebsd"))):
                f = open("yt-dl", "w")
                f.write(
                    f"#!/bin/sh\n\ncd {spath} && {settings.Python.python} gui5.py"
                )
                f.close()

        def set_open():
            openFolder(spath)

        # =====set_controls=====#
        self.set_loadcur_button.clicked.connect(lambda: set_load(
            settings.Youtubedl.audioDir, settings.Youtubedl.videoDir, settings.
            Python.python, settings.Python.pip, settings.Youtubedl.fromPip,
            settings.autoUpdate, settings.Ffmpeg.audioCodec, settings.Ffmpeg.
            videoCodec, settings.Ffmpeg.audioBitrate, settings.Ffmpeg.
            videoQuality, settings.Ffmpeg.append, settings.defaultTab))
        self.set_loaddef_button.clicked.connect(lambda: set_load(
            audioDirDefault, videoDirDefault, "python", "pip", True, False,
            "opus", "libx265", "190k", "24,24,24", "_custom.mkv", 0))
        self.set_folder_button.clicked.connect(set_open)
        self.set_launch_button.clicked.connect(set_makeScript)
        self.set_save_button.clicked.connect(set_save)
        self.set_Tab_combobox.addItem(
            "Audio")  # setting up items in combo list
        self.set_Tab_combobox.addItem("Video")
        self.set_Tab_combobox.addItem("Subs")
        self.set_Tab_combobox.addItem("Re-encode")
        self.set_Tab_combobox.addItem("Update")
        self.set_Tab_combobox.addItem("Settings")
        self.set_Tab_combobox.addItem("About")
        set_load(settings.Youtubedl.audioDir, settings.Youtubedl.videoDir,
                 settings.Python.python, settings.Python.pip,
                 settings.Youtubedl.fromPip, settings.autoUpdate,
                 settings.Ffmpeg.audioCodec, settings.Ffmpeg.videoCodec,
                 settings.Ffmpeg.audioBitrate, settings.Ffmpeg.videoQuality,
                 settings.Ffmpeg.append, settings.defaultTab)
        # endregion

        # region ==========🎓ABOUT🎓==========
        self.about_box.setHtml(
            f"<p style=\"font-size: 20px; white-space: pre\">HorseArmored Inc. (C){year}<br>"
            + f"Version: {ver} gui5 ({curb} branch)<br>" +
            f"Last updated on: {lstupdt}<br>" +
            f"My webpage: <a href=\"https://koleckolp.comli.com\">https://koleckolp.comli.com</a><br>"
            +
            f"Project page: <a href=\"https://github.com/KoleckOLP/yt-dl\">https://github.com/KoleckOLP/yt-dl</a><br>"
            +
            f"need help? ask here: <a href=\"https://github.com/KoleckOLP/yt-dl\">https://discord.gg/W88375j</a><br>"
            + f"youtube-dl (C)2008-2011 Ricardo Garcia Gonzalez<br>" +
            f"                 (C)2011-{year} youtube-dl developers<br>" +
            f"ffmpeg (C)2000-{year} FFmpeg team<br>" +
            f"Thanks to <a href=\"https://github.com/kangalioo\">kangalioo</a> who always helps a ton!<br>"
            +
            f"Thanks to <a href=\"https://github.com/siscodeorg\">siscode</a> for featuring my project<br>"
            + f"and helping me improve it.<br>" +
            f"You can read the changelog: <a href=\"https://github.com/KoleckOLP/yt-dl/blob/master/changelog.md\">here</a></pre></p>"
        )
예제 #50
0
 def __iter__(self):
     p = [0]
     sen = re.compile(Settings.get('sentence_regex'))
     return ifilter(None, imap(lambda x: self.pars(p, x), sen.finditer(self.string)))